Projet

Général

Profil

0001-misc-apply-pyupgrade-69708.patch

Valentin Deniaud, 29 septembre 2022 15:24

Télécharger (155 ko)

Voir les différences:

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

 debian/debian_config_common.py                |   2 +-
 .../management/commands/hobo_deploy.py        |   2 +-
 .../management/commands/hobo_provision.py     |   6 +-
 hobo/agent/authentic2/provisionning.py        |  24 +-
 hobo/agent/authentic2/role_forms.py           |  10 +-
 .../management/commands/import_template.py    |   2 +-
 .../common/management/commands/hobo_deploy.py |   4 +-
 hobo/agent/common/migrations/0001_initial.py  |   3 -
 .../migrations/0002_auto_20160105_1702.py     |   3 -
 .../migrations/0003_auto_20200707_1656.py     |   2 -
 hobo/agent/common/models.py                   |   4 +-
 .../hobo/management/commands/hobo_deploy.py   |   2 +-
 hobo/agent/worker/celery.py                   |   1 -
 hobo/agent/worker/services.py                 |   3 +-
 hobo/applications/migrations/0001_initial.py  |   2 -
 hobo/context_processors.py                    |   2 +-
 hobo/debug/views.py                           |   6 +-
 hobo/emails/forms.py                          |   2 +-
 hobo/emails/validators.py                     |   2 +-
 hobo/environment/forms.py                     |  16 +-
 .../management/commands/check_operational.py  |   2 -
 hobo/environment/management/commands/cook.py  |   1 -
 hobo/environment/migrations/0001_initial.py   |   3 -
 .../0002_authentic_use_as_idp_for_self.py     |   3 -
 .../migrations/0003_auto_20150309_0811.py     |   3 -
 hobo/environment/migrations/0004_fargo.py     |   3 -
 .../migrations/0005_variable_label.py         |   3 -
 .../migrations/0006_auto_20150708_0830.py     |   3 -
 .../migrations/0007_auto_20151008_1406.py     |   3 -
 .../migrations/0008_auto_20151021_1414.py     |   3 -
 hobo/environment/migrations/0009_mandayejs.py |   3 -
 .../migrations/0010_variable_auto.py          |   3 -
 hobo/environment/migrations/0011_chrono.py    |   3 -
 .../migrations/0012_mandayejs_site_app.py     |   3 -
 .../migrations/0013_auto_20160226_1633.py     |   3 -
 hobo/environment/migrations/0014_piwik.py     |   3 -
 hobo/environment/migrations/0015_corbo.py     |   3 -
 hobo/environment/migrations/0016_bijoe.py     |   3 -
 hobo/environment/migrations/0017_hobo.py      |   3 -
 .../migrations/0018_auto_20161102_1929.py     |   3 -
 .../migrations/0019_delete_piwik.py           |   2 -
 .../migrations/0020_delete_corbo_mandaye.py   |   2 -
 hobo/environment/models.py                    |   8 +-
 hobo/environment/views.py                     |  24 +-
 hobo/forms.py                                 |   4 +-
 hobo/journal.py                               |   5 +-
 hobo/logger.py                                |  19 +-
 hobo/matomo/utils.py                          |   2 +-
 hobo/matomo/views.py                          |  14 +-
 hobo/middleware/debug.py                      |   2 +-
 hobo/middleware/stats.py                      |   2 +-
 hobo/multitenant/cache.py                     |   2 +-
 hobo/multitenant/haystack.py                  |   7 +-
 hobo/multitenant/log.py                       |   2 +-
 .../management/commands/__init__.py           |  10 +-
 .../management/commands/create_hobo_tenant.py |   2 +-
 .../management/commands/create_schemas.py     |   2 -
 .../management/commands/list_tenants.py       |   2 +-
 .../management/commands/migrate.py            |   2 +-
 .../management/commands/migrate_schemas.py    |  12 +-
 .../management/commands/runserver.py          |   2 +-
 hobo/multitenant/management/commands/shell.py |   2 +-
 .../commands/showmigrations_schemas.py        |   6 +-
 .../multitenant/management/commands/syncdb.py |   4 +-
 .../management/commands/tenant_command.py     |   3 +-
 hobo/multitenant/mellon.py                    |   2 -
 hobo/multitenant/models.py                    |   2 +-
 hobo/multitenant/settings.py                  |   2 +-
 hobo/multitenant/settings_loaders.py          |   8 +-
 hobo/multitenant/template_loader.py           |  10 +-
 hobo/profile/migrations/0001_initial.py       |   3 -
 hobo/profile/migrations/0002_add_data.py      |  25 +-
 .../0003_attributedefinition_searchable.py    |   2 -
 .../migrations/0004_auto_20200518_1810.py     |   2 -
 hobo/profile/models.py                        |   4 +-
 hobo/rest_authentication.py                   |   2 +-
 hobo/seo/views.py                             |  10 +-
 hobo/theme/views.py                           |   4 +-
 hobo/urls_utils.py                            |   4 +-
 hobo/views.py                                 |   2 +-
 setup.py                                      |   3 +-
 tests/test_cook.py                            |  24 +-
 tests/test_emails.py                          |   2 +-
 tests/test_environment.py                     |   5 +-
 tests/test_health_api.py                      |   2 +-
 tests/test_hobo_deploy.py                     |  24 +-
 tests/test_home_views.py                      |   3 +-
 tests/test_import_template.py                 |   3 +-
 tests/test_maintenance.py                     |   3 +-
 tests/test_matomo_utils.py                    |  10 +-
 tests/test_matomo_views.py                    |   4 +-
 tests/test_settings_loaders.py                |  64 ++--
 tests/test_signature.py                       |   4 +-
 tests/test_theme.py                           |   4 +-
 tests/test_version.py                         |   2 +-
 tests_authentic/settings.py                   |   3 +-
 tests_authentic/test_hobo_deploy.py           |  37 ++-
 tests_authentic/test_provisionning.py         | 198 +++++++-----
 tests_multipublik/settings.py                 |   3 +-
 tests_multitenant/settings.py                 |   3 +-
 tests_multitenant/test_agent_worker.py        |  69 +++--
 tests_multitenant/test_create_tenant.py       |   3 +-
 tests_multitenant/test_hobo_notify.py         | 284 +++++++++---------
 tests_multitenant/test_middleware.py          |   2 -
 tests_multitenant/test_settings.py            |  31 +-
 tests_multitenant/test_tenant_command.py      |  25 +-
 tests_multitenant/test_uwsgidecorators.py     |   2 +-
 tests_multitenant/utilities.py                |   2 +-
 tests_passerelle/settings.py                  |   3 +-
 tests_schemas/test_cook.py                    |   2 +-
 tests_schemas/test_hobo_deploy.py             |   2 +-
 tests_schemas/test_import_template.py         |   2 +-
 tests_schemas/test_rename_hobo_service.py     |   3 +-
 tests_schemas/test_rename_service.py          |   3 +-
 114 files changed, 573 insertions(+), 640 deletions(-)
debian/debian_config_common.py
391 391
# Locale and timezone
392 392
LANGUAGE_CODE = 'fr-fr'
393 393
TIME_ZONE = 'Europe/Paris'
394
LANGUAGES = (('fr', u'Fran\xe7ais'),)
394
LANGUAGES = (('fr', 'Fran\xe7ais'),)
395 395
USE_L10N = True
396 396
USE_TZ = True
397 397

  
hobo/agent/authentic2/management/commands/hobo_deploy.py
31 31

  
32 32
    def __init__(self, *args, **kwargs):
33 33
        self.logger = logging.getLogger(__name__)
34
        super(Command, self).__init__(*args, **kwargs)
34
        super().__init__(*args, **kwargs)
35 35

  
36 36
    def deploy_specifics(self, hobo_environment, tenant):
37 37
        # generate SAML keys
hobo/agent/authentic2/management/commands/hobo_provision.py
38 38
    def provision_roles(self, engine, ous):
39 39
        roles = get_role_model().objects.all()
40 40
        if self.verbosity > 0:
41
            self.stdout.write('Provisionning {} roles.'.format(roles.count()))
41
            self.stdout.write(f'Provisionning {roles.count()} roles.')
42 42
        engine.notify_roles(ous, roles, full=True)
43 43

  
44 44
    def provision_users(self, engine, ous, batch_size=512, batch_sleep=30, verbosity=1):
......
66 66
        normal_users = qs.exclude(roles__in=roles_with_attributes)
67 67

  
68 68
        if self.verbosity > 0:
69
            self.stdout.write('Provisionning {} normal users.'.format(normal_users.count()))
69
            self.stdout.write(f'Provisionning {normal_users.count()} normal users.')
70 70
        do_provision(normal_users)
71 71
        # then those with an admin attribute, use distinct to prevent
72 72
        # duplicates caused by join on a m2m relation
73 73
        admin_users = qs.filter(roles__in=roles_with_attributes).distinct()
74 74
        if self.verbosity > 0:
75
            self.stdout.write('Provisionning {} admin users.'.format(admin_users.count()))
75
            self.stdout.write(f'Provisionning {admin_users.count()} admin users.')
76 76
        do_provision(admin_users)
hobo/agent/authentic2/provisionning.py
202 202
            )
203 203

  
204 204
            all_roles = Role.objects.all().prefetch_related('attributes')
205
            roles = dict((r.id, r) for r in all_roles)
205
            roles = {r.id: r for r in all_roles}
206 206
            user_roles = {}
207 207
            parents = {}
208 208
            for rp in RoleParenting.objects.filter(deleted__isnull=True):
......
249 249
                    if not audience:
250 250
                        continue
251 251
                    logger.info(
252
                        u'provisionning users %s to %s',
253
                        u', '.join(map(force_text, users)),
254
                        u', '.join(audience),
252
                        'provisionning users %s to %s',
253
                        ', '.join(map(force_text, users)),
254
                        ', '.join(audience),
255 255
                    )
