Skip to content

Commit 448451a

Browse files
committed
Django's version is now "3.0".
TODO: re-activate eslint (see .githooks/pre-commit & .githooks/pre-push ) Notes: - django.utils.encoding.force_text() => force_str() - django.utils.html.escape() converts now ' to &#x27; instead of &#39;. - django.utils.http.urlquote() => urllib.parse.quote() - django.utils.http.is_safe_url() => url_has_allowed_host_and_scheme() - Use the old ContentType__str__() method. - The decorator @xframe_options_sameorigin has been used on views which are designed to be displayed in <iframe> (HTML bodies of emails).
1 parent 21e7751 commit 448451a

39 files changed

+206
-136
lines changed

.githooks/pre-commit

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
. .githooks/toolkit
44

5-
PRE_COMMIT_CHECKS=${PRE_COMMIT_CHECKS-"flake8 isort eslint headers"}
5+
#PRE_COMMIT_CHECKS=${PRE_COMMIT_CHECKS-"flake8 isort eslint headers"}
6+
PRE_COMMIT_CHECKS=${PRE_COMMIT_CHECKS-"flake8 isort headers"}
67

78
hook_check_isort() {
89
git diff HEAD~1 --name-only --diff-filter=MARC | { grep '.py$' || true; } | xargs --no-run-if-empty isort --check --diff --atomic

.githooks/pre-push

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
. .githooks/toolkit
44

5-
PRE_PUSH_CHECKS=${PRE_PUSH_CHECKS-"flake8 isort eslint signature"}
5+
#PRE_PUSH_CHECKS=${PRE_PUSH_CHECKS-"flake8 isort eslint signature"}
6+
PRE_PUSH_CHECKS=${PRE_PUSH_CHECKS-"flake8 isort signature"}
67
GIT_PARENT_BRANCH="${GIT_PARENT_BRANCH:-main}"
78

89
hook_check_isort() {

CHANGELOG.txt

+15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
11
== Version 2.3 Work in progress (not released -- this is a draft) ==
22

3+
UPGRADE NOTE :
4+
- You should create a all new virtual environment based on Python 3.6+
5+
(eg: "mkvirtualenv -p /usr/bin/python3XX" if you use 'mkvirtualenv')
6+
and populate it with "pip install -e .[mysql|pgsql]" of course.
7+
- Execute the well known commands "migrate", "generatemedia" & "creme_populate".
8+
9+
Users side :
10+
------------
11+
# The version of Django has been upgraded to 3.0.
12+
13+
314
Developers side :
415
-----------------
16+
- The version of Django is now "3.0".
17+
You should probably read the following releases notes for Django versions :
18+
- https://docs.djangoproject.com/en/3.2/releases/3.0/
19+
520

621
Non breaking changes :
722
----------------------

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ virtual env, in order to keep the old one working).
6969
- These python packages :
7070
(exact versions of Python packages are indicated in the 'setup.cfg' file)
7171
- Mandatory :
72-
- Django 2.2
72+
- Django 3.0
7373
- redis 3.4
7474
- python-dateutil 2.8
7575
- bleach 3.1
@@ -92,7 +92,7 @@ Installation with 'pip':
9292
- You should probably use "virtualenv" (on a Python >= 3.6).
9393
- Creme should be installed using 'pip install -e .'
9494
- About DB server :
95-
- If you use MySQL, you must add the 'mysql' flag:
95+
- If you use MySQL/MariaDB, you must add the 'mysql' flag:
9696
'pip install .[mysql]'
9797
- For PostGreSQL, use 'pip install .[pgsql]' instead.
9898
- SQLite doesn't require a specific flag (see RECOMMENDATIONS).

creme/activities/tests/test_activity.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from django.forms import ModelMultipleChoiceField
1010
from django.forms.utils import ValidationError
1111
from django.urls import reverse
12-
from django.utils.encoding import force_text
12+
from django.utils.encoding import force_str # force_text
1313
from django.utils.timezone import now
1414
from django.utils.translation import gettext as _
1515

@@ -2325,7 +2325,8 @@ def test_dl_ical(self):
23252325
self.assertEqual('text/calendar', response['Content-Type'])
23262326
self.assertEqual('attachment; filename=Calendar.ics', response['Content-Disposition'])
23272327

2328-
content = force_text(response.content)
2328+
# content = force_text(response.content)
2329+
content = force_str(response.content)
23292330
self.assertStartsWith(
23302331
content,
23312332
'BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//CremeCRM//CremeCRM//EN\n'

creme/billing/tests/test_convert.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from django.contrib.contenttypes.models import ContentType
88
from django.db.models.query_utils import Q
99
from django.urls import reverse
10-
from django.utils.encoding import force_text
10+
from django.utils.encoding import force_str # force_text
1111
from django.utils.timezone import now
1212
from django.utils.translation import gettext as _
1313

@@ -214,8 +214,9 @@ def test_convert02_ajax(self):
214214
self.assertEqual(1, SalesOrder.objects.count())
215215

216216
self.assertEqual(
217-
force_text(response.content),
218-
SalesOrder.objects.first().get_absolute_url()
217+
# force_text(response.content),
218+
force_str(response.content),
219+
SalesOrder.objects.first().get_absolute_url(),
219220
)
220221

221222
@skipIfCustomQuote

creme/creme_core/apps.py

+4
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ def ready(self):
156156
for fname in ('app_label', 'model'):
157157
get_ct_field(fname).set_tags(viewable=False)
158158

159+
# NB: the original prefix with app's name => ugly choices for final users
160+
# => use gettext+context had smooth translation instead
161+
ContentType.__str__ = lambda this: this.name
162+
159163

160164
class CremeAppConfig(AppConfig):
161165
# True => App can be used by some services

creme/creme_core/management/commands/build_secret_key.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def handle(self, **options):
4949
from hashlib import sha256
5050
from time import time
5151

52-
from django.utils.encoding import force_text
52+
from django.utils.encoding import force_str # force_text
5353

5454
choice = random.choice
5555

@@ -66,7 +66,8 @@ def handle(self, **options):
6666

6767
random.seed(
6868
sha256(
69-
f'{random.getstate()}{time()}{force_text(kb_seed)}'.encode('utf-8')
69+
# f'{random.getstate()}{time()}{force_text(kb_seed)}'.encode('utf-8')
70+
f'{random.getstate()}{time()}{force_str(kb_seed)}'.encode('utf-8')
7071
).digest()
7172
)
7273

creme/creme_core/management/commands/creme_uninstall.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from django.db import DEFAULT_DB_ALIAS, connections
3030
from django.db.migrations.recorder import MigrationRecorder
3131
from django.dispatch import receiver
32-
from django.utils.encoding import force_text
32+
from django.utils.encoding import force_str # force_text
3333

3434
from creme.creme_core.core.setting_key import setting_key_registry
3535
from creme.creme_core.gui.bricks import Brick
@@ -470,7 +470,8 @@ def _delete_tables(self, app_config, app_label, verbosity):
470470
' [KO] Original error: {error}.\n'
471471
'Remaining tables:\n'
472472
'{models}\n'.format(
473-
error=force_text(e), # PostGreSQL returns localized errors...
473+
# error=force_text(e), # PostGreSQL returns localized errors...
474+
error=force_str(e), # PostGreSQL returns localized errors...
474475
models='\n'.join(model._meta.db_table for model in models),
475476
)
476477
)

creme/creme_core/management/commands/entity_factory.py

-1
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,6 @@ class Command(BaseCommand):
290290

291291
SQL_OPTIMISERS = {
292292
'django.db.backends.mysql': OptimizeMySQLContext,
293-
'django.db.backends.postgresql_psycopg2': OptimizePGSQLContext,
294293
'django.db.backends.postgresql': OptimizePGSQLContext,
295294
# TODO: other DBRMS ?
296295
}

creme/creme_core/management/commands/i18n_overload.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
################################################################################
44
#
5-
# Copyright (c) 2009-2020 Hybird
5+
# Copyright (c) 2009-2021 Hybird
66
#
77
# Permission is hereby granted, free of charge, to any person obtaining a copy
88
# of this software and associated documentation files (the "Software"), to deal
@@ -32,7 +32,7 @@
3232
from django.apps import apps
3333
from django.conf import settings
3434
from django.core.management.base import BaseCommand, CommandError
35-
from django.utils.encoding import smart_text
35+
from django.utils.encoding import smart_str
3636

3737
APP_NAME = 'locale_overload' # TODO: can configure it with command options ??
3838

@@ -181,7 +181,7 @@ def _overload_terms(self, language, verbosity, polib, file_name, *args):
181181
.localize(datetime.now()) \
182182
.strftime('%Y-%m-%d %H:%M%z')
183183

184-
terms = [smart_text(arg) for arg in args]
184+
terms = [smart_str(arg) for arg in args]
185185
entry_count = 0
186186

187187
for app_pofile in self._iter_pofiles(language, polib, file_name):

creme/creme_core/middleware/exceptions.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
################################################################################
44
# Creme is a free/open-source Customer Relationship Management software
5-
# Copyright (C) 2009-2020 Hybird
5+
# Copyright (C) 2009-2021 Hybird
66
#
77
# This program is free software: you can redistribute it and/or modify
88
# it under the terms of the GNU Affero General Public License as published by
@@ -25,7 +25,7 @@
2525
from django.http import Http404, HttpResponse
2626
from django.shortcuts import render
2727
from django.utils.deprecation import MiddlewareMixin
28-
from django.utils.encoding import smart_text
28+
from django.utils.encoding import smart_str # smart_text
2929

3030
from creme.creme_core.core import exceptions as creme_exceptions
3131

@@ -41,7 +41,8 @@ class _AlternativeErrorMiddleware(MiddlewareMixin):
4141

4242
def process_exception(self, request, exception):
4343
if self.error is None or isinstance(exception, self.error):
44-
msg = smart_text(exception)
44+
# msg = smart_text(exception)
45+
msg = smart_str(exception)
4546

4647
if request.is_ajax():
4748
if self.log_ajax:
@@ -52,9 +53,10 @@ def process_exception(self, request, exception):
5253
if self.template is None:
5354
return
5455

55-
return render(request, self.template,
56-
{'error_message': msg}, status=self.status,
57-
)
56+
return render(
57+
request, self.template,
58+
{'error_message': msg}, status=self.status,
59+
)
5860

5961

6062
class BadRequestMiddleware(_AlternativeErrorMiddleware):

creme/creme_core/templatetags/creme_core_tags.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from django.template import Template, TemplateSyntaxError
3232
from django.template.defaulttags import TemplateLiteral
3333
from django.template.library import token_kwargs
34-
from django.utils.encoding import force_text
34+
from django.utils.encoding import force_str # force_text
3535
from django.utils.html import escape, format_html_join
3636
from django.utils.safestring import mark_safe
3737

@@ -658,7 +658,8 @@ def render(self, context):
658658
logger.warning('jsondatablock tag do not accept custom "type" attribute')
659659

660660
attrs = ''.join(
661-
f' {k}="{escape(force_text(v.resolve(context)))}"'
661+
# f' {k}="{escape(force_text(v.resolve(context)))}"'
662+
f' {k}="{escape(force_str(v.resolve(context)))}"'
662663
for k, v in kwargs.items()
663664
)
664665

creme/creme_core/tests/gui/test_field_printers.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1119,7 +1119,8 @@ def test_registry_fk(self):
11191119
self.assertEqual(str(casca.image), get_csv_val(casca, 'image', user))
11201120

11211121
self.assertEqual(
1122-
'<p>Casca&#39;s selfie</p>',
1122+
# '<p>Casca&#39;s selfie</p>',
1123+
'<p>Casca&#x27;s selfie</p>',
11231124
get_html_val(casca, 'image__description', user)
11241125
)
11251126
self.assertEqual(
@@ -1310,7 +1311,8 @@ def test_registry_credentials(self):
13101311
get_html_val(judo, 'image', user)
13111312
)
13121313
self.assertEqual(
1313-
'<p>Judo&#39;s selfie</p>',
1314+
# '<p>Judo&#39;s selfie</p>',
1315+
'<p>Judo&#x27;s selfie</p>',
13141316
get_html_val(judo, 'image__description', user)
13151317
)
13161318

creme/creme_core/tests/models/test_custom_field.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -517,12 +517,13 @@ def test_multi_enum02(self):
517517
entity=orga,
518518
)
519519

