Projet

Général

Profil

0001-misc-apply-pyupgrade-55868.patch

Lauréline Guérin, 27 juillet 2021 16:30

Télécharger (242 ko)

Voir les différences:

Subject: [PATCH 1/2] misc: apply pyupgrade (#55868)

 combo/apps/assets/migrations/0001_initial.py  |  2 -
 .../assets/migrations/0002_key_maxlength.py   |  3 -
 combo/apps/assets/templatetags/assets.py      |  2 +-
 combo/apps/assets/views.py                    | 24 ++---
 combo/apps/calendar/forms.py                  |  4 +-
 .../apps/calendar/migrations/0001_initial.py  |  3 -
 .../0002_bookingcalendar_days_displayed.py    |  3 -
 combo/apps/calendar/models.py                 |  8 +-
 combo/apps/calendar/utils.py                  | 10 +-
 combo/apps/calendar/views.py                  |  2 +-
 .../apps/dashboard/migrations/0001_initial.py |  3 -
 .../migrations/0002_auto_20180105_0846.py     |  3 -
 combo/apps/dashboard/models.py                |  2 +-
 combo/apps/dashboard/views.py                 |  2 +-
 combo/apps/dataviz/forms.py                   |  2 +-
 combo/apps/dataviz/migrations/0001_initial.py |  3 -
 .../0002_gauge_jsonp_data_source.py           |  3 -
 .../0003_cubesbarchart_cubestable.py          |  3 -
 .../migrations/0004_auto_20160108_1048.py     |  3 -
 .../migrations/0005_auto_20160928_1152.py     |  3 -
 .../apps/dataviz/migrations/0006_chartcell.py |  3 -
 .../migrations/0007_auto_20170214_2006.py     |  3 -
 .../migrations/0008_auto_20190328_0857.py     |  2 -
 .../migrations/0009_auto_20190617_1214.py     |  2 -
 .../migrations/0010_auto_20190328_1111.py     |  2 -
 .../migrations/0011_auto_20200813_1100.py     |  2 -
 .../migrations/0012_auto_20201126_1557.py     |  4 +-
 .../migrations/0013_update_chartng_cells.py   |  2 -
 .../migrations/0014_auto_20201130_1534.py     |  2 -
 .../migrations/0015_auto_20201202_1424.py     |  2 -
 .../migrations/0016_auto_20201215_1624.py     |  2 -
 combo/apps/dataviz/models.py                  | 12 +--
 combo/apps/family/migrations/0001_initial.py  |  3 -
 ..._familyinfoscell_restricted_to_unlogged.py |  3 -
 .../0003_familyinfoscell_extra_css_class.py   |  3 -
 ...4_familyinfoscell_last_update_timestamp.py |  3 -
 combo/apps/family/views.py                    |  2 +-
 combo/apps/fargo/migrations/0001_initial.py   |  3 -
 ...002_recentdocumentscell_extra_css_class.py |  3 -
 ...centdocumentscell_last_update_timestamp.py |  3 -
 .../0004_recentdocumentscell_fargo_site.py    |  3 -
 combo/apps/fargo/models.py                    |  4 +-
 combo/apps/gallery/migrations/0001_initial.py |  3 -
 .../gallery/migrations/0002_image_title.py    |  3 -
 .../migrations/0003_gallerycell_title.py      |  3 -
 combo/apps/gallery/views.py                   |  4 +-
 combo/apps/kb/migrations/0001_initial.py      |  2 -
 .../kb/migrations/0002_auto_20200203_1137.py  |  2 -
 combo/apps/kb/models.py                       |  2 +-
 combo/apps/lingo/forms.py                     | 10 +-
 .../commands/notify_new_remote_invoices.py    |  1 -
 combo/apps/lingo/manager_views.py             |  4 +-
 combo/apps/lingo/migrations/0001_initial.py   |  3 -
 .../apps/lingo/migrations/0002_transaction.py |  3 -
 .../migrations/0003_auto_20150306_1047.py     |  3 -
 .../0004_basketitem_notification_date.py      |  3 -
 .../migrations/0005_auto_20150307_1242.py     |  3 -
 .../migrations/0006_transaction_status.py     |  3 -
 .../migrations/0007_lingobasketlinkcell.py    |  3 -
 .../migrations/0008_auto_20150908_1538.py     |  3 -
 .../migrations/0009_auto_20150917_1456.py     |  3 -
 .../0010_regie_payment_min_amount.py          |  3 -
 .../migrations/0011_auto_20151029_1535.py     |  3 -
 .../migrations/0012_auto_20151130_1047.py     |  3 -
 .../migrations/0013_transaction_amount.py     |  3 -
 .../migrations/0014_auto_20160218_1455.py     |  3 -
 .../migrations/0015_auto_20160309_2150.py     |  3 -
 .../migrations/0016_auto_20160319_2028.py     |  3 -
 .../migrations/0017_auto_20160327_0831.py     |  3 -
 .../migrations/0018_auto_20160527_0638.py     |  3 -
 .../migrations/0019_auto_20160531_1336.py     |  3 -
 .../migrations/0020_auto_20160606_1803.py     |  3 -
 .../migrations/0021_transactionoperation.py   |  3 -
 .../lingo/migrations/0022_regie_is_default.py |  3 -
 .../migrations/0023_auto_20160928_1152.py     |  3 -
 .../0024_selfdeclaredinvoicepayment.py        |  3 -
 .../migrations/0025_auto_20161206_1713.py     |  3 -
 .../migrations/0026_auto_20161215_1447.py     |  3 -
 .../migrations/0027_auto_20170214_2006.py     |  3 -
 .../migrations/0028_tipipaymentformcell.py    |  3 -
 .../migrations/0029_auto_20170528_1334.py     |  3 -
 ...030_transaction_to_be_paid_remote_items.py |  3 -
 .../0031_basketitem_waiting_date.py           |  2 -
 .../0032_basketitem_capture_date.py           |  2 -
 .../migrations/0033_auto_20181204_2241.py     |  3 -
 .../migrations/0034_auto_20190426_1159.py     |  2 -
 .../migrations/0035_auto_20190426_1124.py     |  2 -
 .../migrations/0036_auto_20190426_1202.py     |  2 -
 .../0037_regie_transaction_options.py         |  2 -
 .../migrations/0038_hide_cell_if_empty.py     |  2 -
 .../0039_transaction_transaction_date.py      |  2 -
 .../migrations/0040_auto_20200608_1222.py     |  2 -
 ...0041_regie_can_pay_only_one_basket_item.py |  2 -
 combo/apps/lingo/models.py                    | 29 +++---
 combo/apps/lingo/utils.py                     |  1 -
 combo/apps/lingo/views.py                     | 70 +++++++-------
 combo/apps/maps/forms.py                      |  6 +-
 combo/apps/maps/manager_views.py              | 22 ++---
 combo/apps/maps/migrations/0001_initial.py    |  3 -
 combo/apps/maps/migrations/0002_map.py        |  3 -
 .../migrations/0003_auto_20170603_1653.py     |  3 -
 .../maps/migrations/0004_map_initial_state.py |  3 -
 .../migrations/0005_auto_20180212_1742.py     |  3 -
 .../migrations/0006_auto_20180627_0841.py     |  3 -
 .../migrations/0007_auto_20180706_1345.py     |  2 -
 .../maps/migrations/0008_map_layer_options.py |  5 +-
 .../maps/migrations/0009_map_layer_kind.py    |  2 -
 .../maps/migrations/0010_map_layer_opacity.py |  3 -
 .../migrations/0011_map_layer_set_slug.py     |  3 -
 .../migrations/0012_map_layer_slug_unicity.py |  3 -
 .../0013_geojson_query_parameter.py           |  3 -
 .../migrations/0014_geojson_circle_param.py   |  3 -
 combo/apps/maps/models.py                     |  6 +-
 .../notifications/migrations/0001_initial.py  |  3 -
 ...notificationscell_last_update_timestamp.py |  3 -
 .../migrations/0003_notification_origin.py    |  3 -
 .../migrations/0004_auto_20180316_1026.py     |  4 +-
 .../migrations/0005_auto_20180324_0025.py     |  2 -
 combo/apps/notifications/models.py            |  4 +-
 combo/apps/pwa/forms.py                       |  2 +-
 combo/apps/pwa/manager_views.py               | 12 +--
 combo/apps/pwa/migrations/0001_initial.py     |  2 -
 combo/apps/pwa/migrations/0002_pwasettings.py |  2 -
 .../pwa/migrations/0003_pwanavigationentry.py |  2 -
 .../0004_pwasettings_application_icon.py      |  2 -
 .../0005_pwasettings_application_name.py      |  2 -
 .../pwa/migrations/0006_auto_20190628_1042.py |  2 -
 combo/apps/pwa/models.py                      |  5 +-
 combo/apps/search/engines.py                  |  2 +-
 combo/apps/search/forms.py                    |  2 +-
 combo/apps/search/migrations/0001_initial.py  |  3 -
 .../migrations/0002_auto_20180720_1511.py     |  3 -
 .../migrations/0003_create_search_services.py |  3 -
 .../0004_remove_searchcell__search_service.py |  3 -
 .../migrations/0005_searchcell_autofocus.py   |  2 -
 .../search/migrations/0006_indexedcell.py     |  2 -
 .../apps/search/migrations/0007_french_fts.py |  2 -
 .../0008_searchcell_input_placeholder.py      |  2 -
 combo/apps/search/models.py                   |  4 +-
 combo/apps/wcs/context_processors.py          |  9 +-
 combo/apps/wcs/forms.py                       | 10 +-
 combo/apps/wcs/migrations/0001_initial.py     |  3 -
 .../wcs/migrations/0002_auto_20150217_1402.py |  3 -
 .../wcs/migrations/0003_auto_20150218_1151.py |  3 -
 .../wcs/migrations/0004_auto_20150218_1154.py |  3 -
 .../wcs/migrations/0005_auto_20150401_0758.py |  3 -
 .../wcs/migrations/0006_categoriescell.py     |  3 -
 .../migrations/0007_trackingcodeinputcell.py  |  3 -
 .../0008_wcsformcell_cached_json.py           |  3 -
 .../0009_remove_wcscategorycell_link_page.py  |  3 -
 .../wcs/migrations/0010_auto_20151029_1535.py |  3 -
 .../wcs/migrations/0011_auto_20151215_1121.py |  3 -
 ...012_wcsformsofcategorycell_manual_order.py |  3 -
 .../wcs/migrations/0013_auto_20160928_1152.py |  3 -
 .../wcs/migrations/0014_auto_20170214_2006.py |  3 -
 .../0015_wcscurrentformscell_categories.py    |  2 -
 .../0016_backofficesubmissioncell.py          |  2 -
 .../wcs/migrations/0017_wcscareformscell.py   |  2 -
 .../0018_wcscurrentdraftscell_categories.py   |  3 -
 ...0019_wcscurrentformscell_include_drafts.py |  3 -
 combo/apps/wcs/migrations/0020_cards.py       |  3 -
 combo/apps/wcs/migrations/0021_card.py        |  3 -
 combo/apps/wcs/migrations/0022_cards_user.py  |  3 -
 .../apps/wcs/migrations/0023_card_info_id.py  |  3 -
 .../wcs/migrations/0024_card_info_user.py     |  3 -
 .../migrations/0025_submission_categories.py  |  3 -
 .../0028_wcscardscell_without_user.py         |  2 -
 .../wcs/migrations/0029_cards_custom_title.py |  3 -
 .../migrations/0032_forms_user_can_access.py  |  3 -
 combo/apps/wcs/models.py                      | 33 ++++---
 combo/apps/wcs/views.py                       |  6 +-
 combo/data/fields.py                          | 23 +++--
 combo/data/forms.py                           | 10 +-
 combo/data/library.py                         |  2 +-
 combo/data/management/commands/cron.py        |  1 -
 combo/data/management/commands/export_site.py |  2 +-
 combo/data/management/commands/import_site.py |  4 +-
 combo/data/migrations/0001_initial.py         |  3 -
 .../migrations/0002_auto_20150217_1327.py     |  3 -
 combo/data/migrations/0003_menucell.py        |  3 -
 combo/data/migrations/0004_menucell_depth.py  |  3 -
 .../migrations/0005_auto_20150226_0903.py     |  3 -
 combo/data/migrations/0006_linkcell.py        |  3 -
 .../migrations/0007_auto_20150529_1003.py     |  3 -
 .../migrations/0008_auto_20150529_1504.py     |  3 -
 .../migrations/0009_auto_20150529_2247.py     |  3 -
 combo/data/migrations/0010_feedcell.py        |  3 -
 .../migrations/0011_auto_20151028_1047.py     |  3 -
 .../migrations/0012_auto_20151029_1535.py     |  3 -
 combo/data/migrations/0013_parameterscell.py  |  3 -
 .../migrations/0014_menucell_initial_level.py |  3 -
 combo/data/migrations/0015_feedcell_title.py  |  3 -
 combo/data/migrations/0016_feedcell_limit.py  |  3 -
 .../migrations/0017_menucell_root_page.py     |  3 -
 .../data/migrations/0018_parentcontentcell.py |  3 -
 .../migrations/0019_create_parent_cells.py    |  3 -
 .../migrations/0020_auto_20160928_1152.py     |  3 -
 combo/data/migrations/0021_jsoncell.py        |  3 -
 .../migrations/0022_auto_20170214_2006.py     |  3 -
 .../migrations/0023_auto_20170313_1541.py     |  3 -
 combo/data/migrations/0024_configjsoncell.py  |  3 -
 .../migrations/0025_jsoncell_varnames_str.py  |  3 -
 .../migrations/0026_jsoncell_force_async.py   |  3 -
 combo/data/migrations/0027_page_picture.py    |  3 -
 .../data/migrations/0028_jsoncell_timeout.py  |  3 -
 .../migrations/0029_auto_20171022_1242.py     |  3 -
 .../migrations/0030_externallinksearchitem.py |  3 -
 combo/data/migrations/0031_remove_blurps.py   |  3 -
 .../data/migrations/0032_page_description.py  |  3 -
 .../migrations/0033_auto_20180401_1300.py     |  2 -
 combo/data/migrations/0034_redirect.py        |  2 -
 .../migrations/0035_page_related_cells.py     |  2 -
 combo/data/migrations/0036_page_sub_slug.py   |  2 -
 .../migrations/0037_auto_20190701_2118.py     |  2 -
 .../0038_increase_jsoncell_url_max_length.py  |  2 -
 combo/data/migrations/0039_link_list_cell.py  |  3 -
 .../migrations/0040_auto_20200119_1017.py     |  2 -
 .../migrations/0041_auto_20200130_1619.py     |  3 -
 .../0042_page_creation_timestamp.py           |  2 -
 .../0043_delete_externallinksearchitem.py     |  2 -
 combo/data/migrations/0044_validity_info.py   |  5 +-
 combo/data/migrations/0045_link_list_limit.py |  2 -
 combo/data/models.py                          | 64 ++++++-------
 combo/data/utils.py                           |  8 +-
 combo/manager/fields.py                       |  3 +-
 combo/manager/forms.py                        | 12 +--
 combo/manager/views.py                        | 40 ++++----
 combo/profile/__init__.py                     |  1 -
 combo/profile/migrations/0001_initial.py      |  3 -
 combo/profile/migrations/0002_profilecell.py  |  2 -
 combo/profile/models.py                       |  4 +-
 combo/profile/utils.py                        |  2 +-
 combo/public/templatetags/combo.py            |  7 +-
 combo/public/views.py                         | 12 +--
 combo/urls_utils.py                           |  4 +-
 combo/utils/forms.py                          |  8 +-
 combo/utils/requests_wrapper.py               |  2 +-
 setup.py                                      |  3 +-
 tests/settings.py                             |  2 +-
 tests/test_assets.py                          | 12 +--
 tests/test_calendar.py                        |  2 +-
 tests/test_cells.py                           | 36 +++----
 tests/test_cron.py                            |  3 +-
 tests/test_dashboard.py                       |  2 +-
 tests/test_dataviz.py                         | 78 +++++++--------
 tests/test_ensure_jsonbfields.py              |  2 -
 tests/test_fargo.py                           |  2 +-
 tests/test_gallery_cell.py                    |  1 -
 tests/test_lingo_cells.py                     |  6 +-
 tests/test_lingo_manager.py                   |  6 +-
 tests/test_lingo_payment.py                   |  4 +-
 tests/test_lingo_remote_regie.py              |  8 +-
 tests/test_manager.py                         | 25 +++--
 tests/test_maps_cells.py                      |  3 +-
 tests/test_maps_manager.py                    |  7 +-
 tests/test_notification.py                    |  4 +-
 tests/test_pages.py                           | 26 ++---
 tests/test_profile.py                         |  2 +-
 tests/test_public.py                          |  4 +-
 tests/test_publik.py                          |  2 +-
 tests/test_pwa.py                             |  2 +-
 tests/test_requests.py                        |  7 +-
 tests/test_search.py                          | 12 +--
 tests/test_spooler.py                         |  2 +-
 tests/test_utils.py                           |  2 +-
 tests/test_wcs.py                             | 96 +++++++++----------
 tests/test_wcs_templatetags.py                | 10 +-
 267 files changed, 430 insertions(+), 977 deletions(-)
combo/apps/assets/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2018-06-12 11:42
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/assets/migrations/0002_key_maxlength.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/assets/templatetags/assets.py
38 38
            asset = asset_object
39 39
            break
40 40

  
41
        if isinstance(asset_object, six.string_types):
41
        if isinstance(asset_object, str):
42 42
            try:
43 43
                asset = Asset.objects.get(key=asset_object).asset
44 44
                break
combo/apps/assets/views.py
39 39
from .models import Asset
40 40

  
41 41

  
42
class CkEditorAsset(object):
42
class CkEditorAsset:
43 43
    def __init__(self, filepath):
44 44
        self.filepath = filepath
45 45
        self.name = os.path.basename(filepath)
......
69 69
        return ckeditor.views.is_image(self.src)
70 70

  
71 71

  
72
class SlotAsset(object):
72
class SlotAsset:
73 73
    def __init__(self, key=None, name=None, asset_type='image', asset=None):
74 74
        self.key = key
75 75
        self.name = name
......
98 98

  
99 99
    @classmethod
100 100
    def get_assets(cls):
101
        assets = dict([(x.key, x) for x in Asset.objects.all()])
101
        assets = {x.key: x for x in Asset.objects.all()}
102 102
        uniq_slots = {}
103 103
        uniq_slots.update(settings.COMBO_ASSET_SLOTS)
104 104
        cells = CellBase.get_cells(select_related={'__all__': ['page'], 'data_linkcell': ['link_page']})
......
131 131
        return files
132 132

  
133 133
    def get_context_data(self, **kwargs):
134
        context = super(Assets, self).get_context_data(**kwargs)
134
        context = super().get_context_data(**kwargs)
135 135
        context['query'] = self.request.GET.get('q') or ''
136 136
        return context
137 137

  
......
170 170
        ckeditor_upload_view = ckeditor.views.ImageUploadView()
171 171
        self.request.GET = {'CKEditorFuncNum': '-'}  # hack
172 172
        ckeditor_upload_view.post(self.request)
173
        return super(AssetUpload, self).form_valid(form)
173
        return super().form_valid(form)
174 174

  
175 175
    def get_success_url(self):
176 176
        return Assets(request=self.request).get_anchored_url(name=self.request.FILES['upload'].name)
......
204 204
                self.request,
205 205
                _('You have to upload a file with the same extension (%(ext)s).') % {'ext': ext_orig},
206 206
            )
207
            return super(AssetOverwrite, self).form_valid(form)
207
            return super().form_valid(form)
208 208

  
209 209
        default_storage.delete(img_orig)
210 210
        if getattr(settings, 'CKEDITOR_IMAGE_BACKEND', None):
......
220 220
        else:
221 221
            if backend.should_create_thumbnail(saved_path):
222 222
                backend.create_thumbnail(saved_path)
223
        return super(AssetOverwrite, self).form_valid(form)
223
        return super().form_valid(form)
224 224

  
225 225
    def get_success_url(self):
226 226
        img_orig = self.request.GET['img']
......
254 254

  
255 255
    def get_assets(self, cell):
256 256
        asset_slots = cell.get_asset_slots()
257
        assets = dict([(x.key, x) for x in Asset.objects.filter(key__in=asset_slots.keys())])
257
        assets = {x.key: x for x in Asset.objects.filter(key__in=asset_slots.keys())}
258 258
        for key, value in asset_slots.items():
259 259
            yield SlotAsset(
260 260
                key,
......
293 293
            self.asset = Asset(key=self.kwargs['key'])
294 294
        self.asset.asset = self.request.FILES['upload']
295 295
        self.asset.save()
296
        return super(SlotAssetUpload, self).form_valid(form)
296
        return super().form_valid(form)
297 297

  
298 298
    def get_success_url(self):
299 299
        if self.request.GET.get('cell_reference'):
......
349 349
            import_assets(form.cleaned_data['assets_file'], overwrite)
350 350
        except tarfile.TarError:
351 351
            messages.error(self.request, _('The assets file is not valid.'))
352
            return super(AssetsImport, self).form_valid(form)
352
            return super().form_valid(form)
353 353
        messages.success(self.request, _('The assets file has been imported.'))
354
        return super(AssetsImport, self).form_valid(form)
354
        return super().form_valid(form)
355 355

  
356 356

  
357 357
assets_import = AssetsImport.as_view()
......
392 392
    template_name = 'combo/manager_assets_export_size.html'
393 393

  
394 394
    def get_context_data(self, **kwargs):
395
        context = super(AssetsExportSize, self).get_context_data(**kwargs)
395
        context = super().get_context_data(**kwargs)
396 396
        media_prefix = default_storage.path('')
397 397
        computed_size = 0
398 398
        for basedir, dirnames, filenames in os.walk(media_prefix):
combo/apps/calendar/forms.py
37 37
        )
38 38

  
39 39
    def __init__(self, *args, **kwargs):
40
        super(BookingCalendarForm, self).__init__(*args, **kwargs)
40
        super().__init__(*args, **kwargs)
41 41
        agenda_references = get_agendas()
42 42
        formdef_references = get_wcs_options('/api/formdefs/')
43 43
        self.fields['agenda_reference'].widget = forms.Select(choices=agenda_references)
......
47 47
class BookingForm(forms.Form):
48 48
    def __init__(self, *args, **kwargs):