256 256
                    self.notify_agents(
257 257
                        {
......
269 269
        elif users:
270 270
            audience = [audience for ou in ous.keys() for s, audience in self.get_audience(ou)]
271 271
            logger.info(
272
                u'deprovisionning users %s from %s', u', '.join(map(force_text, users)), u', '.join(audience)
272
                'deprovisionning users %s from %s', ', '.join(map(force_text, users)), ', '.join(audience)
273 273
            )
274 274
            self.notify_agents(
275 275
                {
......
298 298
                tuple(allowed_technical_roles_prefixes)
299 299
            )
300 300

  
301
        roles = set([role for role in roles if not is_forbidden_technical_role(role)])
301
        roles = {role for role in roles if not is_forbidden_technical_role(role)}
302 302
        if mode == 'provision':
303 303
            self.complete_roles(roles)
304 304

  
......
333 333
                ]
334 334

  
335 335
            audience = [entity_id for service, entity_id in self.get_audience(ou)]
336
            logger.info(u'%sning roles %s to %s', mode, roles, audience)
336
            logger.info('%sning roles %s to %s', mode, roles, audience)
337 337
            self.notify_agents(
338 338
                {
339 339
                    '@type': mode,
......
381 381
            self.notify_users(ous, deleted.get(User, []), mode='deprovision')
382 382
        except Exception:
383 383
            # last step, clear everything
384
            logger.exception(u'error in provisionning thread')
384
            logger.exception('error in provisionning thread')
385 385
        finally:
386 386
            self.threads.discard(threading.current_thread())
387 387

  
......
408 408
        for role in roles:
409 409
            role.emails = []
410 410
            role.emails_to_members = True
411
            role.details = u''
411
            role.details = ''
412 412
            for attribute in role.attributes.all():
413 413
                if attribute.name in ('emails', 'emails_to_members', 'details') and attribute.kind == 'json':
414 414
                    setattr(role, attribute.name, json.loads(attribute.value))
......
428 428
        if not isinstance(instance, (User, Role, RoleAttribute, AttributeValue)):
429 429
            return
430 430
        # ignore last_login update on login
431
        if isinstance(instance, User) and (update_fields and set(update_fields) == set(['last_login'])):
431
        if isinstance(instance, User) and (update_fields and set(update_fields) == {'last_login'}):
432 432
            return
433 433
        if isinstance(instance, RoleAttribute):
434 434
            instance = instance.role
......
506 506
                    f.write('%s %s ' % (datetime.datetime.now().isoformat(), connection.tenant.domain_url))
507 507
                    json.dump(data, f, indent=2)
508 508
                    f.write('\n')
509
            except IOError:
509
            except OSError:
510 510
                pass
511 511

  
512 512
        if getattr(settings, 'HOBO_HTTP_PROVISIONNING', True):
......
543 543
                response = requests.put(sign_url(url, service['secret']), json=data)
544 544
                response.raise_for_status()
545 545
            except requests.RequestException as e:
546
                logger.error(u'error provisionning to %s (%s)', audience, e)
546
                logger.error('error provisionning to %s (%s)', audience, e)
547 547
            else:
548 548
                leftover_audience.remove(audience)
549 549
        return leftover_audience
hobo/agent/authentic2/role_forms.py
25 25
from django.utils.translation import ugettext_lazy as _
26 26

  
27 27

  
28
class ListValidator(object):
28
class ListValidator:
29 29
    def __init__(self, item_validator):
30 30
        self.item_validator = item_validator
31 31

  
......
42 42
        if not value:
43 43
            return ''
44 44
        if not isinstance(value, str):
45
            return u', '.join(value)
45
            return ', '.join(value)
46 46
        return value
47 47

  
48 48

  
......
54 54
        self.max_length = max_length
55 55
        self.min_length = min_length
56 56
        item_validators = kwargs.pop('item_validators', [])
57
        super(CommaSeparatedCharField, self).__init__(*args, **kwargs)
57
        super().__init__(*args, **kwargs)
58 58
        for item_validator in item_validators:
59 59
            self.validators.append(ListValidator(item_validator))
60 60

  
......
97 97
                if role_attribute.name in fields:
98 98
                    continue
99 99
                initial[role_attribute.name] = json.loads(role_attribute.value)
100
        super(RoleForm, self).__init__(*args, **kwargs)
100
        super().__init__(*args, **kwargs)
101 101

  
102 102
    def save(self, commit=True):
103 103
        fields = [x.name for x in Role._meta.get_fields()]
104 104
        assert commit
105
        instance = super(RoleForm, self).save(commit=commit)
105
        instance = super().save(commit=commit)
106 106
        for field in self.cleaned_data:
107 107
            if field in fields:
108 108
                continue
hobo/agent/combo/management/commands/import_template.py
21 21
class Command(import_template.Command):
22 22
    def handle(self, *args, **kwargs):
23 23
        try:
24
            return super(Command, self).handle(*args, **kwargs)
24
            return super().handle(*args, **kwargs)
25 25
        except import_template.UnknownTemplateError:
26 26
            # ignore errors if template name contains portal-user or portal-agent as
27 27
            # those names do not actually require an existing file to work.
hobo/agent/common/management/commands/hobo_deploy.py
1
from __future__ import print_function
2

  
3 1
import json
4 2
import os
5 3
import subprocess
......
51 49
            for tenant in TenantMiddleware.get_tenants():
52 50
                try:
53 51
                    hobo_environment = tenant.get_hobo_json()
54
                except IOError:
52
                except OSError:
55 53
                    continue
56 54
                try:
57 55
                    me = [x for x in hobo_environment.get('services') if x.get('this') is True][0]
hobo/agent/common/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

  
hobo/agent/common/migrations/0002_auto_20160105_1702.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/agent/common/migrations/0003_auto_20200707_1656.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.18 on 2020-07-07 14:56
3
from __future__ import unicode_literals
4 2

  
5 3
import django.contrib.postgres.fields
6 4
from django.db import migrations, models
hobo/agent/common/models.py
5 5

  
6 6
class Role(Group):
7 7
    uuid = models.CharField(max_length=32, db_index=True)
8
    description = models.TextField(default=u'')
9
    details = models.TextField(default=u'')
8
    description = models.TextField(default='')
9
    details = models.TextField(default='')
10 10
    emails = ArrayField(models.CharField(max_length=128), default=list)
11 11
    emails_to_members = models.BooleanField(default=True)
12 12

  
hobo/agent/hobo/management/commands/hobo_deploy.py
17 17
    def deploy_specifics(self, hobo_environment, tenant):
18 18
        me = [x for x in hobo_environment.get('services') if x.get('this')][0]
19 19
        if not me.get('secondary'):
20
            super(Command, self).deploy_specifics(hobo_environment, tenant)
20
            super().deploy_specifics(hobo_environment, tenant)
21 21

  
22 22
        with tenant_context(tenant):
23 23
            services = hobo_environment.get('services')
hobo/agent/worker/celery.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
from celery import Celery
20 19
from kombu.common import Broadcast
hobo/agent/worker/services.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 fnmatch
20 19
import json
......
30 29
from . import settings
31 30

  
32 31

  
33
class BaseService(object):
32
class BaseService:
34 33
    tenants_dirs = None
35 34

  
36 35
    def __init__(self, base_url, title, secret_key, **kwargs):
hobo/applications/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.29 on 2022-01-09 13:16
3
from __future__ import unicode_literals
4 2

  
5 3
import django.contrib.postgres.fields.jsonb
6 4
import django.db.models.deletion
hobo/context_processors.py
39 39
    return template_vars
40 40

  
41 41

  
42
class RemoteTemplate(object):
42
class RemoteTemplate:
43 43
    PAGE_CACHE_KEY = 'page-cache'
44 44

  
45 45
    def __init__(self, source):
hobo/debug/views.py
37 37
        return get_setting_variable('INTERNAL_IPS.extend')
38 38

  
39 39
    def get_initial(self):
40
        initial = super(HomeView, self).get_initial()
40
        initial = super().get_initial()
41 41
        initial['debug_log'] = bool(self.debug_log_variable.json)
42 42
        initial['debug_ips'] = self.debug_ips_variable.json
43 43
        return initial
......
47 47
        return self.request.META.get('REMOTE_ADDR') or None
48 48

  
49 49
    def get_context_data(self, **kwargs):
50
        ctx = super(HomeView, self).get_context_data(**kwargs)
50
        ctx = super().get_context_data(**kwargs)
51 51
        ctx['current_ip_debug'] = self.current_ip in self.debug_ips_variable.json
52 52
        return ctx
53 53

  
......
67 67
            debug_ips = self.toggle_value(debug_ips, self.current_ip)
68 68
        self.debug_ips_variable.json = debug_ips
69 69
        self.debug_ips_variable.save()
70
        return super(HomeView, self).form_valid(form)
70
        return super().form_valid(form)
71 71

  
72 72

  
73 73
home = HomeView.as_view()
hobo/emails/forms.py
50 50
    )
51 51

  
52 52
    def __init__(self, *args, **kwargs):
53
        super(EmailsForm, self).__init__(*args, **kwargs)
53
        super().__init__(*args, **kwargs)
54 54
        self.fields['email_signature'].widget.attrs = {'rows': 4, 'cols': 80}
hobo/emails/validators.py
45 45
            smtp.quit()
46 46
        finally:
47 47
            smtp.close()
48
    except (socket.error, IOError, OSError) as e:
48
    except OSError as e:
49 49
        raise ValidationError(
50 50
            _('Error while connecting to %(server)s: %(msg)s') % {'server': mx_server, 'msg': e}
51 51
        )
hobo/environment/forms.py
37 37
class BaseForm(forms.ModelForm):
38 38
    def __init__(self, *args, **kwargs):
39 39
        choices = self.get_template_choices()
40
        super(BaseForm, self).__init__(*args, **kwargs)
40
        super().__init__(*args, **kwargs)
41 41
        if len(choices) < 2 or self.instance.id:
42 42
            del self.fields['template_name']
43 43
        else:
......
84 84
        choices = self.get_template_choices()
85 85
        if not self.instance.id and len(choices) == 1:
86 86
            self.instance.template_name = choices[0][0]
87
        return super(BaseForm, self).save(commit=commit)
87
        return super().save(commit=commit)
88 88

  
89 89

  
90 90
class AuthenticForm(BaseForm):
......
93 93
        exclude = EXCLUDED_FIELDS
94 94

  
95 95
    def __init__(self, *args, **kwargs):
96
        super(AuthenticForm, self).__init__(*args, **kwargs)
96
        super().__init__(*args, **kwargs)
97 97
        if not self.instance.is_operational() and not self.initial.get('use_as_idp_for_self'):
98 98
            del self.fields['use_as_idp_for_self']
99 99

  
......
102 102
            if self.cleaned_data.get('use_as_idp_for_self'):
103 103
                # this idp was just marked as the idp to use, unmark all others
104 104
                Authentic.objects.update(use_as_idp_for_self=False)
105
        return super(AuthenticForm, self).save(commit=commit)
105
        return super().save(commit=commit)
106 106

  
107 107

  
108 108
class WcsForm(BaseForm):
......
166 166

  
167 167
    def __init__(self, service=None, **kwargs):
168 168
        self.service = service
169
        super(VariableForm, self).__init__(**kwargs)
169
        super().__init__(**kwargs)
170 170

  
171 171
    def save(self, commit=True):
172 172
        if self.service:
173 173
            self.instance.service = self.service
174
        return super(VariableForm, self).save(commit=commit)
174
        return super().save(commit=commit)
175 175

  
176 176

  
177
class VariablesFormMixin(object):
177
class VariablesFormMixin:
178 178
    form_class = None
179 179
    success_message = None
180 180
    variables = []
181 181

  
182 182
    def get_context_data(self, **kwargs):
183
        context = super(VariablesFormMixin, self).get_context_data(**kwargs)
183
        context = super().get_context_data(**kwargs)
184 184
        if self.request.POST:
185 185
            form_data = self.request.POST
186 186
        else:
hobo/environment/management/commands/check_operational.py
1
from __future__ import print_function
2

  
3 1
from optparse import make_option
4 2

  
5 3
from django.core.management.base import BaseCommand
hobo/environment/management/commands/cook.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 json
20 19
import os
hobo/environment/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

  
hobo/environment/migrations/0002_authentic_use_as_idp_for_self.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0003_auto_20150309_0811.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0004_fargo.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0005_variable_label.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0006_auto_20150708_0830.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0007_auto_20151008_1406.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0008_auto_20151021_1414.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0009_mandayejs.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0010_variable_auto.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0011_chrono.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0012_mandayejs_site_app.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0013_auto_20160226_1633.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0014_piwik.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0015_corbo.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0016_bijoe.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0017_hobo.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0018_auto_20161102_1929.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

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

  
6 3

  
hobo/environment/migrations/0019_delete_piwik.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2019-02-28 10:28
3
from __future__ import unicode_literals
4 2

  
5 3
from django.db import migrations
6 4

  
hobo/environment/migrations/0020_delete_corbo_mandaye.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.29 on 2021-02-28 09:57
3
from __future__ import unicode_literals
4 2

  
5 3
import django.core.validators
6 4
from django.db import migrations, models
hobo/environment/models.py
152 152
        return (self.last_operational_check_timestamp - self.last_update_timestamp) < two_minutes
153 153

  
154 154
    def as_dict(self):
155
        as_dict = dict([(x, y) for (x, y) in self.__dict__.items() if isinstance(y, (int, str))])
155
        as_dict = {x: y for (x, y) in self.__dict__.items() if isinstance(y, (int, str))}
156 156
        as_dict['base_url'] = self.get_base_url_path()
157 157
        if self.legacy_urls:
158 158
            as_dict['legacy_urls'] = self.legacy_urls
159 159
        as_dict['service-id'] = self.Extra.service_id
160 160
        as_dict['service-label'] = force_text(self.Extra.service_label)
161
        as_dict['variables'] = dict(((v.name, v.json) for v in self.variables.all()))
161
        as_dict['variables'] = {v.name: v.json for v in self.variables.all()}
162 162
        as_dict['secondary'] = self.secondary
163 163
        if self.get_saml_sp_metadata_url():
164 164
            as_dict['saml-sp-metadata-url'] = self.get_saml_sp_metadata_url()
......
182 182
                raise ValidationError(_('This slug is already used. It must be unique.'))
183 183
            if service.title == self.title and service.secondary is False and self.secondary is False:
184 184
                raise ValidationError(_('This title is already used. It must be unique.'))
185
        return super(ServiceBase, self).clean(*args, **kwargs)
185
        return super().clean(*args, **kwargs)
186 186

  
187 187
    def save(self, *args, **kwargs):
188 188
        self.base_url = self.base_url.strip().lower()
......
192 192
            self.secret_key = get_random_string(50, SECRET_CHARS)
193 193

  
194 194
        is_new = self.id is None
195
        super(ServiceBase, self).save(*args, **kwargs)
195
        super().save(*args, **kwargs)
196 196

  
197 197
        if is_new and settings.SERVICE_EXTRA_VARIABLES:
198 198
            for variable in settings.SERVICE_EXTRA_VARIABLES.get(self.Extra.service_id, []):
hobo/environment/views.py
33 33
from .models import AVAILABLE_SERVICES, Variable
34 34

  
35 35

  
36
class AvailableService(object):
36
class AvailableService:
37 37
    def __init__(self, klass):
38 38
        self.id = klass.Extra.service_id
39 39
        self.label = klass._meta.verbose_name
......
43 43
    template_name = 'environment/home.html'
44 44

  
45 45
    def get_context_data(self, **kwargs):
46
        context = super(HomeView, self).get_context_data(**kwargs)
46
        context = super().get_context_data(**kwargs)
47 47
        context['available_services'] = [AvailableService(x) for x in AVAILABLE_SERVICES if x.is_enabled()]
48 48
        installed_services = [x for x in utils.get_installed_services() if not x.secondary]
49 49
        for service in installed_services:
......
62 62
    template_name = 'environment/variables.html'
63 63

  
64 64
    def get_context_data(self, **kwargs):
65
        context = super(VariablesView, self).get_context_data(**kwargs)
65
        context = super().get_context_data(**kwargs)
66 66
        context['variables'] = Variable.objects.filter(auto=False, service_pk__isnull=True).order_by('label')
67 67
        return context
68 68

  
......
72 72
    form_class = forms.VariableForm
73 73

  
74 74
    def get_form_kwargs(self):
75
        kwargs = super(VariableCreateView, self).get_form_kwargs()
75
        kwargs = super().get_form_kwargs()
76 76
        if 'service' in self.kwargs:
77 77
            service_id = self.kwargs.pop('service')
78 78
            service_slug = self.kwargs.pop('slug')
......
130 130
    success_url = reverse_lazy('environment-home')
131 131

  
132 132
    def get_context_data(self, **kwargs):
133
        context = super(ServiceCreateView, self).get_context_data(**kwargs)
133
        context = super().get_context_data(**kwargs)
134 134
        context['model_name'] = self.model._meta.verbose_name
135 135
        return context
136 136

  
137 137
    def get_initial(self):
138
        initial = super(ServiceCreateView, self).get_initial()
138
        initial = super().get_initial()
139 139
        initial['base_url'] = utils.create_base_url(
140 140
            self.request.build_absolute_uri(), self.model.Extra.service_default_slug
141 141
        )
......
147 147

  
148 148
    def get(self, request, *args, **kwargs):
149 149
        self.service_id = kwargs.pop('service')
150
        return super(ServiceCreateView, self).get(request, *args, **kwargs)
150
        return super().get(request, *args, **kwargs)
151 151

  
152 152
    def post(self, request, *args, **kwargs):
153 153
        self.service_id = kwargs.pop('service')
154
        return super(ServiceCreateView, self).post(request, *args, **kwargs)
154
        return super().post(request, *args, **kwargs)
155 155

  
156 156
    def get_form_class(self):
157 157
        for service in AVAILABLE_SERVICES:
......
166 166
    success_url = reverse_lazy('environment-home')
167 167

  
168 168
    def get_context_data(self, **kwargs):
169
        context = super(ServiceUpdateView, self).get_context_data(**kwargs)
169
        context = super().get_context_data(**kwargs)
170 170
        context['model_name'] = self.model._meta.verbose_name
171 171
        return context
172 172

  
......
176 176
    def get(self, request, *args, **kwargs):
177 177
        self.service_id = kwargs.pop('service')
178 178
        self.get_form_class()
179
        return super(ServiceUpdateView, self).get(request, *args, **kwargs)
179
        return super().get(request, *args, **kwargs)
180 180

  
181 181
    def post(self, request, *args, **kwargs):
182 182
        self.service_id = kwargs.pop('service')
183 183
        self.get_form_class()
184
        return super(ServiceUpdateView, self).post(request, *args, **kwargs)
184
        return super().post(request, *args, **kwargs)
185 185

  
186 186
    def get_form_class(self):
187 187
        for service in AVAILABLE_SERVICES:
......
219 219
            return self.form_invalid(form)
220 220

  
221 221
        utils.import_parameters(parameters_json)
222
        return super(ImportView, self).form_valid(form)
222
        return super().form_valid(form)
223 223

  
224 224

  
225 225
class ExportView(View):
hobo/forms.py
12 12
    required_css_class = 'required'
13 13

  
14 14
    def __init__(self, *args, **kwargs):
15
        super(HoboForm, self).__init__(*args, **kwargs)
15
        super().__init__(*args, **kwargs)
16 16
        self.fields['schema_name'].required = False
17 17

  
18 18
    def clean(self):
19 19
        from django.template.defaultfilters import slugify
20 20

  
21
        cleaned_data = super(HoboForm, self).clean()
21
        cleaned_data = super().clean()
22 22
        if not cleaned_data.get('schema_name') and cleaned_data.get('domain_url'):
23 23
            cleaned_data['schema_name'] = slugify(cleaned_data['domain_url'])
24 24
        return cleaned_data
hobo/journal.py
1
#  -*- Mode: python; coding:utf-8; indent-tabs-mode: nil -*- */
2 1
#
3 2
#
4 3
#  Copyright 2012 David Strauss <david@davidstrauss.net>
......
79 78
    if CODE_FILE is not None:
80 79
        args.append('CODE_FILE=' + CODE_FILE)
81 80
    if CODE_LINE is not None:
82
        args.append('CODE_LINE={:d}'.format(CODE_LINE))
81
        args.append(f'CODE_LINE={CODE_LINE:d}')
83 82
    if CODE_FUNC is not None:
84 83
        args.append('CODE_FUNC=' + CODE_FUNC)
85 84

  
......
140 139
    """
141 140

  
142 141
    def __init__(self, level=_logging.NOTSET, sender_function=send, **kwargs):
143
        super(JournalHandler, self).__init__(level)
142
        super().__init__(level)
144 143

  
145 144
        for name in kwargs:
146 145
            if not _valid_field_name(name):
hobo/logger.py
34 34
        warnings.warn(
35 35
            'SettingsLogLevel is deprecated, use DEBUG_LOG instead.', DeprecationWarning, stacklevel=2
36 36
        )
37
        return super(SettingsLogLevel, cls).__new__(value)
37
        return super().__new__(value)
38 38

  
39 39

  
40 40
class RequestContextFilter(logging.Filter):
......
120 120
    def filter(self, record):
121 121
        record.levelno = logging.DEBUG
122 122
        record.levelname = 'DEBUG'
123
        return super(ForceDebugFilter, self).filter(record)
123
        return super().filter(record)
124 124

  
125 125

  
126 126
class LogRecord(logging.LogRecord):
127 127
    '''Subclass LogRecord to make multiline log parseable'''
128 128

  
129 129
    def getMessage(self):
130
        return super(LogRecord, self).getMessage().replace('\n', '\n ')
130
        return super().getMessage().replace('\n', '\n ')
131 131

  
132 132

  
133 133
class TimedRotatingFileHandler(logging.handlers.TimedRotatingFileHandler):
......
135 135
        old_class = record.__class__
136 136
        record.__class__ = LogRecord
137 137
        try:
138
            return super(TimedRotatingFileHandler, self).format(record)
138
            return super().format(record)
139 139
        finally:
140 140
            record.__class__ = old_class
141 141

  
142 142

  
143
class DebugLogFilter(object):
143
class DebugLogFilter:
144 144
    '''Filter debug log records based on the DEBUG_LOG setting'''
145 145

  
146 146
    def filter(self, record):
......
163 163
            return bool(debug_log)
164 164

  
165 165

  
166
class DebugLog(object):
166
class DebugLog:
167 167
    def __init__(self, path):
168 168
        self.path = path
169 169

  
......
228 228
            return
229 229
        if not os.path.exists(debug_log_path):
230 230
            return
231
        for record in cls(debug_log_path)._parse(cursor=cursor):
232
            yield record
231
        yield from cls(debug_log_path)._parse(cursor=cursor)
233 232

  
234 233

  
235 234
class ClampLogLevel(logging.Filter):
236 235
    def __init__(self, level):
237 236
        self.levelname = level.upper()
238 237
        self.levelno = getattr(logging, self.levelname)
239
        super(ClampLogLevel, self).__init__()
238
        super().__init__()
240 239

  
241 240
    def filter(self, record):
242 241
        if record.levelno > self.levelno:
243 242
            record.levelno = self.levelno
244 243
            record.levelname = self.levelname
245
        return super(ClampLogLevel, self).filter(record)
244
        return super().filter(record)
hobo/matomo/utils.py
109 109
    """expected Matomo error responses"""
110 110

  
111 111

  
112
class MatomoWS(object):
112
class MatomoWS:
113 113
    """api for matomo webservices"""
114 114

  
115 115
    def __init__(self):
hobo/matomo/views.py
39 39
    success_url = reverse_lazy('matomo-home')
40 40

  
41 41
    def get_initial(self):
42
        initial = super(HomeView, self).get_initial()
42
        initial = super().get_initial()
43 43
        initial['tracking_js'] = get_tracking_js()
44 44
        return initial
45 45

  
46 46
    def form_valid(self, form):
47 47
        tracking_js = form.cleaned_data['tracking_js']
48 48
        put_tracking_js(tracking_js)
49
        return super(HomeView, self).form_valid(form)
49
        return super().form_valid(form)
50 50

  
51 51
    def get_context_data(self, **kwargs):
52
        context = super(HomeView, self).get_context_data(**kwargs)
52
        context = super().get_context_data(**kwargs)
53 53
        tracking_js = get_tracking_js()
54 54
        logme_url = get_variable_value('matomo_logme_url')
55 55
        context['logme_url'] = logme_url
......
80 80
    success_url = reverse_lazy('matomo-home')
81 81

  
82 82
    def get_initial(self):
83
        initial = super(EnableManualView, self).get_initial()
83
        initial = super().get_initial()
84 84
        initial['tracking_js'] = get_tracking_js()
85 85
        return initial
86 86

  
......
89 89
        put_tracking_js(tracking_js)
90 90
        logme_url = get_variable('matomo_logme_url')
91 91
        logme_url.delete()
92
        return super(EnableManualView, self).form_valid(form)
92
        return super().form_valid(form)
93 93

  
94 94

  
95 95
enable_manual = EnableManualView.as_view()
......
111 111
                matomo.create_fake_first_tracking_visit(id_site)
112 112
            except MatomoException as exc:
113 113
                messages.warning(self.request, 'ping: ' + str(exc))
114
        return super(EnableAutoView, self).form_valid(form)
114
        return super().form_valid(form)
115 115

  
116 116

  
117 117
enable_auto = EnableAutoView.as_view()
......
126 126
        put_tracking_js('')
127 127
        variable = get_variable('matomo_logme_url')
128 128
        variable.delete()
129
        return super(DisableView, self).form_valid(form)
129
        return super().form_valid(form)
130 130

  
131 131

  
132 132
disable = DisableView.as_view()
hobo/middleware/debug.py
17 17
from django.conf import settings
18 18

  
19 19

  
20
class InternalIPMiddleware(object):
20
class InternalIPMiddleware:
21 21
    def __init__(self, get_response=None):
22 22
        self.get_response = get_response
23 23

  
hobo/middleware/stats.py
97 97

  
98 98
        if connection.queries_logged:
99 99
            sql_queries_count = len(connection.queries)
100
            sql_queries_time = sum([float(x['time']) for x in connection.queries])
100
            sql_queries_time = sum(float(x['time']) for x in connection.queries)
101 101
            requests_queries_count_by_host_view_status_method.labels(
102 102
                host_name, view_name, status_code, http_method
103 103
            ).observe(sql_queries_count)
hobo/multitenant/cache.py
4 4
from django.utils.module_loading import import_string
5 5

  
6 6

  
7
class TenantBaseCache(object):
7
class TenantBaseCache:
8 8
    '''Prepend the tenant schema name to the cache prefix'''
9 9

  
10 10
    def set_key_prefix(self, prefix):
hobo/multitenant/haystack.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 os
20 19
import shutil
......
43 42
            # when there are opened files.
44 43
            renamed_path = self.path + '.deleted-%s' % time.time()
45 44
            os.rename(self.path, renamed_path)
46
        super(WhooshSearchBackend, self).delete_index()
45
        super().delete_index()
47 46
        if renamed_path:
48 47
            # remove afterwards and ignore errors (residual directories will
49 48
            # have to be cleaned manually)
50 49
            try:
51 50
                shutil.rmtree(renamed_path)
52
            except (IOError, OSError):
51
            except OSError:
53 52
                pass
54 53

  
55 54
    @property
......
62 61
        pass
63 62

  
64 63
    def setup(self):
65
        super(WhooshSearchBackend, self).setup()
64
        super().setup()
66 65
        # make it be always reinitialized
67 66
        self.setup_complete = False
68 67

  
hobo/multitenant/log.py
22 22
    def format_subject(self, subject):
23 23
        from .models import Tenant
24 24

  
25
        subject = super(AdminEmailHandler, self).format_subject(subject)
25
        subject = super().format_subject(subject)
26 26
        try:
27 27
            subject = '[%s] %s' % (connection.get_tenant().domain_url, subject)
28 28
        except AttributeError:
hobo/multitenant/management/commands/__init__.py
26 26
        """
27 27
        Sets option_list and help dynamically.
28 28
        """
29
        obj = super(BaseTenantCommand, cls).__new__(cls, *args, **kwargs)
29
        obj = super().__new__(cls, *args, **kwargs)
30 30

  
31 31
        app_name = get_commands()[obj.COMMAND_NAME]
32 32
        if isinstance(app_name, BaseCommand):
......
48 48
        return obj
49 49

  
50 50
    def add_arguments(self, parser):
51
        super(BaseTenantCommand, self).add_arguments(parser)
51
        super().add_arguments(parser)
52 52
        parser.add_argument("-d", "--domain", dest="domain")
53 53
        # use the privately held reference to the underlying command to invoke
54 54
        # the add_arguments path on this parser instance
......
88 88
                self.execute_command(tenant, self.COMMAND_NAME, *args, **options)
89 89

  
90 90

  
91
class InteractiveTenantOption(object):
91
class InteractiveTenantOption:
92 92
    def add_arguments(self, parser):
93 93
        parser.add_argument("-d", "--domain", dest="domain", help='specify tenant domain')
94 94

  
......
135 135
    """
136 136

  
137 137
    def __new__(cls, *args, **kwargs):
138
        obj = super(TenantWrappedCommand, cls).__new__(cls, *args, **kwargs)
138
        obj = super().__new__(cls, *args, **kwargs)
139 139
        obj.command_instance = obj.COMMAND()
140 140
        return obj
141 141

  
142 142
    def add_arguments(self, parser):
143
        super(TenantWrappedCommand, self).add_arguments(parser)
143
        super().add_arguments(parser)
144 144
        self.command_instance.add_arguments(parser)
145 145

  
146 146
    def handle(self, *args, **options):
hobo/multitenant/management/commands/create_hobo_tenant.py
22 22
            hostnames.remove('-')
23 23
            hostnames.extend([x.strip() for x in sys.stdin.readlines()])
24 24

  
25
        super(Command, self).handle(hostnames, **options)
25
        super().handle(hostnames, **options)
26 26

  
27 27
        # create SP keys for each tenant
28 28
        for hostname in hostnames:
hobo/multitenant/management/commands/create_schemas.py
1
from __future__ import print_function
2

  
3 1
from django.core.management.base import BaseCommand
4 2
from django.db import connection
5 3

  
hobo/multitenant/management/commands/list_tenants.py
11 11
        all_tenants = TenantMiddleware.get_tenants()
12 12

  
13 13
        for tenant in all_tenants:
14
            print("{0} {1}".format(tenant.schema_name, tenant.domain_url))
14
            print(f"{tenant.schema_name} {tenant.domain_url}")
hobo/multitenant/management/commands/migrate.py
21 21
                "instead. Please read the documentation if you don't know why you "
22 22
                "shouldn't call migrate directly!".format(database)
23 23
            )
24
        super(Command, self).handle(*args, **options)
24
        super().handle(*args, **options)
25 25

  
26 26

  
27 27
if django_is_in_test_mode():
hobo/multitenant/management/commands/migrate_schemas.py
33 33
    requires_system_checks = []
34 34

  
35 35
    def add_arguments(self, parser):
36
        super(MigrateSchemasCommand, self).add_arguments(parser)
36
        super().add_arguments(parser)
37 37
        command = MigrateCommand()
38 38
        command.add_arguments(parser)
39 39
        parser.set_defaults(verbosity=0)
40 40

  
41 41
    def handle(self, *args, **options):
42
        super(MigrateSchemasCommand, self).handle(*args, **options)
42
        super().handle(*args, **options)
43 43
        if self.domain:
44 44
            try:
45 45
                tenant = TenantMiddleware.get_tenant_by_hostname(self.domain)
46 46
            except TenantNotFound:
47
                raise RuntimeError('Tenant "{}" does not exist'.format(self.domain))
47
                raise RuntimeError(f'Tenant "{self.domain}" does not exist')
48 48
            else:
49 49
                self.run_migrations(tenant, settings.TENANT_APPS)
50 50
        elif self.schema_name:
......
56 56
                    app_labels.append(app.label)
57 57
            loader = MigrationLoader(None)
58 58
            loader.load_disk()
59
            all_migrations = set(
60
                [(app, migration) for app, migration in loader.disk_migrations if app in app_labels]
61
            )
59
            all_migrations = {
60
                (app, migration) for app, migration in loader.disk_migrations if app in app_labels
61
            }
62 62
            for tenant in TenantMiddleware.get_tenants():
63 63
                connection.set_tenant(tenant, include_public=False)
64 64
                applied_migrations = self.get_applied_migrations(app_labels)
hobo/multitenant/management/commands/runserver.py
40 40
        handler.
41 41

  
42 42
        """
43
        handler = super(Command, self).get_handler(*args, **options)
43
        handler = super().get_handler(*args, **options)
44 44
        use_static_handler = options.get('use_static_handler', True)
45 45
        insecure_serving = options.get('insecure_serving', False)
46 46
        if use_static_handler and (settings.DEBUG or insecure_serving):
hobo/multitenant/management/commands/shell.py
8 8

  
9 9
    def handle(self, *args, **kwargs):
10 10
        disable_global_logging()
11
        super(Command, self).handle(*args, **kwargs)
11
        super().handle(*args, **kwargs)
hobo/multitenant/management/commands/showmigrations_schemas.py
26 26
    help = "Show database schema migrations."
27 27

  
28 28
    def add_arguments(self, parser):
29
        super(ShowMigrationsSchemasCommand, self).add_arguments(parser)
29
        super().add_arguments(parser)
30 30
        command = ShowMigrationsCommand()
31 31
        command.add_arguments(parser)
32 32

  
33 33
    def handle(self, *args, **options):
34
        super(ShowMigrationsSchemasCommand, self).handle(*args, **options)
34
        super().handle(*args, **options)
35 35
        if self.domain:
36 36
            try:
37 37
                tenant = TenantMiddleware.get_tenant_by_hostname(self.domain)
38 38
            except TenantNotFound:
39
                raise RuntimeError('Schema "{}" does not exist'.format(self.schema_name))
39
                raise RuntimeError(f'Schema "{self.schema_name}" does not exist')
40 40
            self.run_showmigrations(tenant, settings.TENANT_APPS)
41 41
        else:
42 42
            for tenant in TenantMiddleware.get_tenants():
hobo/multitenant/management/commands/syncdb.py
21 21
            and not django_is_in_test_mode()
22 22
        ):
23 23
            raise CommandError(
24
                "syncdb has been disabled, for database '{0}'. "
24
                "syncdb has been disabled, for database '{}'. "
25 25
                "Use sync_schemas instead. Please read the "
26 26
                "documentation if you don't know why "
27 27
                "you shouldn't call syncdb directly!".format(database)
28 28
            )
29
        super(Command, self).handle(*args, **options)
29
        super().handle(*args, **options)
hobo/multitenant/management/commands/tenant_command.py
1
# -*- coding: utf-8 -*-
2 1
# this file derive from django-tenant-schemas
3 2
#   Author: Bernardo Pires Carneiro
4 3
#   Email: carneiro.be@gmail.com
......
141 140
                        print(prefix + msg)
142 141
                    continue
143 142
                if args_verbosity.verbosity > 1:
144
                    print(u'* Running command %s on tenant %s' % (command, tenant.domain_url))
143
                    print('* Running command %s on tenant %s' % (command, tenant.domain_url))
145 144
                error = run_command_from_argv(klass, args)
146 145
                if error:
147 146
                    errors.append(error)
hobo/multitenant/mellon.py
1
from __future__ import absolute_import
2

  
3 1
import json
4 2
import logging
5 3
import os
hobo/multitenant/models.py
20 20
        pass
21 21

  
22 22
    def __unicode__(self):
23
        return u'Tenant %s (%s)' % (self.domain_url, self.schema_name)
23
        return 'Tenant %s (%s)' % (self.domain_url, self.schema_name)
24 24

  
25 25
    def __str__(self):
26 26
        return 'Tenant %s (%s)' % (self.domain_url, self.schema_name)
hobo/multitenant/settings.py
27 27
    return getattr(import_module(module), attr)
28 28

  
29 29

  
30
class TenantSettingsWrapper(object):
30
class TenantSettingsWrapper:
31 31
    local = threading.local()
32 32

  
33 33
    def __init__(self, default_settings):
hobo/multitenant/settings_loaders.py
10 10
from hobo.theme.utils import get_theme
11 11

  
12 12

  
13
class FileBaseSettingsLoader(object):
13
class FileBaseSettingsLoader:
14 14
    """
15 15
    Base middleware class for loading settings from FILENAME.
16 16
    Child classes MUST override update_settings_from_path().
......
36 36
        raise NotImplemented
37 37

  
38 38

  
39
class SettingsDictUpdateMixin(object):
39
class SettingsDictUpdateMixin:
40 40
    def do_update(self, tenant_settings, key, value):
41 41
        old_value = getattr(tenant_settings, key, {})
42 42
        new_value = old_value.copy()
......
306 306
            break
307 307

  
308 308

  
309
class CookieNames(object):
309
class CookieNames:
310 310
    def get_new_time(self, tenant):
311 311
        return 0
312 312

  
......
395 395
            tenant_settings.MELLON_PRIVATE_KEY = saml_key
396 396

  
397 397

  
398
class SiteBaseUrl(object):
398
class SiteBaseUrl:
399 399
    def get_new_time(self, tenant):
400 400
        tenant_dir = os.path.join(settings.TENANT_BASE, tenant.domain_url)
401 401
        for filename in ['unsecure', 'base_url']:
hobo/multitenant/template_loader.py
19 19

  
20 20
class CachedLoader(DjangoCachedLoader):
21 21
    def cache_key(self, template_name, template_dirs, skip=None):
22
        key = super(CachedLoader, self).cache_key(template_name, template_dirs, skip=skip)
22
        key = super().cache_key(template_name, template_dirs, skip=skip)
23 23
        if connection.tenant:
24 24
            return connection.tenant.domain_url + '-' + key
25 25
        return key
......
51 51
                    known_dirnames = (
52 52
                        list(
53 53
                            itertools.chain(
54
                                *[
54
                                *(
55 55
                                    (
56 56
                                        '%s/variants/%s/portal-agent' % (x, theme_value),
57 57
                                        '%s/variants/%s' % (x, theme_value),
58 58
                                    )
59 59
                                    for x in known_dirnames
60
                                ]
60
                                )
61 61
                            )
62 62
                        )
63 63
                        + known_dirnames
......
66 66
                    known_dirnames = (
67 67
                        list(
68 68
                            itertools.chain(
69
                                *[
69
                                *(
70 70
                                    (
71 71
                                        '%s/variants/%s/portal-user' % (x, theme_value),
72 72
                                        '%s/variants/%s' % (x, theme_value),
73 73
                                    )
74 74
                                    for x in known_dirnames
75
                                ]
75
                                )
76 76
                            )
77 77
                        )
78 78
                        + known_dirnames
hobo/profile/migrations/0001_initial.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

  
hobo/profile/migrations/0002_add_data.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4 1
from django.db import migrations
5 2

  
6 3

  
......
8 5
    AttributeDefinition = apps.get_model('profile', 'AttributeDefinition')
9 6

  
10 7
    attributes = [
11
        {'label': u'Civilité', 'name': 'title', 'kind': 'title', 'disabled': True},
12
        {'label': u'Prénom', 'name': 'first_name', 'required': True, 'asked_on_registration': True},
13
        {'label': u'Nom', 'name': 'last_name', 'required': True, 'asked_on_registration': True},
14
        {'label': u'Adresse électronique', 'name': 'email', 'kind': 'email', 'required': True},
15
        {'label': u'Adresse', 'name': 'address'},
16
        {'label': u'Code postal', 'name': 'zipcode'},
17
        {'label': u'Commune', 'name': 'city'},
18
        {'label': u'Pays', 'name': 'country', 'disabled': True},
19
        {'label': u'Date de naissance', 'name': 'birthdate', 'kind': 'birthdate', 'disabled': True},
20
        {'label': u'Téléphone', 'name': 'phone', 'kind': 'phone_number'},
21
        {'label': u'Mobile', 'name': 'mobile', 'kind': 'phone_number'},
8
        {'label': 'Civilité', 'name': 'title', 'kind': 'title', 'disabled': True},
9
        {'label': 'Prénom', 'name': 'first_name', 'required': True, 'asked_on_registration': True},
10
        {'label': 'Nom', 'name': 'last_name', 'required': True, 'asked_on_registration': True},
11
        {'label': 'Adresse électronique', 'name': 'email', 'kind': 'email', 'required': True},
12
        {'label': 'Adresse', 'name': 'address'},
13
        {'label': 'Code postal', 'name': 'zipcode'},
14
        {'label': 'Commune', 'name': 'city'},
15
        {'label': 'Pays', 'name': 'country', 'disabled': True},
16
        {'label': 'Date de naissance', 'name': 'birthdate', 'kind': 'birthdate', 'disabled': True},
17
        {'label': 'Téléphone', 'name': 'phone', 'kind': 'phone_number'},
18
        {'label': 'Mobile', 'name': 'mobile', 'kind': 'phone_number'},
22 19
    ]
23 20

  
24 21
    for i, attribute_dict in enumerate(attributes):
hobo/profile/migrations/0003_attributedefinition_searchable.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.12 on 2019-01-01 09:46
3
from __future__ import unicode_literals
4 2

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

  
hobo/profile/migrations/0004_auto_20200518_1810.py
1
# -*- coding: utf-8 -*-
2 1
# Generated by Django 1.11.17 on 2020-05-18 18:10
3
from __future__ import unicode_literals
4 2

  
5 3
import django.core.validators
6 4
from django.db import migrations, models
hobo/profile/models.py
67 67
        ordering = ['order']
68 68

  
69 69
    def as_dict(self):
70
        as_dict = dict([(x, y) for (x, y) in self.__dict__.items() if type(y) in (str, bool)])
70
        as_dict = {x: y for (x, y) in self.__dict__.items() if type(y) in (str, bool)}
71 71
        return as_dict
72 72

  
73 73
    def get_real_kind_display(self):
......
78 78
    def save(self, *args, **kwargs):
79 79
        if self.order is None:
80 80
            self.order = max([0] + [x.order for x in AttributeDefinition.objects.all()]) + 1
81
        super(AttributeDefinition, self).save(*args, **kwargs)
81
        super().save(*args, **kwargs)
hobo/rest_authentication.py
90 90
class PublikAuthentication(authentication.BaseAuthentication):
91 91
    def __init__(self, *args, **kwargs):
92 92
        self.logger = logging.getLogger(__name__)
93
        super(PublikAuthentication, self).__init__(*args, **kwargs)
93
        super().__init__(*args, **kwargs)
94 94

  
95 95
    def resolve_user(self, request):
96 96
        User = get_user_model()
hobo/seo/views.py
42 42
    success_url = reverse_lazy('seo-home')
43 43

  
44 44
    def get_initial(self):
45
        initial = super(HomeView, self).get_initial()
45
        initial = super().get_initial()
46 46
        initial['meta_description'] = get_variable('meta_description').value
47 47
        initial['meta_keywords'] = get_variable('meta_keywords').value
48 48
        return initial
......
50 50
    def form_valid(self, form):
51 51
        set_variable('meta_description', form.cleaned_data['meta_description'])
52 52
        set_variable('meta_keywords', form.cleaned_data['meta_keywords'])
53
        return super(HomeView, self).form_valid(form)
53
        return super().form_valid(form)
54 54

  
55 55
    def get_context_data(self, **kwargs):
56
        context = super(HomeView, self).get_context_data(**kwargs)
56
        context = super().get_context_data(**kwargs)
57 57
        context['robots_txt'] = get_variable('robots_txt').value
58 58
        context['mode'] = get_mode(context['robots_txt'])
59 59
        return context
......
78 78
    success_url = reverse_lazy('seo-home')
79 79

  
80 80
    def get_initial(self):
81
        initial = super(CustomizeView, self).get_initial()
81
        initial = super().get_initial()
82 82
        initial['content'] = get_variable('robots_txt').value
83 83
        return initial
84 84

  
85 85
    def form_valid(self, form):
86 86
        set_variable('robots_txt', form.cleaned_data['content'])
87
        return super(CustomizeView, self).form_valid(form)
87
        return super().form_valid(form)
88 88

  
89 89

  
90 90
customize = CustomizeView.as_view()
hobo/theme/views.py
32 32
    template_name = 'hobo/theme_home.html'
33 33

  
34 34
    def get_context_data(self, **kwargs):
35
        context = super(HomeView, self).get_context_data(**kwargs)
35
        context = super().get_context_data(**kwargs)
36 36

  
37 37
        def hsv(theme):
38 38
            theme_colour = theme.get('variables').get('theme_color') or '#FFFFFF'
39 39
            if theme_colour == '#FFFFFF':
40 40
                return (1, 1, 1)
41 41
            theme_rgb = [int(x, 16) for x in (theme_colour[1:3], theme_colour[3:5], theme_colour[5:])]
42
            theme_hsv = colorsys.rgb_to_hsv(*[1.0 * x / 255 for x in theme_rgb])
42
            theme_hsv = colorsys.rgb_to_hsv(*(1.0 * x / 255 for x in theme_rgb))
43 43
            return theme_hsv
44 44

  
45 45
        context['themes'] = get_themes()
hobo/urls_utils.py
10 10

  
11 11
class DecoratedURLPattern(URLPattern):
12 12
    def resolve(self, *args, **kwargs):
13
        result = super(DecoratedURLPattern, self).resolve(*args, **kwargs)
13
        result = super().resolve(*args, **kwargs)
14 14
        if result:
15 15
            result.func = self._decorate_with(result.func)
16 16
        return result
......
18 18

  
19 19
class DecoratedRegexURLResolver(URLResolver):
20 20
    def resolve(self, *args, **kwargs):
21
        result = super(DecoratedRegexURLResolver, self).resolve(*args, **kwargs)
21
        result = super().resolve(*args, **kwargs)
22 22
        if result:
23 23
            result.func = self._decorate_with(result.func)
24 24
        return result
hobo/views.py
34 34
    template_name = 'hobo/home.html'
35 35

  
36 36
    def get_context_data(self, **kwargs):
37
        context = super(Home, self).get_context_data(**kwargs)
37
        context = super().get_context_data(**kwargs)
38 38
        context['services'] = [x for x in get_installed_services() if not x.secondary]
39 39
        context['has_authentic'] = bool(Authentic.objects.filter(secondary=False))
40 40
        context['has_global_title'] = Variable.objects.filter(name='global_title').exists()
setup.py
1 1
#! /usr/bin/env python
2
# -*- coding: utf-8 -*-
3 2

  
4 3
import glob
5 4
import os
......
31 30

  
32 31
def get_version():
33 32
    if os.path.exists('VERSION'):
34
        version_file = open('VERSION', 'r')
33
        version_file = open('VERSION')
35 34
        version = version_file.read()
36 35
        version_file.close()
37 36
        return version
tests/test_cook.py
1 1
import json
2 2
import os
3 3
from io import StringIO
4
from unittest.mock import Mock, call, mock_open, patch
4 5

  
5 6
import pytest
6 7
from django.contrib.auth.models import User
7 8
from django.contrib.contenttypes.models import ContentType
8 9
from django.core.management.base import CommandError
9
from mock import Mock, call, mock_open, patch
10 10

  
11 11
from hobo.environment.management.commands.cook import Command
12 12
from hobo.environment.models import (
......
30 30
    """no exception raised if url are available"""
31 31
    command = Command()
32 32
    command.server_action = 'mock a server_action handler (ex: hobo-create)'
33
    action, action_args = 'server-action', {u'url': u'https://test.org/'}
33
    action, action_args = 'server-action', {'url': 'https://test.org/'}
34 34

  
35 35
    monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
36 36
    monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
......
42 42
    """raise CommandError"""
43 43
    command = Command()
44 44
    command.server_action = 'mock a server_action handler (ex: hobo-create)'
45
    action, action_args = 'not-a-server-action', {u'url': u'https://test.org/'}
45
    action, action_args = 'not-a-server-action', {'url': 'https://test.org/'}
46 46

  
47 47
    monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
48 48
    monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
......
55 55
    """raise CommandError"""
56 56
    command = Command()
57 57
    command.server_action = 'mock a server_action handler (ex: hobo-create)'
58
    action, action_args = 'server-action', {u'url': u'https://test.org/'}
58
    action, action_args = 'server-action', {'url': 'https://test.org/'}
59 59

  
60 60
    monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: False)
61 61
    monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: True)
......
68 68
    """raise CommandError"""
69 69
    command = Command()
70 70
    command.server_action = 'mock a server_action handler (ex: hobo-create)'
71
    action, action_args = 'server-action', {u'url': u'https://test.org/'}
71
    action, action_args = 'server-action', {'url': 'https://test.org/'}
72 72

  
73 73
    monkeypatch.setattr(ServiceBase, 'is_resolvable', lambda x: True)
74 74
    monkeypatch.setattr(ServiceBase, 'has_valid_certificate', lambda x: False)
......
106 106
        handler.write(json.dumps(recipe))
107 107

  
108 108
    command.run_cook(recipe_path)
109
    assert command.check_action.mock_calls == [call(u'create-hobo', {u'url': u'https://entrouvert.org/'})]
110
    assert command.create_hobo.mock_calls == [call(url=u'https://entrouvert.org/')]
109
    assert command.check_action.mock_calls == [call('create-hobo', {'url': 'https://entrouvert.org/'})]
110
    assert command.create_hobo.mock_calls == [call(url='https://entrouvert.org/')]
111 111
    assert mocked_notify_agents.mock_calls == []
112 112
    assert command.wait_operationals.mock_calls == [call(timeout=42)]
113 113

  
......
123 123
        handler.write(json.dumps(recipe))
124 124

  
125 125
    command.run_cook(recipe_path)
126
    assert command.create_authentic.mock_calls == [call(title=u'Connexion', url=u'https://entrouvert.org/')]
126
    assert command.create_authentic.mock_calls == [call(title='Connexion', url='https://entrouvert.org/')]
127 127

  
128 128

  
129 129
def test_load_variables_from(db, tmpdir):
......
153 153
        handler.write(json.dumps(recipe))
154 154

  
155 155
    command.run_cook(recipe_path)
156
    assert command.create_hobo.mock_calls == [call(url=u'https://entrouvert.org/')]
157
    assert command.create_authentic.mock_calls == [call(url=u'https://foo1/')]
158
    assert command.create_combo.mock_calls == [call(not_a_string=[], url=u'https://bar2/')]
156
    assert command.create_hobo.mock_calls == [call(url='https://entrouvert.org/')]
157
    assert command.create_authentic.mock_calls == [call(url='https://foo1/')]
158
    assert command.create_combo.mock_calls == [call(not_a_string=[], url='https://bar2/')]
159 159

  
160 160

  
161 161
def test_wait_operationals(db, monkeypatch):
......
357 357
    with patch('hobo.environment.management.commands.cook.open', mocked_open, create=True):
358 358
        command.create_hobo('http://entrouvert.org/and_much')
359 359
    assert command.create_site.mock_calls == [
360
        call(Hobo, 'http://entrouvert.org/and_much', None, u'hobo-none', template_name='', variables=None)
360
        call(Hobo, 'http://entrouvert.org/and_much', None, 'hobo-none', template_name='', variables=None)
361 361
    ]
362 362
    assert mocked_call_command.mock_calls == []
363 363
    assert len(mocked_connection.set_tenant.mock_calls) == 1
tests/test_emails.py
4 4
import smtplib
5 5
import socket
6 6
import threading
7
from unittest import mock
7 8

  
8 9
import dns.resolver
9
import mock
10 10
import pytest
11 11
from django.core.exceptions import ValidationError
12 12
from django.utils.encoding import force_text
tests/test_environment.py
1
# -*- coding: utf-8 -*-
2 1
import json
3 2

  
4 3
import pytest
......
44 43
    with pytest.raises(ValidationError) as e:
45 44
        passerelle.clean()
46 45

  
47
    assert e.value.messages[0] == u'This slug is already used. It must be unique.'
46
    assert e.value.messages[0] == 'This slug is already used. It must be unique.'
48 47

  
49 48

  
50 49
def test_unique_title():
......
69 68
    with pytest.raises(ValidationError) as e:
70 69
        combo.clean()
71 70

  
72
    assert e.value.messages[0] == u'This title is already used. It must be unique.'
71
    assert e.value.messages[0] == 'This title is already used. It must be unique.'
73 72

  
74 73
    # secondary services can be added
75 74
    combo.secondary = True
tests/test_health_api.py
1 1
import json
2 2
import socket
3
from unittest.mock import MagicMock
3 4

  
4 5
import pytest
5 6
import requests
6 7
from django.core.cache import cache
7 8
from django.utils import timezone
8 9
from httmock import HTTMock, remember_called, urlmatch
9
from mock import MagicMock
10 10

  
11 11
from hobo.environment.models import Authentic, Combo
12 12

  
tests/test_hobo_deploy.py
4 4
import os
5 5
import sys
6 6
from io import StringIO
7
from unittest.mock import Mock, call, patch
7 8

  
8 9
import pytest
9
from mock import Mock, call, patch
10 10
from requests import Response, exceptions
11 11

  
12 12
from hobo.agent.common.management.commands.hobo_deploy import Command, CommandError, replace_file
......
21 21

  
22 22
    content = 'content of my new file'
23 23
    replace_file(path, content)
24
    with open(path, 'r') as handler:
24
    with open(path) as handler:
25 25
        assert handler.read() == content
26 26

  
27 27
    content = 'new content for my file'
28 28
    replace_file(path, content)
29
    with open(path, 'r') as handler:
29
    with open(path) as handler:
30 30
        assert handler.read() == content
31 31

  
32 32

  
......
164 164
                tenant,
165 165
            )
166 166
        ]
167
        with open(tenant_hobo_json, 'r') as handler:  # hobo.json file
167
        with open(tenant_hobo_json) as handler:  # hobo.json file
168 168
            content = json.load(handler)
169 169
        assert ENVIRONMENT['services'][0]['this'] is True  # new entry added
170 170
        assert json.dumps(content, sort_keys=True), json.dumps(ENVIRONMENT, sort_keys=True)
......
224 224
    tenant.domain_url = 'combo.dev.publik.love'
225 225

  
226 226
    command.generate_saml_keys(tenant)
227
    with open('%s/saml.key' % str(tmpdir), 'r') as handler:
227
    with open('%s/saml.key' % str(tmpdir)) as handler:
228 228
        key = handler.read()
229
    with open('%s/saml.crt' % str(tmpdir), 'r') as handler:
229
    with open('%s/saml.crt' % str(tmpdir)) as handler:
230 230
        crt = handler.read()
231 231

  
232 232
    # if files exist don't regenerate them
233 233
    command.generate_saml_keys(tenant)
234
    with open('%s/saml.key' % str(tmpdir), 'r') as handler:
234
    with open('%s/saml.key' % str(tmpdir)) as handler:
235 235
        assert key == handler.read()
236
    with open('%s/saml.crt' % str(tmpdir), 'r') as handler:
236
    with open('%s/saml.crt' % str(tmpdir)) as handler:
237 237
        assert crt == handler.read()
238 238

  
239 239

  
......
269 269
    # normal case (stop when configuration on a service success for this tenant)
270 270
    mocked_get.side_effect = [response1]
271 271
    command.configure_service_provider(ENVIRONMENT, tenant)
272
    with open(tenant_idp_metadata, 'r') as handler:
272
    with open(tenant_idp_metadata) as handler:
273 273
        assert handler.read() == 'my saml idp metadata (1)'
274 274

  
275 275
    # no 'idp_url' JSON entry
......
277 277
    os.remove(tenant_idp_metadata)
278 278
    command.configure_service_provider(env, tenant)
279 279
    with pytest.raises(IOError, match='No such file or directory'):
280
        open(tenant_idp_metadata, 'r')
280
        open(tenant_idp_metadata)
281 281

  
282 282
    # idp not available
283 283
    response1.status_code = 500
284 284
    mocked_get.side_effect = [exceptions.RequestException, response1]
285 285
    command.configure_service_provider(ENVIRONMENT, tenant)
286 286
    with pytest.raises(IOError, match='No such file or directory'):
287
        open(tenant_idp_metadata, 'r')
287
        open(tenant_idp_metadata)
288 288

  
289 289
    # case when idp is becoming available
290 290
    mocked_get.side_effect = [response1, response2]
291 291
    command.configure_service_provider(ENVIRONMENT, tenant)
292
    with open(tenant_idp_metadata, 'r') as handler:
292
    with open(tenant_idp_metadata) as handler:
293 293
        assert handler.read() == 'my saml idp metadata (2)'
294 294

  
295 295

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

  
5
import mock
6 5
import pytest
7 6
from django.contrib.auth.models import User
8 7
from test_manager import login
tests/test_import_template.py
1
import mock
1
from unittest import mock
2

  
2 3
import pytest
3 4
from django.conf import settings
4 5
from django.core.management import load_command_class
tests/test_maintenance.py
1
import mock
1
from unittest import mock
2

  
2 3
from test_manager import login
3 4

  
4 5
from hobo.environment.models import Variable
tests/test_matomo_utils.py
1
# -*- coding: utf-8 -*-
2

  
3 1
import json
2
from unittest import mock
4 3

  
5
import mock
6 4
import pytest
7 5
from django.test import override_settings
8 6
from django.utils.encoding import force_text
......
630 628
        content = PING_NOSTATUS_ERROR
631 629
        response.json = mock.MagicMock(return_value=json.loads(content))
632 630
        mocked_post.return_value = response
633
        with pytest.raises(MatomoException, match='internal error on ping \(status expected\)'):
631
        with pytest.raises(MatomoException, match=r'internal error on ping \(status expected\)'):
634 632
            matomo.create_fake_first_tracking_visit('42')
635 633

  
636 634
        # failure (no dict)
637 635
        content = PING_NODICT_ERROR
638 636
        response.json = mock.MagicMock(return_value=content)
639 637
        mocked_post.return_value = response
640
        with pytest.raises(MatomoException, match='internal error on ping \(dict expected\)'):
638
        with pytest.raises(MatomoException, match=r'internal error on ping \(dict expected\)'):
641 639
            matomo.create_fake_first_tracking_visit('42')
642 640

  
643 641
        # failure (no JSON)
644 642
        response.json = mock.MagicMock(side_effect=ValueError('not a JSON'))
645 643
        mocked_post.return_value = response
646
        with pytest.raises(MatomoException, match='internal error on ping \(JSON expected\)'):
644
        with pytest.raises(MatomoException, match=r'internal error on ping \(JSON expected\)'):
647 645
            matomo.create_fake_first_tracking_visit('42')
648 646

  
649 647
        # failure (status 500)
tests/test_matomo_views.py
1
# -*- coding: utf-8 -*-
2

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

  
6
import mock
7 5
import pytest
8 6
from django.contrib.auth.models import User
9 7
from django.test import override_settings
tests/test_settings_loaders.py
21 21
    env = get_hobo_json()
22 22
    fields = env['profile']['fields']
23 23
    assert [x['name'] for x in fields] == [
24
        u'title',
25
        u'first_name',
26
        u'last_name',
27
        u'email',
28
        u'address',
29
        u'zipcode',
30
        u'city',
31
        u'country',
32
        u'birthdate',
33
        u'phone',
34
        u'mobile',
24
        'title',
25
        'first_name',
26
        'last_name',
27
        'email',
28
        'address',
29
        'zipcode',
30
        'city',
31
        'country',
32
        'birthdate',
33
        'phone',
34
        'mobile',
35 35
    ]
36 36

  
37 37
    # swap title and mobile fields
......
44 44
    env = get_hobo_json()
45 45
    fields = env['profile']['fields']
46 46
    assert [x['name'] for x in fields] == [
47
        u'mobile',
48
        u'first_name',
49
        u'last_name',
50
        u'email',
51
        u'address',
52
        u'zipcode',
53
        u'city',
54
        u'country',
55
        u'birthdate',
56
        u'phone',
57
        u'title',
47
        'mobile',
48
        'first_name',
49
        'last_name',
50
        'email',
51
        'address',
52
        'zipcode',
53
        'city',
54
        'country',
55
        'birthdate',
56
        'phone',
57
        'title',
58 58
    ]
59 59

  
60 60
    assert [x['name'] for x in fields if x['disabled']] == ['country', 'birthdate', 'title']
61 61
    profile_fields = [x['name'] for x in fields if not x['disabled']]
62 62
    assert profile_fields == [
63
        u'mobile',
64
        u'first_name',
65
        u'last_name',
66
        u'email',
67
        u'address',
68
        u'zipcode',
69
        u'city',
70
        u'phone',
63
        'mobile',
64
        'first_name',
65
        'last_name',
66
        'email',
67
        'address',
68
        'zipcode',
69
        'city',
70
        'phone',
71 71
    ]
72 72

  
73 73
    # serialize hobo.json
......
82 82
    loader = AuthenticLoader()
83 83
    loader.update_settings_from_path(tenant_settings, path)
84 84
    assert tenant_settings.A2_PROFILE_FIELDS == profile_fields
85
    assert tenant_settings.A2_REQUIRED_FIELDS == [u'first_name', u'last_name', u'email']
86
    assert tenant_settings.A2_REGISTRATION_FIELDS == [u'first_name', u'last_name']
85
    assert tenant_settings.A2_REQUIRED_FIELDS == ['first_name', 'last_name', 'email']
86
    assert tenant_settings.A2_REGISTRATION_FIELDS == ['first_name', 'last_name']
87 87

  
88 88

  
89 89
def test_mellon_backoffice_login_hint_setting_from_path(tmpdir):
tests/test_signature.py
32 32
    assert '&nonce=' in signature.sign_url(URL, KEY)
33 33

  
34 34
    # Test unicode key conversion to UTF-8
35
    assert signature.check_url(signature.sign_url(URL, u'\xe9\xe9'), b'\xc3\xa9\xc3\xa9')
36
    assert signature.check_url(signature.sign_url(URL, b'\xc3\xa9\xc3\xa9'), u'\xe9\xe9')
35
    assert signature.check_url(signature.sign_url(URL, '\xe9\xe9'), b'\xc3\xa9\xc3\xa9')
36
    assert signature.check_url(signature.sign_url(URL, b'\xc3\xa9\xc3\xa9'), '\xe9\xe9')
37 37

  
38 38
    # Test timedelta parameter
39 39
    now = datetime.datetime.utcnow()
tests/test_theme.py
1
# -*- coding: utf-8 -*-
1
from unittest.mock import patch
2

  
2 3
import pytest
3 4
from django.core.exceptions import ValidationError
4
from mock import patch
5 5
from test_manager import login
6 6

  
7 7
from hobo.environment.models import Variable
tests/test_version.py
14 14

  
15 15
    settings.MIDDLEWARE = ('hobo.middleware.version.VersionMiddleware',) + tuple(settings.MIDDLEWARE)
16 16
    json_response = client.get('/__version__').json()
17
    assert set(json_response.keys()) == set(['pytest', 'pytest-django'])
17
    assert set(json_response.keys()) == {'pytest', 'pytest-django'}
tests_authentic/settings.py
1 1
import builtins
2 2
import os
3

  
4
from mock import mock_open, patch
3
from unittest.mock import mock_open, patch
5 4

  
6 5
import hobo.test_utils
7 6

  
tests_authentic/test_hobo_deploy.py
1
# -*- coding: utf-8 -*-
2 1
import json
3 2
import os
4 3
import shutil
5 4
import tempfile
6 5
import time
6
from unittest import mock
7 7

  
8
import mock
9 8
import pytest
10 9
from authentic2.data_transfer import export_site
11 10
from django.core.management import call_command
......
45 44
                {
46 45
                    'model': 'a2_rbac.role',
47 46
                    'fields': {
48
                        'name': u'Service petite enfance',
49
                        'slug': u'service-petite-enfance',
47
                        'name': 'Service petite enfance',
48
                        'slug': 'service-petite-enfance',
50 49
                    },
51 50
                },
52 51
                {
53 52
                    'model': 'a2_rbac.role',
54 53
                    'fields': {
55
                        'name': u'Service état-civil',
56
                        'slug': u'service-etat-civil',
54
                        'name': 'Service état-civil',
55
                        'slug': 'service-etat-civil',
57 56
                    },
58 57
                },
59 58
            ],