520-
with self.assertNumQueries(3):
520+
# with self.assertNumQueries(3):
521+
with self.assertNumQueries(2):
521522
cf_value.set_value_n_save([enum_value1, enum_value2])
522523

523524
self.assertSetEqual(
524525
{enum_value1, enum_value2},
525-
{*self.refresh(cf_value).value.all()}
526+
{*self.refresh(cf_value).value.all()},
526527
)
527528

528529
def test_delete(self):

creme/creme_core/tests/views/test_job.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from django.db.models import Max
77
from django.test.utils import override_settings
88
from django.urls import reverse
9-
from django.utils.encoding import smart_text
9+
from django.utils.encoding import smart_str
1010
from django.utils.formats import date_format
1111
from django.utils.timezone import localtime, now
1212
from django.utils.translation import gettext as _
@@ -51,7 +51,7 @@ def tearDown(self):
5151

5252
# TODO: move to base class ?
5353
def _assertCount(self, response, found, count):
54-
self.assertEqual(count, smart_text(response.content).count(found))
54+
self.assertEqual(count, smart_str(response.content).count(found))
5555

5656
def _build_enable_url(self, job):
5757
return reverse('creme_core__enable_job', args=(job.id,))

creme/creme_core/tests/views/test_listview.py

+15-8
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55
from functools import partial
66
from json import dumps as json_dump
77
from random import shuffle
8+
from urllib.parse import quote
89
from xml.etree.ElementTree import tostring as html_tostring
910