49 49
        self.cell = kwargs.pop('cell')
50
        super(BookingForm, self).__init__(*args, **kwargs)
50
        super().__init__(*args, **kwargs)
51 51
        self.cleaned_data = {}
52 52

  
53 53
    def is_valid(self):
combo/apps/calendar/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import datetime
5 2

  
6 3
from django.db import migrations, models
combo/apps/calendar/migrations/0002_bookingcalendar_days_displayed.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/calendar/models.py
59 59
        return settings.BOOKING_CALENDAR_CELL_ENABLED and is_chrono_enabled() and is_wcs_enabled()
60 60

  
61 61
    def is_visible(self, **kwargs):
62
        return (
63
            self.agenda_reference
64
            and self.formdef_reference
65
            and super(BookingCalendar, self).is_visible(**kwargs)
66
        )
62
        return self.agenda_reference and self.formdef_reference and super().is_visible(**kwargs)
67 63

  
68 64
    def get_cell_extra_context(self, context):
69 65
        if context.get('placeholder_search_mode'):
70 66
            return {}
71
        extra_context = super(BookingCalendar, self).get_cell_extra_context(context)
67
        extra_context = super().get_cell_extra_context(context)
72 68
        events_data = get_chrono_events(self.agenda_reference, not (context.get('synchronous')))
73 69
        extra_context.update(
74 70
            get_calendar_context_vars(context['request'], extra_context['cell'], events_data)
combo/apps/calendar/utils.py
128 128
    return url
129 129

  
130 130

  
131
class DaySlot(object):
131
class DaySlot:
132 132
    def __init__(self, date_time, available, exist=True):
133 133
        self.date_time = localtime(make_aware(date_time))
134 134
        self.available = available
......
142 142
        return '%s' % self.date_time.isoformat()
143 143

  
144 144

  
145
class WeekDay(object):
145
class WeekDay:
146 146
    def __init__(self, date):
147 147
        self.date = date
148 148
        self.slots = []
......
168 168
        return max(self.slots, key=lambda x: x.date_time.time())
169 169

  
170 170

  
171
class Calendar(object):
171
class Calendar:
172 172
    def __init__(self, offset, days_displayed, min_duration):
173 173
        self.offset = offset
174 174
        self.days_displayed = days_displayed
......
227 227
        return day.get_slot(slot.time())
228 228

  
229 229
    def get_minimum_slot(self):
230
        return min([day.get_minimum_slot().date_time.time() for day in self.days])
230
        return min(day.get_minimum_slot().date_time.time() for day in self.days)
231 231

  
232 232
    def get_maximum_slot(self):
233
        return max([day.get_maximum_slot().date_time.time() for day in self.days])
233
        return max(day.get_maximum_slot().date_time.time() for day in self.days)
combo/apps/calendar/views.py
49 49
    template_name = 'calendar/booking_calendar_content.html'
50 50

  
51 51
    def get_context_data(self, **kwargs):
52
        context = super(CalendarContentAjaxView, self).get_context_data(**kwargs)
52
        context = super().get_context_data(**kwargs)
53 53
        context['cell'] = self.object
54 54
        events_data = get_chrono_events(self.object.agenda_reference, context.get('synchronous'))
55 55
        context.update(get_calendar_context_vars(self.request, self.object, events_data))
combo/apps/dashboard/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.conf import settings
5 2
from django.db import migrations, models
6 3

  
combo/apps/dashboard/migrations/0002_auto_20180105_0846.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/dashboard/models.py
54 54
            for x in ValidityInfo.objects.filter(invalid_since__lt=now() - datetime.timedelta(days=2))
55 55
        }
56 56
        context['tiles'] = [x for x in tiles if (x.cell_type_id, x.cell_pk) not in validity_info_dict]
57
        return super(DashboardCell, self).render(context)
57
        return super().render(context)
58 58

  
59 59

  
60 60
class Tile(models.Model):
combo/apps/dashboard/views.py
158 158
def dashboard_reorder_tiles(request, *args, **kwargs):
159 159
    dashboard = DashboardCell.objects.filter(page__snapshot__isnull=True)[0]
160 160
    new_order = request.GET['order'].split(',')
161
    tiles = dict((str(x.id), x) for x in Tile.objects.filter(id__in=new_order))
161
    tiles = {str(x.id): x for x in Tile.objects.filter(id__in=new_order)}
162 162
    for i, tile_id in enumerate(new_order):
163 163
        tile = tiles.get(tile_id)
164 164
        if tile.user != request.user:
combo/apps/dataviz/forms.py
34 34
        fields = ('title', 'url')
35 35

  
36 36
    def __init__(self, *args, **kwargs):
37
        super(ChartForm, self).__init__(*args, **kwargs)
37
        super().__init__(*args, **kwargs)
38 38
        available_charts = []
39 39
        for site_key, site_dict in settings.KNOWN_SERVICES.get('bijoe').items():
40 40
            result = requests.get(
combo/apps/dataviz/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/dataviz/migrations/0002_gauge_jsonp_data_source.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/dataviz/migrations/0003_cubesbarchart_cubestable.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/dataviz/migrations/0004_auto_20160108_1048.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/dataviz/migrations/0005_auto_20160928_1152.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/dataviz/migrations/0006_chartcell.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/dataviz/migrations/0007_auto_20170214_2006.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import datetime
5 2

  
6 3
from django.db import migrations, models
combo/apps/dataviz/migrations/0008_auto_20190328_0857.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2019-03-28 07:57
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations
6 4

  
combo/apps/dataviz/migrations/0009_auto_20190617_1214.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2019-06-17 10:14
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/dataviz/migrations/0010_auto_20190328_1111.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2019-03-28 10:11
3
from __future__ import unicode_literals
4 2

  
5 3
import django.db.models.deletion
6 4
from django.contrib.postgres.fields import JSONField
combo/apps/dataviz/migrations/0011_auto_20200813_1100.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2020-08-13 09:00
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/dataviz/migrations/0012_auto_20201126_1557.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.29 on 2020-11-26 14:57
3
from __future__ import unicode_literals
4 2

  
5 3
import django.db.models.deletion
6 4
from django.db import migrations, models
......
35 33
        ),
36 34
        migrations.AlterUniqueTogether(
37 35
            name='statistic',
38
            unique_together=set([('slug', 'site_slug', 'service_slug')]),
36
            unique_together={('slug', 'site_slug', 'service_slug')},
39 37
        ),
40 38
        migrations.AddField(
41 39
            model_name='chartngcell',
combo/apps/dataviz/migrations/0013_update_chartng_cells.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.29 on 2020-11-30 14:26
3
from __future__ import unicode_literals
4 2

  
5 3
from django.conf import settings
6 4
from django.db import migrations
combo/apps/dataviz/migrations/0014_auto_20201130_1534.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.29 on 2020-11-30 14:34
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations
6 4

  
combo/apps/dataviz/migrations/0015_auto_20201202_1424.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.29 on 2020-12-02 13:24
3
from __future__ import unicode_literals
4 2

  
5 3
from django.contrib.postgres.fields import JSONField
6 4
from django.db import migrations
combo/apps/dataviz/migrations/0016_auto_20201215_1624.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.29 on 2020-12-15 15:24
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/dataviz/models.py
111 111
        return ''
112 112

  
113 113
    def get_cell_extra_context(self, context):
114
        context = super(ChartCell, self).get_cell_extra_context(context)
114
        context = super().get_cell_extra_context(context)
115 115
        context['title'] = self.title
116 116
        context['url'] = self.url
117 117
        return context
......
271 271
        )
272 272

  
273 273
    def get_cell_extra_context(self, context):
274
        ctx = super(ChartNgCell, self).get_cell_extra_context(context)
274
        ctx = super().get_cell_extra_context(context)
275 275
        if self.chart_type == 'table' and self.statistic and self.statistic.url:
276 276
            try:
277 277
                chart = self.get_chart(raise_if_not_cached=not (context.get('synchronous')))
......
508 508
            tmp_items = sorted(zip(chart.x_labels, data), key=lambda x: (x[1] or 0))
509 509
        elif self.sort_order == 'desc':
510 510
            tmp_items = sorted(zip(chart.x_labels, data), key=lambda x: (x[1] or 0), reverse=True)
511
        x_labels, sorted_data = zip(*[(label, value) for label, value in tmp_items])
511
        x_labels, sorted_data = zip(*((label, value) for label, value in tmp_items))
512 512
        chart.x_labels = list(x_labels)
513 513
        return list(sorted_data)
514 514

  
......
568 568

  
569 569
            return format_duration
570 570
        elif measure == 'percent':
571
            percent_formatter = lambda x: '{:.1f}%'.format(x)
571
            percent_formatter = lambda x: f'{x:.1f}%'
572 572
            return percent_formatter
573 573

  
574 574
    def make_percent(self, series_data):
575 575
        for i, values in enumerate(zip(*series_data)):
576
            sum_values = sum([v for v in values if v is not None])
576
            sum_values = sum(v for v in values if v is not None)
577 577
            if sum_values == 0:
578 578
                continue
579 579

  
......
595 595
            # "W" and "o" are interpreted by Django's date filter and should be left as is. First W is
596 596
            # backslash escaped to prevent it from being interpreted, translators should refer to Django's
597 597
            # documentation in order to know if the new letter resulting of translation should be escaped or not.
598
            '_week': gettext('\WW-o'),
598
            '_week': gettext(r'\WW-o'),
599 599
            '_month': 'm-Y',
600 600
            '_year': 'Y',
601 601
            '_weekday': 'l',
combo/apps/family/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import ckeditor.fields
5 2
from django.db import migrations, models
6 3

  
combo/apps/family/migrations/0002_familyinfoscell_restricted_to_unlogged.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/family/migrations/0003_familyinfoscell_extra_css_class.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/family/migrations/0004_familyinfoscell_last_update_timestamp.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import datetime
5 2

  
6 3
from django.db import migrations, models
combo/apps/family/views.py
52 52
            messages.error(self.request, error_message)
53 53
        else:
54 54
            messages.info(self.request, _('Your account was successfully linked.'))
55
        return super(FamilyLinkView, self).form_valid(form)
55
        return super().form_valid(form)
56 56

  
57 57

  
58 58
class FamilyUnlinkView(TemplateView):
combo/apps/fargo/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/fargo/migrations/0002_recentdocumentscell_extra_css_class.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/fargo/migrations/0003_recentdocumentscell_last_update_timestamp.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import datetime
5 2

  
6 3
from django.db import migrations, models
combo/apps/fargo/migrations/0004_recentdocumentscell_fargo_site.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/fargo/models.py
62 62
        user = kwargs.get('user')
63 63
        if not user or user.is_anonymous:
64 64
            return False
65
        return super(RecentDocumentsCell, self).is_visible(**kwargs)
65
        return super().is_visible(**kwargs)
66 66

  
67 67
    @classmethod
68 68
    def is_enabled(cls):
......
105 105

  
106 106
    def render(self, context):
107 107
        context.update(self.get_json('api/documents/recently-added/', context))
108
        return super(RecentDocumentsCell, self).render(context)
108
        return super().render(context)
109 109

  
110 110

  
111 111
def get_fargo_services():
combo/apps/gallery/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/gallery/migrations/0002_image_title.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/gallery/migrations/0003_gallerycell_title.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/gallery/views.py
40 40
        form.instance.gallery_id = self.kwargs.get('gallery_pk')
41 41
        other_images = form.instance.gallery.image_set.all()
42 42
        if other_images:
43
            form.instance.order = max([x.order for x in other_images]) + 1
43
            form.instance.order = max(x.order for x in other_images) + 1
44 44
        else:
45 45
            form.instance.order = 0
46
        return super(ImageAddView, self).form_valid(form)
46
        return super().form_valid(form)
47 47

  
48 48
    def get_success_url(self):
49 49
        return (
combo/apps/kb/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2020-01-31 15:40
3
from __future__ import unicode_literals
4 2

  
5 3
import django.db.models.deletion
6 4
from django.db import migrations, models
combo/apps/kb/migrations/0002_auto_20200203_1137.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.17 on 2020-02-03 10:37
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/kb/models.py
44 44
        verbose_name = _('Latest Page Updates')
45 45

  
46 46
    def get_cell_extra_context(self, context):
47
        extra_context = super(LatestPageUpdatesCell, self).get_cell_extra_context(context)
47
        extra_context = super().get_cell_extra_context(context)
48 48
        if self.root_page:
49 49
            pages = self.root_page.get_descendants_and_me()
50 50
        else:
combo/apps/lingo/forms.py
98 98
        ]
99 99

  
100 100
    def __init__(self, *args, **kwargs):
101
        super(RegieForm, self).__init__(*args, **kwargs)
101
        super().__init__(*args, **kwargs)
102 102
        fields, initial = create_form_fields(
103 103
            self.instance.eopayment.get_parameters(scope='transaction'),
104 104
            self.instance.transaction_options,
......
107 107
        self.initial.update(initial)
108 108

  
109 109
    def save(self):
110
        instance = super(RegieForm, self).save()
110
        instance = super().save()
111 111
        instance.transaction_options = compute_json_field(
112 112
            self.instance.eopayment.get_parameters(scope='transaction'), self.cleaned_data
113 113
        )
......
121 121
        fields = ['label', 'slug', 'service']
122 122

  
123 123
    def __init__(self, *args, **kwargs):
124
        super(PaymentBackendForm, self).__init__(*args, **kwargs)
124
        super().__init__(*args, **kwargs)
125 125
        fields, initial = create_form_fields(
126 126
            self.instance.eopayment.get_parameters(scope='global'), self.instance.service_options
127 127
        )
......
131 131
            self.fields['service'].disabled = True
132 132

  
133 133
    def save(self):
134
        instance = super(PaymentBackendForm, self).save()
134
        instance = super().save()
135 135
        instance.service_options = compute_json_field(
136 136
            self.instance.eopayment.get_parameters(scope='global'), self.cleaned_data
137 137
        )
......
148 148
    )
149 149

  
150 150
    def __init__(self, *args, **kwargs):
151
        super(TransactionExportForm, self).__init__(*args, **kwargs)
151
        super().__init__(*args, **kwargs)
152 152
        today = datetime.date.today()
153 153
        self.initial['start_date'] = today - datetime.timedelta(days=30)
154 154
        self.initial['end_date'] = today
combo/apps/lingo/management/commands/notify_new_remote_invoices.py
1
# -*- coding: utf-8 -*-
2 1
#
3 2
# lingo - basket and payment system
4 3
# Copyright (C) 2018  Entr'ouvert
combo/apps/lingo/manager_views.py
95 95
    paginate_by = 10
96 96

  
97 97
    def get_context_data(self, **kwargs):
98
        context = super(TransactionListView, self).get_context_data(**kwargs)
98
        context = super().get_context_data(**kwargs)
99 99
        context['query'] = self.request.GET.get('q') or ''
100 100
        return context
101 101

  
......
126 126
    paginate_by = 10
127 127

  
128 128
    def get_context_data(self, **kwargs):
129
        context = super(BasketItemErrorListView, self).get_context_data(**kwargs)
129
        context = super().get_context_data(**kwargs)
130 130
        context['query'] = self.request.GET.get('q') or ''
131 131
        return context
132 132

  
combo/apps/lingo/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.conf import settings
5 2
from django.contrib.postgres.fields import JSONField
6 3
from django.db import migrations, models
combo/apps/lingo/migrations/0002_transaction.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.contrib.postgres.fields import JSONField
5 2
from django.db import migrations, models
6 3

  
combo/apps/lingo/migrations/0003_auto_20150306_1047.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0004_basketitem_notification_date.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0005_auto_20150307_1242.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.conf import settings
5 2
from django.db import migrations, models
6 3

  
combo/apps/lingo/migrations/0006_transaction_status.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0007_lingobasketlinkcell.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0008_auto_20150908_1538.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import ckeditor.fields
5 2
from django.db import migrations, models
6 3

  
combo/apps/lingo/migrations/0009_auto_20150917_1456.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.conf import settings
5 2
from django.db import migrations, models
6 3

  
combo/apps/lingo/migrations/0010_regie_payment_min_amount.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0011_auto_20151029_1535.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0012_auto_20151130_1047.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0013_transaction_amount.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0014_auto_20160218_1455.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0015_auto_20160309_2150.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0016_auto_20160319_2028.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0017_auto_20160327_0831.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import ckeditor.fields
5 2
from django.db import migrations, models
6 3

  
combo/apps/lingo/migrations/0018_auto_20160527_0638.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0019_auto_20160531_1336.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0020_auto_20160606_1803.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0021_transactionoperation.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.contrib.postgres.fields import JSONField
5 2
from django.db import migrations, models
6 3

  
combo/apps/lingo/migrations/0022_regie_is_default.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0023_auto_20160928_1152.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0024_selfdeclaredinvoicepayment.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import ckeditor.fields
5 2
from django.db import migrations, models
6 3

  
combo/apps/lingo/migrations/0025_auto_20161206_1713.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.conf import settings
5 2
from django.db import migrations, models
6 3

  
combo/apps/lingo/migrations/0026_auto_20161215_1447.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0027_auto_20170214_2006.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import datetime
5 2

  
6 3
from django.db import migrations, models
combo/apps/lingo/migrations/0028_tipipaymentformcell.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3
import combo.data.fields
combo/apps/lingo/migrations/0029_auto_20170528_1334.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.contrib.postgres.fields import JSONField
5 2
from django.db import migrations, models
6 3

  
combo/apps/lingo/migrations/0030_transaction_to_be_paid_remote_items.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0031_basketitem_waiting_date.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.8 on 2018-01-31 14:24
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/lingo/migrations/0032_basketitem_capture_date.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.15 on 2018-10-05 15:33
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/lingo/migrations/0033_auto_20181204_2241.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/lingo/migrations/0034_auto_20190426_1159.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2019-04-26 09:59
3
from __future__ import unicode_literals
4 2

  
5 3
import django.db.models.deletion
6 4
from django.contrib.postgres.fields import JSONField
combo/apps/lingo/migrations/0035_auto_20190426_1124.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2019-04-26 09:24
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations
6 4

  
combo/apps/lingo/migrations/0036_auto_20190426_1202.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2019-04-26 10:02
3
from __future__ import unicode_literals
4 2

  
5 3
import django.db.models.deletion
6 4
from django.db import migrations, models
combo/apps/lingo/migrations/0037_regie_transaction_options.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2019-05-14 12:02
3
from __future__ import unicode_literals
4 2

  
5 3
from django.contrib.postgres.fields import JSONField
6 4
from django.db import migrations, models
combo/apps/lingo/migrations/0038_hide_cell_if_empty.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2020-03-31 13:12
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/lingo/migrations/0039_transaction_transaction_date.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.29 on 2020-04-03 20:19
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/lingo/migrations/0040_auto_20200608_1222.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2020-06-08 10:22
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/lingo/migrations/0041_regie_can_pay_only_one_basket_item.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2020-10-01 11:53
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/lingo/models.py
1
# -*- coding: utf-8 -*-
2 1
#
3 2
# lingo - basket and payment system
4 3
# Copyright (C) 2015  Entr'ouvert
......
68 67

  
69 68
class UnsignedPaymentException(PaymentException):
70 69
    def __init__(self, transaction, *args, **kwargs):
71
        super(UnsignedPaymentException, self).__init__(*args, **kwargs)
70
        super().__init__(*args, **kwargs)
72 71
        self.transaction = transaction
73 72

  
74 73

  
......
163 162

  
164 163
    def make_eopayment(self, *, request=None, automatic_return_url=None, normal_return_url=None, **kwargs):
165 164
        options = self.service_options or {}
166
        if isinstance(options, six.string_types):
165
        if isinstance(options, str):
167 166
            # backward compatibility when used againt postgresql < 9.4 and
168 167
            # service_options is received as a string.
169 168
            try:
......
329 328
            qs.update(is_default=False)
330 329
        elif not self.__class__.objects.filter(is_default=True).exists():
331 330
            self.is_default = True
332
        super(Regie, self).save(*args, **kwargs)
331
        super().save(*args, **kwargs)
333 332

  
334 333
    def natural_key(self):
335 334
        return (self.slug,)
......
688 687
        return reverse('basket-item-pay-view', kwargs={'item_signature': signature})
689 688

  
690 689

  
691
class RemoteItem(object):
690
class RemoteItem:
692 691
    payment_date = None
693 692

  
694 693
    def __init__(
......
745 744

  
746 745
    @classmethod
747 746
    def transactions_for_remote_items(cls, queryset, remote_items):
748
        remote_item_ids = set(remote_item.id for remote_item in remote_items if not remote_item.paid)
747
        remote_item_ids = {remote_item.id for remote_item in remote_items if not remote_item.paid}
749 748
        if not remote_item_ids:
750 749
            return Transaction.objects.none()
751 750

  
......
878 877
                    'unable to notify payment for remote item %s from transaction %s', item_id, self
879 878
                )
880 879
            else:
881
                logger.info(u'notified payment for remote item %s from transaction %s', item_id, self)
880
                logger.info('notified payment for remote item %s from transaction %s', item_id, self)
882 881
                subject = _('Invoice #%s') % remote_item.display_id