......
151 150
                    'description': '',
152 151
                    'required': False,
153 152
                    'user_visible': True,
154
                    'label': u'Civilité',
153
                    'label': 'Civilité',
155 154
                    'disabled': True,
156 155
                    'user_editable': True,
157 156
                    'asked_on_registration': False,
......
162 161
                    'description': '',
163 162
                    'required': True,
164 163
                    'user_visible': True,
165
                    'label': u'Prénom',
164
                    'label': 'Prénom',
166 165
                    'disabled': False,
167 166
                    'user_editable': True,
168 167
                    'asked_on_registration': True,
......
184 183
                    'description': '',
185 184
                    'required': True,
186 185
                    'user_visible': True,
187
                    'label': u'Adresse électronique',
186
                    'label': 'Adresse électronique',
188 187
                    'disabled': False,
189 188
                    'user_editable': True,
190 189
                    'asked_on_registration': False,
......
228 227
                    'description': '',
229 228
                    'required': False,
230 229
                    'user_visible': True,
231
                    'label': u'Téléphone',
230
                    'label': 'Téléphone',
232 231
                    'disabled': False,
233 232
                    'user_editable': True,
234 233
                    'asked_on_registration': False,
......
312 311
                'service-id': 'wcs',
313 312
                'template_name': 'commune',
