Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Django 2.2 #7196

Merged
merged 111 commits into from
Jul 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
25da29d
Complete removal of nose test artifacts
SmileyChris Mar 18, 2019
c61c220
Update base requirements to Django 2.2 and python 3 compatibile packages
SmileyChris Apr 15, 2019
f2200e5
Fix print statements and django urlresolvers path
SmileyChris Apr 15, 2019
f17f6e4
Remove old futures
SmileyChris Apr 15, 2019
a19a17c
Futurize stage 1
SmileyChris Apr 15, 2019
2514896
Futurize stage 2
SmileyChris Apr 15, 2019
9daf338
Fix renamed RegexURLResolver
SmileyChris Apr 15, 2019
a9ae672
Update beautifulsoup4 for Py3 compatibility
SmileyChris Apr 15, 2019
818c375
Fix project name
SmileyChris Apr 15, 2019
da913cf
Fix invalid unicode
SmileyChris Apr 15, 2019
1333046
Fix simple cache backend
SmileyChris Apr 15, 2019
12ebfd3
Post-futurize flake8 fixes
SmileyChris Apr 15, 2019
8968268
Switch docker to python 3, more requirements upgrades
SmileyChris Apr 15, 2019
1776151
Fix django url resolvers reference
SmileyChris Apr 15, 2019
b616875
Fix a resolver method renamed in Django 2
SmileyChris Apr 15, 2019
7bd20d7
bytestring encoding fixes
SmileyChris Apr 15, 2019
84017ea
Fix sitemap.json write mode for Python 3
SmileyChris Apr 16, 2019
596269a
Python 3 doesn't support '<' between None and int now, so enforce an …
SmileyChris Apr 16, 2019
835a551
Avoid some failures due to manifestfilestorage during collection by c…
SmileyChris Apr 16, 2019
2e6caae
No more file type in Python 3
SmileyChris Apr 16, 2019
83c35a8
Regex fixes
SmileyChris Apr 16, 2019
cd605a6
markdown tweaks
SmileyChris Apr 16, 2019
756131b
jsonfield default changed to strings in migration
SmileyChris Apr 16, 2019
ab227e5
Pytest fixes
SmileyChris Apr 16, 2019
17eeba5
Fix all test collection failures
SmileyChris Apr 16, 2019
514b175
Use test settings
SmileyChris Apr 16, 2019
6e36fac
Add cssselect (new subdependency) to dev requirements
SmileyChris Apr 28, 2019
4c19dd0
Better check for pytest execution
SmileyChris Apr 28, 2019
054c7fb
Fix old division from futurize
SmileyChris Apr 28, 2019
d6f0095
Remove basestring from futurize
SmileyChris Apr 28, 2019
6f55dbf
Fix icalendar encoding issue with Python 3 upgrade
SmileyChris Apr 28, 2019
6a5af7e
Faster test discovery
SmileyChris Apr 28, 2019
a509b4d
Fix LocaleURLMiddleware stripping invalid unicode
SmileyChris Apr 28, 2019
1fca41b
Refactor and fix firefox_desktop tests
SmileyChris Apr 28, 2019
48238e9
Remove some unused widgets
SmileyChris Apr 28, 2019
5564086
Fix Widget.render to work with Django 2.1+
SmileyChris Apr 28, 2019
1ee80cc
Fix str to int comparison
SmileyChris Apr 28, 2019
bee01fd
Use Django's JsonResponse rather than custom
SmileyChris Apr 28, 2019
2650046
Fix encoding issues in tests
SmileyChris Apr 28, 2019
3d3ff03
Removed unused test mixin
SmileyChris Apr 29, 2019
451665d
Middleware fixes
SmileyChris Apr 29, 2019
b515b3e
Fix pytest deprecations
SmileyChris Apr 29, 2019
f23ab0b
Remove an extraneous basestring reference
SmileyChris Apr 29, 2019
10c9bfa
Flake fixes
SmileyChris Apr 29, 2019
54e3872
Add python cache files to dockerignore
SmileyChris Apr 29, 2019
cbdba4a
Fix non-int comparison
SmileyChris Apr 29, 2019
b3b45d5
Fix python3 iterator next() format
SmileyChris Apr 29, 2019
258dc19
Update middleware to new Django 2 format
SmileyChris Apr 29, 2019
fce79c0
Fix encoding errors in tests
SmileyChris Apr 29, 2019
b95230d
Fix URLResolver change in Django 2
SmileyChris Apr 29, 2019
4bb179b
Fix pagenode next in tests
SmileyChris Apr 29, 2019
e6545ec
Django 2.2.0 -> 2.2.1
SmileyChris May 2, 2019
ceef5ad
__unicode__ -> __str__
SmileyChris May 9, 2019
8549c9e
Encoding fixes
SmileyChris May 9, 2019
236d56e
Python 3 next format
SmileyChris May 9, 2019
7eb9923
Mock fixes
SmileyChris May 9, 2019
d50e7d4
BytesIO encoding
SmileyChris May 9, 2019
439e548
Response decoding
SmileyChris May 9, 2019
e66d667
Mock string rather than bytes file reading
SmileyChris May 9, 2019
b813147
Csrf html5 test fix
SmileyChris May 9, 2019
4ea0f4a
Pyquery test fixes
SmileyChris May 9, 2019
455d672
Remove reliance on dict ordering in tests
SmileyChris May 9, 2019
2f6414b
Fix issue with mock.patch
SmileyChris May 9, 2019
6c35f88
Test fixes for __unicode__ -> __str__
SmileyChris May 9, 2019
7703db4
Remove test not needed now in latest django (underlying bug fixed)
SmileyChris May 15, 2019
b89aec7
Re-fix form test changed in rebase
SmileyChris May 15, 2019
fe2dca3
Fix as_urlpatterns test broken in merge with master
SmileyChris May 15, 2019
d2b5e18
Fix missing import
SmileyChris May 16, 2019
643ec48
Fix markdown encoding in legal_docs view, update markdown
SmileyChris May 16, 2019
335416d
Regex escape sequence fixes
SmileyChris May 16, 2019
43bbe29
Flake8 upgrade, fixes, and excludes so it can be run without path args
SmileyChris May 16, 2019
5142545
Fix unescaped periods in regex strirngs
SmileyChris May 16, 2019
7c705df
Fix FrameOptionsHeader middleware, upgrade commonware
SmileyChris May 17, 2019
dd4874a
Update tests to work with BytesIO change in legal_docs view
SmileyChris May 17, 2019
0d30015
Fix a response header test
SmileyChris May 17, 2019
f3567ed
Better valid url assertion in tests
SmileyChris May 17, 2019
eb34ff7
Remove legacy enum34 from requirements
SmileyChris May 22, 2019
b1d7fe5
Fix some template references to py2 iteritems
SmileyChris May 31, 2019
53d4545
Fix a functional test bytestring comparison
SmileyChris May 31, 2019
cd56dbb
Remove HttpResponseJSON import re-introduced during rebase
jgmize Jun 29, 2019
4a3db90
Add variant assignment that went missing during rebase
jgmize Jun 29, 2019
04665eb
Fix over-indentation
jgmize Jun 29, 2019
aca787a
Fix undefined variables introduced by rebase
jgmize Jun 29, 2019
1e84141
Fix invalid escape sequences using raw strings
jgmize Jun 29, 2019
28a67b0
Fix unquote import
jgmize Jun 29, 2019
4639b17
Handle request.keywords.get('viewport') is False
jgmize Jun 29, 2019
14f8745
Check hasattr(request.keywords.get('viewport'), 'args') before use
jgmize Jun 29, 2019
305a380
Add self.firefox_android to TestFirefoxAll
jgmize Jun 29, 2019
e5b5dc3
Remove old whatsnew templates reintroduced during rebase
jgmize Jun 29, 2019
14e41ba
Fix missing FirefoxAndroid import
jgmize Jun 29, 2019
d5d0e0b
Remove check for settings.OTHER_NEWSLETTERS
jgmize Jun 29, 2019
92fd50f
Fix more rebase errors
jgmize Jun 29, 2019
61016dc
Remove en-ZA from show_newsletter locales
jgmize Jun 29, 2019
01d36ef
Restore beta channel detection
jgmize Jun 29, 2019
6323684
Replace mark.viewport('mobile') with selenium_mobile fixture
jgmize Jun 29, 2019
2756b0f
Fix more rebase errors
jgmize Jun 29, 2019
1a76e70
Remove unused FxVersionRedirectsMixin
jgmize Jun 29, 2019
d6c5112
Delete duplicate test with incorrect assertion
jgmize Jun 29, 2019
cd256f9
Fix another rebase error: prepend 'self.' to firefox_desktop
jgmize Jul 1, 2019
986c026
Fix issue with cached settings on a few tests when running pytest loc…
SmileyChris Jul 2, 2019
a099f0a
Fix a few more unescaped periods in regex strings
SmileyChris Jul 2, 2019
f0a3501
Remove deprecated smoke mark
jgmize Jul 2, 2019
eaaddd7
Remove unnecessary pytest.param
jgmize Jul 2, 2019
f39dca0
Tidy up some futurize cruft
SmileyChris Jul 3, 2019
9457926
Revert a test import change
SmileyChris Jul 3, 2019
fb12e4f
Fix all previously ignored flake8 exceptions
SmileyChris Jul 3, 2019
7040330
Fix a deprecated pytest yield test
SmileyChris Jul 3, 2019
0ba4ed3
Simplify raw object classes
SmileyChris Jul 3, 2019
43e6e20
Fix the futurize list(dict.values()) unnecessary changes
SmileyChris Jul 3, 2019
1e9d391
Fix flake8 formatting exception
SmileyChris Jul 3, 2019
15737ac
Use force_text rather than manual isinstance
SmileyChris Jul 3, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.git
.env
**/__pycache__
**/*.pyc
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ RUN gulp build --production
########
# Python dependencies builder
#
FROM python:2-stretch AS python-builder
FROM python:3-slim AS python-builder
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should pin a Python minor version just to be sure we have consistent builds. python:3.7-slim e.g..


WORKDIR /app
ENV LANG=C.UTF-8
Expand All @@ -34,6 +34,7 @@ ENV PATH="/venv/bin:$PATH"
COPY docker/bin/apt-install /usr/local/bin/
RUN apt-install gettext build-essential libxml2-dev libxslt1-dev libxslt1.1

RUN pip install virtualenv
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With Python 3 venv is built in. You change these 2 lines to just RUN python -m venv /venv

RUN virtualenv /venv

COPY requirements/base.txt requirements/prod.txt ./requirements/
Expand All @@ -45,7 +46,7 @@ RUN pip install --no-cache-dir -r requirements/prod.txt
########
# django app container
#
FROM python:2-slim-stretch AS app-base
FROM python:3-slim AS app-base

# Extra python env
ENV PYTHONDONTWRITEBYTECODE=1
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ clean:
git clean -f

lint: .docker-build-pull
${DC} run test flake8 bedrock lib tests
${DC} run test flake8
${DC} run assets gulp js:lint css:lint

test: .docker-build-pull
Expand Down
10 changes: 5 additions & 5 deletions bedrock/base/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class SimpleDictCache(LocMemCache):
def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
key = self.make_key(key, version=version)
self.validate_key(key)
with self._lock.writer():
with self._lock:
if self._has_expired(key):
self._set(key, value, timeout)
return True
Expand All @@ -22,13 +22,13 @@ def get(self, key, default=None, version=None):
key = self.make_key(key, version=version)
self.validate_key(key)
value = default
with self._lock.reader():
with self._lock:
if not self._has_expired(key):
value = self._cache[key]
if value is not default:
return value

with self._lock.writer():
with self._lock:
try:
del self._cache[key]
del self._expire_info[key]
Expand All @@ -39,7 +39,7 @@ def get(self, key, default=None, version=None):
def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
key = self.make_key(key, version=version)
self.validate_key(key)
with self._lock.writer():
with self._lock:
self._set(key, value, timeout)

def incr(self, key, delta=1, version=None):
Expand All @@ -48,6 +48,6 @@ def incr(self, key, delta=1, version=None):
raise ValueError("Key '%s' not found" % key)
new_value = value + delta
key = self.make_key(key, version=version)
with self._lock.writer():
with self._lock:
self._cache[key] = new_value
return new_value
2 changes: 1 addition & 1 deletion bedrock/base/log_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def emit(self, record):
cfg[key] = value

# Set the level and handlers for all loggers.
for logger in cfg['loggers'].values() + [cfg['root']]:
for logger in list(cfg['loggers'].values()) + [cfg['root']]:
if 'handlers' not in logger:
logger['handlers'] = ['syslog' if use_syslog else 'console']
if 'level' not in logger:
Expand Down
3 changes: 1 addition & 2 deletions bedrock/base/management/commands/update_www_config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from __future__ import print_function

import os

Expand Down Expand Up @@ -27,7 +26,7 @@ def refresh_db_values():

ConfigValue.objects.all().delete()
count = 0
for name, value in values.iteritems():
for name, value in values.items():
if value:
ConfigValue.objects.create(name=name, value=value)
count += 1
Expand Down
48 changes: 37 additions & 11 deletions bedrock/base/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,41 @@
the locale codes.
"""
import base64
import urllib
import urllib.parse
from urllib.parse import unquote
from warnings import warn

from commonware.middleware import FrameOptionsHeader as OldFrameOptionsHeader
from commonware.middleware import RobotsTagHeader as OldRobotsTagHeader
from django.conf import settings
from django.core.exceptions import MiddlewareNotUsed
from django.http import HttpResponsePermanentRedirect, HttpResponse
from django.utils.encoding import force_text
from django.http import HttpResponse, HttpResponsePermanentRedirect
from django.utils.deprecation import MiddlewareMixin

from . import urlresolvers
from lib.l10n_utils import translation

from . import urlresolvers


class LocaleURLMiddleware(object):
class LocaleURLMiddleware:
"""
1. Search for the locale.
2. Save it in the request.
3. Strip them from the URL.
"""

def __init__(self):
def __init__(self, get_response=None):
if not settings.USE_I18N or not settings.USE_L10N:
warn("USE_I18N or USE_L10N is False but LocaleURLMiddleware is "
"loaded. Consider removing bedrock.base.middleware."
"LocaleURLMiddleware from your MIDDLEWARE_CLASSES setting.")
"LocaleURLMiddleware from your MIDDLEWARE setting.")
self.get_response = get_response

def __call__(self, request):
response = self.process_request(request)
if response:
return response
return self.get_response(request)

def process_request(self, request):
prefixer = urlresolvers.Prefixer(request)
Expand All @@ -37,11 +48,11 @@ def process_request(self, request):

if full_path != request.path:
query_string = request.META.get('QUERY_STRING', '')
full_path = urllib.quote(full_path.encode('utf-8'))
full_path = urllib.parse.quote(full_path.encode('utf-8'))

if query_string:
full_path = '?'.join(
[full_path, force_text(query_string, errors='ignore')])
[full_path, unquote(query_string, errors='ignore')])

response = HttpResponsePermanentRedirect(full_path)

Expand All @@ -58,14 +69,21 @@ def process_request(self, request):
translation.activate(prefixer.locale or settings.LANGUAGE_CODE)


class BasicAuthMiddleware(object):
class BasicAuthMiddleware:
"""
Middleware to protect the entire site with a single basic-auth username and password.
Set the BASIC_AUTH_CREDS environment variable to enable.
"""
def __init__(self):
def __init__(self, get_response=None):
if not settings.BASIC_AUTH_CREDS:
raise MiddlewareNotUsed
self.get_response = None

def __call__(self, request):
response = self.process_request(request)
if response:
return response
return self.get_response(request)

def process_request(self, request):
required_auth = settings.BASIC_AUTH_CREDS
Expand All @@ -85,3 +103,11 @@ def process_request(self, request):
realm = settings.APP_NAME or 'bedrock-demo'
response['WWW-Authenticate'] = 'Basic realm="{}"'.format(realm)
return response


class RobotsTagHeader(OldRobotsTagHeader, MiddlewareMixin):
pass


class FrameOptionsHeader(OldFrameOptionsHeader, MiddlewareMixin):
pass
1 change: 0 additions & 1 deletion bedrock/base/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models

Expand Down
2 changes: 1 addition & 1 deletion bedrock/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class ConfigValue(models.Model):
class Meta:
app_label = 'base'

def __unicode__(self):
def __str__(self):
return '%s=%s' % (self.name, self.value)


Expand Down
23 changes: 11 additions & 12 deletions bedrock/base/templatetags/helpers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import datetime
import urllib
import urlparse
import urllib.parse

from django.conf import settings
from django.contrib.staticfiles.storage import staticfiles_storage
Expand Down Expand Up @@ -73,43 +72,43 @@ def urlparams(url_, hash=None, **query):
New query params will be appended to exising parameters, except duplicate
names, which will be replaced.
"""
url = urlparse.urlparse(url_)
url = urllib.parse.urlparse(url_)
fragment = hash if hash is not None else url.fragment

# Use dict(parse_qsl) so we don't get lists of values.
q = url.query
query_dict = dict(urlparse.parse_qsl(smart_str(q))) if q else {}
query_dict = dict(urllib.parse.parse_qsl(smart_str(q))) if q else {}
query_dict.update((k, v) for k, v in query.items())

query_string = _urlencode([(k, v) for k, v in query_dict.items()
if v is not None])
new = urlparse.ParseResult(url.scheme, url.netloc, url.path, url.params,
query_string, fragment)
new = urllib.parse.ParseResult(
url.scheme, url.netloc, url.path, url.params, query_string, fragment)
return new.geturl()


def _urlencode(items):
"""A Unicode-safe URLencoder."""
try:
return urllib.urlencode(items)
return urllib.parse.urlencode(items)
except UnicodeEncodeError:
return urllib.urlencode([(k, smart_str(v)) for k, v in items])
return urllib.parse.urlencode([(k, smart_str(v)) for k, v in items])


@library.filter
def mailtoencode(txt):
"""Url encode a string using %20 for spaces."""
if isinstance(txt, unicode):
if isinstance(txt, str):
txt = txt.encode('utf-8')
return urllib.quote(txt)
return urllib.parse.quote(txt)


@library.filter
def urlencode(txt):
"""Url encode a string using + for spaces."""
if isinstance(txt, unicode):
if isinstance(txt, str):
txt = txt.encode('utf-8')
return urllib.quote_plus(txt)
return urllib.parse.quote_plus(txt)


@library.global_function
Expand Down
6 changes: 3 additions & 3 deletions bedrock/base/tests/test_accepted_locales.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ def test_dev_languages(self):
# simulate the successful result of the DEV_LANGUAGES list
# comprehension defined in settings.
settings.DEV_LANGUAGES = ['en-US', 'fr']
assert settings.LANGUAGE_URL_MAP == {'en-us': 'en-US', 'fr': 'fr'}, \
('DEV is True, but DEV_LANGUAGES are not used to define the '
'allowed locales.')
assert settings.LANGUAGE_URL_MAP == {'en-us': 'en-US', 'fr': 'fr'}, (
'DEV is True, but DEV_LANGUAGES are not used to define the '
'allowed locales.')

def test_prod_languages(self):
"""Test the accepted locales on prod instances.
Expand Down
11 changes: 7 additions & 4 deletions bedrock/base/tests/test_middleware.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from urllib.parse import urlencode

from django.test import TestCase, RequestFactory
from django.test.utils import override_settings

Expand All @@ -15,7 +17,7 @@ def test_redirects_to_correct_language(self):
"""Should redirect to lang prefixed url."""
path = '/the/dude/'
req = self.rf.get(path, HTTP_ACCEPT_LANGUAGE='de')
resp = LocaleURLMiddleware().process_request(req)
resp = self.middleware.process_request(req)
self.assertEqual(resp['Location'], '/de' + path)

@override_settings(DEV_LANGUAGES=('es', 'fr'),
Expand All @@ -24,17 +26,18 @@ def test_redirects_to_default_language(self):
"""Should redirect to default lang if not in settings."""
path = '/the/dude/'
req = self.rf.get(path, HTTP_ACCEPT_LANGUAGE='de')
resp = LocaleURLMiddleware().process_request(req)
resp = self.middleware.process_request(req)
self.assertEqual(resp['Location'], '/en-US' + path)

@override_settings(DEV_LANGUAGES=('de', 'fr'))
def test_redirects_to_correct_language_despite_unicode_errors(self):
"""Should redirect to lang prefixed url, stripping invalid chars."""
path = '/the/dude/'
corrupt_querystring = '?a\xa4\x91b\xa4\x91i\xc0de=s'
corrupt_querystring = '?' + urlencode(
{b'a\xa4\x91b\xa4\x91i\xc0de': 's'})
corrected_querystring = '?abide=s'
req = self.rf.get(path + corrupt_querystring,
HTTP_ACCEPT_LANGUAGE='de')
resp = LocaleURLMiddleware().process_request(req)
resp = self.middleware.process_request(req)
self.assertEqual(resp['Location'],
'/de' + path + corrected_querystring)
Loading