883 882
                local_item = BasketItem.objects.create(
884 883
                    user=self.user,
......
1066 1065
        items = BasketItem.get_items_to_be_paid(context['request'].user)
1067 1066
        if not items:
1068 1067
            return
1069
        total = sum([x.amount for x in items])
1068
        total = sum(x.amount for x in items)
1070 1069
        if total == int(total):
1071 1070
            total = int(total)
1072
        return {'badge': _(u'%s€') % localize(total)}
1071
        return {'badge': _('%s€') % localize(total)}
1073 1072

  
1074 1073
    def render(self, context):
1075 1074
        basket_template = template.loader.get_template('lingo/combo/basket.html')
......
1081 1080
            regies[item.regie_id]['items'].append(item)
1082 1081

  
1083 1082
        for items in regies.values():
1084
            items['total'] = sum([x.amount for x in items['items']])
1083
            items['total'] = sum(x.amount for x in items['items'])
1085 1084

  
1086 1085
        context['regies'] = sorted(regies.values(), key=lambda x: x['regie'].label)
1087 1086
        return basket_template.render(context)
......
1147 1146
            return ''
1148 1147
        basket_template = template.loader.get_template('lingo/combo/basket_link.html')
1149 1148
        context['items'] = BasketItem.get_items_to_be_paid(user=context['request'].user)
1150
        context['total'] = sum([x.amount for x in context['items']])
1149
        context['total'] = sum(x.amount for x in context['items'])
1151 1150
        return basket_template.render(context)
1152 1151

  
1153 1152

  
......
1198 1197
        return [], []
1199 1198

  
1200 1199
    def get_cell_extra_context(self, context):
1201
        ctx = super(Items, self).get_cell_extra_context(context)
1200
        ctx = super().get_cell_extra_context(context)
1202 1201
        if context.get('placeholder_search_mode'):
1203 1202
            # don't call webservices when we're just looking for placeholders
1204 1203
            return ctx
......
1220 1219
        self.context = context
1221 1220
        if not context.get('synchronous'):
1222 1221
            raise NothingInCacheException()
1223
        return super(Items, self).render(context)
1222
        return super().render(context)
1224 1223

  
1225 1224

  
1226 1225
@register_cell_class
......
1273 1272
    def render(self, context):
1274 1273
        context['synchronous'] = True
1275 1274
        context['page_path'] = context['request'].path
1276
        return super(SelfDeclaredInvoicePayment, self).render(context)
1275
        return super().render(context)
1277 1276

  
1278 1277

  
1279 1278
TIPI_CONTROL_PROCOTOLS = (
......
1326 1325
        return getattr(settings, 'LINGO_TIPI_CELL_PAYMENT_URL', 'https://www.payfip.gouv.fr/tpa/paiement.web')
1327 1326

  
1328 1327
    def get_cell_extra_context(self, context):
1329
        extra_context = super(TipiPaymentFormCell, self).get_cell_extra_context(context)
1328
        extra_context = super().get_cell_extra_context(context)
1330 1329
        form_fields = self.get_default_form_class().base_fields
1331 1330
        field_definitions = (
1332 1331
            {'protocol': 'any', 'fields': ['exer']},
combo/apps/lingo/utils.py
1
# -*- coding: utf-8 -*-
2 1
# lingo - basket and payment system
3 2
# Copyright (C) 2020  Entr'ouvert
4 3
#
combo/apps/lingo/views.py
98 98
class LocaleDecimal(Decimal):
99 99
    # accept , instead of . for French users comfort
100 100
    def __new__(cls, value="0", *args, **kwargs):
101
        if isinstance(value, six.string_types) and settings.LANGUAGE_CODE.startswith('fr-'):
101
        if isinstance(value, str) and settings.LANGUAGE_CODE.startswith('fr-'):
102 102
            value = value.replace(',', '.')
103
        return super(LocaleDecimal, cls).__new__(cls, value, *args, **kwargs)
103
        return super().__new__(cls, value, *args, **kwargs)
104 104

  
105 105

  
106 106
class RegiesApiView(ListView):
......
121 121

  
122 122
    @csrf_exempt
123 123
    def dispatch(self, *args, **kwargs):
124
        return super(AddBasketItemApiView, self).dispatch(*args, **kwargs)
124
        return super().dispatch(*args, **kwargs)
125 125

  
126 126
    def get_amount(self, amount):
127 127
        if isinstance(amount, list):
128
            d = Decimal(sum([LocaleDecimal(a) for a in amount]))
128
            d = Decimal(sum(LocaleDecimal(a) for a in amount))
129 129
        else:
130 130
            d = LocaleDecimal(amount)
131 131
        return d.quantize(Decimal('0.01'), ROUND_HALF_UP)
......
237 237

  
238 238
    @csrf_exempt
239 239
    def dispatch(self, *args, **kwargs):
240
        return super(RemoveBasketItemApiView, self).dispatch(*args, **kwargs)
240
        return super().dispatch(*args, **kwargs)
241 241

  
242 242
    def post(self, request, *args, **kwargs):
243 243
        if not lingo_check_request_signature(request):
......
285 285

  
286 286
    @csrf_exempt
287 287
    def dispatch(self, *args, **kwargs):
288
        return super(ValidateTransactionApiView, self).dispatch(*args, **kwargs)
288
        return super().dispatch(*args, **kwargs)
289 289

  
290 290
    def post(self, request, *args, **kwargs):
291 291
        if not lingo_check_request_signature(request):
......
295 295
            transaction = Transaction.objects.get(id=request.GET['transaction_id'])
296 296
        except Transaction.DoesNotExist:
297 297
            logger.warning(
298
                u'received validate request for unknown transaction %s', request.GET['transaction_id']
298
                'received validate request for unknown transaction %s', request.GET['transaction_id']
299 299
            )
300 300
            raise Http404
301 301

  
302 302
        amount = LocaleDecimal(request.GET['amount'])
303 303

  
304
        logger.info(u'validating amount %s for transaction %s', amount, smart_text(transaction.id))
304
        logger.info('validating amount %s for transaction %s', amount, smart_text(transaction.id))
305 305
        try:
306 306
            result = transaction.make_eopayment(request=request).backend.validate(
307 307
                amount, transaction.bank_data
308 308
            )
309 309
        except eopayment.ResponseError as e:
310
            logger.error(u'failed in validation operation: %s', e)
310
            logger.error('failed in validation operation: %s', e)
311 311
            return JsonResponse({'err': 1, 'e': force_text(e)})
312 312

  
313
        logger.info(u'bank validation result: %r', result)
313
        logger.info('bank validation result: %r', result)
314 314
        operation = TransactionOperation(
315 315
            transaction=transaction, kind='validation', amount=amount, bank_result=result
316 316
        )
......
324 324

  
325 325
    @csrf_exempt
326 326
    def dispatch(self, *args, **kwargs):
327
        return super(CancelTransactionApiView, self).dispatch(*args, **kwargs)
327
        return super().dispatch(*args, **kwargs)
328 328

  
329 329
    def post(self, request, *args, **kwargs):
330 330
        if not lingo_check_request_signature(request):
......
334 334
            transaction = Transaction.objects.get(id=request.GET['transaction_id'])
335 335
        except Transaction.DoesNotExist:
336 336
            logger.warning(
337
                u'received validate request for unknown transaction %s', request.GET['transaction_id']
337
                'received validate request for unknown transaction %s', request.GET['transaction_id']
338 338
            )
339 339
            raise Http404
340 340

  
341 341
        amount = LocaleDecimal(request.GET['amount'])
342 342

  
343
        logger.info(u'cancelling amount %s for transaction %s', amount, smart_text(transaction.id))
343
        logger.info('cancelling amount %s for transaction %s', amount, smart_text(transaction.id))
344 344
        try:
345 345
            result = transaction.make_eopayment(request=request).backend.cancel(amount, transaction.bank_data)
346 346
        except eopayment.ResponseError as e:
347
            logger.error(u'failed in cancel operation: %s', e)
347
            logger.error('failed in cancel operation: %s', e)
348 348
            return JsonResponse({'err': 1, 'e': force_text(e)})
349 349

  
350
        logger.info(u'bank cancellation result: %r', result)
350
        logger.info('bank cancellation result: %r', result)
351 351
        operation = TransactionOperation(
352 352
            transaction=transaction, kind='cancellation', amount=amount, bank_result=result
353 353
        )
......
356 356
        return JsonResponse({'err': 0, 'extra': result})
357 357

  
358 358

  
359
class PayMixin(object):
359
class PayMixin:
360 360
    @atomic
361 361
    def handle_payment(
362 362
        self, request, regie, items, remote_items, next_url='/', email='', firstname='', lastname=''
......
381 381
            messages.error(request, _('Some items are already paid.'))
382 382
            return HttpResponseRedirect(next_url)
383 383

  
384
        total_amount = sum([x.amount for x in remote_items or items])
384
        total_amount = sum(x.amount for x in remote_items or items)
385 385

  
386 386
        if total_amount < regie.payment_min_amount:
387
            messages.warning(request, _(u'Minimal payment amount is %s €.') % regie.payment_min_amount)
387
            messages.warning(request, _('Minimal payment amount is %s €.') % regie.payment_min_amount)
388 388
            return HttpResponseRedirect(
389 389
                get_payment_status_view(next_url=next_url if remote_items else items[0].source_url)
390 390
            )
391 391

  
392 392
        for item in items:
393 393
            if item.regie != regie:
394
                messages.error(request, _(u'Invalid grouping for basket items.'))
394
                messages.error(request, _('Invalid grouping for basket items.'))
395 395
                return HttpResponseRedirect(next_url)
396 396
        user = request.user if request.user.is_authenticated else None
397 397
        transaction = Transaction()
......
454 454
            messages.error(request, _('Failed to initiate payment request'))
455 455
            return HttpResponseRedirect(get_payment_status_view(next_url=next_url))
456 456
        logger.info(
457
            u'emitted payment request with id %s',
457
            'emitted payment request with id %s',
458 458
            smart_text(order_id),
459 459
            extra={'eopayment_order_id': smart_text(order_id), 'eopayment_data': repr(data)},
460 460
        )
......
505 505
                for item_id in request.POST.getlist('item'):
506 506
                    remote_items.append(regie.get_invoice(user, item_id, update_paid=True))
507 507
            except (requests.exceptions.RequestException, RemoteInvoiceException):
508
                messages.error(request, _(u'Technical error: impossible to retrieve invoices.'))
508
                messages.error(request, _('Technical error: impossible to retrieve invoices.'))
509 509
                return HttpResponseRedirect(next_url)
510 510
            except ObjectDoesNotExist:
511
                messages.error(request, _(u'No invoice was found.'))
511
                messages.error(request, _('No invoice was found.'))
512 512
                return HttpResponseRedirect(next_url)
513 513
        else:
514 514
            if user is None:
515
                messages.error(request, _(u'Payment requires to be logged in.'))
515
                messages.error(request, _('Payment requires to be logged in.'))
516 516
                return HttpResponseRedirect(next_url)
517 517

  
518 518
            if not regie_id:
......
521 521
                regie_id = items[0].regie_id
522 522
                for item in items:
523 523
                    if item.regie_id != regie_id:
524
                        messages.error(request, _(u'Invalid grouping for basket items.'))
524
                        messages.error(request, _('Invalid grouping for basket items.'))
525 525
                        return HttpResponseRedirect(next_url)
526 526

  
527 527
            regie = Regie.objects.get(id=regie_id)
......
540 540
            capture_date = items[0].capture_date
541 541
            for item in items:
542 542
                if item.capture_date != capture_date:
543
                    messages.error(request, _(u'Invalid grouping for basket items: different capture dates.'))
543
                    messages.error(request, _('Invalid grouping for basket items: different capture dates.'))
544 544
                    return HttpResponseRedirect(next_url)
545 545

  
546 546
        if user:
......
549 549
            # user is not authenticated, it comes from ItemCell where an email
550 550
            # can be given in the payment form.
551 551
            if not request.POST.get('email'):
552
                messages.warning(request, _(u'You must give an email address.'))
552
                messages.warning(request, _('You must give an email address.'))
553 553
                return HttpResponseRedirect(request.POST.get('item_url'))
554 554
            email = request.POST.get('email')
555 555

  
......
634 634
            raise Http404("A payment backend or regie primary key or slug must be specified")
635 635

  
636 636
        payment = payment_backend.make_eopayment(request=request)
637
        logger.info(u'received payment response: %r', backend_response)
637
        logger.info('received payment response: %r', backend_response)
638 638
        try:
639 639
            eopayment_response_kwargs = {'redirect': not callback}
640 640
            if transaction is not None:
......
647 647
            payment_response = payment.response(backend_response, **eopayment_response_kwargs)
648 648
        except eopayment.PaymentException as e:
649 649
            logger.error(
650
                u'failed to process payment response: %s',
650
                'failed to process payment response: %s',
651 651
                e,
652 652
                extra={'eopayment_raw_response': repr(backend_response)},
653 653
            )
......
674 674

  
675 675
    @csrf_exempt
676 676
    def dispatch(self, *args, **kwargs):
677
        return super(CallbackView, self).dispatch(*args, **kwargs)
677
        return super().dispatch(*args, **kwargs)
678 678

  
679 679

  
680 680
class ReturnView(PaymentView):
681 681
    @csrf_exempt
682 682
    def dispatch(self, *args, **kwargs):
683
        return super(ReturnView, self).dispatch(*args, **kwargs)
683
        return super().dispatch(*args, **kwargs)
684 684

  
685 685
    def get(self, request, *args, **kwargs):
686 686
        return self.handle_return(request, request.environ['QUERY_STRING'], **kwargs)
......
735 735

  
736 736

  
737 737
class ItemDownloadView(View):
738
    http_method_names = [u'get']
738
    http_method_names = ['get']
739 739

  
740 740
    def get(self, request, *args, **kwargs):
741 741
        try:
......
768 768

  
769 769

  
770 770
class ItemView(TemplateView):
771
    http_method_names = [u'get']
771
    http_method_names = ['get']
772 772

  
773 773
    def get_context_data(self, **kwargs):
774 774
        ret = {'item_url': self.request.get_full_path()}
......
804 804
    template_name = 'lingo/combo/cancel-item.html'
805 805

  
806 806
    def get_context_data(self, **kwargs):
807
        context = super(CancelItemView, self).get_context_data(**kwargs)
807
        context = super().get_context_data(**kwargs)
808 808
        context['basket_url'] = get_basket_url()
809 809
        return context
810 810

  
......
831 831

  
832 832
    @csrf_exempt
833 833
    def dispatch(self, *args, **kwargs):
834
        return super(SelfInvoiceView, self).dispatch(*args, **kwargs)
834
        return super().dispatch(*args, **kwargs)
835 835

  
836 836
    def get(self, request, *args, **kwargs):
837 837
        try:
......
902 902
        next_url = request.session.get('lingo_next_url', {}).get(str(transaction_id))
903 903
        if not next_url:
904 904
            next_url = get_basket_url()
905
            if len(set([item.source_url for item in transaction.items.all()])) == 1:
905
            if len({item.source_url for item in transaction.items.all()}) == 1:
906 906
                next_url = transaction.items.first().source_url
907 907
        next_url = request.build_absolute_uri(next_url)
908 908

  
combo/apps/maps/forms.py
40 40
        }
41 41

  
42 42
    def __init__(self, *args, **kwargs):
43
        super(MapLayerForm, self).__init__(*args, **kwargs)
43
        super().__init__(*args, **kwargs)
44 44
        if self.instance.pk is None:
45 45
            # new instance, delete some fields
46 46
            del self.fields['slug']
......
71 71
                del self.fields[field]
72 72

  
73 73
    def clean(self):
74
        cleaned_data = super(MapLayerForm, self).clean()
74
        cleaned_data = super().clean()
75 75

  
76 76
        if self.instance.kind == 'tiles' and cleaned_data.get('tiles_default') is True:
77 77
            if MapLayer.objects.filter(kind='tiles', tiles_default=True).exclude(pk=self.instance.pk):
......
88 88

  
89 89
    def __init__(self, *args, **kwargs):
90 90
        self.kind = kwargs.pop('kind')
91
        super(MapLayerOptionsForm, self).__init__(*args, **kwargs)
91
        super().__init__(*args, **kwargs)
92 92
        # if edition, no possibility to change the layer
93 93
        if self.instance.pk:
94 94
            del self.fields['map_layer']
combo/apps/maps/manager_views.py
26 26
from .models import Map, MapLayer, MapLayerOptions
27 27

  
28 28

  
29
class MapLayerMixin(object):
29
class MapLayerMixin:
30 30
    model = MapLayer
31 31
    success_url = reverse_lazy('maps-manager-homepage')
32 32

  
......
36 36
    ordering = ['kind', 'label']
37 37

  
38 38
    def get_context_data(self, **kwargs):
39
        context = super(ManagerHomeView, self).get_context_data(**kwargs)
39
        context = super().get_context_data(**kwargs)
40 40
        context['map_list'] = Map.objects.all()
41 41
        return context
42 42

  
......
46 46
    template_name = 'maps/map_layer_form.html'
47 47

  
48 48
    def get_form_kwargs(self):
49
        kwargs = super(LayerAddView, self).get_form_kwargs()
49
        kwargs = super().get_form_kwargs()
50 50
        kwargs['instance'] = self.model(kind=self.kwargs['kind'])
51 51
        return kwargs
52 52

  
......
69 69
            self.cell = CellBase.get_cell(kwargs['cell_reference'], page=kwargs['page_pk'])
70 70
        except Map.DoesNotExist:
71 71
            raise Http404
72
        return super(MapCellAddLayer, self).dispatch(request, *args, **kwargs)
72
        return super().dispatch(request, *args, **kwargs)
73 73

  
74 74
    def get_form_kwargs(self):
75
        kwargs = super(MapCellAddLayer, self).get_form_kwargs()
75
        kwargs = super().get_form_kwargs()
76 76
        kwargs['instance'] = MapLayerOptions(map_cell=self.cell)
77 77
        kwargs['kind'] = self.kwargs['kind']
78 78
        return kwargs
......
84 84
            comment=_('added layer "%(layer)s" to cell "%(cell)s"')
85 85
            % {'layer': form.instance.map_layer, 'cell': self.cell},
86 86
        )
87
        return super(MapCellAddLayer, self).form_valid(form)
87
        return super().form_valid(form)
88 88

  
89 89
    def get_success_url(self):
90 90
        return '%s#cell-%s' % (
......
106 106
        except Map.DoesNotExist:
107 107
            raise Http404
108 108
        self.object = get_object_or_404(MapLayerOptions, pk=kwargs['layeroptions_pk'], map_cell=self.cell)
109
        return super(MapCellEditLayer, self).dispatch(request, *args, **kwargs)
109
        return super().dispatch(request, *args, **kwargs)
110 110

  
111 111
    def get_object(self, *args, **kwargs):
112 112
        return self.object
113 113

  
114 114
    def get_form_kwargs(self):
115
        kwargs = super(MapCellEditLayer, self).get_form_kwargs()
115
        kwargs = super().get_form_kwargs()
116 116
        kwargs['kind'] = self.object.map_layer.kind
117 117
        return kwargs
118 118

  
......
123 123
            comment=_('changed options of layer "%(layer)s" in cell "%(cell)s"')
124 124
            % {'layer': form.instance.map_layer, 'cell': self.cell},
125 125
        )
126
        return super(MapCellEditLayer, self).form_valid(form)
126
        return super().form_valid(form)
127 127

  
128 128
    def get_success_url(self):
129 129
        return '%s#cell-%s' % (
......
144 144
        except Map.DoesNotExist:
145 145
            raise Http404
146 146
        self.object = get_object_or_404(MapLayerOptions, pk=kwargs['layeroptions_pk'], map_cell=self.cell)
147
        return super(MapCellDeleteLayer, self).dispatch(request, *args, **kwargs)
147
        return super().dispatch(request, *args, **kwargs)
148 148

  
149 149
    def get_object(self, *args, **kwargs):
150 150
        return self.object
151 151

  
152 152
    def delete(self, request, *args, **kwargs):
153
        response = super(MapCellDeleteLayer, self).delete(request, *args, **kwargs)
153
        response = super().delete(request, *args, **kwargs)
154 154
        PageSnapshot.take(
155 155
            self.cell.page,
156 156
            request=self.request,
combo/apps/maps/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3
from combo.apps.maps.models import ICONS
combo/apps/maps/migrations/0002_map.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/maps/migrations/0003_auto_20170603_1653.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/maps/migrations/0004_map_initial_state.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/maps/migrations/0005_auto_20180212_1742.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/maps/migrations/0006_auto_20180627_0841.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/maps/migrations/0007_auto_20180706_1345.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2018-07-06 11:45
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/maps/migrations/0008_map_layer_options.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import django.db.models.deletion
5 2
from django.db import migrations, models
6 3

  
......
54 51
                ),
55 52
                migrations.AlterUniqueTogether(
56 53
                    name='maplayeroptions',
57
                    unique_together=set([('map_cell', 'map_layer')]),
54
                    unique_together={('map_cell', 'map_layer')},
58 55
                ),
59 56
            ],
60 57
            database_operations=[],
combo/apps/maps/migrations/0009_map_layer_kind.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2020-02-07 09:00
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/maps/migrations/0010_map_layer_opacity.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import django.core.validators
5 2
from django.db import migrations, models
6 3

  
combo/apps/maps/migrations/0011_map_layer_set_slug.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations
5 2
from django.utils.text import slugify
6 3

  
combo/apps/maps/migrations/0012_map_layer_slug_unicity.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/maps/migrations/0013_geojson_query_parameter.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/maps/migrations/0014_geojson_circle_param.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/maps/models.py
158 158
                slug = '%s-%s' % (base_slug, i)
159 159
                i += 1
160 160
            self.slug = slug
161
        super(MapLayer, self).save(*args, **kwargs)
161
        super().save(*args, **kwargs)
162 162

  
163 163
    def __str__(self):
164 164
        return self.label
......
287 287

  
288 288
                def get_feature_words(properties):
289 289
                    for property in properties.values():
290
                        if isinstance(property, six.string_types):
290
                        if isinstance(property, str):
291 291
                            feature_words.append(property)
292 292
                        elif isinstance(property, dict):
293 293
                            get_feature_words(property)
......
465 465
        ]
466 466

  
467 467
    def get_cell_extra_context(self, context):
468
        ctx = super(Map, self).get_cell_extra_context(context)
468
        ctx = super().get_cell_extra_context(context)
469 469
        ctx['title'] = self.title
470 470
        default_position = self.get_default_position()
471 471
        ctx['init_lat'] = default_position['lat']
combo/apps/notifications/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.conf import settings
5 2
from django.db import migrations, models
6 3

  
combo/apps/notifications/migrations/0002_notificationscell_last_update_timestamp.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import datetime
5 2

  
6 3
from django.db import migrations, models
combo/apps/notifications/migrations/0003_notification_origin.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/notifications/migrations/0004_auto_20180316_1026.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.11 on 2018-03-16 10:26
3
from __future__ import unicode_literals
4 2

  
5 3
from django.conf import settings
6 4
from django.db import migrations
......
16 14
    operations = [
17 15
        migrations.AlterUniqueTogether(
18 16
            name='notification',
19
            unique_together=set([('user', 'external_id')]),
17
            unique_together={('user', 'external_id')},
20 18
        ),
21 19
    ]
combo/apps/notifications/migrations/0005_auto_20180324_0025.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.11 on 2018-03-24 00:25
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/notifications/models.py
181 181
        user = kwargs.get('user')
182 182
        if user is None or not user.is_authenticated:
183 183
            return False
184
        return super(NotificationsCell, self).is_visible(**kwargs)
184
        return super().is_visible(**kwargs)
185 185

  
186 186
    def get_cell_extra_context(self, context):
187
        extra_context = super(NotificationsCell, self).get_cell_extra_context(context)
187
        extra_context = super().get_cell_extra_context(context)
188 188
        user = getattr(context.get('request'), 'user', None)
189 189
        if user and user.is_authenticated:
190 190
            qs = Notification.objects.visible(user)
combo/apps/pwa/forms.py
27 27
        exclude = ('push_notifications_infos',)
28 28

  
29 29
    def __init__(self, *args, **kwargs):
30
        super(PwaSettingsForm, self).__init__(*args, **kwargs)
30
        super().__init__(*args, **kwargs)
31 31
        self.fields['application_icon'].widget.attrs = {'accept': 'image/jpeg,image/png'}
32 32

  
33 33
    def clean_application_icon(self):
combo/apps/pwa/manager_views.py
34 34
    success_url = reverse_lazy('pwa-manager-homepage')
35 35

  
36 36
    def get_initial(self):
37
        initial = super(ManagerHomeView, self).get_initial()
37
        initial = super().get_initial()
38 38
        initial['application_name'] = self.get_object().get_application_name()
39 39
        return initial
40 40

  
41 41
    def form_valid(self, form):
42 42
        if form.instance.application_name == PwaSettings.get_default_application_name():
43 43
            form.instance.application_name = ''
44
        return super(ManagerHomeView, self).form_valid(form)
44
        return super().form_valid(form)
45 45

  
46 46
    def get_object(self):
47 47
        return PwaSettings.singleton()
48 48

  
49 49
    def get_context_data(self, **kwargs):
50
        context = super(ManagerHomeView, self).get_context_data(**kwargs)
50
        context = super().get_context_data(**kwargs)
51 51
        context['navigation_entries'] = PwaNavigationEntry.objects.all()
52 52
        return context
53 53

  
54 54

  
55
class ManagerNavigationEntryMixin(object):
55
class ManagerNavigationEntryMixin:
56 56
    model = PwaNavigationEntry
57 57
    fields = [
58 58
        'label',
......
83 83
        elif form.instance.url:
84 84
            form.add_error('url', _('An URL cannot be specified when a page is selected.'))
85 85
        if form.errors:
86
            return super(ManagerNavigationEntryMixin, self).form_invalid(form)
87
        return super(ManagerNavigationEntryMixin, self).form_valid(form)
86
            return super().form_invalid(form)
87
        return super().form_valid(form)
88 88

  
89 89

  
90 90
class ManagerAddNavigationEntry(ManagerNavigationEntryMixin, CreateView):
combo/apps/pwa/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2018-11-29 09:45
3
from __future__ import unicode_literals
4 2

  
5 3
import django.db.models.deletion
6 4
from django.conf import settings
combo/apps/pwa/migrations/0002_pwasettings.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2018-12-27 08:44
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/pwa/migrations/0003_pwanavigationentry.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2018-12-27 14:27
3
from __future__ import unicode_literals
4 2

  
5 3
import django.db.models.deletion
6 4
from django.db import migrations, models
combo/apps/pwa/migrations/0004_pwasettings_application_icon.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2019-01-04 19:36
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/pwa/migrations/0005_pwasettings_application_name.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.20 on 2019-04-16 14:08
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/pwa/migrations/0006_auto_20190628_1042.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2019-06-28 08:42
3
from __future__ import unicode_literals
4 2

  
5 3
from django.contrib.postgres.fields import JSONField
6 4
from django.db import migrations, models
combo/apps/pwa/models.py
1
# -*- coding: utf-8 -*
2 1
#
3 2
# combo - content management system
4 3
# Copyright (C) 2015-2018  Entr'ouvert
......
42 41
    application_icon = models.FileField(
43 42
        verbose_name=_('Application Icon'),
44 43
        help_text=_(
45
            u'Icon file must be in JPEG or PNG format, and should be a square of at least 512×512 pixels.'
44
            'Icon file must be in JPEG or PNG format, and should be a square of at least 512×512 pixels.'
46 45
        ),
47 46
        upload_to='pwa',
48 47
        blank=True,
......
70 69
            }
71 70
        elif not self.push_notifications:
72 71
            self.push_notifications_infos = {}
73
        return super(PwaSettings, self).save(**kwargs)
72
        return super().save(**kwargs)
74 73

  
75 74
    @classmethod
76 75
    def singleton(cls):
combo/apps/search/engines.py
17 17
from django.conf import settings
18 18

  
19 19

  
20
class Engines(object):
20
class Engines:
21 21
    """Singleton object that serves as a registry of search engines."""
22 22

  
23 23
    def __init__(self):
combo/apps/search/forms.py
86 86
        pages_queryset = Page.objects.filter(snapshot__isnull=True, sub_slug='').order_by('title')
87 87
        pages = Page.get_as_reordered_flat_hierarchy(pages_queryset)
88 88
        pages_choices = [('', '---------')] + [
89
            (x.id, {'label': '%s %s' % (u'\u00a0' * x.level * 2, x.title), 'disabled': x.slug in used_slugs})
89
            (x.id, {'label': '%s %s' % ('\u00a0' * x.level * 2, x.title), 'disabled': x.slug in used_slugs})
90 90
            for x in pages
91 91
        ]
92 92
        # if '_text' without page is already selected, page is required
combo/apps/search/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/search/migrations/0002_auto_20180720_1511.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.contrib.postgres.fields import JSONField
5 2
from django.db import migrations
6 3

  
combo/apps/search/migrations/0003_create_search_services.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations
5 2

  
6 3

  
combo/apps/search/migrations/0004_remove_searchcell__search_service.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/search/migrations/0005_searchcell_autofocus.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2019-11-20 13:06
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/search/migrations/0006_indexedcell.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.17 on 2020-01-20 15:30
3
from __future__ import unicode_literals
4 2

  
5 3
import django.db.models.deletion
6 4
from django.db import migrations, models
combo/apps/search/migrations/0007_french_fts.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.17 on 2020-02-19 08:20
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, transaction
6 4
from django.db.migrations.operations.base import Operation
combo/apps/search/migrations/0008_searchcell_input_placeholder.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2020-04-08 17:22
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/apps/search/models.py
62 62
    def is_visible(self, **kwargs):
63 63
        if not self._search_services.get('data'):
64 64
            return False
65
        return super(SearchCell, self).is_visible(**kwargs)
65
        return super().is_visible(**kwargs)
66 66

  
67 67
    def get_default_form_class(self):
68 68
        from .forms import SearchCellForm
......
156 156
            context[self.varname] = request.GET.get(self.varname)
157 157

  
158 158
    def get_cell_extra_context(self, context):
159
        extra_context = super(SearchCell, self).get_cell_extra_context(context)
159
        extra_context = super().get_cell_extra_context(context)
160 160
        # if there is a q_<slug> in query_string, send it to the template (to be
161 161
        # used as an initial query) and remove it from query_string
162 162
        initial_q = None
combo/apps/wcs/context_processors.py
32 32
    return None
33 33

  
34 34

  
35
class LazyCardDefObjectsManager(object):
35
class LazyCardDefObjectsManager:
36 36
    def __init__(self, service_key, card_id, custom_view_id=None, filters=None, user=Ellipsis):
37 37
        self._service_key = service_key
38 38
        self._card_id = card_id
......
147 147

  
148 148
    def __iter__(self):
149 149
        self._populate_cache()
150
        for data in self._cached_resultset:
151
            yield data
150
        yield from self._cached_resultset
152 151

  
153 152
    def __nonzero__(self):
154 153
        return any(self)
155 154

  
156 155

  
157
class LazyCardDef(object):
156
class LazyCardDef:
158 157
    def __init__(self, slug):
159 158
        if ':' in slug:
160 159
            self.service_key, self.card_id = slug.split(':')[:2]
......
167 166
        return LazyCardDefObjectsManager(self.service_key, self.card_id)
168 167

  
169 168

  
170
class Cards(object):
169
class Cards:
171 170
    def __getattr__(self, attr):
172 171
        try:
173 172
            return LazyCardDef(attr)
combo/apps/wcs/forms.py
42 42
        fields = ('formdef_reference',)
43 43

  
44 44
    def __init__(self, *args, **kwargs):
45
        super(WcsFormCellForm, self).__init__(*args, **kwargs)
45
        super().__init__(*args, **kwargs)
46 46
        formdef_references = get_wcs_options('/api/formdefs/')
47 47
        self.fields['formdef_reference'].widget = forms.Select(choices=formdef_references)
48 48

  
......
108 108
        fields = ('category_reference',)
109 109

  
110 110
    def __init__(self, *args, **kwargs):
111
        super(WcsCategoryCellForm, self).__init__(*args, **kwargs)
111
        super().__init__(*args, **kwargs)
112 112
        references = get_wcs_options('/api/categories/')
113 113
        self.fields['category_reference'].widget = forms.Select(choices=references)
114 114

  
......
119 119
        fields = ('category_reference', 'ordering', 'manual_order', 'limit')
120 120

  
121 121
    def __init__(self, *args, **kwargs):
122
        super(WcsFormsOfCategoryCellForm, self).__init__(*args, **kwargs)
122
        super().__init__(*args, **kwargs)
123 123
        references = get_wcs_options('/api/categories/')
124 124
        formdef_references = get_wcs_options('/api/formdefs/', include_category_slug=True)
125 125
        self.fields['ordering'].widget = forms.Select(
......
134 134
class CategoriesSelectMultiple(forms.SelectMultiple):
135 135
    def format_value(self, value):
136 136
        value = json.loads(value)
137
        return super(CategoriesSelectMultiple, self).format_value(value.get('data') or [])
137
        return super().format_value(value.get('data') or [])
138 138

  
139 139
    def value_from_datadict(self, data, files, name):
140 140
        if isinstance(data, MultiValueDict):
......
142 142
        return data.get(name, None)
143 143

  
144 144

  
145
class WcsFormsMixin(object):
145
class WcsFormsMixin:
146 146
    def _init_wcs_site(self):
147 147
        if len(get_wcs_services()) == 1:
148 148
            self.fields['wcs_site'].widget = forms.HiddenInput()
combo/apps/wcs/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3
import combo.apps.wcs.models
combo/apps/wcs/migrations/0002_auto_20150217_1402.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/wcs/migrations/0003_auto_20150218_1151.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/wcs/migrations/0004_auto_20150218_1154.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/wcs/migrations/0005_auto_20150401_0758.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/wcs/migrations/0006_categoriescell.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3
import combo.apps.wcs.models
combo/apps/wcs/migrations/0007_trackingcodeinputcell.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/wcs/migrations/0008_wcsformcell_cached_json.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.contrib.postgres.fields import JSONField
5 2
from django.db import migrations, models
6 3

  
combo/apps/wcs/migrations/0009_remove_wcscategorycell_link_page.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/wcs/migrations/0010_auto_20151029_1535.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/wcs/migrations/0011_auto_20151215_1121.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/wcs/migrations/0012_wcsformsofcategorycell_manual_order.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.contrib.postgres.fields import JSONField
5 2
from django.db import migrations, models
6 3

  
combo/apps/wcs/migrations/0013_auto_20160928_1152.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/wcs/migrations/0014_auto_20170214_2006.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import datetime
5 2

  
6 3
from django.db import migrations, models
combo/apps/wcs/migrations/0015_wcscurrentformscell_categories.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.8 on 2018-01-21 12:50
3
from __future__ import unicode_literals
4 2

  
5 3
from django.contrib.postgres.fields import JSONField
6 4
from django.db import migrations
combo/apps/wcs/migrations/0016_backofficesubmissioncell.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2018-08-10 08:05
3
from __future__ import unicode_literals
4 2

  
5 3
import django.db.models.deletion
6 4
from django.db import migrations, models
combo/apps/wcs/migrations/0017_wcscareformscell.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2019-10-18 13:48
3
from __future__ import unicode_literals
4 2

  
5 3
import django.db.models.deletion
6 4
from django.db import migrations, models
combo/apps/wcs/migrations/0018_wcscurrentdraftscell_categories.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.contrib.postgres.fields import JSONField
5 2
from django.db import migrations
6 3

  
combo/apps/wcs/migrations/0019_wcscurrentformscell_include_drafts.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/wcs/migrations/0020_cards.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import django.db.models.deletion
5 2
from django.db import migrations, models
6 3

  
combo/apps/wcs/migrations/0021_card.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import django.db.models.deletion
5 2
from django.contrib.postgres.fields import JSONField
6 3
from django.db import migrations, models
combo/apps/wcs/migrations/0022_cards_user.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/wcs/migrations/0023_card_info_id.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/wcs/migrations/0024_card_info_user.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/wcs/migrations/0025_submission_categories.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.contrib.postgres.fields import JSONField
5 2
from django.db import migrations
6 3

  
combo/apps/wcs/migrations/0028_wcscardscell_without_user.py
1
from __future__ import unicode_literals
2

  
3 1
from django.db import migrations, models
4 2

  
5 3

  
combo/apps/wcs/migrations/0029_cards_custom_title.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/apps/wcs/migrations/0032_forms_user_can_access.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import django.contrib.postgres.fields.jsonb
5 2
import django.db.models.deletion
6 3
from django.db import migrations, models
combo/apps/wcs/models.py
1
# -*- coding: utf-8 -*-
2 1
#
3 2
# combo - content management system
4 3
# Copyright (C) 2014-2015  Entr'ouvert
......
124 123
        populate_cache()
125 124

  
126 125
    def get_cell_extra_context(self, context):
127
        context = super(WcsFormCell, self).get_cell_extra_context(context)
126
        context = super().get_cell_extra_context(context)
128 127
        context['slug'] = self.formdef_reference.split(':')[-1]
129 128
        context['title'] = self.cached_title
130 129
        context['url'] = self.cached_url + 'tryauth'
......
262 261
        return WcsCategoryCellForm
263 262

  
264 263
    def get_cell_extra_context(self, context):
265
        context = super(WcsCategoryCell, self).get_cell_extra_context(context)
264
        context = super().get_cell_extra_context(context)
266 265
        if not self.category_reference:
267 266
            return context
268 267
        context['slug'] = self.category_reference.split(':')[-1]
......
272 271
        return context
273 272

  
274 273

  
275
class WcsBlurpMixin(object):
274
class WcsBlurpMixin:
276 275
    is_enabled = classmethod(is_wcs_enabled)
277 276
    cache_duration = 5
278 277
    api_url = None
......
299 298
            wcs_sites = get_wcs_services()
300 299

  
301 300
        result = {}
302
        returns = set([])
301
        returns = set()
303 302
        for wcs_slug, _wcs_site in wcs_sites.items():
304 303
            api_url = self.get_api_url_for_site(context, wcs_slug)
305 304
            if not api_url:
......
363 362
        abstract = True
364 363

  
365 364
    def get_additional_label(self):
366
        wcs_sites = dict([(x, y.get('title')) for x, y in get_wcs_services().items()])
365
        wcs_sites = {x: y.get('title') for x, y in get_wcs_services().items()}
367 366
        if len(wcs_sites.keys()) < 2:
368 367
            return ''
369 368
        if self.wcs_site in wcs_sites:
......
390 389
        )
391 390

  
392 391
    def get_cell_extra_context(self, context):
393
        extra_context = super(WcsDataBaseCell, self).get_cell_extra_context(context)
392
        extra_context = super().get_cell_extra_context(context)
394 393
        extra_context.update(WcsBlurpMixin.get_cell_extra_context(self, context))
395 394
        return extra_context
396 395

  
......
406 405
        user = kwargs.get('user')
407 406
        if not user or user.is_anonymous:
408 407
            return False
409
        return super(WcsUserDataBaseCell, self).is_visible(**kwargs)
408
        return super().is_visible(**kwargs)
410 409

  
411 410

  
412
class CategoriesValidityMixin(object):
411
class CategoriesValidityMixin:
413 412
    def check_validity(self):
414 413
        categories = self.categories.get('data', [])
415 414

  
......
435 434
        self.mark_as_valid()
436 435

  
437 436

  
438
class CategoriesFilteringMixin(object):
437
class CategoriesFilteringMixin:
439 438
    def get_api_url_for_site(self, context, wcs_slug):
440 439
        url = self.get_api_url(context)
441 440

  
......
491 490
        return 'combo/wcs/current_forms.html'
492 491

  
493 492
    def get_additional_label(self):
494
        initial_label = super(WcsCurrentFormsCell, self).get_additional_label()
493
        initial_label = super().get_additional_label()
495 494
        if self.include_drafts:
496 495
            if self.current_forms and self.done_forms:
497 496
                label = _('All Forms and Drafts')
......
511 510
        return label
512 511

  
513 512
    def get_cell_extra_context(self, context):
514
        context = super(WcsCurrentFormsCell, self).get_cell_extra_context(context)
513
        context = super().get_cell_extra_context(context)
515 514

  
516 515
        for wcs_site in context['user_forms']:
517 516
            if not context['user_forms'].get(wcs_site):
......
568 567
        return '/api/user/drafts'
569 568

  
570 569
    def get_cell_extra_context(self, context):
571
        context = super(WcsCurrentDraftsCell, self).get_cell_extra_context(context)
570
        context = super().get_cell_extra_context(context)
572 571

  
573 572
        for wcs_site in context['current_drafts']:
574 573
            if not context['current_drafts'].get(wcs_site):
......
658 657
        self.mark_as_valid()
659 658

  
660 659
    def get_cell_extra_context(self, context):
661
        extra_context = super(WcsFormsOfCategoryCell, self).get_cell_extra_context(context)
660
        extra_context = super().get_cell_extra_context(context)
662 661
        extra_context.update(WcsBlurpMixin.get_cell_extra_context(self, context))
663 662
        if not self.category_reference:
664 663
            return extra_context
......
791 790
        verbose_name = _('Form Categories')
792 791

  
793 792

  
794
class CardMixin(object):
793
class CardMixin:
795 794
    invalid_reason_codes = invalid_reason_codes
796 795

  
797 796
    def is_relevant(self, context):
......
1062 1061
        )
1063 1062

  
1064 1063
    def get_cell_extra_context(self, context):
1065
        extra_context = super(TrackingCodeInputCell, self).get_cell_extra_context(context)
1064
        extra_context = super().get_cell_extra_context(context)
1066 1065
        if not self.wcs_site:
1067 1066
            self.wcs_site = list(get_wcs_services().keys())[0]
1068 1067
        extra_context['url'] = get_wcs_services().get(self.wcs_site).get('url')
......
1094 1093
        return BackofficeSubmissionCellForm
1095 1094

  
1096 1095
    def get_cell_extra_context(self, context):
1097
        context = super(BackofficeSubmissionCell, self).get_cell_extra_context(context)
1096
        context = super().get_cell_extra_context(context)
1098 1097
        all_formdefs = context.pop('all_formdefs')
1099 1098
        formdefs = {}
1100 1099

  
combo/apps/wcs/views.py
42 42
    def dispatch(self, *args, **kwargs):
43 43
        # CSRF check must be disabled as the cell may be distributed to other
44 44
        # sites in a skeleton.
45
        return super(TrackingCodeView, self).dispatch(*args, **kwargs)
45
        return super().dispatch(*args, **kwargs)
46 46

  
47 47
    @classmethod
48 48
    def search(self, code, request, wcs_site=None):
......
92 92
            if redirect_to_other_domain:
93 93
                raise
94 94
            else:
95
                messages.error(self.request, _(u'Looking up tracking code is currently rate limited.'))
95
                messages.error(self.request, _('Looking up tracking code is currently rate limited.'))
96 96
        else:
97 97
            if url:
98 98
                return HttpResponseRedirect(url)
......
103 103
                    next_url += '?'
104 104
                next_url += 'unknown-tracking-code'
105 105
            else:
106
                messages.error(self.request, _(u'The tracking code could not been found.'))
106
                messages.error(self.request, _('The tracking code could not been found.'))
107 107

  
108 108
        return HttpResponseRedirect(next_url)
109 109

  
combo/data/fields.py
1
# -*- coding: utf-8 -*-
2 1
#
3 2
# combo - content management system
4 3
# Copyright (C) 2015-2017  Entr'ouvert
......
33 32
            'external_plugin_resources': self.external_plugin_resources,
34 33
        }