314 313
                'slug': 'montpellier-metropole',
315
                'title': u'Montpellier-Métropole',
314
                'title': 'Montpellier-Métropole',
316 315
                'base_url': 'http://eservices.example.net',
317 316
                'saml-sp-metadata-url': 'http://eservices.example.net/saml/metadata',
318 317
            },
319 318
            {
320 319
                'service-id': 'passerelle',
321 320
                'slug': 'passerelle',
322
                'title': u'Passerelle',
321
                'title': 'Passerelle',
323 322
                'base_url': 'http://passerelle.example.net',
324 323
                'saml-sp-metadata-url': 'http://passerelle.example.net/saml/metadata',
325 324
            },
......
340 339
                'service-id': 'combo',
341 340
                'template_name': 'portal-user',
342 341
                'slug': 'portal',
343
                'title': u'Portail Montpellier-Métropole',
342
                'title': 'Portail Montpellier-Métropole',
344 343
                'base_url': 'http://portal.example.net',
345 344
                'saml-sp-metadata-url': 'http://portal.example.net/saml/metadata',
346 345
            },
......
364 363
    # check role mass provisionning to new services
365 364
    # two wcs => two ous => two audiences
366 365
    assert mock_notify.call_count == 2
367
    audiences = sorted([arg[0][0]['audience'] for arg in mock_notify.call_args_list])