1011
from django.conf import settings
1112
from django.contrib.contenttypes.models import ContentType
1213
from django.db.models import Q
1314
from django.test.utils import override_settings
1415
from django.urls import reverse
15-
from django.utils.encoding import force_text
16-
from django.utils.http import urlquote
16+
from django.utils.encoding import force_str # force_text
17+
# from django.utils.http import urlquote
1718
from django.utils.timezone import now
1819
from django.utils.translation import gettext as _
1920
from django.utils.translation import pgettext
@@ -429,7 +430,8 @@ def post(selection):
429430
self.assertInHTML(
430431
f'<input class="lv-state-field" value="{selection}" '
431432
f'name="selection" type="hidden" />',
432-
force_text(response.content),
433+
# force_text(response.content),
434+
force_str(response.content),
433435
)
434436

435437
post('none')
@@ -450,7 +452,8 @@ def get(selection):
450452
self.assertInHTML(
451453
f'<input class="lv-state-field" value="{selection}" '
452454
f'name="selection" type="hidden" />',
453-
force_text(response.content),
455+
# force_text(response.content),
456+
force_str(response.content),
454457
)
455458

456459
get('none')
@@ -1003,7 +1006,8 @@ def test_ordering_fastmode_01(self):
10031006
r'.creme_core_fakecontact.\..birthday. ASC( NULLS FIRST)?, '
10041007
r'.creme_core_fakecontact.\..last_name. ASC( NULLS FIRST)?, '
10051008
r'.creme_core_fakecontact.\..first_name. ASC( NULLS FIRST)?, '
1006-
r'.creme_core_fakecontact.\..cremeentity_ptr_id. ASC( NULLS FIRST)? LIMIT'
1009+
# r'.creme_core_fakecontact.\..cremeentity_ptr_id. ASC( NULLS FIRST)? LIMIT'
1010+
r'.creme_core_fakecontact.\..cremeentity_ptr_id. ASC( NULLS FIRST)? LIMIT'
10071011
)
10081012