35 34
        defaults.update(kwargs)
36
        return super(RichTextField, self).formfield(**defaults)
35
        return super().formfield(**defaults)
37 36

  
38 37

  
39 38
class RichTextFormField(ckeditor.fields.RichTextFormField):
40 39
    def clean(self, value):
41
        value = super(RichTextFormField, self).clean(value)
40
        value = super().clean(value)
42 41
        if settings.LANGUAGE_CODE.startswith('fr-'):
43 42
            # apply some typographic rules
44
            value = value.replace(u'&laquo; ', u'«\u202f')
45
            value = value.replace(u'« ', u'«\u202f')
46
            value = value.replace(u' &raquo;', u'\u202f»')
47
            value = value.replace(u' »', u'\u202f»')
48
            value = value.replace(u' :', u'\u00a0:')
49
            value = value.replace(u' ;', u'\u202f;')
50
            value = value.replace(u' !', u'\u202f!')
51
            value = value.replace(u' ?', u'\u202f?')
43
            value = value.replace('&laquo; ', '«\u202f')
44
            value = value.replace('« ', '«\u202f')
45
            value = value.replace(' &raquo;', '\u202f»')
46
            value = value.replace(' »', '\u202f»')
47
            value = value.replace(' :', '\u00a0:')
48
            value = value.replace(' ;', '\u202f;')
49
            value = value.replace(' !', '\u202f!')
50
            value = value.replace(' ?', '\u202f?')
52 51
        return value
53 52

  
54 53

  
......
68 67
        value = super(forms.URLField, self).to_python(value)
69 68
        if '{{' in value or '{%' in value:
70 69
            return value
71
        return super(TemplatableURLField, self).to_python(value)
70
        return super().to_python(value)
combo/data/forms.py
26 26
@cache_during_request
27 27
def get_page_choices():
28 28
    pages = Page.get_as_reordered_flat_hierarchy(Page.objects.all())
29
    return [(x.id, '%s %s' % (u'\u00a0' * x.level * 2, x.title)) for x in pages]
29
    return [(x.id, '%s %s' % ('\u00a0' * x.level * 2, x.title)) for x in pages]