366
    audiences = sorted(arg[0][0]['audience'] for arg in mock_notify.call_args_list)
368 367
    assert audiences == [
369 368
        ['http://clapiers.example.net/saml/metadata'],
370 369
        [
......
466 465
        # to their "ou" excluding their superuser role, 3 admin roles for users,
467 466
        # roles and services, and 2 loaded roles, petite enfance and état-civil
468 467
        assert Role.objects.filter(ou__isnull=False, service__isnull=True).count() == 10
469
        for service_id in set(s['service-id'] for s in other_services):
468
        for service_id in {s['service-id'] for s in other_services}:
470 469
            same_services = [s for s in other_services if s['service-id'] == service_id]
471 470
            for i, service in enumerate(same_services):
472 471
                assert LibertyProvider.objects.filter(slug=service['slug']).count() == 1
......
517 516
                    assert Role.objects.filter(ou=provider.ou, service__isnull=True).count() == 5
518 517
                    assert (
519 518
                        Role.objects.filter(
520
                            ou=provider.ou, service__isnull=True, name=u'Service petite enfance'
519
                            ou=provider.ou, service__isnull=True, name='Service petite enfance'
521 520
                        ).count()
522 521
                        == 1
523 522
                    )
524 523
                    assert (
525 524
                        Role.objects.filter(
526
                            ou=provider.ou, service__isnull=True, name=u'Service état-civil'
525
                            ou=provider.ou, service__isnull=True, name='Service état-civil'
527 526
                        ).count()
528 527
                        == 1
529 528
                    )
......
679 678
            {
680 679
                'service-id': 'passerelle',
681 680
                'slug': 'passerelle',
682
                'title': u'Passerelle',
681
                'title': 'Passerelle',
683 682
                'base_url': 'http://passerelle.example.net',
684 683
                'saml-sp-metadata-url': 'http://passerelle.example.net/saml/metadata',
685 684
            },
......
731 730
            {
732 731
                'service-id': 'passerelle',
733 732
                'slug': 'passerelle',
734
                'title': u'Passerelle',
733
                'title': 'Passerelle',
735 734
                'base_url': 'http://new-passerelle.example.net',
736 735
                'saml-sp-metadata-url': 'http://new-passerelle.example.net/saml/metadata',
737 736
                'legacy_urls': [
tests_authentic/test_provisionning.py
1
# -*- coding: utf-8 -*-
2

  
3 1
import json
4 2
import os
3
from unittest.mock import ANY, call, patch
5 4

  
6 5
import lasso
7 6
import pytest
......
13 12
from django.contrib.auth import get_user_model
14 13
from django.core.management import call_command
15 14
from django_rbac.utils import get_ou_model
16
from mock import ANY, call, patch
17 15
from tenant_schemas.utils import tenant_context
18 16

  
19 17
from hobo import signature
......
41 39
            assert arg == call(ANY)
42 40
            arg = arg[0][0]
43 41
            assert isinstance(arg, dict)
44
            assert set(arg.keys()) == set(['audience', '@type', 'objects', 'full'])
42
            assert set(arg.keys()) == {'audience', '@type', 'objects', 'full'}
45 43
            assert arg['audience'] == ['http://provider.com']
46 44
            assert arg['@type'] == 'provision'
47 45
            assert arg['full'] is False
48 46
            objects = arg['objects']
49 47
            assert isinstance(objects, dict)
50
            assert set(objects.keys()) == set(['data', '@type'])
48
            assert set(objects.keys()) == {'data', '@type'}
51 49
            assert objects['@type'] == 'role'
52 50
            data = objects['data']
53 51
            assert isinstance(data, list)
54 52
            assert len(data) == 1
55 53
            o = data[0]
56
            assert set(o.keys()) == set(
57
                ['details', 'emails_to_members', 'description', 'uuid', 'name', 'slug', 'emails']
58
            )
54
            assert set(o.keys()) == {
55
                'details',
56
                'emails_to_members',
57
                'description',
58
                'uuid',
59
                'name',
60
                'slug',
61
                'emails',
62
            }
59 63
            assert o['details'] == ''
60 64
            assert o['emails_to_members'] is True
61 65
            assert o['emails'] == []
......
73 77
            assert arg == call(ANY)
74 78
            arg = arg[0][0]
75 79
            assert isinstance(arg, dict)
76
            assert set(arg.keys()) == set(['audience', '@type', 'objects', 'full'])
80
            assert set(arg.keys()) == {'audience', '@type', 'objects', 'full'}
77 81
            assert arg['audience'] == ['http://provider.com']
78 82
            assert arg['@type'] == 'provision'
79 83
            assert arg['full'] is False
80 84
            objects = arg['objects']
81 85
            assert isinstance(objects, dict)
82
            assert set(objects.keys()) == set(['data', '@type'])
86
            assert set(objects.keys()) == {'data', '@type'}
83 87
            assert objects['@type'] == 'role'
84 88
            data = objects['data']
85 89
            assert isinstance(data, list)
86 90
            assert len(data) == 1
87 91
            o = data[0]
88
            assert set(o.keys()) == set(
89
                ['details', 'emails_to_members', 'description', 'uuid', 'name', 'slug', 'emails']
90
            )
92
            assert set(o.keys()) == {
93
                'details',
94
                'emails_to_members',
95
                'description',
96
                'uuid',
97
                'name',
98
                'slug',
99
                'emails',
100
            }
91 101
            assert o['details'] == ''
92 102
            assert o['emails_to_members'] is True
93 103
            assert o['emails'] == emails
......
101 111
            assert arg == call(ANY)
102 112
            arg = arg[0][0]
103 113
            assert isinstance(arg, dict)
104
            assert set(arg.keys()) == set(['audience', '@type', 'objects', 'full'])
114
            assert set(arg.keys()) == {'audience', '@type', 'objects', 'full'}
105 115
            assert arg['audience'] == ['http://provider.com']
106 116
            assert arg['@type'] == 'deprovision'
107 117
            assert arg['full'] is False
108 118
            objects = arg['objects']
109 119
            assert isinstance(objects, dict)
110
            assert set(objects.keys()) == set(['data', '@type'])
120
            assert set(objects.keys()) == {'data', '@type'}
111 121
            assert objects['@type'] == 'role'
112 122
            data = objects['data']
113 123
            assert isinstance(data, list)
114 124
            assert len(data) == 1
115 125
            o = data[0]
116
            assert set(o.keys()) == set(['uuid'])
126
            assert set(o.keys()) == {'uuid'}
117 127

  
118 128

  
119 129
def test_provision_user(transactional_db, tenant, caplog):
......
134 144
            attribute = Attribute.objects.create(label='Code postal', name='code_postal', kind='string')
135 145
            with provisionning:
136 146
                user1 = User.objects.create(
137
                    username=u'Étienne',
147
                    username='Étienne',
138 148
                    email='etienne.dugenou@example.net',
139
                    first_name=u'Étienne',
140
                    last_name=u'Dugenou',
149
                    first_name='Étienne',
150
                    last_name='Dugenou',
141 151
                    ou=get_default_ou(),
142 152
                )
143 153
                user2 = User.objects.create(
144
                    username=u'john.doe',
154
                    username='john.doe',
145 155
                    email='iohn.doe@example.net',
146
                    first_name=u'John',
147
                    last_name=u'Doe',
156
                    first_name='John',
157
                    last_name='Doe',
148 158
                    is_active=False,
149 159
                    ou=get_default_ou(),
150 160
                )
......
156 166
            assert arg == call(ANY)
157 167
            arg = arg[0][0]
158 168
            assert isinstance(arg, dict)
159
            assert set(arg.keys()) == set(['issuer', 'audience', '@type', 'objects', 'full'])
169
            assert set(arg.keys()) == {'issuer', 'audience', '@type', 'objects', 'full'}
160 170
            assert arg['issuer'] == 'https://%s/idp/saml2/metadata' % tenant.domain_url
161 171
            assert arg['audience'] == ['http://provider.com']
162 172
            assert arg['@type'] == 'provision'
163 173
            assert arg['full'] is False
164 174
            objects = arg['objects']
165 175
            assert isinstance(objects, dict)
166
            assert set(objects.keys()) == set(['data', '@type'])
176
            assert set(objects.keys()) == {'data', '@type'}
167 177
            assert objects['@type'] == 'user'
168 178
            data = objects['data']
169 179
            assert isinstance(data, list)
170 180
            assert len(data) == 2
171
            assert len(set([o['uuid'] for o in data])) == 2
181
            assert len({o['uuid'] for o in data}) == 2
172 182
            for o in data:
173
                assert set(o.keys()) >= set(
174
                    ['uuid', 'username', 'first_name', 'is_superuser', 'last_name', 'email', 'roles']
175
                )
183
                assert set(o.keys()) >= {
184
                    'uuid',
185
                    'username',
186
                    'first_name',
187
                    'is_superuser',
188
                    'last_name',
189
                    'email',
190
                    'roles',
191
                }
176 192
                assert o['uuid'] in users
177 193
                user = users[o['uuid']]
178 194
                assert o['username'] == user.username
......
197 213
            assert arg == call(ANY)
198 214
            arg = arg[0][0]
199 215
            assert isinstance(arg, dict)
200
            assert set(arg.keys()) == set(['issuer', 'audience', '@type', 'objects', 'full'])
216
            assert set(arg.keys()) == {'issuer', 'audience', '@type', 'objects', 'full'}
201 217
            assert arg['issuer'] == 'https://%s/idp/saml2/metadata' % tenant.domain_url
202 218
            assert arg['audience'] == ['http://provider.com']
203 219
            assert arg['@type'] == 'provision'
204 220
            assert arg['full'] is False
205 221
            objects = arg['objects']
206 222
            assert isinstance(objects, dict)
207
            assert set(objects.keys()) == set(['data', '@type'])
223
            assert set(objects.keys()) == {'data', '@type'}
208 224
            assert objects['@type'] == 'user'
209 225
            data = objects['data']
210 226
            assert isinstance(data, list)
211 227
            assert len(data) == 2
212 228
            for o, user in zip(data, [user1, user2]):
213
                assert set(o.keys()) >= set(
214
                    [
215
                        'code_postal',
216
                        'uuid',
217
                        'username',
218
                        'first_name',
219
                        'is_superuser',
220
                        'last_name',
221
                        'email',
222
                        'roles',
223
                    ]
224
                )
229
                assert set(o.keys()) >= {
230
                    'code_postal',
231
                    'uuid',
232
                    'username',
233
                    'first_name',
234
                    'is_superuser',
235
                    'last_name',
236
                    'email',
237
                    'roles',
238
                }
225 239
                assert o['uuid'] == user.uuid
226 240
                assert o['username'] == user.username
227 241
                assert o['first_name'] == user.first_name
......
235 249

  
236 250
            # test a service in a second OU also get the provisionning message
237 251
            notify_agents.reset_mock()
238
            ou2 = get_ou_model().objects.create(name=u'ou2', slug=u'ou2')
252
            ou2 = get_ou_model().objects.create(name='ou2', slug='ou2')
239 253
            LibertyProvider.objects.create(
240 254
                ou=ou2,
241 255
                name='provider2',
......
251 265
            assert notify_agents.call_count == 2
252 266
            assert set(
253 267
                notify_agents.mock_calls[0][1][0]['audience'] + notify_agents.mock_calls[1][1][0]['audience']
254
            ) == set(['http://provider.com', 'http://provider2.com'])
268
            ) == {'http://provider.com', 'http://provider2.com'}
255 269
            ou2.delete()
256 270

  
257 271
            notify_agents.reset_mock()
......
263 277
            assert arg == call(ANY)
264 278
            arg = arg[0][0]
265 279
            assert isinstance(arg, dict)
266
            assert set(arg.keys()) == set(['issuer', 'audience', '@type', 'objects', 'full'])
280
            assert set(arg.keys()) == {'issuer', 'audience', '@type', 'objects', 'full'}
267 281
            assert arg['issuer'] == 'https://%s/idp/saml2/metadata' % tenant.domain_url
268 282
            assert arg['audience'] == ['http://provider.com']
269 283
            assert arg['@type'] == 'provision'
270 284
            assert arg['full'] is False
271 285
            objects = arg['objects']
272 286
            assert isinstance(objects, dict)
273
            assert set(objects.keys()) == set(['data', '@type'])
287
            assert set(objects.keys()) == {'data', '@type'}
274 288
            assert objects['@type'] == 'user'
275 289
            data = objects['data']
276 290
            assert isinstance(data, list)
277 291
            assert len(data) == 1
278 292
            for o in data:
279
                assert set(o.keys()) >= set(
280
                    ['uuid', 'username', 'first_name', 'is_superuser', 'last_name', 'email', 'roles']
281
                )
293
                assert set(o.keys()) >= {
294
                    'uuid',
295
                    'username',
296
                    'first_name',
297
                    'is_superuser',
298
                    'last_name',
299
                    'email',
300
                    'roles',
301
                }
282 302
                assert o['uuid'] == user1.uuid
283 303
                assert o['username'] == user1.username
284 304
                assert o['first_name'] == user1.first_name
......
301 321
            assert arg == call(ANY)
302 322
            arg = arg[0][0]
303 323
            assert isinstance(arg, dict)
304
            assert set(arg.keys()) == set(['issuer', 'audience', '@type', 'objects', 'full'])
324
            assert set(arg.keys()) == {'issuer', 'audience', '@type', 'objects', 'full'}
305 325
            assert arg['issuer'] == 'https://%s/idp/saml2/metadata' % tenant.domain_url
306 326
            assert arg['audience'] == ['http://provider.com']
307 327
            assert arg['@type'] == 'provision'
308 328
            assert arg['full'] is False
309 329
            objects = arg['objects']
310 330
            assert isinstance(objects, dict)
311
            assert set(objects.keys()) == set(['data', '@type'])
331
            assert set(objects.keys()) == {'data', '@type'}
312 332
            assert objects['@type'] == 'user'
313 333
            data = objects['data']
314 334
            assert isinstance(data, list)
315 335
            assert len(data) == 2
316 336
            for o in data:
317
                assert set(o.keys()) >= set(
318
                    ['uuid', 'username', 'first_name', 'is_superuser', 'last_name', 'email', 'roles']
319
                )
337
                assert set(o.keys()) >= {
338
                    'uuid',
339
                    'username',
340
                    'first_name',
341
                    'is_superuser',
342
                    'last_name',
343
                    'email',
344
                    'roles',
345
                }
320 346
                assert o['uuid'] in users
321 347
                user = users[o['uuid']]
322 348
                assert o['uuid'] == user.uuid
......
328 354
                    {'name': r.name, 'slug': r.slug, 'uuid': r.uuid} for r in user.roles.all()
329 355
                ]
330 356
                assert o['is_superuser'] is (user == user1)
331
            assert len(set(x['uuid'] for x in notify_agents.call_args_list[1][0][0]['objects']['data'])) == 2
357
            assert len({x['uuid'] for x in notify_agents.call_args_list[1][0][0]['objects']['data']}) == 2
332 358

  
333 359
            notify_agents.reset_mock()
334 360
            with provisionning:
......
339 365
            assert arg == call(ANY)
340 366
            arg = arg[0][0]
341 367
            assert isinstance(arg, dict)
342
            assert set(arg.keys()) == set(['issuer', 'audience', '@type', 'objects', 'full'])
368
            assert set(arg.keys()) == {'issuer', 'audience', '@type', 'objects', 'full'}
343 369
            assert arg['issuer'] == 'https://%s/idp/saml2/metadata' % tenant.domain_url
344 370
            assert arg['audience'] == ['http://provider.com']
345 371
            assert arg['@type'] == 'provision'
346 372
            assert arg['full'] is False
347 373
            objects = arg['objects']
348 374
            assert isinstance(objects, dict)
349
            assert set(objects.keys()) == set(['data', '@type'])
375
            assert set(objects.keys()) == {'data', '@type'}
350 376
            assert objects['@type'] == 'user'
351 377
            data = objects['data']
352 378
            assert isinstance(data, list)
353 379
            assert len(data) == 1
354 380
            for o in data:
355
                assert set(o.keys()) >= set(
356
                    ['uuid', 'username', 'first_name', 'is_superuser', 'last_name', 'email', 'roles']
357
                )
381
                assert set(o.keys()) >= {
382
                    'uuid',
383
                    'username',
384
                    'first_name',
385
                    'is_superuser',
386
                    'last_name',
387
                    'email',
388
                    'roles',
389
                }
358 390
                assert o['uuid'] == user1.uuid
359 391
                assert o['username'] == user1.username
360 392
                assert o['first_name'] == user1.first_name
......
373 405
            assert arg == call(ANY)
374 406
            arg = arg[0][0]
375 407
            assert isinstance(arg, dict)
376
            assert set(arg.keys()) == set(['issuer', 'audience', '@type', 'objects', 'full'])
408
            assert set(arg.keys()) == {'issuer', 'audience', '@type', 'objects', 'full'}
377 409
            assert arg['issuer'] == 'https://%s/idp/saml2/metadata' % tenant.domain_url
378 410
            assert arg['audience'] == ['http://provider.com']
379 411
            assert arg['@type'] == 'provision'
380 412
            assert arg['full'] is False
381 413
            objects = arg['objects']
382 414
            assert isinstance(objects, dict)
383
            assert set(objects.keys()) == set(['data', '@type'])
415
            assert set(objects.keys()) == {'data', '@type'}
384 416
            assert objects['@type'] == 'user'
385 417
            data = objects['data']
386 418
            assert isinstance(data, list)
387 419
            assert len(data) == 1
388 420
            for o in data:
389
                assert set(o.keys()) >= set(
390
                    ['uuid', 'username', 'first_name', 'is_superuser', 'last_name', 'email', 'roles']
391
                )
421
                assert set(o.keys()) >= {
422
                    'uuid',
423
                    'username',
424
                    'first_name',
425
                    'is_superuser',
426
                    'last_name',
427
                    'email',
428
                    'roles',
429
                }
392 430
                assert o['uuid'] == user1.uuid
393 431
                assert o['username'] == user1.username
394 432
                assert o['first_name'] == user1.first_name
......
399 437
                    r1 = {'uuid': role.uuid, 'name': role.name, 'slug': role.slug}
400 438
                    r2 = {'uuid': child_role.uuid, 'name': child_role.name, 'slug': child_role.slug}
401 439
                    assert r == r1 or r == r2
402
                assert len(set(r['uuid'] for r in o['roles'])) == 2
440
                assert len({r['uuid'] for r in o['roles']}) == 2
403 441
                assert o['is_superuser'] is True
404 442

  
405 443
            notify_agents.reset_mock()
......
411 449
            assert arg == call(ANY)
412 450
            arg = arg[0][0]
413 451
            assert isinstance(arg, dict)
414
            assert set(arg.keys()) == set(['issuer', 'audience', '@type', 'objects', 'full'])
452
            assert set(arg.keys()) == {'issuer', 'audience', '@type', 'objects', 'full'}
415 453
            assert arg['issuer'] == 'https://%s/idp/saml2/metadata' % tenant.domain_url
416 454
            assert arg['audience'] == ['http://provider.com']
417 455
            assert arg['@type'] == 'provision'
418 456
            assert arg['full'] is False
419 457
            objects = arg['objects']
420 458
            assert isinstance(objects, dict)
421
            assert set(objects.keys()) == set(['data', '@type'])
459
            assert set(objects.keys()) == {'data', '@type'}
422 460
            assert objects['@type'] == 'user'
423 461
            data = objects['data']
424 462
            assert isinstance(data, list)
425 463
            assert len(data) == 1
426 464
            for o in data:
427
                assert set(o.keys()) >= set(
428
                    ['uuid', 'username', 'first_name', 'is_superuser', 'last_name', 'email', 'roles']
429
                )
465
                assert set(o.keys()) >= {
466
                    'uuid',
467
                    'username',
468
                    'first_name',
469
                    'is_superuser',
470
                    'last_name',
471
                    'email',
472
                    'roles',
473
                }
430 474
                assert o['uuid'] == user1.uuid
431 475
                assert o['username'] == user1.username
432 476
                assert o['first_name'] == user1.first_name
......
438 482
                assert o['is_superuser'] is False
439 483

  
440 484
            notify_agents.reset_mock()
441
            ou2 = get_ou_model().objects.create(name=u'ou2', slug=u'ou2')
485
            ou2 = get_ou_model().objects.create(name='ou2', slug='ou2')
442 486
            LibertyProvider.objects.create(
443 487
                ou=get_default_ou(),
444 488
                name='provider2',
......
454 498
            assert arg == call(ANY)
455 499
            arg = arg[0][0]
456 500
            assert isinstance(arg, dict)
457
            assert set(arg.keys()) == set(['issuer', 'audience', '@type', 'objects', 'full'])
501
            assert set(arg.keys()) == {'issuer', 'audience', '@type', 'objects', 'full'}
458 502
            assert arg['issuer'] == 'https://%s/idp/saml2/metadata' % tenant.domain_url
459
            assert set(arg['audience']) == set(['http://provider.com', 'http://provider2.com'])
503
            assert set(arg['audience']) == {'http://provider.com', 'http://provider2.com'}
460 504
            assert arg['@type'] == 'deprovision'
461 505
            assert arg['full'] is False
462 506
            objects = arg['objects']
463 507
            assert isinstance(objects, dict)
464
            assert set(objects.keys()) == set(['data', '@type'])
508
            assert set(objects.keys()) == {'data', '@type'}
465 509
            assert objects['@type'] == 'user'
466 510
            data = objects['data']
467 511
            assert isinstance(data, list)
468 512
            assert len(data) == 2
469
            assert len(set([o['uuid'] for o in data])) == 2
513
            assert len({o['uuid'] for o in data}) == 2
470 514
            for o in data:
471
                assert set(o.keys()) == set(['uuid'])
515
                assert set(o.keys()) == {'uuid'}
472 516
                assert o['uuid'] in users
473 517

  
474 518

  
tests_multipublik/settings.py
1 1
import builtins
2 2
import os.path
3

  
4
from mock import mock_open, patch
3
from unittest.mock import mock_open, patch
5 4

  
6 5
import hobo.test_utils
7 6
from hobo.settings import *
tests_multitenant/settings.py
1 1
import builtins
2 2
import os
3

  
4
from mock import mock_open, patch
3
from unittest.mock import mock_open, patch
5 4

  
6 5
import hobo.test_utils
7 6

  
tests_multitenant/test_agent_worker.py
1
# -*- coding: utf-8 -*-
2 1
import importlib
3 2
import json
4 3
import os
4
from unittest import mock
5 5

  
6
import mock
7 6
import pytest
8 7
from django.utils.encoding import force_text
9 8

  
......
11 10
from hobo.agent.worker.services import deploy, notify
12 11

  
13 12
ENVIRONMENT = {
14
    u'timestamp': '2022-02-22',
15
    u'services': [
13
    'timestamp': '2022-02-22',
14
    'services': [
16 15
        {
17
            u'service-id': u'hobo',
18
            u'slug': u'hobo',
19
            u'title': u'Hobo primary',
20
            u'base_url': u'https://hobo1.dev.publik.love/',
21
            u'this': True,
22
            u'secret_key': u'1nesüper5Cr!eteKAaY~',
16
            'service-id': 'hobo',
17
            'slug': 'hobo',
18
            'title': 'Hobo primary',
19
            'base_url': 'https://hobo1.dev.publik.love/',
20
            'this': True,
21
            'secret_key': '1nesüper5Cr!eteKAaY~',
23 22
        },
24 23
        {
25
            u'service-id': u'combo',
26
            u'slug': u'portal',
27
            u'title': u'Compte citoyen',
28
            u'base_url': u'https://combo.dev.publik.love/',
29
            u'secret_key': u'1nesüper5Cr!eteKAaY~',
24
            'service-id': 'combo',
25
            'slug': 'portal',
26
            'title': 'Compte citoyen',
27
            'base_url': 'https://combo.dev.publik.love/',
28
            'secret_key': '1nesüper5Cr!eteKAaY~',
30 29
        },
31 30
        {
32
            u'service-id': u'wcs',
33
            u'slug': u'eservices',
34
            u'title': u'Démarches',
35
            u'base_url': u'https://wcs.dev.publik.love/',
36
            u'secret_key': u'1nesüper5Cr!eteKAaY~',
31
            'service-id': 'wcs',
32
            'slug': 'eservices',
33
            'title': 'Démarches',
34
            'base_url': 'https://wcs.dev.publik.love/',
35
            'secret_key': '1nesüper5Cr!eteKAaY~',
37 36
        },
38 37
        {
39
            u'service-id': u'hobo',
40
            u'slug': u'hobo',
41
            u'title': u'skip beacause of agent host patterns',
42
            u'base_url': u'https://hobo2.dev.publik.love/',
43
            u'secondary': True,
44
            u'secret_key': u'1nesüper5Cr!eteKAaY~',
38
            'service-id': 'hobo',
39
            'slug': 'hobo',
40
            'title': 'skip beacause of agent host patterns',
41
            'base_url': 'https://hobo2.dev.publik.love/',
42
            'secondary': True,
43
            'secret_key': '1nesüper5Cr!eteKAaY~',
45 44
        },
46 45
        {
47
            u'service-id': u'passerelle',
48
            u'slug': u'passerelle',
49
            u'title': u'skipped because no secret_key',
50
            u'base_url': u'https://passerelle.dev.publik.love/',
46
            'service-id': 'passerelle',
47
            'slug': 'passerelle',
48
            'title': 'skipped because no secret_key',
49
            'base_url': 'https://passerelle.dev.publik.love/',
51 50
        },
52 51
        {
53
            u'service-id': u'unknown',
54
            u'title': u'skipped because unknown service-id',
52
            'service-id': 'unknown',
53
            'title': 'skipped because unknown service-id',
55 54
        },
56 55
    ],
57 56
}
......
96 95
    deploy(ENVIRONMENT)
97 96

  
98 97
    # process called
99
    mock_calls = set(x[1][0] for x in mocked_subprocess.Popen.mock_calls)
98
    mock_calls = {x[1][0] for x in mocked_subprocess.Popen.mock_calls}
100 99
    assert len(mock_calls) == 4
101 100
    assert '/usr/bin/hobo-manage hobo_deploy https://hobo1.dev.publik.love/ -' in mock_calls
102 101
    assert '/usr/bin/wcsctl hobo_deploy https://wcs.dev.publik.love/ -' in mock_calls
......
125 124
    importlib.reload(settings)
126 125
    deploy(ENVIRONMENT)
127 126
    # process called
128
    mock_calls = set(x[1][0] for x in mocked_subprocess.Popen.mock_calls)
127
    mock_calls = {x[1][0] for x in mocked_subprocess.Popen.mock_calls}
129 128
    assert len(mock_calls) == 3
130 129
    assert '/usr/bin/hobo-manage hobo_deploy https://hobo1.dev.publik.love/ -' in mock_calls
131 130
    assert '/usr/bin/wcsctl hobo_deploy https://wcs.dev.publik.love/ -' in mock_calls
......
146 145
    notify(NOTIFICATION)
147 146

  
148 147
    # process called
149
    mock_calls = set(x[1][0] for x in mocked_subprocess.Popen.mock_calls)
148
    mock_calls = {x[1][0] for x in mocked_subprocess.Popen.mock_calls}
150 149
    assert mock_calls == {'/usr/lib/combo/manage.py hobo_notify -'}
151 150

  
152 151
    # notification sent
tests_multitenant/test_create_tenant.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
import mock
17
from unittest import mock
18

  
18 19
import pytest
19 20
from django.contrib.auth.models import User
20 21
from django.core.management import call_command
tests_multitenant/test_hobo_notify.py
1
# -*- coding: utf-8 -*-
2

  
3 1
import logging
4 2

  
5 3
import pytest
......
20 18
    for tenant in tenants:
21 19
        with tenant_context(tenant):
22 20
            notification = {
23
                u'@type': u'provision',
24
                u'audience': [u'http://coin.com/saml/metadata'],
25
                u'objects': {
26
                    u'@type': 'role',
27
                    u'data': [
21
                '@type': 'provision',
22
                'audience': ['http://coin.com/saml/metadata'],
23
                'objects': {
24
                    '@type': 'role',
25
                    'data': [
28 26
                        {
29
                            u'uuid': u'12345',
30
                            u'name': u'Service petite enfance',
31
                            u'slug': u'service-petite-enfance',
32
                            u'description': u'Role du service petite enfance %s' % tenant.domain_url,
27
                            'uuid': '12345',
28
                            'name': 'Service petite enfance',
29
                            'slug': 'service-petite-enfance',
30
                            'description': 'Role du service petite enfance %s' % tenant.domain_url,
33 31
                        }
34 32
                    ],
35 33
                },
......
42 40
    for tenant in tenants:
43 41
        with tenant_context(tenant):
44 42
            notification = {
45
                u'@type': u'provision',
46
                u'audience': [u'%s/saml/metadata' % tenant.get_base_url()],
47
                u'objects': {
48
                    u'@type': 'role',
49
                    u'data': [
43
                '@type': 'provision',
44
                'audience': ['%s/saml/metadata' % tenant.get_base_url()],
45
                'objects': {
46
                    '@type': 'role',
47
                    'data': [
50 48
                        {
51
                            u'uuid': u'12345',
52
                            u'name': u'Service petite enfance',
53
                            u'slug': u'service-petite-enfance',
54
                            u'description': u'Role du service petite enfance %s' % tenant.domain_url,
55
                            u'details': u'Some details',
56
                            u'emails': [u'foo@bar.com', u'test@entrouvert.org'],
57
                            u'emails_to_members': False,
49
                            'uuid': '12345',
50
                            'name': 'Service petite enfance',
51
                            'slug': 'service-petite-enfance',
52
                            'description': 'Role du service petite enfance %s' % tenant.domain_url,
53
                            'details': 'Some details',
54
                            'emails': ['foo@bar.com', 'test@entrouvert.org'],
55
                            'emails_to_members': False,
58 56
                        }
59 57
                    ],
60 58
                },
......
63 61
            assert Group.objects.count() == 1
64 62
            assert Role.objects.count() == 1
65 63
            role = Role.objects.get()
66
            assert role.uuid == u'12345'
67
            assert role.name == u'Service petite enfance'
68
            assert role.description == u'Role du service petite enfance %s' % tenant.domain_url
69
            assert role.details == u'Some details'
70
            assert role.emails == [u'foo@bar.com', u'test@entrouvert.org']
64
            assert role.uuid == '12345'
65
            assert role.name == 'Service petite enfance'
66
            assert role.description == 'Role du service petite enfance %s' % tenant.domain_url
67
            assert role.details == 'Some details'
68
            assert role.emails == ['foo@bar.com', 'test@entrouvert.org']
71 69
            assert role.emails_to_members is False
72 70

  
73 71
    # test full provisionning
74 72
    for tenant in tenants:
75 73
        with tenant_context(tenant):
76 74
            notification = {
77
                u'@type': u'provision',
78
                u'full': True,
79
                u'audience': [u'%s/saml/metadata' % tenant.get_base_url()],
80
                u'objects': {
81
                    u'@type': 'role',
82
                    u'data': [
75
                '@type': 'provision',
76
                'full': True,
77
                'audience': ['%s/saml/metadata' % tenant.get_base_url()],
78
                'objects': {
79
                    '@type': 'role',
80
                    'data': [
83 81
                        {
84
                            u'uuid': u'xyz',
85
                            u'name': u'Service état civil',
86
                            u'slug': u'service-etat-civil',
87
                            u'description': u'Role du service état civil %s' % tenant.domain_url,
82
                            'uuid': 'xyz',
83
                            'name': 'Service état civil',
84
                            'slug': 'service-etat-civil',
85
                            'description': 'Role du service état civil %s' % tenant.domain_url,
88 86
                        }
89 87
                    ],
90 88
                },
......
93 91
            assert Group.objects.count() == 1
94 92
            assert Role.objects.count() == 1
95 93
            role = Role.objects.get()
96
            assert role.uuid == u'xyz'
97
            assert role.name == u'Service état civil'
98
            assert role.description == u'Role du service état civil %s' % tenant.domain_url
94
            assert role.uuid == 'xyz'
95
            assert role.name == 'Service état civil'
96
            assert role.description == 'Role du service état civil %s' % tenant.domain_url
99 97

  
100 98
    # test deprovision
101 99
    for tenant in tenants:
102 100
        with tenant_context(tenant):
103 101
            notification = {
104
                u'@type': u'deprovision',
105
                u'audience': [u'%s/saml/metadata' % tenant.get_base_url()],
106
                u'objects': {
107
                    u'@type': 'role',
108
                    u'data': [
102
                '@type': 'deprovision',
103
                'audience': ['%s/saml/metadata' % tenant.get_base_url()],
104
                'objects': {
105
                    '@type': 'role',
106
                    'data': [
109 107
                        {
110
                            u'uuid': u'xyz',
111
                            u'name': u'Service état civil',
112
                            u'slug': u'service-etat-civil',
113
                            u'description': u'Role du service état civil %s' % tenant.domain_url,
108
                            'uuid': 'xyz',
109
                            'name': 'Service état civil',
110
                            'slug': 'service-etat-civil',
111
                            'description': 'Role du service état civil %s' % tenant.domain_url,
114 112
                        }
115 113
                    ],
116 114
                },
......
123 121
    for tenant in tenants:
124 122
        with tenant_context(tenant):
125 123
            notification = {
126
                u'@type': u'provision',
127
                u'audience': [u'%s/saml/metadata' % tenant.get_base_url()],
128
                u'objects': {
129
                    u'@type': 'role',
130
                    u'data': [
124
                '@type': 'provision',
125
                'audience': ['%s/saml/metadata' % tenant.get_base_url()],
126
                'objects': {
127
                    '@type': 'role',
128
                    'data': [
131 129
                        {
132
                            u'uuid': u'12345',
133
                            u'name': u'Service petite enfance',
134
                            u'slug': u'service-petite-enfance',
135
                            u'description': u'Role du service petite enfance %s' % tenant.domain_url,
130
                            'uuid': '12345',
131
                            'name': 'Service petite enfance',
132
                            'slug': 'service-petite-enfance',
133
                            'description': 'Role du service petite enfance %s' % tenant.domain_url,
136 134
                        }
137 135
                    ],
138 136
                },
......
142 140
            assert Role.objects.count() == 1
143 141
            # test update by uuid
144 142
            notification = {
145
                u'@type': u'provision',
146
                u'audience': [u'%s/saml/metadata' % tenant.get_base_url()],
147
                u'objects': {
148
                    u'@type': 'role',
149
                    u'data': [
143
                '@type': 'provision',
144
                'audience': ['%s/saml/metadata' % tenant.get_base_url()],
145
                'objects': {
146
                    '@type': 'role',
147
                    'data': [
150 148
                        {
151
                            u'uuid': u'12345',
152
                            u'name': u'Service petite enfance2',
153
                            u'slug': u'service-petite-enfance2',
154
                            u'description': u'Role du service petite enfance %s' % tenant.domain_url,
149
                            'uuid': '12345',
150
                            'name': 'Service petite enfance2',
151
                            'slug': 'service-petite-enfance2',
152
                            'description': 'Role du service petite enfance %s' % tenant.domain_url,
155 153
                        }
156 154
                    ],
157 155
                },
......
162 160
            assert Role.objects.get().name == notification['objects']['data'][0]['name']
163 161
            # test uuid change
164 162
            notification = {
165
                u'@type': u'provision',
166
                u'audience': [u'%s/saml/metadata' % tenant.get_base_url()],
167
                u'objects': {
168
                    u'@type': 'role',
169
                    u'data': [
163
                '@type': 'provision',
164
                'audience': ['%s/saml/metadata' % tenant.get_base_url()],
165
                'objects': {
166
                    '@type': 'role',
167
                    'data': [
170 168
                        {
171
                            u'uuid': u'xyz',
172
                            u'name': u'Service petite enfance2',
173
                            u'slug': u'service-petite-enfance2',
174
                            u'description': u'Role du service petite enfance %s' % tenant.domain_url,
169
                            'uuid': 'xyz',
170
                            'name': 'Service petite enfance2',
171
                            'slug': 'service-petite-enfance2',
172
                            'description': 'Role du service petite enfance %s' % tenant.domain_url,
175 173
                        }
176 174
                    ],
177 175
                },
......
184 182
            Role.objects.create(uuid='12345', name='Foo', description='foo')
185 183
            assert Role.objects.count() == 2
186 184
            notification = {
187
                u'@type': u'provision',
188
                u'audience': [u'%s/saml/metadata' % tenant.get_base_url()],
189
                u'objects': {
190
                    u'@type': 'role',
191
                    u'data': [
185
                '@type': 'provision',
186
                'audience': ['%s/saml/metadata' % tenant.get_base_url()],
187
                'objects': {
188
                    '@type': 'role',
189
                    'data': [
192 190
                        {
193
                            u'uuid': u'12345',
194
                            u'name': u'Service petite enfance2',
195
                            u'slug': u'service-petite-enfance2',
196
                            u'description': u'Role du service petite enfance %s' % tenant.domain_url,
191
                            'uuid': '12345',
192
                            'name': 'Service petite enfance2',
193
                            'slug': 'service-petite-enfance2',
194
                            'description': 'Role du service petite enfance %s' % tenant.domain_url,
197 195
                        }
198 196
                    ],
199 197
                },
......
201 199
            Command.process_notification(tenant, notification)
202 200
            assert Group.objects.count() == 2
203 201
            assert Role.objects.count() == 2
204
            assert Role.objects.filter(uuid='12345', name=u'Service petite enfance').count() == 0
202
            assert Role.objects.filter(uuid='12345', name='Service petite enfance').count() == 0
205 203
            assert caplog.records[-1].levelno == logging.ERROR
206 204
            assert caplog.records[-1].msg.startswith('cannot provision')
207
            assert caplog.records[-1].args == (u'Service petite enfance2', u'12345')
205
            assert caplog.records[-1].args == ('Service petite enfance2', '12345')
208 206

  
209 207

  
210 208
def test_hobo_notify_roles_db_queries(caplog, tenants):
......
358 356
    for tenant in tenants:
359 357
        with tenant_context(tenant):
360 358
            notification = {
361
                u'@type': u'provision',
362
                u'audience': [u'%s/saml/metadata' % tenant.get_base_url()],
363
                u'objects': {
364
                    u'@type': 'role',
365
                    u'data': [
359
                '@type': 'provision',
360
                'audience': ['%s/saml/metadata' % tenant.get_base_url()],
361
                'objects': {
362
                    '@type': 'role',
363
                    'data': [
366 364
                        {
367
                            u'uuid': u'12345',
368
                            u'name': u'Service petite enfance',
369
                            u'slug': u'service-petite-enfance',
370
                            u'description': u'Role du service petite enfance %s' % tenant.domain_url,
365
                            'uuid': '12345',
366
                            'name': 'Service petite enfance',
367
                            'slug': 'service-petite-enfance',
368
                            'description': 'Role du service petite enfance %s' % tenant.domain_url,
371 369
                        }
372 370
                    ],
373 371
                },
......
376 374
            assert Group.objects.count() == 1
377 375
            assert Role.objects.count() == 1
378 376
            role = Role.objects.get()
379
            assert role.uuid == u'12345'
380
            assert role.name == u'Service petite enfance'
381
            assert role.description == u'Role du service petite enfance %s' % tenant.domain_url
377
            assert role.uuid == '12345'
378
            assert role.name == 'Service petite enfance'
379
            assert role.description == 'Role du service petite enfance %s' % tenant.domain_url
382 380

  
383 381
    # test user provisionning
384 382
    for tenant in tenants:
385 383
        with tenant_context(tenant):
386 384
            notification = {
387
                u'@type': u'provision',
388
                u'issuer': 'http://idp.example.net/idp/saml/metadata',
389
                u'audience': [u'%s/saml/metadata' % tenant.get_base_url()],
390
                u'objects': {
391
                    u'@type': 'user',
392
                    u'data': [
385
                '@type': 'provision',
386
                'issuer': 'http://idp.example.net/idp/saml/metadata',
387
                'audience': ['%s/saml/metadata' % tenant.get_base_url()],
388
                'objects': {
389
                    '@type': 'user',
390
                    'data': [
393 391
                        {
394
                            u'uuid': u'a' * 32,
395
                            u'first_name': u'John',
396
                            u'last_name': u'Doe',
397
                            u'email': u'john.doe@example.net',
398
                            u'is_superuser': False,
399
                            u'roles': [
392
                            'uuid': 'a' * 32,
393
                            'first_name': 'John',
394
                            'last_name': 'Doe',
395
                            'email': 'john.doe@example.net',
396
                            'is_superuser': False,
397
                            'roles': [
400 398
                                {
401
                                    u'uuid': u'12345',
402
                                    u'name': u'Service petite enfance',
403
                                    u'description': u'etc.',
399
                                    'uuid': '12345',
400
                                    'name': 'Service petite enfance',
401
                                    'description': 'etc.',
404 402
                                },
405 403
                                {
406
                                    u'uuid': u'xyz',
407
                                    u'name': u'Service état civil',
408
                                    u'description': u'etc.',
404
                                    'uuid': 'xyz',
405
                                    'name': 'Service état civil',
406
                                    'description': 'etc.',
409 407
                                },
410 408
                            ],
411 409
                        }
......
437 435
    for tenant in tenants:
438 436
        with tenant_context(tenant):
439 437
            notification = {
440
                u'@type': u'provision',
441
                u'issuer': 'http://idp.example.net/idp/saml/metadata',
442
                u'audience': [u'%s/saml/metadata' % tenant.get_base_url()],
443
                u'objects': {
444
                    u'@type': 'user',
445
                    u'data': [
438
                '@type': 'provision',
439
                'issuer': 'http://idp.example.net/idp/saml/metadata',
440
                'audience': ['%s/saml/metadata' % tenant.get_base_url()],
441
                'objects': {
442
                    '@type': 'user',
443
                    'data': [
446 444
                        {
447
                            u'uuid': u'a' * 32,
448
                            u'first_name': u'John',
449
                            u'last_name': u'Doe',
450
                            u'email': u'john.doe@example.net',
451
                            u'is_superuser': True,
452
                            u'roles': [
445
                            'uuid': 'a' * 32,
446
                            'first_name': 'John',
447
                            'last_name': 'Doe',
448
                            'email': 'john.doe@example.net',
449
                            'is_superuser': True,
450
                            'roles': [
453 451
                                {
454
                                    u'uuid': u'12345',
455
                                    u'name': u'Service petite enfance',
456
                                    u'description': u'etc.',
452
                                    'uuid': '12345',
453
                                    'name': 'Service petite enfance',
454
                                    'description': 'etc.',
457 455
                                },
458 456
                                {
459
                                    u'uuid': u'xyz',
460
                                    u'name': u'Service état civil',
461
                                    u'description': u'etc.',
457
                                    'uuid': 'xyz',
458
                                    'name': 'Service état civil',
459
                                    'description': 'etc.',
462 460
                                },
463 461
                            ],
464 462
                        }
......
490 488
    for tenant in tenants:
491 489
        with tenant_context(tenant):
492 490
            notification = {
493
                u'@type': u'deprovision',
494
                u'issuer': 'http://idp.example.net/idp/saml/metadata',
495
                u'audience': [u'%s/saml/metadata' % tenant.get_base_url()],
496
                u'objects': {
497
                    u'@type': 'user',
498
                    u'data': [
491
                '@type': 'deprovision',
492
                'issuer': 'http://idp.example.net/idp/saml/metadata',
493
                'audience': ['%s/saml/metadata' % tenant.get_base_url()],
494
                'objects': {
495
                    '@type': 'user',
496
                    'data': [
499 497
                        {
500
                            u'uuid': u'a' * 32,
498
                            'uuid': 'a' * 32,
501 499
                        }
502 500
                    ],
503 501
                },
tests_multitenant/test_middleware.py
1
from __future__ import unicode_literals
2

  
3 1
import pytest
4 2

  
5 3
from hobo.multitenant.middleware import TenantMiddleware
tests_multitenant/test_settings.py
193 193
            assert 'authentic' in settings.KNOWN_SERVICES
194 194
            assert 'other' in settings.KNOWN_SERVICES['authentic']
195 195
            authentic_other_keys = set(settings.KNOWN_SERVICES['authentic']['other'].keys())
196
            assert (
197
                set(
198
                    [
199
                        'url',
200
                        'backoffice-menu-url',
201
                        'title',
202
                        'orig',
203
                        'verif_orig',
204
                        'secret',
205
                        'template_name',
206
                        'variables',
207
                        'saml-sp-metadata-url',
208
                        'provisionning-url',
209
                        'secondary',
210
                    ]
211
                )
212
                == authentic_other_keys
213
            )
196
            assert {
197
                'url',
198
                'backoffice-menu-url',
199
                'title',
200
                'orig',
201
                'verif_orig',
202
                'secret',
203
                'template_name',
204
                'variables',
205
                'saml-sp-metadata-url',
206
                'provisionning-url',
207
                'secondary',
208
            } == authentic_other_keys
214 209
            assert (
215 210
                settings.KNOWN_SERVICES['authentic']['other']['url'] == hobo_json['services'][2]['base_url']
216 211
            )
tests_multitenant/test_tenant_command.py
1
# -*- coding: utf-8 -*-
2

  
3 1
import json
4 2
import os
5 3
import sys
4
from unittest import mock
6 5

  
7
import mock
8 6
import pytest
9 7
from django.core.management import BaseCommand, call_command, load_command_class
10 8
from django.core.management.base import CommandError
......
15 13
pytestmark = pytest.mark.django_db
16 14

  
17 15

  
18
class RecordTenant(object):
16
class RecordTenant:
19 17
    def __init__(self):
20 18
        self.tenants = []
21 19

  
......
41 39
    execute_from_command_line(['manage.py', 'tenant_command', 'clearsessions', '--all-tenants'])
42 40
    assert handle.call_count == 2
43 41
    assert len(handle.side_effect.tenants) == 2
44
    assert set(tenant.domain_url for tenant in handle.side_effect.tenants) == set(
45
        ['tenant1.example.net', 'tenant2.example.net']
46
    )
42
    assert {tenant.domain_url for tenant in handle.side_effect.tenants} == {
43
        'tenant1.example.net',
44
        'tenant2.example.net',
45
    }
47 46

  
48 47

  
49 48
@mock.patch('django.contrib.sessions.management.commands.clearsessions.Command.handle')
......
127 126

  
128 127
    class UnicodeErrorCommand(BaseCommand):
129 128
        def handle(self, *args, **kwargs):
130
            raise Exception(u'héhé')
129
            raise Exception('héhé')
131 130

  
132 131
    class BytesErrorCommand(BaseCommand):
133 132
        def handle(self, *args, **kwargs):
......
135 134

  
136 135
    class MixOfBothCommand(BaseCommand):
137 136
        def handle(self, *args, **kwargs):
138
            raise Exception([force_bytes('héhé'), u'hého'])
137
            raise Exception([force_bytes('héhé'), 'hého'])
139 138

  
140 139
    class WtfExceptionCommand(BaseCommand):
141 140
        def handle(self, *args, **kwargs):
......
166 165
    with pytest.raises(SystemExit):
167 166
        klass.run_from_argv(['manage.py', 'tenant_command', 'uni-error', '--all-tenants'])
168 167
    captured = capsys.readouterr()
169
    assert u'Tenant tenant1.example.net (tenant1_example_net): Exception: héhé' in captured.err
170
    assert u'Tenant tenant2.example.net (tenant2_example_net): Exception: héhé' in captured.err
171
    assert u'Command failed on multiple tenants' in captured.err
168
    assert 'Tenant tenant1.example.net (tenant1_example_net): Exception: héhé' in captured.err
169
    assert 'Tenant tenant2.example.net (tenant2_example_net): Exception: héhé' in captured.err
170
    assert 'Command failed on multiple tenants' in captured.err
172 171

  
173 172
    with pytest.raises(SystemExit):
174 173
        klass.run_from_argv(['manage.py', 'tenant_command', 'bytes-error', '--all-tenants'])
......
181 180

  
182 181
    captured = capsys.readouterr()
183 182
    assert repr(force_bytes('héhé')) in captured.err
184
    assert repr(u'hého') in captured.err
183
    assert repr('hého') in captured.err
185 184

  
186 185
    with pytest.raises(SystemExit):
187 186
        klass.run_from_argv(['manage.py', 'tenant_command', 'wtf-error', '--all-tenants'])
tests_multitenant/test_uwsgidecorators.py
1 1
import importlib
2 2
import pickle
3
from unittest import mock
3 4

  
4
import mock
5 5
import pytest
6 6

  
7 7
import hobo.multitenant.uwsgidecorators
tests_multitenant/utilities.py
1
class PatchDefaultSettings(object):
1
class PatchDefaultSettings:
2 2
    empty = object()
3 3

  
4 4
    def __init__(self, settings, **kwargs):
tests_passerelle/settings.py
1 1
import builtins
2 2
import os
3

  
4
from mock import mock_open, patch
3
from unittest.mock import mock_open, patch
5 4

  
6 5
import hobo.test_utils
7 6

  
tests_schemas/test_cook.py
39 39
    # below JSON file was created by this instruction
40 40
    # json.dump(environment, open('tests_schemas/example_env.json', 'w'),
41 41
    #          sort_keys=True, indent=4, separators=(',', ': '))
42
    expected_env = json.load(open('tests_schemas/example_env.json', 'r'))
42
    expected_env = json.load(open('tests_schemas/example_env.json'))
43 43

  
44 44
    # remove secret_key and timestamp values that alway change
45 45
    environment['timestamp'] = 'XXXXXXXXXX.XX'
tests_schemas/test_hobo_deploy.py
1 1
import os
2
from unittest import mock
2 3

  
3
import mock
4 4
import pytest
5 5
from django.core.management import call_command, get_commands, load_command_class
6 6
from tenant_schemas.utils import tenant_context
tests_schemas/test_import_template.py
1 1
import os
2
from unittest import mock
2 3

  
3
import mock
4 4
import pytest
5 5
from django.core.management import call_command, load_command_class
6 6

  
tests_schemas/test_rename_hobo_service.py
1
from unittest.mock import Mock
2

  
1 3
import pytest
2 4
from django.core.management import call_command
3 5
from django.core.management.base import CommandError
4
from mock import Mock
5 6
from tenant_schemas.utils import tenant_context
6 7

  
7 8
from hobo.environment.models import Passerelle, ServiceBase
tests_schemas/test_rename_service.py
1
from unittest.mock import Mock
2

  
1 3
import pytest
2 4
from django.core.management import call_command
3 5
from django.core.management.base import CommandError
4
from mock import Mock
5 6
from tenant_schemas.utils import tenant_context
6 7

  
7 8
from hobo.environment.models import Passerelle, ServiceBase
8
-