10091013
@override_settings(FAST_QUERY_MODE_THRESHOLD=2)
@@ -1014,7 +1018,8 @@ def test_ordering_fastmode_02(self):
10141018
sql,
10151019
r'ORDER BY'
10161020
r' .creme_core_fakecontact.\..birthday. ASC( NULLS FIRST)?,'
1017-
r' .creme_core_fakecontact.\..cremeentity_ptr_id. ASC( NULLS FIRST)? LIMIT'
1021+
# r' .creme_core_fakecontact.\..cremeentity_ptr_id. ASC( NULLS FIRST)? LIMIT'
1022+
r' .creme_core_fakecontact.\..cremeentity_ptr_id. ASC( NULLS FIRST)? LIMIT'
10181023
)
10191024

10201025
def test_efilter01(self):
@@ -1176,8 +1181,10 @@ def test_header_buttons(self):
11761181
dl_uri = data_hrefs[1]
11771182
self.assertStartsWith(dl_uri, dl_url)
11781183
self.assertIn(f'hfilter={hf.id}', dl_uri)
1179-
self.assertIn(f'&extra_q={urlquote(q_filter)}', dl_uri)
1180-
self.assertIn(f'&search-regular_field-phone={urlquote(searched_phone)}', dl_uri)
1184+
# self.assertIn(f'&extra_q={urlquote(q_filter)}', dl_uri)
1185+
self.assertIn(f'&extra_q={quote(q_filter)}', dl_uri)
1186+
# self.assertIn(f'&search-regular_field-phone={urlquote(searched_phone)}', dl_uri)
1187+
self.assertIn(f'&search-regular_field-phone={quote(searched_phone)}', dl_uri)
11811188

11821189
dl_header_uri = data_hrefs[2]
11831190
self.assertStartsWith(dl_header_uri, dl_url)

0 commit comments

Comments
 (0)