30 30

  
31 31

  
32 32
class MenuCellForm(forms.ModelForm):
......
35 35
        fields = ('depth', 'initial_level', 'root_page')
36 36

  
37 37
    def __init__(self, *args, **kwargs):
38
        super(MenuCellForm, self).__init__(*args, **kwargs)
38
        super().__init__(*args, **kwargs)
39 39
        self.fields['root_page'].widget = forms.Select(choices=get_page_choices())
40 40

  
41 41

  
......
45 45
        fields = ('title', 'url', 'link_page', 'anchor')
46 46

  
47 47
    def __init__(self, *args, **kwargs):
48
        super(LinkCellForm, self).__init__(*args, **kwargs)
48
        super().__init__(*args, **kwargs)
49 49
        self.fields['link_page'].widget = forms.Select(choices=[(None, '-----')] + get_page_choices())
50 50

  
51 51

  
......
55 55
        fields = ['title', 'limit']
56 56

  
57 57
    def __init__(self, *args, **kwargs):
58
        super(LinkListCellForm, self).__init__(*args, **kwargs)
58
        super().__init__(*args, **kwargs)
59 59

  
60 60

  
61 61
class ConfigJsonForm(forms.ModelForm):
......
71 71
        # reset parameters in instance as the value is actually created from
72 72
        # additional fields.
73 73
        kwargs['instance'].parameters = None
74
        super(ConfigJsonForm, self).__init__(*args, **kwargs)
74
        super().__init__(*args, **kwargs)
75 75

  
76 76
        field_classes = {
77 77
            'string': forms.CharField,
combo/data/library.py
17 17
from collections import OrderedDict
18 18

  
19 19

  
20
class Library(object):
20
class Library:
21 21
    """Singleton object that serves as a registry of the classes
22 22
    providing page cells."""
23 23

  
combo/data/management/commands/cron.py
14 14
# You should have received a copy of the GNU Affero General Public License
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17
from __future__ import print_function
18 17

  
19 18
import sys
20 19
import traceback
combo/data/management/commands/export_site.py
45 45
            if options['output'] and options['output'] != '-':
46 46
                try:
47 47
                    output = open(options['output'], 'wb')
48
                except IOError as e:
48
                except OSError as e:
49 49
                    raise CommandError(e)
50 50
                export_site_tar(output)
51 51
                output.close()
combo/data/management/commands/import_site.py
43 43
            else:
44 44
                try:
45 45
                    fd = stack.enter_context(open(filename, 'rb'))
46
                except IOError as e:
46
                except OSError as e:
47 47
                    raise CommandError(e)
48 48
                try:
49 49
                    tarfile.open(mode='r', fileobj=fd)
50 50
                except tarfile.TarError as e:
51 51
                    format = 'json'
52
                    fd = open(filename, 'r')
52
                    fd = open(filename)
53 53
                else:
54 54
                    format = 'tar'
55 55
                    fd = open(filename, 'rb')
combo/data/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import ckeditor.fields
5 2
from django.db import migrations, models
6 3

  
combo/data/migrations/0002_auto_20150217_1327.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0003_menucell.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0004_menucell_depth.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0005_auto_20150226_0903.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import ckeditor.fields
5 2
from django.db import migrations, models
6 3

  
combo/data/migrations/0006_linkcell.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0007_auto_20150529_1003.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0008_auto_20150529_1504.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0009_auto_20150529_2247.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0010_feedcell.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0011_auto_20151028_1047.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0012_auto_20151029_1535.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0013_parameterscell.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.contrib.postgres.fields import JSONField
5 2
from django.db import migrations, models
6 3

  
combo/data/migrations/0014_menucell_initial_level.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0015_feedcell_title.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0016_feedcell_limit.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0017_menucell_root_page.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0018_parentcontentcell.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0019_create_parent_cells.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.conf import settings
5 2
from django.db import migrations, models
6 3

  
combo/data/migrations/0020_auto_20160928_1152.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0021_jsoncell.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3
import combo.data.models
combo/data/migrations/0022_auto_20170214_2006.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import datetime
5 2

  
6 3
from django.db import migrations, models
combo/data/migrations/0023_auto_20170313_1541.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0024_configjsoncell.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.contrib.postgres.fields import JSONField
5 2
from django.db import migrations, models
6 3

  
combo/data/migrations/0025_jsoncell_varnames_str.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3
import combo.data.fields
combo/data/migrations/0026_jsoncell_force_async.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0027_page_picture.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0028_jsoncell_timeout.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0029_auto_20171022_1242.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3
import combo.data.models
combo/data/migrations/0030_externallinksearchitem.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0031_remove_blurps.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0032_page_description.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0033_auto_20180401_1300.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.8 on 2018-04-01 13:00
3
from __future__ import unicode_literals
4 2

  
5 3
import django.db.models.deletion
6 4
from django.conf import settings
combo/data/migrations/0034_redirect.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2018-07-13 06:40
3
from __future__ import unicode_literals
4 2

  
5 3
import django.db.models.deletion
6 4
from django.db import migrations, models
combo/data/migrations/0035_page_related_cells.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2018-06-02 11:03
3
from __future__ import unicode_literals
4 2

  
5 3
from django.contrib.postgres.fields import JSONField
6 4
from django.db import migrations
combo/data/migrations/0036_page_sub_slug.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2018-08-08 18:30
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/data/migrations/0037_auto_20190701_2118.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2019-07-01 19:18
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/data/migrations/0038_increase_jsoncell_url_max_length.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.27 on 2020-01-08 10:14
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/data/migrations/0039_link_list_cell.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import django.db.models.deletion
5 2
from django.db import migrations, models
6 3

  
combo/data/migrations/0040_auto_20200119_1017.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.17 on 2020-01-19 09:17
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/data/migrations/0041_auto_20200130_1619.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations, models
5 2

  
6 3

  
combo/data/migrations/0042_page_creation_timestamp.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2020-01-31 15:40
3
from __future__ import unicode_literals
4 2

  
5 3
import django.utils.timezone
6 4
from django.db import migrations, models
combo/data/migrations/0043_delete_externallinksearchitem.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.17 on 2020-01-20 15:30
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations
6 4

  
combo/data/migrations/0044_validity_info.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
import django.db.models.deletion
5 2
from django.db import migrations, models
6 3

  
......
36 33
        ),
37 34
        migrations.AlterUniqueTogether(
38 35
            name='validityinfo',
39
            unique_together=set([('content_type', 'object_id')]),
36
            unique_together={('content_type', 'object_id')},
40 37
        ),
41 38
    ]
combo/data/migrations/0045_link_list_limit.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2020-03-17 09:34
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations, models
6 4

  
combo/data/models.py
134 134
    return context
135 135

  
136 136

  
137
class Placeholder(object):
137
class Placeholder:
138 138
    def __init__(
139 139
        self, key, name=None, acquired=False, optional=False, render=True, cell=None, force_synchronous=False
140 140
    ):
......
157 157

  
158 158
    def __init__(self, *args, **kwargs):
159 159
        self.snapshots = kwargs.pop('snapshots', False)
160
        super(PageManager, self).__init__(*args, **kwargs)
160
        super().__init__(*args, **kwargs)
161 161

  
162 162
    def get_by_natural_key(self, path):
163 163
        parts = [x for x in path.strip('/').split('/') if x] or ['index']
164 164
        return self.get(slug=parts[-1])
165 165

  
166 166
    def get_queryset(self):
167
        queryset = super(PageManager, self).get_queryset()
167
        queryset = super().get_queryset()
168 168
        if self.snapshots:
169 169
            return queryset.filter(snapshot__isnull=False)
170 170
        else:
......
251 251
            self.slug = slug
252 252
        if not self.template_name:
253 253
            self.template_name = settings.COMBO_DEFAULT_PUBLIC_TEMPLATE
254
        return super(Page, self).save(*args, **kwargs)
254
        return super().save(*args, **kwargs)
255 255

  
256 256
    def get_parents_and_self(self):
257 257
        pages = [self]
......
477 477
    @classmethod
478 478
    def load_serialized_page(cls, json_page, page=None, snapshot=None, request=None):
479 479
        json_page['model'] = 'data.page'
480
        json_page['fields']['groups'] = [
481
            [x] for x in json_page['fields']['groups'] if isinstance(x, six.string_types)
482
        ]
480
        json_page['fields']['groups'] = [[x] for x in json_page['fields']['groups'] if isinstance(x, str)]
483 481
        created = None
484 482
        if page is None:
485 483
            page, created = Page.objects.get_or_create(slug=json_page['fields']['slug'], snapshot=snapshot)
......
501 499
        page.object.snapshot = snapshot
502 500
        page.save()
503 501
        for cell in json_page.get('cells'):
504
            cell['fields']['groups'] = [
505
                [x] for x in cell['fields']['groups'] if isinstance(x, six.string_types)
506
            ]
502
            cell['fields']['groups'] = [[x] for x in cell['fields']['groups'] if isinstance(x, str)]
507 503
            cell['fields']['page'] = page.object.id
508 504

  
509 505
        # if there were cells, remove them
......
699 695

  
700 696

  
701 697
@python_2_unicode_compatible
702
class CellBase(six.with_metaclass(CellMeta, models.Model)):
698
class CellBase(models.Model, metaclass=CellMeta):
703 699

  
704 700
    page = models.ForeignKey(Page, on_delete=models.CASCADE)
705 701
    placeholder = models.CharField(max_length=20)
......
748 744
        label = self.get_verbose_name()
749 745
        additional_label = self.get_additional_label()
750 746
        if label and additional_label:
751
            return u'%s (%s)' % (label, re.sub(r'\r?\n', u' ', force_text(additional_label)))
747
            return '%s (%s)' % (label, re.sub(r'\r?\n', ' ', force_text(additional_label)))
752 748
        else:
753 749
            return force_text(label)
754 750

  
......
794 790
            return ''
795 791

  
796 792
        # add has-asset-<slug> for each asset found
797
        css = sorted(['has-asset-{}'.format(v) for k, v in self._asset_keys.items() if k in self._assets])
793
        css = sorted(f'has-asset-{v}' for k, v in self._asset_keys.items() if k in self._assets)
798 794
        # add has-any-asset if at least one asset defined
799 795
        if self._assets:
800 796
            css.append('has-any-asset')
......
811 807
        return self.slug
812 808

  
813 809
    def get_label_for_asset(self):
814
        return _(u'%(cell_label)s on page %(page_name)s (%(page_slug)s)') % {
810
        return _('%(cell_label)s on page %(page_name)s (%(page_slug)s)') % {
815 811
            'cell_label': str(self),
816 812
            'page_name': str(self.page),
817 813
            'page_slug': self.page.slug,
......
840 836
            if slot_template_data.get('suffix'):
841 837
                suffix = ' (%s)' % slot_template_data['suffix']
842 838
            slot_key = self.get_asset_slot_key(slot_template_key)
843
            label = u'%(prefix)s — %(label)s%(suffix)s' % {
839
            label = '%(prefix)s — %(label)s%(suffix)s' % {
844 840
                'prefix': slot_template_data['prefix'],
845 841
                'label': self.get_label_for_asset(),
846 842
                'suffix': suffix,
847 843
            }
848
            short_label = u'%(prefix)s%(suffix)s' % {'prefix': slot_template_data['prefix'], 'suffix': suffix}
844
            short_label = '%(prefix)s%(suffix)s' % {'prefix': slot_template_data['prefix'], 'suffix': suffix}
849 845
            slots[slot_key] = {
850 846
                'label': label,
851 847
                'short_label': short_label,
......
1237 1233

  
1238 1234
    @classmethod
1239 1235
    def get_cell_types(cls):
1240
        d = super(TextCell, cls).get_cell_types()
1236
        d = super().get_cell_types()
1241 1237
        d[0]['order'] = -1
1242 1238
        return d
1243 1239

  
1244 1240
    def get_cell_extra_context(self, context):
1245
        extra_context = super(TextCell, self).get_cell_extra_context(context)
1241
        extra_context = super().get_cell_extra_context(context)
1246 1242
        text = self.text or ''
1247 1243
        force_absolute_url = context.get('force_absolute_url') or context.get('render_skeleton')
1248 1244

  
......
1346 1342
    def get_cell_extra_context(self, context):
1347 1343
        from combo.public.menu import render_menu
1348 1344

  
1349
        ctx = super(MenuCell, self).get_cell_extra_context(context)
1345
        ctx = super().get_cell_extra_context(context)
1350 1346
        ctx['menu'] = render_menu(
1351 1347
            context,
1352 1348
            level=self.initial_level,
......
1389 1385
    def save(self, *args, **kwargs):
1390 1386
        if 'update_fields' in kwargs:
1391 1387
            # don't check validity
1392
            return super(LinkCell, self).save(*args, **kwargs)
1388
            return super().save(*args, **kwargs)
1393 1389

  
1394
        result = super(LinkCell, self).save(*args, **kwargs)
1390
        result = super().save(*args, **kwargs)
1395 1391
        # check validity
1396 1392
        self.check_validity()
1397 1393
        return result
......
1429 1425
    def get_cell_extra_context(self, context):
1430 1426
        force_absolute_url = context.get('force_absolute_url') or context.get('render_skeleton')
1431 1427
        request = context.get('request')
1432
        extra_context = super(LinkCell, self).get_cell_extra_context(context)
1428
        extra_context = super().get_cell_extra_context(context)
1433 1429
        if self.link_page:
1434 1430
            extra_context['title'] = self.title or self.link_page.title
1435 1431
            extra_context['description'] = self.link_page.description
......
1523 1519
        return utils.ellipsize(title)
1524 1520

  
1525 1521
    def get_cell_extra_context(self, context):
1526
        extra_context = super(LinkListCell, self).get_cell_extra_context(context)
1522
        extra_context = super().get_cell_extra_context(context)
1527 1523
        links = []
1528 1524
        for cell in context.get('page_cells', []):
1529 1525
            if not hasattr(cell, 'add_as_link_label'):
......
1604 1600
        verbose_name = _('RSS/Atom Feed')
1605 1601

  
1606 1602
    def is_visible(self, **kwargs):
1607
        return bool(self.url) and super(FeedCell, self).is_visible(**kwargs)
1603
        return bool(self.url) and super().is_visible(**kwargs)
1608 1604

  
1609 1605
    def save(self, *args, **kwargs):
1610 1606
        result = super().save(*args, **kwargs)
......
1615 1611
        return result
1616 1612

  
1617 1613
    def get_cell_extra_context(self, context):
1618
        extra_context = super(FeedCell, self).get_cell_extra_context(context)
1614
        extra_context = super().get_cell_extra_context(context)
1619 1615

  
1620 1616
        if not self.url:
1621 1617
            self.mark_as_invalid('data_url_not_defined')
......
1657 1653
        feed_content = cache.get(cache_key)
1658 1654
        if not context.get('synchronous') and feed_content is None:
1659 1655
            raise NothingInCacheException()
1660
        return super(FeedCell, self).render(context)
1656
        return super().render(context)
1661 1657

  
1662 1658

  
1663 1659
@register_cell_class
......
1741 1737
        return result
1742 1738

  
1743 1739
    def is_visible(self, **kwargs):
1744
        return bool(self.url) and super(JsonCellBase, self).is_visible(**kwargs)
1740
        return bool(self.url) and super().is_visible(**kwargs)
1745 1741

  
1746 1742
    def is_user_dependant(self, context=None):
1747 1743
        urls = [self.url] + [x['url'] for x in self.additional_data or []]
......
1754 1750
        return {}
1755 1751

  
1756 1752
    def get_cell_extra_context(self, context, invalidate_cache=False):
1757
        extra_context = super(JsonCellBase, self).get_cell_extra_context(context)
1753
        extra_context = super().get_cell_extra_context(context)
1758 1754
        if context.get('placeholder_search_mode'):
1759 1755
            # don't call webservices when we're just looking for placeholders
1760 1756
            return extra_context
......
1813 1809
                extra_context[data_key + '_exception'] = e
1814 1810
                logger = logging.getLogger(__name__)
1815 1811
                if log_errors:
1816
                    logger.warning(u'error on request %r: %s', url, force_text(e))
1812
                    logger.warning('error on request %r: %s', url, force_text(e))
1817 1813
                else:
1818
                    logger.debug(u'error on request %r: %s', url, force_text(e))
1814
                    logger.debug('error on request %r: %s', url, force_text(e))
1819 1815
                continue
1820 1816
            extra_context[data_key + '_status'] = json_response.status_code
1821 1817
            if json_response.status_code // 100 == 2:
......
1847 1843
                    # ignore returns of url with more than one variable
1848 1844
                    continue
1849 1845
                returns.append(extra_context.get(data_url['key'] + '_status'))
1850
            returns = set([s for s in returns if s is not None])
1846
            returns = {s for s in returns if s is not None}
1851 1847
            if returns and 200 not in returns:  # not a single valid answer
1852 1848
                if 404 in returns:
1853 1849
                    self.mark_as_invalid('data_url_not_found')
......
1955 1951
            tmpl = engines['django'].from_string(self.template_string)
1956 1952
            context.update(self.get_cell_extra_context(context))
1957 1953
            return tmpl.render(context, context.get('request'))
1958
        return super(JsonCellBase, self).render(context)
1954
        return super().render(context)
1959 1955

  
1960 1956

  
1961 1957
@register_cell_class
......
1989 1985

  
1990 1986
class ConfigJsonCellManager(models.Manager):
1991 1987
    def get_queryset(self):
1992
        queryset = super(ConfigJsonCellManager, self).get_queryset()
1988
        queryset = super().get_queryset()
1993 1989
        return queryset.filter(key__in=settings.JSON_CELL_TYPES.keys())
1994 1990

  
1995 1991

  
......
2026 2022

  
2027 2023
    @property
2028 2024
    def css_class_names(self):
2029
        return super(ConfigJsonCell, self).css_class_names + ' ' + self.key
2025
        return super().css_class_names + ' ' + self.key
2030 2026

  
2031 2027
    @property
2032 2028
    def ajax_refresh(self):
combo/data/utils.py
94 94
    groups = set()
95 95
    for page in data.get('pages') or []:
96 96
        for group in page['fields']['groups']:
97
            groups.add(group if isinstance(group, six.string_types) else group[0])
97
            groups.add(group if isinstance(group, str) else group[0])
98 98
        for cell in page['cells']:
99 99
            for group in cell['fields']['groups']:
100
                groups.add(group if isinstance(group, six.string_types) else group[0])
100
                groups.add(group if isinstance(group, str) else group[0])
101 101

  
102
    existing_groups = set([x.name for x in Group.objects.filter(name__in=groups)])
102
    existing_groups = {x.name for x in Group.objects.filter(name__in=groups)}
103 103
    missing_groups = groups - existing_groups
104 104
    if missing_groups:
105
        raise MissingGroups(names=sorted([x for x in missing_groups]))
105
        raise MissingGroups(names=sorted(x for x in missing_groups))
106 106

  
107 107
    with transaction.atomic():
108 108
        if clean:
combo/manager/fields.py
1
# -*- coding: utf-8 -*-
2 1
#
3 2
# combo - content management system
4 3
# Copyright (C) 2015-2019  Entr'ouvert
......
37 36
        if data.name and data.name.endswith('.svg'):
38 37
            # bypass image field Pillow check
39 38
            return super(forms.ImageField, self).to_python(data)
40
        return super(ImageIncludingSvgField, self).to_python(data)
39
        return super().to_python(data)
combo/manager/forms.py
157 157
        fields = ('public', 'groups')
158 158

  
159 159
    def __init__(self, *args, **kwargs):
160
        super(PageVisibilityForm, self).__init__(*args, **kwargs)
160
        super().__init__(*args, **kwargs)
161 161
        self.fields['groups'].queryset = Group.objects.order_by('name')
162 162

  
163 163

  
......
167 167
        fields = ('template_name',)
168 168

  
169 169
    def __init__(self, *args, **kwargs):
170
        super(PageSelectTemplateForm, self).__init__(*args, **kwargs)
170
        super().__init__(*args, **kwargs)
171 171
        self.fields['template_name'].widget = forms.Select(choices=get_template_name_choices())
172 172

  
173 173

  
......
186 186
        return value
187 187

  
188 188
    def save(self, *args, **kwargs):
189
        page = super(PageEditRedirectionForm, self).save(*args, **kwargs)
189
        page = super().save(*args, **kwargs)
190 190
        page.redirect_url = page.redirect_url.strip()
191 191
        page.save()
192 192
        return page
......
203 203
        instance = kwargs['instance']
204 204
        initial = kwargs.pop('initial', {})
205 205
        initial['include_in_navigation'] = not instance.exclude_from_navigation
206
        super(PageEditIncludeInNavigationForm, self).__init__(initial=initial, *args, **kwargs)
206
        super().__init__(initial=initial, *args, **kwargs)
207 207

  
208 208
    def save(self, *args, **kwargs):
209
        super(PageEditIncludeInNavigationForm, self).save(*args, **kwargs)
209
        super().save(*args, **kwargs)
210 210
        self.instance.exclude_from_navigation = not self.cleaned_data['include_in_navigation']
211 211
        self.instance.save()
212 212
        return self.instance
......
241 241
                    initial['visibility'] = 'groups-none'
242 242
                else:
243 243
                    initial['visibility'] = 'groups-any'
244
        super(CellVisibilityForm, self).__init__(*args, **kwargs)
244
        super().__init__(*args, **kwargs)
245 245

  
246 246
    def save(self):
247 247
        if self.cleaned_data['visibility'] == 'all':
combo/manager/views.py
72 72

  
73 73
    def get_context_data(self, **kwargs):
74 74
        self.object_list = Page.get_as_reordered_flat_hierarchy(self.object_list)
75
        context = super(HomepageView, self).get_context_data(**kwargs)
75
        context = super().get_context_data(**kwargs)
76 76
        context['extra_actions'] = plugins.get_extra_manager_actions()
77 77
        context['collapse_pages'] = settings.COMBO_MANAGE_HOME_COLLAPSE_PAGES
78 78
        return context
......
138 138
            for page in pages:
139 139
                PageSnapshot.take(page, request=self.request, comment=_('imported'))
140 140

  
141
        return super(SiteImportView, self).form_valid(form)
141
        return super().form_valid(form)
142 142

  
143 143

  
144 144
site_import = SiteImportView.as_view()
......
176 176
        return kwargs
177 177

  
178 178
    def get_initial(self):
179
        initial = super(PageAddView, self).get_initial()
179
        initial = super().get_initial()
180 180
        if not Page.objects.exists():  # first page
181 181
            initial['title'] = _('Home')
182 182
        return initial
......
208 208
    comment = None
209 209

  
210 210
    def form_valid(self, form):
211
        result = super(PageEditView, self).form_valid(form)
211
        result = super().form_valid(form)
212 212
        PageSnapshot.take(self.get_object(), request=self.request, comment=self.comment)
213 213
        return result
214 214

  
......
228 228
    def form_valid(self, form):
229 229
        old_template_name = self.get_object().template_name
230 230
        new_template_name = self.object.template_name
231
        response = super(PageSelectTemplateView, self).form_valid(form)
231
        response = super().form_valid(form)
232 232
        if old_template_name != new_template_name:
233 233
            old_placeholder_keys = [x.key for x in self.get_object().get_placeholders(request=self.request)]
234 234
            page_cells = CellBase.get_cells(page_id=self.object.id)
......
324 324
    template_name = 'combo/page_view.html'
325 325

  
326 326
    def get_context_data(self, **kwargs):
327
        context = super(PageView, self).get_context_data(**kwargs)
327
        context = super().get_context_data(**kwargs)
328 328
        cell_type_groups = {}
329 329
        for cell_type in CellBase.get_all_cell_types():
330 330
            if not cell_type['group'] in cell_type_groups:
......
415 415

  
416 416
    def get_context_data(self, **kwargs):
417 417
        subpages = Page.objects.filter(parent=self.get_object().id)
418
        context = super(PageDeleteView, self).get_context_data()
418
        context = super().get_context_data()
419 419
        context['display_choice'] = True if subpages else False
420 420
        return context
421 421

  
......
445 445
        if with_children:
446 446
            pages = instance.get_descendants_and_me()
447 447
            ordered_pages = Page.get_as_reordered_flat_hierarchy(pages, root_page=instance)
448
            filename_part = '{}_and_subpages'.format(instance.slug)
448
            filename_part = f'{instance.slug}_and_subpages'
449 449
        else:
450 450
            ordered_pages = [instance]
451 451
            filename_part = instance.slug
......
489 489
        return super().form_valid(form)
490 490

  
491 491
    def get_context_data(self, **kwargs):
492
        context = super(PageDuplicateView, self).get_context_data(**kwargs)
492
        context = super().get_context_data(**kwargs)
493 493
        context['page'] = Page.objects.get(id=self.kwargs['pk'])
494 494
        return context
495 495

  
......
516 516
    template_name = 'combo/snapshot_restore.html'
517 517

  
518 518
    def get_context_data(self, **kwargs):
519
        context = super(SnapshotRestoreView, self).get_context_data(**kwargs)
519
        context = super().get_context_data(**kwargs)
520 520
        context['page'] = Page.objects.get(id=self.kwargs['page_pk'])
521 521
        return context
522 522

  
......
557 557
        return [self.template_name or self.object.manager_form_template]
558 558

  
559 559
    def get_context_data(self, **kwargs):
560
        context = super(PageEditCellView, self).get_context_data(**kwargs)
560
        context = super().get_context_data(**kwargs)
561 561
        context.update(self.get_object().get_extra_manager_context())
562 562
        context['cell'] = self.get_object()
563 563
        context['page'] = context['cell'].page
......
590 590
            form = self.get_form_class()(instance=self.object, prefix=self.get_prefix())
591 591
            response = self.form_invalid(form)  # avoid redirection
592 592
        else:
593
            response = super(PageEditCellView, self).form_valid(form)
593
            response = super().form_valid(form)
594 594
        PageSnapshot.take(
595 595
            self.object.page, request=self.request, comment=_('changed cell "%s"') % self.object
596 596
        )
......
615 615
        cell = self.get_object()
616 616
        comment = _('removed cell "%s"') % cell
617 617
        page = cell.page
618
        response = super(PageDeleteCellView, self).delete(request, *args, **kwargs)
618
        response = super().delete(request, *args, **kwargs)
619 619
        PageSnapshot.take(page, request=self.request, comment=comment)
620 620
        return response
621 621

  
......
787 787
                break
788 788
        if self.model is None:
789 789
            raise Http404
790
        return super(PageListCellAddLinkView, self).dispatch(request, *args, **kwargs)
790
        return super().dispatch(request, *args, **kwargs)
791 791

  
792 792
    def get_form_class(self):
793 793
        return self.model().get_default_form_class()
794 794

  
795 795
    def get_form_kwargs(self):
796
        kwargs = super(PageListCellAddLinkView, self).get_form_kwargs()
796
        kwargs = super().get_form_kwargs()
797 797
        kwargs['instance'] = self.model(page=self.cell.page, placeholder=self.cell.link_placeholder)
798 798
        return kwargs
799 799

  
......
804 804
        else:
805 805
            form.instance.order = 1
806 806
        PageSnapshot.take(self.cell.page, request=self.request, comment=_('changed cell "%s"') % self.cell)
807
        response = super(PageListCellAddLinkView, self).form_valid(form)
807
        response = super().form_valid(form)
808 808
        self.cell.check_validity()
809 809
        return response
810 810

  
......
833 833
        if self.object.placeholder != self.cell.link_placeholder:
834 834
            raise Http404
835 835
        self.model = self.object.__class__
836
        return super(PageListCellEditLinkView, self).dispatch(request, *args, **kwargs)
836
        return super().dispatch(request, *args, **kwargs)
837 837

  
838 838
    def get_object(self, *args, **kwargs):
839 839
        return self.object
......
846 846
            self.object = form.save()
847 847
            response = self.form_invalid(form)  # avoid redirection
848 848
        else:
849
            response = super(PageListCellEditLinkView, self).form_valid(form)
849
            response = super().form_valid(form)
850 850
        PageSnapshot.take(self.cell.page, request=self.request, comment=_('changed cell "%s"') % self.cell)
851 851
        self.cell.check_validity()
852 852
        return response
......
876 876
        if self.object.placeholder != self.cell.link_placeholder:
877 877
            raise Http404
878 878
        self.model = self.object.__class__
879
        return super(PageListCellDeleteLinkView, self).dispatch(request, *args, **kwargs)
879
        return super().dispatch(request, *args, **kwargs)
880 880

  
881 881
    def get_object(self, *args, **kwargs):
882 882
        return self.object
883 883

  
884 884
    def delete(self, request, *args, **kwargs):
885
        response = super(PageListCellDeleteLinkView, self).delete(request, *args, **kwargs)
885
        response = super().delete(request, *args, **kwargs)
886 886
        PageSnapshot.take(self.cell.page, request=self.request, comment=_('changed cell "%s"') % self.cell)
887 887
        self.cell.check_validity()
888 888
        return response
combo/profile/__init__.py
1
# -*- coding: utf-8 -*-
2 1
#
3 2
# combo - content management system
4 3
# Copyright (C) 2014-2018  Entr'ouvert
combo/profile/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.conf import settings
5 2
from django.db import migrations, models
6 3

  
combo/profile/migrations/0002_profilecell.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2018-08-10 13:52
3
from __future__ import unicode_literals
4 2

  
5 3
import django.db.models.deletion
6 4
from django.db import migrations, models
combo/profile/models.py
49 49
        user = kwargs.get('user')
50 50
        if not user or user.is_anonymous:
51 51
            return False
52
        return super(ProfileCell, self).is_visible(**kwargs)
52
        return super().is_visible(**kwargs)
53 53

  
54 54
    def get_cell_extra_context(self, context):
55
        extra_context = super(ProfileCell, self).get_cell_extra_context(context)
55
        extra_context = super().get_cell_extra_context(context)
56 56
        extra_context['profile_fields'] = OrderedDict()
57 57
        if extra_context.get('profile') is not None:
58 58
            for attribute in settings.USER_PROFILE_CONFIG.get('fields'):
combo/profile/utils.py
23 23
    UserSAMLIdentifier = None
24 24

  
25 25

  
26
class ProxiedUser(object):
26
class ProxiedUser:
27 27
    is_authenticated = True
28 28
    is_anonymous = False
29 29

  
combo/public/templatetags/combo.py
14 14
# You should have received a copy of the GNU Affero General Public License
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17
from __future__ import absolute_import
18 17

  
19 18
import copy
20 19
import datetime
......
448 447

  
449 448

  
450 449
def parse_float(value):
451
    if isinstance(value, six.string_types):
450
    if isinstance(value, str):
452 451
        # replace , by . for French users comfort
453 452
        value = value.replace(',', '.')
454 453
    try:
......
590 589

  
591 590

  
592 591
def parse_decimal(value, default=Decimal(0)):
593
    if isinstance(value, six.string_types):
592
    if isinstance(value, str):
594 593
        # replace , by . for French users comfort
595 594
        value = value.replace(',', '.')
596 595
    try:
......
689 688
def phonenumber_fr(value, separator=' '):
690 689
    DROMS = ('262', '508', '590', '594', '596')
691 690

  
692
    if not value or not isinstance(value, six.string_types):
691
    if not value or not isinstance(value, str):
693 692
        return value
694 693
    number = value.strip()
695 694
    if not number:
combo/public/views.py
364 364
    response = render(request, template_name, ctx)
365 365
    response['X-Combo-Page-Id'] = str(selected_page.id)
366 366
    response['X-Combo-Skeleton-Pages'] = json.dumps(
367
        dict([(x.id, utils.get_templated_url(x.redirect_url)) for x in same_domain_pages])
367
        {x.id: utils.get_templated_url(x.redirect_url) for x in same_domain_pages}
368 368
    )
369 369
    return response
370 370

  
371 371

  
372
class StyleDemoPage(object):
372
class StyleDemoPage:
373 373
    def __init__(self, request):
374 374
        self.request = request
375 375
        self.template_name = request.GET.get('template') or 'standard'
......
413 413
                    attr = 'value="%s"' % template_key
414 414
                    if template_key == self.page.template_name:
415 415
                        attr += ' selected="selected"'
416
                    options_html.append(u'<option %s>%s</option>' % (attr, template_dict['name']))
417
                cell.text = u'''<form><select name="template">%s</select>
416
                    options_html.append('<option %s>%s</option>' % (attr, template_dict['name']))
417
                cell.text = '''<form><select name="template">%s</select>
418 418
                                <button>%s</button></form>''' % (
419 419
                    '\n'.join(options_html),
420 420
                    _('Select'),
......
584 584
    # load assets
585 585
    for cell in cells:
586 586
        cell._asset_keys = cell.get_asset_slot_keys()
587
    asset_keys = list(set(chain(*[c._asset_keys.keys() for c in cells])))
587
    asset_keys = list(set(chain(*(c._asset_keys.keys() for c in cells))))
588 588
    assets = list(Asset.objects.filter(key__in=asset_keys))
589 589
    for cell in cells:
590 590
        cell._assets = {a.key: a for a in assets if a.key in cell._asset_keys.keys()}
......
620 620
        return page_not_found(request, *args, **kwargs)
621 621

  
622 622
    if Page.objects.exists() and all(
623
        (not x.is_visible(request.user) for x in Page.objects.filter(parent_id__isnull=True))
623
        not x.is_visible(request.user) for x in Page.objects.filter(parent_id__isnull=True)
624 624
    ):
625 625
        # if none of the first-level pages can be viewed by the user, display
626 626
        # native django error page.
combo/urls_utils.py
29 29

  
30 30
class DecoratedURLPattern(URLPattern):
31 31
    def resolve(self, *args, **kwargs):
32
        result = super(DecoratedURLPattern, self).resolve(*args, **kwargs)
32
        result = super().resolve(*args, **kwargs)
33 33
        if result:
34 34
            result.func = self._decorate_with(result.func)
35 35
        return result
......
37 37

  
38 38
class DecoratedURLResolver(URLResolver):
39 39
    def resolve(self, *args, **kwargs):
40
        result = super(DecoratedURLResolver, self).resolve(*args, **kwargs)
40
        result = super().resolve(*args, **kwargs)
41 41
        if result:
42 42
            result.func = self._decorate_with(result.func)
43 43
        return result
combo/utils/forms.py
27 27
            self.with_checkboxes = kwargs.pop('with_checkboxes')
28 28
        else:
29 29
            self.with_checkboxes = False
30
        super(MultiSortWidget, self).__init__(*args, **kwargs)
30
        super().__init__(*args, **kwargs)
31 31

  
32 32
    def render(self, name, value, attrs=None, choices=(), renderer=None):
33 33
        # reorder choices to get them in the current value order
......
43 43
                self.choices.insert(0, option_tuple)
44 44

  
45 45
        # render the <select multiple>
46
        rendered = super(MultiSortWidget, self).render(name, value, attrs=attrs)
46
        rendered = super().render(name, value, attrs=attrs)
47 47

  
48 48
        # include it in a <div> that will be turned into an appropriate widget
49 49
        # in javascript
......
61 61

  
62 62
    def render_options(self, choices, value):
63 63
        value = value.get('data') or []
64
        return super(MultiSortWidget, self).render_options(choices, value)
64
        return super().render_options(choices, value)
65 65

  
66 66
    def value_from_datadict(self, data, files, name):
67 67
        if isinstance(data, MultiValueDict):
......
70 70

  
71 71
    def format_value(self, value):
72 72
        value = value.get('data') or []
73
        return super(MultiSortWidget, self).format_value(value)
73
        return super().format_value(value)
combo/utils/requests_wrapper.py
134 134

  
135 135
        kwargs['timeout'] = kwargs.get('timeout') or settings.REQUESTS_TIMEOUT
136 136

  
137
        response = super(Requests, self).request(method, url, **kwargs)
137
        response = super().request(method, url, **kwargs)
138 138
        if log_errors and (response.status_code // 100 != 2):
139 139
            extra = {}
140 140
            if django_request:
setup.py
1 1
#! /usr/bin/env python
2
# -*- coding: utf-8 -*-
3 2

  
4 3
import glob
5 4
import itertools
......
35 34
    tag exists, take 0.0- and add the length of the commit log.
36 35
    """
37 36
    if os.path.exists('VERSION'):
38
        with open('VERSION', 'r') as v:
37
        with open('VERSION') as v:
39 38
            return v.read()
40 39
    if os.path.exists('.git'):
41 40
        p = subprocess.Popen(
tests/settings.py
68 68

  
69 69
if 'DISABLE_MIGRATIONS' in os.environ:
70 70

  
71
    class DisableMigrations(object):
71
    class DisableMigrations:
72 72
        def __contains__(self, item):
73 73
            return True
74 74

  
tests/test_assets.py
1
# -*- coding: utf-8 -*-
2

  
3 1
import base64
4 2
import os
5 3
import tarfile
......
66 64
    resp = app.post_json(reverse('api-assets-set', kwargs={'key': 'plop'}), params={}, status=400)
67 65
    assert resp.json.get('err') == 1
68 66

  
69
    for invalid_value in (None, 'not base 64', u'éléphant'):
67
    for invalid_value in (None, 'not base 64', 'éléphant'):
70 68
        resp = app.post_json(
71 69
            reverse('api-assets-set', kwargs={'key': 'plop'}),
72 70
            params={
......
121 119
    data = untar_assets_files(tar)
122 120
    assert [x['fields']['key'] for x in data['assets']] == ['banner', 'favicon']
123 121
    assert count_asset_files() == 2
124
    assert open('%s/assets/test.png' % path, 'r').read() == 'test'
125
    assert open('%s/assets/test2.png' % path, 'r').read() == 'foo'
122
    assert open('%s/assets/test.png' % path).read() == 'test'
123
    assert open('%s/assets/test2.png' % path).read() == 'foo'
126 124
    clean_assets_files()
127 125

  
128 126

  
......
143 141
    fd = open(filename, 'rb')
144 142
    import_assets(fd, overwrite=True)
145 143
    assert count_asset_files() == 2
146
    assert open('%s/assets/test.png' % path, 'r').read() == 'test'
147
    assert open('%s/assets/test2.png' % path, 'r').read() == 'test2'
144
    assert open('%s/assets/test.png' % path).read() == 'test'
145
    assert open('%s/assets/test2.png' % path).read() == 'test2'
148 146
    clean_assets_files()
149 147
    assert count_asset_files() == 0
150 148
    clean_assets_files()
tests/test_calendar.py
1 1
import datetime
2 2
import json
3
from unittest import mock
3 4

  
4
import mock
5 5
import pytest
6 6
from django.contrib.auth.models import User
7 7
from django.core.cache import cache
tests/test_cells.py
2 2
import json
3 3
import os
4 4
import re
5
from unittest import mock
5 6

  
6
import mock
7 7
import pytest
8 8
import requests
9 9
from django.apps import apps
......
81 81
    cells = [TextCelleWithMedia() for i in range(3)]
82 82
    assert (
83 83
        force_text(sum((cell.media for cell in cells), Media()))
84
        == u'<script type="text/javascript" src="/static/coincoin.js"></script>'
84
        == '<script type="text/javascript" src="/static/coincoin.js"></script>'
85 85
    )
86 86

  
87 87

  
......
1340 1340
    assert Page.objects.get(id=page.id).related_cells['cell_types'] == ['data_textcell']
1341 1341

  
1342 1342
    LinkCell(page=page, placeholder='content', order=0, title='Test', url='http://example.net').save()
1343
    assert set(Page.objects.get(id=page.id).related_cells['cell_types']) == set(
1344
        ['data_textcell', 'data_linkcell']
1345
    )
1343
    assert set(Page.objects.get(id=page.id).related_cells['cell_types']) == {'data_textcell', 'data_linkcell'}
1346 1344

  
1347 1345
    with CaptureQueriesContext(connection) as ctx:
1348 1346
        assert len(CellBase.get_cells(page=Page.objects.get(id=page.id))) == 3
1349 1347
        assert len(ctx.captured_queries) == 1 + 2
1350 1348

  
1351 1349
    TextCell.objects.get(order=1).delete()
1352
    assert set(Page.objects.get(id=page.id).related_cells['cell_types']) == set(
1353
        ['data_textcell', 'data_linkcell']
1354
    )
1350
    assert set(Page.objects.get(id=page.id).related_cells['cell_types']) == {'data_textcell', 'data_linkcell'}
1355 1351

  
1356 1352
    TextCell.objects.get(order=0).delete()
1357
    assert set(Page.objects.get(id=page.id).related_cells['cell_types']) == set(['data_linkcell'])
1353
    assert set(Page.objects.get(id=page.id).related_cells['cell_types']) == {'data_linkcell'}
1358 1354

  
1359 1355
    with CaptureQueriesContext(connection) as ctx:
1360 1356
        assert len(CellBase.get_cells(page=Page.objects.get(id=page.id))) == 1
......
1371 1367
    Page.objects.get(id=page.id).get_cells()
1372 1368

  
1373 1369
    TextCell(page=page, placeholder='content', order=0, text='hello').save()
1374
    assert set(Page.objects.get(id=page.id).related_cells['cell_types']) == set(
1375
        ['data_textcell', 'data_linkcell']
1376
    )
1370
    assert set(Page.objects.get(id=page.id).related_cells['cell_types']) == {'data_textcell', 'data_linkcell'}
1377 1371

  
1378 1372

  
1379 1373
def test_link_list_cell_duplicate():
......
1475 1469
    # only text cells are defined for assets
1476 1470
    settings.COMBO_CELL_ASSET_SLOTS = {'data_textcell': {'picture': {'prefix': 'Picture'}}}
1477 1471
    resp = app.get('/manage/assets/')
1478
    assert u'Picture — %s' % text_cell.get_label_for_asset() in resp.text
1479
    assert u'Picture — %s' % list_cell.get_label_for_asset() not in resp.text
1480
    assert u'Picture — %s' % item.get_label_for_asset() not in resp.text
1472
    assert 'Picture — %s' % text_cell.get_label_for_asset() in resp.text
1473
    assert 'Picture — %s' % list_cell.get_label_for_asset() not in resp.text
1474
    assert 'Picture — %s' % item.get_label_for_asset() not in resp.text
1481 1475

  
1482 1476
    # text and list link cells are defined for assets
1483 1477
    settings.COMBO_CELL_ASSET_SLOTS = {
......
1486 1480
        'data_linkcell': {'picture': {'prefix': 'Picture', 'suffix': 'test'}},
1487 1481
    }
1488 1482
    resp = app.get('/manage/assets/')
1489
    assert u'Picture — %s' % text_cell.get_label_for_asset() in resp.text
1490
    assert u'Picture — %s' % list_cell.get_label_for_asset() in resp.text
1483
    assert 'Picture — %s' % text_cell.get_label_for_asset() in resp.text
1484
    assert 'Picture — %s' % list_cell.get_label_for_asset() in resp.text
1491 1485
    # but items are excluded
1492 1486
    assert item.get_slug_for_asset() is None  # slug for asset is always None for items
1493
    assert u'Picture — %s' % item.get_label_for_asset() not in resp.text
1487
    assert 'Picture — %s' % item.get_label_for_asset() not in resp.text
1494 1488

  
1495 1489
    # test slugs
1496 1490
    link_cell = LinkCell.objects.create(
......
1500 1494
    )
1501 1495
    resp = app.get('/manage/assets/')
1502 1496
    assert link_cell.get_slug_for_asset() == ''
1503
    assert u'Picture — %s' % link_cell.get_label_for_asset() not in resp.text
1497
    assert 'Picture — %s' % link_cell.get_label_for_asset() not in resp.text
1504 1498

  
1505 1499
    link_cell.slug = 'foo'
1506 1500
    link_cell.save()
1507 1501
    resp = app.get('/manage/assets/')
1508 1502
    assert link_cell.get_slug_for_asset() == 'foo'
1509
    assert u'Picture — %s (test)' % link_cell.get_label_for_asset() in resp.text
1503
    assert 'Picture — %s (test)' % link_cell.get_label_for_asset() in resp.text
1510 1504

  
1511 1505
    link_cell.slug = ''
1512 1506
    link_cell.url = ''
......
1514 1508
    link_cell.save()
1515 1509
    resp = app.get('/manage/assets/')
1516 1510
    assert link_cell.get_slug_for_asset() == 'test_cell_assets'
1517
    assert u'Picture — %s (test)' % link_cell.get_label_for_asset() in resp.text
1511
    assert 'Picture — %s (test)' % link_cell.get_label_for_asset() in resp.text
tests/test_cron.py
1
import mock
1
from unittest import mock
2

  
2 3
import pytest
3 4
from django.core.management import call_command
4 5
from django.core.management.base import CommandError
tests/test_dashboard.py
1 1
import datetime
2 2
import json
3 3
import os
4
from unittest import mock
4 5

  
5
import mock
6 6
import pytest
7 7
from django.apps import apps
8 8
from django.conf import settings
tests/test_dataviz.py
1 1
import json
2 2
import urllib.parse
3 3
from datetime import date, timedelta
4
from unittest import mock
4 5

  
5
import mock
6 6
import pytest
7 7
from django.apps import apps
8 8
from django.contrib.auth.models import Group, User
......
485 485
    assert chart.__class__.__name__ == 'Pie'
486 486
    assert chart.x_labels == ['web', 'mail', 'phone', 'email']
487 487
    assert chart.raw_series == [
488
        ([222], {'title': u'web'}),
489
        ([134], {'title': u'mail'}),
490
        ([53], {'title': u'email'}),
488
        ([222], {'title': 'web'}),
489
        ([134], {'title': 'mail'}),
490
        ([53], {'title': 'email'}),
491 491
    ]
492 492

  
493 493
    # data in Y
......
507 507
    chart = cell.get_chart()
508 508
    assert chart.x_labels == ['web', 'mail', 'phone', 'email']
509 509
    assert chart.raw_series == [
510
        ([222, 134, 0, 53], {'title': u'foo'}),
511
        ([122, 114, 2, 33], {'title': u'bar'}),
510
        ([222, 134, 0, 53], {'title': 'foo'}),
511
        ([122, 114, 2, 33], {'title': 'bar'}),
512 512
    ]
513 513

  
514 514
    # stacked bar with percent
......
518 518
    chart = cell.get_chart()
519 519
    assert chart.x_labels == ['web', 'mail', 'phone', 'email']
520 520
    assert chart.raw_series == [
521
        ([64.5, 54, 0, 61.6], {'title': u'foo'}),
522
        ([35.5, 46, 100, 38.4], {'title': u'bar'}),
521
        ([64.5, 54, 0, 61.6], {'title': 'foo'}),
522
        ([35.5, 46, 100, 38.4], {'title': 'bar'}),
523 523
    ]
524 524
    assert all(x + y == 100 for x, y in zip(chart.raw_series[0][0], chart.raw_series[1][0]))
525 525

  
......
538 538
    chart = cell.get_chart()
539 539
    assert chart.x_labels == ['web', 'mail', 'phone', 'email']
540 540
    assert chart.raw_series == [
541
        ([222, 134, 0, 53], {'title': u'foo'}),
542
        ([122, 114, 2, 33], {'title': u'bar'}),
541
        ([222, 134, 0, 53], {'title': 'foo'}),
542
        ([122, 114, 2, 33], {'title': 'bar'}),
543 543
    ]
544 544

  
545 545
    # loop/Y
......
548 548
    chart = cell.get_chart()
549 549
    assert chart.x_labels == ['web', 'mail', 'phone', 'email']
550 550
    assert chart.raw_series == [
551
        ([222, 134, 0, 53], {'title': u'foo'}),
552
        ([122, 114, 2, 33], {'title': u'bar'}),
551
        ([222, 134, 0, 53], {'title': 'foo'}),
552
        ([122, 114, 2, 33], {'title': 'bar'}),
553 553
    ]
554 554

  
555 555
    # loop/X/Y
......
669 669
    assert chart.__class__.__name__ == 'Pie'
670 670
    assert chart.x_labels == ['web', 'mail', 'email']
671 671
    assert chart.raw_series == [
672
        ([222], {'title': u'web'}),
673
        ([134], {'title': u'mail'}),
674
        ([53], {'title': u'email'}),
672
        ([222], {'title': 'web'}),
673
        ([134], {'title': 'mail'}),
674
        ([53], {'title': 'email'}),
675 675
    ]
676 676

  
677 677
    # data in Y
......
691 691
    chart = cell.get_chart()
692 692
    assert chart.x_labels == ['web', 'mail', 'phone', 'email']
693 693
    assert chart.raw_series == [
694
        ([222, 134, 0, 53], {'title': u'foo'}),
695
        ([122, 114, 2, 33], {'title': u'bar'}),
694
        ([222, 134, 0, 53], {'title': 'foo'}),
695
        ([122, 114, 2, 33], {'title': 'bar'}),
696 696
    ]
697 697

  
698 698
    # single data point
......
710 710
    chart = cell.get_chart()
711 711
    assert chart.x_labels == ['web', 'mail', 'phone', 'email']
712 712
    assert chart.raw_series == [
713
        ([222, 134, 0, 53], {'title': u'foo'}),
714
        ([122, 114, 2, 33], {'title': u'bar'}),
713
        ([222, 134, 0, 53], {'title': 'foo'}),
714
        ([122, 114, 2, 33], {'title': 'bar'}),
715 715
    ]
716 716

  
717 717
    # loop/Y
......
720 720
    chart = cell.get_chart()
721 721
    assert chart.x_labels == ['web', 'mail', 'phone', 'email']
722 722
    assert chart.raw_series == [
723
        ([222, 134, 0, 53], {'title': u'foo'}),
724
        ([122, 114, 2, 33], {'title': u'bar'}),
723
        ([222, 134, 0, 53], {'title': 'foo'}),
724
        ([122, 114, 2, 33], {'title': 'bar'}),
725 725
    ]
726 726

  
727 727
    # all null
......
779 779
    assert chart.__class__.__name__ == 'Pie'
780 780
    assert chart.x_labels == ['email', 'mail', 'phone', 'web']
781 781
    assert chart.raw_series == [
782
        ([53], {'title': u'email'}),
783
        ([134], {'title': u'mail'}),
784
        ([222], {'title': u'web'}),
782
        ([53], {'title': 'email'}),
783
        ([134], {'title': 'mail'}),
784
        ([222], {'title': 'web'}),
785 785
    ]
786 786

  
787 787
    # data in Y
......
801 801
    chart = cell.get_chart()
802 802
    assert chart.x_labels == ['web', 'mail', 'phone', 'email']
803 803
    assert chart.raw_series == [
804
        ([222, 134, 0, 53], {'title': u'foo'}),
805
        ([122, 114, 2, 33], {'title': u'bar'}),
804
        ([222, 134, 0, 53], {'title': 'foo'}),
805
        ([122, 114, 2, 33], {'title': 'bar'}),
806 806
    ]
807 807

  
808 808
    # single data point
......
820 820
    chart = cell.get_chart()
821 821
    assert chart.x_labels == ['web', 'mail', 'phone', 'email']
822 822
    assert chart.raw_series == [
823
        ([222, 134, 0, 53], {'title': u'foo'}),
824
        ([122, 114, 2, 33], {'title': u'bar'}),
823
        ([222, 134, 0, 53], {'title': 'foo'}),
824
        ([122, 114, 2, 33], {'title': 'bar'}),
825 825
    ]
826 826

  
827 827
    # loop/Y
......
830 830
    chart = cell.get_chart()
831 831
    assert chart.x_labels == ['web', 'mail', 'phone', 'email']
832 832
    assert chart.raw_series == [
833
        ([222, 134, 0, 53], {'title': u'foo'}),
834
        ([122, 114, 2, 33], {'title': u'bar'}),
833
        ([222, 134, 0, 53], {'title': 'foo'}),
834
        ([122, 114, 2, 33], {'title': 'bar'}),
835 835
    ]
836 836

  
837 837
    # empty data
......
871 871
    assert chart.__class__.__name__ == 'Pie'
872 872
    assert chart.x_labels == ['web', 'mail', 'email', 'phone']
873 873
    assert chart.raw_series == [
874
        ([222], {'title': u'web'}),
875
        ([134], {'title': u'mail'}),
876
        ([53], {'title': u'email'}),
874
        ([222], {'title': 'web'}),
875
        ([134], {'title': 'mail'}),
876
        ([53], {'title': 'email'}),
877 877
    ]
878 878

  
879 879
    # data in Y
......
893 893
    chart = cell.get_chart()
894 894
    assert chart.x_labels == ['web', 'mail', 'phone', 'email']
895 895
    assert chart.raw_series == [
896
        ([222, 134, 0, 53], {'title': u'foo'}),
897
        ([122, 114, 2, 33], {'title': u'bar'}),
896
        ([222, 134, 0, 53], {'title': 'foo'}),
897
        ([122, 114, 2, 33], {'title': 'bar'}),
898 898
    ]
899 899

  
900 900
    # single data point
......
912 912
    chart = cell.get_chart()
913 913
    assert chart.x_labels == ['web', 'mail', 'phone', 'email']
914 914
    assert chart.raw_series == [
915
        ([222, 134, 0, 53], {'title': u'foo'}),
916
        ([122, 114, 2, 33], {'title': u'bar'}),
915
        ([222, 134, 0, 53], {'title': 'foo'}),
916
        ([122, 114, 2, 33], {'title': 'bar'}),
917 917
    ]
918 918

  
919 919
    # loop/Y
......
922 922
    chart = cell.get_chart()
923 923
    assert chart.x_labels == ['web', 'mail', 'phone', 'email']
924 924
    assert chart.raw_series == [
925
        ([222, 134, 0, 53], {'title': u'foo'}),
926
        ([122, 114, 2, 33], {'title': u'bar'}),
925
        ([222, 134, 0, 53], {'title': 'foo'}),
926
        ([122, 114, 2, 33], {'title': 'bar'}),
927 927
    ]
928 928

  
929 929
    # empty data
tests/test_ensure_jsonbfields.py
1
# -*- coding: utf-8 -*-
2

  
3 1
import pytest
4 2
from django.core.management import call_command
5 3
from django.db import connection
tests/test_fargo.py
1 1
import json
2 2
import re
3
from unittest import mock
3 4

  
4
import mock
5 5
import pytest
6 6
from django.test import override_settings
7 7

  
tests/test_gallery_cell.py
1
# -*- coding: utf-8 -*-
2 1
import os
3 2

  
4 3
import pytest
tests/test_lingo_cells.py
1
# -*- coding: utf-8 -*-
2

  
3 1
import eopayment
4 2
import pytest
5 3
from django.contrib.auth.models import User
......
88 86
    item_anonymous.save()
89 87

  
90 88
    assert cell.is_relevant(context) is True
91
    assert cell.get_badge(context) == {'badge': u'12345€'}
89
    assert cell.get_badge(context) == {'badge': '12345€'}
92 90

  
93 91
    item.cancellation_date = timezone.now()
94 92
    item.save()
......
103 101

  
104 102
    item.amount = 123.45
105 103
    item.save()
106
    assert cell.get_badge(context) == {'badge': u'123.45€'}
104
    assert cell.get_badge(context) == {'badge': '123.45€'}
107 105

  
108 106

  
109 107
def test_basket_cell_can_pay_only_one_basket_item(regie, user):
tests/test_lingo_manager.py
1
# -*- coding: utf-8 -*-
2

  
3 1
import datetime
4 2
from decimal import Decimal
3
from unittest import mock
5 4

  
6 5
import eopayment
7
import mock
8 6
import pytest
9 7
from django.contrib.auth.models import User
10 8
from django.db import connection
......
172 170
    test_add_regie(app, admin_user, payment_backend)
173 171
    regie = Regie.objects.filter(slug='test')[0]
174 172
    user = User.objects.create_user('dimebag', 'dime@bag.pan', 'pwd')
175
    user.last_name = u'Darëll'
173
    user.last_name = 'Darëll'
176 174
    user.first_name = 'Dimebag'
177 175
    user.save()
178 176

  
tests/test_lingo_payment.py
3 3
from contextlib import contextmanager
4 4
from datetime import datetime, timedelta
5 5
from decimal import Decimal
6
from unittest import mock
6 7

  
7 8
import eopayment
8 9
import httmock
9
import mock
10 10
import pytest
11 11
from django.apps import apps
12 12
from django.conf import settings
......
728 728
        url = sign_url(url, key)
729 729
        data = {'basket_item_id': basket_item_id, 'notify': 'true'}
730 730
        resp = app.post_json(url, params=data)
731
        assert request.call_args[0] == ('POST', u'http://example.com/jump/trigger/cancelled')
731
        assert request.call_args[0] == ('POST', 'http://example.com/jump/trigger/cancelled')
732 732
        assert not BasketItem.objects.filter(amount=42, cancellation_date__isnull=True).exists()
733 733
        assert BasketItem.objects.filter(amount=21, cancellation_date__isnull=True).exists()
734 734

  
tests/test_lingo_remote_regie.py
1
# -*- coding: utf-8 -*-
2

  
3 1
import copy
4 2
import json
5 3
from decimal import Decimal
4
from unittest import mock
6 5

  
7 6
import eopayment
8 7
import httmock
9
import mock
10 8
import pytest
11 9
from django.apps import apps
12 10
from django.conf import settings
......
108 106
    return regie
109 107

  
110 108

  
111
class MockUser(object):
109
class MockUser:
112 110
    email = 'foo@example.net'
113 111
    is_authenticated = True
114 112

  
......
739 737
    assert len(mailoutbox) == 1
740 738
    assert mailoutbox[0].recipients() == ['foo@example.net']
741 739
    assert mailoutbox[0].from_email == settings.DEFAULT_FROM_EMAIL
742
    assert mailoutbox[0].subject == u'Nouvelle facture numéro 01 disponible'
740
    assert mailoutbox[0].subject == 'Nouvelle facture numéro 01 disponible'
743 741
    html_message = mailoutbox[0].alternatives[0][0]
744 742
    assert 'http://localhost' in mailoutbox[0].body
745 743
    assert 'http://localhost' in html_message
tests/test_manager.py
4 4
import os
5 5
import re
6 6
import shutil
7
from unittest import mock
7 8

  
8
import mock
9 9
import pytest
10 10
from django.conf import settings
11 11
from django.contrib.auth.models import Group
......
893 893
    with CaptureQueriesContext(connection) as ctx:
894 894
        resp = resp.form.submit()
895 895
        assert len(ctx.captured_queries) == 272
896
    assert set(Page.objects.get(slug='one').related_cells['cell_types']) == set(
897
        ['data_textcell', 'data_linkcell']
898
    )
896
    assert set(Page.objects.get(slug='one').related_cells['cell_types']) == {'data_textcell', 'data_linkcell'}
899 897
    assert Page.objects.count() == 4
900 898
    assert LinkCell.objects.count() == 2
901 899
    assert LinkCell.objects.get(page__slug='one').link_page.slug == 'two'
......
934 932
    cell.save()
935 933
    Asset(key='collectivity:banner', asset=File(BytesIO(b'test'), 'test.png')).save()
936 934
    path = default_storage.path('')
937
    assert open('%s/assets/test.png' % path, 'r').read() == 'test'
935
    assert open('%s/assets/test.png' % path).read() == 'test'
938 936

  
939 937
    app = login(app)
940 938
    resp = app.get('/manage/')
......
959 957
    assert PageSnapshot.objects.all().count() == 1
960 958
    assert TextCell.objects.count() == 1
961 959
    assert Asset.objects.filter(key='collectivity:banner').count() == 1
962
    assert open('%s/assets/test.png' % path, 'r').read() == 'foo'
960
    assert open('%s/assets/test.png' % path).read() == 'foo'
963 961

  
964 962
    os.remove('%s/assets/test.png' % path)
965 963
    app = login(app)
......
967 965
    resp = resp.click('Import Site')
968 966
    resp.form['site_file'] = Upload('site-export.json', site_export, 'application/json')
969 967
    resp = resp.form.submit()
970
    assert open('%s/assets/test.png' % path, 'r').read() == 'test'
968
    assert open('%s/assets/test.png' % path).read() == 'test'
971 969

  
972 970

  
973 971
def test_site_export_import_missing_group(app, admin_user):
......
1070 1068
    cell.mark_as_invalid('foo_bar_reason')
1071 1069
    resp = app.get('/manage/cells/invalid-report/')
1072 1070
    assert resp.context['object_list'] == [cell]
1073
    assert '<a href="/manage/pages/{}/">{}</a>'.format(page.pk, page.title) in resp.text
1071
    assert f'<a href="/manage/pages/{page.pk}/">{page.title}</a>' in resp.text
1074 1072
    assert (
1075
        '<a href="/manage/pages/{}/#cell-{}">{}</a>'.format(page.pk, cell.get_reference(), cell.get_label())
1076
        in resp.text
1073
        f'<a href="/manage/pages/{page.pk}/#cell-{cell.get_reference()}">{cell.get_label()}</a>' in resp.text
1077 1074
    )
1078 1075

  
1079 1076
    # cells from snapshot are not reported
......
1210 1207
}
1211 1208

  
1212 1209

  
1213
class SearchServices(object):
1210
class SearchServices:
1214 1211
    def __init__(self, search_services):
1215 1212
        self.search_services = search_services
1216 1213

  
......
1441 1438
        resp = app.get('/manage/pages/%s/' % page.id)
1442 1439
        resp.form['cdata_textcell-%s-text' % cells[0].id].value = 'Hello : World'
1443 1440
        resp = resp.form.submit()
1444
        assert TextCell.objects.get(id=cells[0].id).text == u'Hello\u00a0: World'
1441
        assert TextCell.objects.get(id=cells[0].id).text == 'Hello\u00a0: World'
1445 1442

  
1446 1443

  
1447 1444
def test_edit_json_cell(app, admin_user):
......
2045 2042
    resp = resp.click('Import')
2046 2043
    resp.form['assets_file'] = Upload('test.tar', content)
2047 2044
    resp = resp.form.submit()
2048
    assert sum([len(x[2]) for x in os.walk(default_storage.path(''))]) == 2
2045
    assert sum(len(x[2]) for x in os.walk(default_storage.path(''))) == 2
2049 2046
    resp = resp.follow()
2050 2047
    assert 'The assets file has been imported.' in resp.text
2051 2048

  
......
2084 2081
    resp = resp.click('Import')
2085 2082
    resp.form['assets_file'] = Upload('test.tar', b'garbage')
2086 2083
    resp = resp.form.submit()
2087
    assert sum([len(x[2]) for x in os.walk(default_storage.path(''))]) == 0
2084
    assert sum(len(x[2]) for x in os.walk(default_storage.path(''))) == 0
2088 2085
    resp = resp.follow()
2089 2086
    assert 'The assets file is not valid.' in resp.text
2090 2087

  
tests/test_maps_cells.py
1
# -*- coding: utf-8 -*-
2 1
import json
2
from unittest import mock
3 3

  
4
import mock
5 4
import pytest
6 5
from django.conf import settings
7 6
from django.contrib.auth.models import Group, User
tests/test_maps_manager.py
1
# -*- coding: utf-8 -*-
1
from unittest import mock
2 2

  
3
import mock
4 3
import pytest
5 4

  
6 5
from combo.apps.maps.models import Map, MapLayer, MapLayerOptions
......
176 175

  
177 176
    app = login(app)
178 177
    resp = app.get('/manage/maps/', status=200)
179
    assert '/manage/pages/{}/#cell-{}'.format(page.pk, map1.get_reference()) in resp.text
180
    assert '/manage/pages/{}/#cell-{}'.format(page.pk, map2.get_reference()) in resp.text
178
    assert f'/manage/pages/{page.pk}/#cell-{map1.get_reference()}' in resp.text
179
    assert f'/manage/pages/{page.pk}/#cell-{map2.get_reference()}' in resp.text
181 180

  
182 181

  
183 182
@mock.patch('combo.apps.maps.models.requests.get')
tests/test_notification.py
1 1
import json
2 2
from datetime import timedelta as timedelta
3 3
from decimal import Decimal
4
from unittest import mock
4 5

  
5
import mock
6 6
import pytest
7 7
from django.contrib.auth.models import User
8 8
from django.test import Client
......
143 143

  
144 144
    app = login_app(app, username='jane.doe', password='jane.doe')
145 145
    resp = app.get('/api/menu-badges/?page[]=%s' % page.id)
146
    assert resp.json == {'{}'.format(page.id): {'badge': '1'}}
146
    assert resp.json == {f'{page.id}': {'badge': '1'}}
147 147

  
148 148

  
149 149
def test_notification_ws(john_doe):
tests/test_pages.py
18 18

  
19 19
def test_page_order():
20 20
    page = Page()
21
    page.title = u'foo'
21
    page.title = 'foo'
22 22
    page.save()
23 23
    page2 = Page()
24
    page2.title = u'bar'
24
    page2.title = 'bar'
25 25
    page2.save()
26 26

  
27 27
    assert Page.objects.get(id=page.id).order < Page.objects.get(id=page2.id).order
......
29 29

  
30 30
def test_page_url():
31 31
    page = Page()
32
    page.slug = u'foo'
32
    page.slug = 'foo'
33 33
    page.save()
34 34
    assert page.get_online_url() == '/foo/'
35 35
    page2 = Page()
......
147 147

  
148 148

  
149 149
def test_import_export_pages():
150
    page = Page(title=u'foo', slug='foo', order=0, description="Foo's page")
150
    page = Page(title='foo', slug='foo', order=0, description="Foo's page")
151 151
    page.save()
152 152

  
153 153
    cell = TextCell(page=page, text='foo', order=0, placeholder='content')
154 154
    cell.save()
155 155

  
156
    page2 = Page(title=u'bar', slug='bar', order=1, parent=page, description="Bar's page")
156
    page2 = Page(title='bar', slug='bar', order=1, parent=page, description="Bar's page")
157 157
    page2.save()
158 158

  
159 159
    cell = TextCell(page=page2, text='bar', order=0, placeholder='content')
......
177 177

  
178 178

  
179 179
def test_import_export_pages_with_links():
180
    page = Page(title=u'foo', slug='foo', order=0)
180
    page = Page(title='foo', slug='foo', order=0)
181 181
    page.save()
182 182

  
183
    page2 = Page(title=u'bar', slug='bar', order=1)
183
    page2 = Page(title='bar', slug='bar', order=1)
184 184
    page2.save()
185 185

  
186 186
    cell = LinkCell(page=page, title='bar', placeholder='content', link_page=page2, order=1)
......
328 328

  
329 329

  
330 330
def test_import_export_management_commands():
331
    page = Page(title=u'foo', slug='foo', order=0)
331
    page = Page(title='foo', slug='foo', order=0)
332 332
    page.save()
333 333

  
334 334
    cell = TextCell(page=page, text='foo', order=0, placeholder='content')
335 335
    cell.save()
336 336

  
337
    page2 = Page(title=u'bar', slug='bar', order=1, parent=page)
337
    page2 = Page(title='bar', slug='bar', order=1, parent=page)
338 338
    page2.save()
339 339

  
340 340
    cell = TextCell(page=page2, text='bar', order=0, placeholder='content')
......
372 372

  
373 373

  
374 374
def test_get_placeholders():
375
    page = Page(title=u'foo', slug='foo', template_name='standard-sidebar', order=0)
375
    page = Page(title='foo', slug='foo', template_name='standard-sidebar', order=0)
376 376
    request = RequestFactory().get('/')
377 377
    placeholders = page.get_placeholders(request=request)
378 378
    assert [x.key for x in placeholders] == ['content', 'sidebar', 'footer']
......
394 394
        }
395 395
    ):
396 396
        placeholders = page.get_placeholders(request=request)
397
        assert set([x.key for x in placeholders]) == set(['content', 'content2', 'sidebar', 'footer'])
397
        assert {x.key for x in placeholders} == {'content', 'content2', 'sidebar', 'footer'}
398 398
        footer_placeholder = [x for x in placeholders if x.key == 'footer'][0]
399 399
        assert footer_placeholder.acquired is False
400 400

  
401 401

  
402 402
def test_render(app):
403 403
    page = Page(
404
        title=u'foo', slug='foo', template_name='standard-sidebar', order=0, description="page description"
404
        title='foo', slug='foo', template_name='standard-sidebar', order=0, description="page description"
405 405
    )
406 406
    page.save()
407 407
    response = app.get(page.get_online_url())
......
411 411

  
412 412
def test_render_cell_having_href_template_error(app):
413 413
    page = Page(
414
        title=u'foo', slug='foo', template_name='standard-sidebar', order=0, description="page description"
414
        title='foo', slug='foo', template_name='standard-sidebar', order=0, description="page description"
415 415
    )
416 416
    page.save()
417 417
    cell = TextCell(
tests/test_profile.py
1 1
import datetime
2 2
import json
3
from unittest import mock
3 4

  
4
import mock
5 5
import pytest
6 6
from django.test import override_settings
7 7

  
tests/test_public.py
2 2
import json
3 3
import os
4 4
import re
5
from unittest import mock
5 6

  
6
import mock
7 7
import pytest
8 8
from django.conf import settings
9 9
from django.contrib.auth.models import Group, User
......
980 980

  
981 981

  
982 982
def test_synchronous_placeholder(app):
983
    page = Page(title=u'foo', slug='foo', template_name='standard', order=0)
983
    page = Page(title='foo', slug='foo', template_name='standard', order=0)
984 984
    page.save()
985 985
    cell = FeedCell(page=page, placeholder='content', url='http://example.net', order=1)
986 986
    cell.save()
tests/test_publik.py
27 27
    return user
28 28

  
29 29

  
30
class KnownServices(object):
30
class KnownServices:
31 31
    def __init__(self, known_services):
32 32
        self.known_services = known_services
33 33
        self.orig_value = settings.KNOWN_SERVICES
tests/test_pwa.py
1 1
import base64
2 2
import os
3
from unittest import mock
3 4

  
4
import mock
5 5
import pytest
6 6
import pywebpush
7 7
from django.conf import settings
tests/test_requests.py
1
# -*- coding: utf-8 -*-
1
from unittest import mock
2 2

  
3
import mock
4 3
import pytest
5 4
from django.contrib.auth.models import AnonymousUser
6 5
from django.utils.six.moves.urllib import parse as urlparse
......
8 7
from combo.utils import NothingInCacheException, check_query, requests
9 8

  
10 9

  
11
class MockUser(object):
10
class MockUser:
12 11
    email = 'foo@example.net'
13 12
    is_authenticated = True
14 13

  
......
150 149
            requests.get('http://cache.example.org/other', raise_if_not_cached=True)
151 150

  
152 151
        # check with unicode url
153
        assert requests.get(u'http://cache.example.org/éléphant').content == b'hello second world'
152
        assert requests.get('http://cache.example.org/éléphant').content == b'hello second world'
tests/test_search.py
1 1
import datetime
2 2
import json
3 3
import os
4
from unittest import mock
4 5

  
5
import mock
6 6
import pytest
7 7
from django.conf import settings
8 8
from django.contrib.auth.models import AnonymousUser, Group, User
......
46 46
TEMPLATE_VARS = {'search_url': 'http://search.example.net/'}
47 47

  
48 48

  
49
class SearchServices(object):
49
class SearchServices:
50 50
    def __init__(self, search_services):
51 51
        self.search_services = search_services
52 52

  
......
893 893
        mock_resp = Response()
894 894
        mock_resp.status_code = 500
895 895
        requests_get.return_value = mock_resp
896
        assert set(engines.get_engines().keys()) == set(['tracking-code', 'formdata:c21f969b', '_text'])
896
        assert set(engines.get_engines().keys()) == {'tracking-code', 'formdata:c21f969b', '_text'}
897 897
    with mock.patch('combo.apps.wcs.utils.requests.get') as requests_get:
898 898
        requests_get.side_effect = ConnectionError()
899
        assert set(engines.get_engines().keys()) == set(['tracking-code', 'formdata:c21f969b', '_text'])
899
        assert set(engines.get_engines().keys()) == {'tracking-code', 'formdata:c21f969b', '_text'}
900 900
    with mock.patch('combo.apps.wcs.utils.requests.get') as requests_get:
901 901
        mock_resp = Response()
902 902
        mock_resp.status_code = 404
903 903
        requests_get.return_value = mock_resp
904
        assert set(engines.get_engines().keys()) == set(['tracking-code', 'formdata:c21f969b', '_text'])
904
        assert set(engines.get_engines().keys()) == {'tracking-code', 'formdata:c21f969b', '_text'}
905 905

  
906 906

  
907 907
@mock.patch('combo.apps.wcs.utils.get_wcs_json')
......
1429 1429
    # Check that title matching gets precedence over content matching
1430 1430
    assert len(hits) == 2
1431 1431
    assert hits[0]['text'] == page_of_interest.title
1432
    assert hits[0]['url'] == '/{}/'.format(page_of_interest.slug)
1432
    assert hits[0]['url'] == f'/{page_of_interest.slug}/'
1433 1433
    assert hits[0]['rank'] > hits[1]['rank']
tests/test_spooler.py
1 1
import importlib
2 2
import pickle
3 3
import sys
4
from unittest import mock
4 5

  
5
import mock
6 6
import pytest
7 7

  
8 8
from combo.utils import spooler
tests/test_utils.py
9 9
from combo.utils import TemplateError, aes_hex_decrypt, aes_hex_encrypt, get_templated_url
10 10

  
11 11

  
12
class MockUser(object):
12
class MockUser:
13 13
    email = 'foo=3@example.net'
14 14
    is_authenticated = True
15 15

  
tests/test_wcs.py
1
# -*- coding: utf-8 -*-
2

  
3 1
import copy
4 2
import json
5 3
import re
4
from unittest import mock
6 5

  
7
import mock
8 6
import pytest
9 7
from django.apps import apps
10 8
from django.conf import settings
......
223 221
}
224 222

  
225 223

  
226
class MockUser(object):
224
class MockUser:
227 225
    email = 'foo@example.net'
228 226
    is_authenticated = True
229 227
    is_anonymous = False
......
232 230
        return None
233 231

  
234 232

  
235
class MockUserWithNameId(object):
233
class MockUserWithNameId:
236 234
    email = 'foo@example.net'
237 235
    is_authenticated = True
238 236
    is_anonymous = False
......
307 305
    form_class = cell.get_default_form_class()
308 306
    form = form_class()
309 307
    assert form.fields['formdef_reference'].widget.choices == [
310
        (u'default:a-private-form', u'test : a private form'),
311
        (u'default:a-second-form-title', u'test : a second form title'),
312
        (u'default:form-title', u'test : form title'),
313
        (u'default:third-form-title', u'test : Third form title'),
314
        (u'other:a-private-form', u'test2 : a private form'),
315
        (u'other:a-second-form-title', u'test2 : a second form title'),
316
        (u'other:form-title', u'test2 : form title'),
317
        (u'other:third-form-title', u'test2 : Third form title'),
308
        ('default:a-private-form', 'test : a private form'),
309
        ('default:a-second-form-title', 'test : a second form title'),
310
        ('default:form-title', 'test : form title'),
311
        ('default:third-form-title', 'test : Third form title'),
312
        ('other:a-private-form', 'test2 : a private form'),
313
        ('other:a-second-form-title', 'test2 : a second form title'),
314
        ('other:form-title', 'test2 : form title'),
315
        ('other:third-form-title', 'test2 : Third form title'),
318 316
    ]
319 317

  
320 318

  
......
324 322
    page.save()
325 323
    cell = WcsFormCell(page=page, placeholder='content', order=0)
326 324
    assert cell.get_additional_label() is None
327
    cell.formdef_reference = u'default:form-title'
325
    cell.formdef_reference = 'default:form-title'
328 326
    cell.save()
329 327
    assert cell.cached_title == 'form title'
330 328
    assert cell.get_additional_label() == 'form title'
......
354 352
    assert validity_info.invalid_reason_code == 'wcs_form_not_defined'
355 353
    assert validity_info.invalid_since is not None
356 354

  
357
    cell.formdef_reference = u'default:form-title'
355
    cell.formdef_reference = 'default:form-title'
358 356
    cell.save()
359 357
    assert ValidityInfo.objects.exists() is False
360 358

  
......
378 376
        cell.save()
379 377
    assert ValidityInfo.objects.exists() is False
380 378

  
381
    cell.formdef_reference = u'default:foobar'
379
    cell.formdef_reference = 'default:foobar'
382 380
    cell.save()
383 381
    validity_info = ValidityInfo.objects.latest('pk')
384 382
    assert validity_info.invalid_reason_code == 'wcs_form_not_found'
......
390 388
    page = Page(title='xxx', slug='test_form_cell_save_cache', template_name='standard')
391 389
    page.save()
392 390
    cell = WcsFormCell(page=page, placeholder='content', order=0)
393
    cell.formdef_reference = u'default:form-title'
391
    cell.formdef_reference = 'default:form-title'
394 392
    cell.save()
395 393
    site_export = [page.get_serialized_page()]
396 394
    cell.delete()
......
409 407
    page.save()
410 408
    cell = WcsCategoryCell(page=page, placeholder='content', order=0)
411 409
    assert cell.get_additional_label() is None
412
    cell.category_reference = u'default:test-3'
410
    cell.category_reference = 'default:test-3'
413 411
    cell.save()
414 412
    assert cell.cached_title == 'Test 3'
415 413
    assert cell.get_additional_label() == 'Test 3'
......
423 421
    assert validity_info.invalid_reason_code == 'wcs_category_not_defined'
424 422
    assert validity_info.invalid_since is not None
425 423

  
426
    cell.category_reference = u'default:test-3'
424
    cell.category_reference = 'default:test-3'
427 425
    cell.save()
428 426
    assert ValidityInfo.objects.exists() is False
429 427

  
......
459 457
    page = Page(title='xxx', slug='test_form_cell_render', template_name='standard')
460 458
    page.save()
461 459
    cell = WcsFormCell(page=page, placeholder='content', order=0)
462
    cell.formdef_reference = u'default:form-title'
460
    cell.formdef_reference = 'default:form-title'
463 461
    cell.save()
464 462
    result = cell.render({})
465 463
    assert 'http://127.0.0.1:8999/form-title/tryauth' in result
......
473 471
    form = form_class()
474 472
    assert form.fields['wcs_site'].widget.choices == [
475 473
        ('', 'All'),
476
        (u'default', u'test'),
477
        (u'other', u'test2'),
474
        ('default', 'test'),
475
        ('other', 'test2'),
478 476
    ]
479 477
    assert 'current_forms' in form.fields
480 478
    assert cell.get_additional_label() == 'All Sites - Current Forms'
......
726 724
    form = form_class()
727 725
    assert form.fields['wcs_site'].widget.choices == [
728 726
        ('', 'All'),
729
        (u'default', u'test'),
730
        (u'other', u'test2'),
727
        ('default', 'test'),
728
        ('other', 'test2'),
731 729
    ]
732 730
    assert cell.get_additional_label() == 'All Sites'
733 731
    cell.wcs_site = 'default'
......
925 923
    form = form_class()
926 924
    assert form.fields['wcs_site'].widget.choices == [
927 925
        ('', 'All'),
928
        (u'default', u'test'),
929
        (u'other', u'test2'),
926
        ('default', 'test'),
927
        ('other', 'test2'),
930 928
    ]
931 929
    assert cell.get_additional_label() == 'All Sites'
932 930
    cell.wcs_site = 'default'
......
1094 1092
    form_class = cell.get_default_form_class()
1095 1093
    form = form_class()
1096 1094
    assert form.fields['category_reference'].widget.choices == [
1097
        (u'default:test-3', u'test : Test 3'),
1098
        (u'default:test-9', u'test : Test 9'),
1099
        (u'other:test-3', u'test2 : Test 3'),
1100
        (u'other:test-9', u'test2 : Test 9'),
1095
        ('default:test-3', 'test : Test 3'),
1096
        ('default:test-9', 'test : Test 9'),
1097
        ('other:test-3', 'test2 : Test 3'),
1098
        ('other:test-9', 'test2 : Test 9'),
1101 1099
    ]
1102 1100

  
1103 1101

  
......
1568 1566
def test_cards_cell_render(mock_send, context):
1569 1567
    page = Page.objects.create(title='xxx', template_name='standard')
1570 1568
    cell = WcsCardsCell(page=page, placeholder='content', order=0)
1571
    cell.carddef_reference = u'default:card_model_1'
1569
    cell.carddef_reference = 'default:card_model_1'
1572 1570
    cell.save()
1573 1571

  
1574 1572
    # query should fail as nothing is cached
......
1602 1600
    assert '<a href="/foo/12"><span class="card-title">bb</span></a>' in result
1603 1601
    assert '<a href="/foo/13"><span class="card-title">cc</span></a>' in result
1604 1602

  
1605
    cell.carddef_reference = u'default:card_model_1:foo'
1603
    cell.carddef_reference = 'default:card_model_1:foo'
1606 1604
    cell.save()
1607 1605
    page.sub_slug = 'card_model_1_id'
1608 1606
    page.save()
......
1666 1664
def test_cards_cell_render_user(mock_send, context, nocache):
1667 1665
    page = Page.objects.create(title='xxx', template_name='standard')
1668 1666
    cell = WcsCardsCell(page=page, placeholder='content', order=0)
1669
    cell.carddef_reference = u'default:card_model_1'
1667
    cell.carddef_reference = 'default:card_model_1'
1670 1668
    cell.save()
1671 1669

  
1672 1670
    context['card_model_1_id'] = 11
......
1869 1867
def test_card_cell_render(mock_send, context):
1870 1868
    page = Page.objects.create(title='xxx', template_name='standard')
1871 1869
    cell = WcsCardInfosCell(page=page, placeholder='content', order=0)
1872
    cell.carddef_reference = u'default:card_model_1'
1870
    cell.carddef_reference = 'default:card_model_1'
1873 1871
    cell.custom_title = 'Foo bar {{ card.fields.title }}'
1874 1872
    cell.save()
1875 1873

  
......
1934 1932
def test_card_cell_render_identifier(mock_send, context, nocache):
1935 1933
    page = Page.objects.create(title='xxx', template_name='standard')
1936 1934
    cell = WcsCardInfosCell(page=page, placeholder='content', order=0)
1937
    cell.carddef_reference = u'default:card_model_1'
1935
    cell.carddef_reference = 'default:card_model_1'
1938 1936
    cell.save()
1939 1937

  
1940 1938
    context['card_model_1_id'] = 11
......
1971 1969
def test_card_cell_render_user(mock_send, context, nocache):
1972 1970
    page = Page.objects.create(title='xxx', template_name='standard')
1973 1971
    cell = WcsCardInfosCell(page=page, placeholder='content', order=0)
1974
    cell.carddef_reference = u'default:card_model_1'
1972
    cell.carddef_reference = 'default:card_model_1'
1975 1973
    cell.save()
1976 1974

  
1977 1975
    context['card_model_1_id'] = 11
......
2031 2029
    assert requests_get.call_args_list[0][0][0] == '/api/code/FOOBAR'
2032 2030
    assert requests_get.call_args_list[1][0][0] == '/api/code/FOOBAR'
2033 2031
    remote_service_urls = [c[1]['remote_service']['url'] for c in requests_get.call_args_list]
2034
    assert set(remote_service_urls) == set(['http://127.0.0.1:8999/', 'http://127.0.0.2:8999/'])
2032
    assert set(remote_service_urls) == {'http://127.0.0.1:8999/', 'http://127.0.0.2:8999/'}
2035 2033
    assert resp.status_code == 302
2036 2034
    resp = resp.follow()
2037 2035
    assert '<li class="error">The tracking code could not been found.</li>' in resp.text
......
2130 2128
def test_cell_assets(mock_send, settings, app, admin_user):
2131 2129
    page = Page.objects.create(title='xxx', slug='test_cell_assets', template_name='standard')
2132 2130
    cell1 = WcsFormCell.objects.create(
2133
        page=page, placeholder='content', order=0, formdef_reference=u'default:form-title'
2131
        page=page, placeholder='content', order=0, formdef_reference='default:form-title'
2134 2132
    )
2135 2133

  
2136 2134
    cell2 = WcsFormsOfCategoryCell.objects.create(
......
2152 2150
        'wcs_wcsformsofcategorycell': {'logo': {'prefix': 'Logo blabla', 'suffix': 'test'}},
2153 2151
    }
2154 2152
    resp = app.get('/manage/assets/')
2155
    assert u'Logo — %s' % cell2.get_label_for_asset() in resp.text
2156
    assert u'Logo blabla — %s' % cell2.get_label_for_asset() not in resp.text
2157
    assert u'Picture — %s' % cell1.get_label_for_asset() in resp.text
2158
    assert u'Picture blabla — %s' % cell1.get_label_for_asset() not in resp.text
2153
    assert 'Logo — %s' % cell2.get_label_for_asset() in resp.text
2154
    assert 'Logo blabla — %s' % cell2.get_label_for_asset() not in resp.text
2155
    assert 'Picture — %s' % cell1.get_label_for_asset() in resp.text
2156
    assert 'Picture blabla — %s' % cell1.get_label_for_asset() not in resp.text
2159 2157
    # New settings
2160 2158
    settings.WCS_CATEGORY_ASSET_SLOTS = {}
2161 2159
    settings.WCS_FORM_ASSET_SLOTS = {}
......
2164 2162
        'wcs_wcsformsofcategorycell': {'logo': {'prefix': 'Logo'}},
2165 2163
    }
2166 2164
    resp = app.get('/manage/assets/')
2167
    assert u'Logo — %s' % cell2.get_label_for_asset() in resp.text
2168
    assert u'Picture — %s' % cell1.get_label_for_asset() in resp.text
2165
    assert 'Logo — %s' % cell2.get_label_for_asset() in resp.text
2166
    assert 'Picture — %s' % cell1.get_label_for_asset() in resp.text
2169 2167

  
2170 2168
    # test suffix
2171 2169
    settings.COMBO_CELL_ASSET_SLOTS = {
......
2173 2171
        'wcs_wcsformsofcategorycell': {'logo': {'prefix': 'Logo', 'suffix': 'test'}},
2174 2172
    }
2175 2173
    resp = app.get('/manage/assets/')
2176
    assert u'Logo — %s (test)' % cell2.get_label_for_asset() in resp.text
2177
    assert u'Picture — %s (test)' % cell1.get_label_for_asset() in resp.text
2174
    assert 'Logo — %s (test)' % cell2.get_label_for_asset() in resp.text
2175
    assert 'Picture — %s (test)' % cell1.get_label_for_asset() in resp.text
2178 2176

  
2179 2177

  
2180 2178
def test_tracking_code_search(settings, app, nocache):
......
2202 2200
    assert requests_get.call_args_list[0][0][0] == '/api/code/BBCCDDFF'
2203 2201
    assert requests_get.call_args_list[1][0][0] == '/api/code/BBCCDDFF'
2204 2202
    remote_service_urls = [c[1]['remote_service']['url'] for c in requests_get.call_args_list]
2205
    assert set(remote_service_urls) == set(['http://127.0.0.1:8999/', 'http://127.0.0.2:8999/'])
2203
    assert set(remote_service_urls) == {'http://127.0.0.1:8999/', 'http://127.0.0.2:8999/'}
2206 2204

  
2207 2205
    with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
2208 2206
        requests_get.return_value = MockedRequestResponse(
......
2431 2429

  
2432 2430

  
2433 2431
def test_import_export_pages_with_links():
2434
    page = Page(title=u'bar', slug='bar', order=1)
2432
    page = Page(title='bar', slug='bar', order=1)
2435 2433
    page.save()
2436 2434

  
2437 2435
    cell = LinkListCell.objects.create(order=0, placeholder='content', page=page)
......
2478 2476

  
2479 2477

  
2480 2478
def test_view_page_with_wcs_cells_num_queries(app, admin_user):
2481
    page = Page.objects.create(title=u'bar', slug='index', order=1)
2479
    page = Page.objects.create(title='bar', slug='index', order=1)
2482 2480
    for i in range(0, 15):
2483 2481
        WcsCurrentDraftsCell.objects.create(page=page, placeholder='content', order=i)
2484 2482
    for i in range(15, 50):
tests/test_wcs_templatetags.py
1
# -*- coding: utf-8 -*-
2

  
3 1
import copy
4 2
import json
3
from unittest import mock
5 4

  
6
import mock
7 5
import pytest
8 6
from django.template import Context, Template
9 7
from django.test.client import RequestFactory
......
25 23
    return ctx
26 24

  
27 25

  
28
class MockAnonymousUser(object):
26
class MockAnonymousUser:
29 27
    is_authenticated = False
30 28
    is_anonymous = True
31 29

  
32 30

  
33
class MockUser(object):
31
class MockUser:
34 32
    email = 'foo@example.net'
35 33
    is_authenticated = True
36 34
    is_anonymous = False
......
39 37
        return None
40 38

  
41 39

  
42
class MockUserWithNameId(object):
40
class MockUserWithNameId:
43 41
    email = 'foo@example.net'
44 42
    is_authenticated = True
45 43
    is_anonymous = False
46
-