From 11a7ba5acfec08eab6a6833f364d714afbf3193b Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Thu, 18 Mar 2021 15:42:43 +0000 Subject: [PATCH 1/2] Fix handling of '&' URL separators in tests Current Python versions as of February 2021 no longer treat the ; character as a URL parameter separator: https://python-security.readthedocs.io/vuln/urllib-query-string-semicolon-separator.html This breaks the tests for the url_replace tag, as they attempt to parse a URL generated by a Django template. HTML autoescaping is enabled, so & characters in the URL will be escaped as &. This discrepancy between escaped and unescaped HTML was previously masked because the closing ; was also treated as a separator. --- tests/templatetags/test_url_replace.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/templatetags/test_url_replace.py b/tests/templatetags/test_url_replace.py index fc98d9e2..75f015cd 100644 --- a/tests/templatetags/test_url_replace.py +++ b/tests/templatetags/test_url_replace.py @@ -1,3 +1,4 @@ +from html import unescape import urllib.parse as urlparse from ..test_case import AppTestCase @@ -11,7 +12,7 @@ def test_kwarg_added(self): {"request": fake_request}, ) # parse the url as they can be reordered unpredictably - parsed = urlparse.parse_qs(urlparse.urlparse(rendered).query) + parsed = urlparse.parse_qs(urlparse.urlparse(unescape(rendered)).query) self.assertDictEqual(parsed, {"page": ["1"]}) def test_kwarg_appended(self): @@ -21,7 +22,7 @@ def test_kwarg_appended(self): {"request": fake_request}, ) # parse the url as they can be reordered unpredictably - parsed = urlparse.parse_qs(urlparse.urlparse(rendered).query) + parsed = urlparse.parse_qs(urlparse.urlparse(unescape(rendered)).query) self.assertDictEqual(parsed, {"foo": ["bar"], "page": ["1"]}) def test_kwarg_replaced(self): @@ -31,5 +32,5 @@ def test_kwarg_replaced(self): {"request": fake_request}, ) # parse the url as they can be reordered unpredictably - parsed = urlparse.parse_qs(urlparse.urlparse(rendered).query) + parsed = urlparse.parse_qs(urlparse.urlparse(unescape(rendered)).query) self.assertDictEqual(parsed, {"foo": ["bar"], "page": ["5"]}) From 56c34c41a1f2bc5d7708694605d5172df0800784 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Thu, 18 Mar 2021 15:11:44 +0000 Subject: [PATCH 2/2] Add Wagtail 2.12 compatibility On Wagtail 2.12, switch to using raw_data in place of the deprecated stream_data. Switching to indexing the stream directly as a list (as per https://docs.wagtail.io/en/stable/releases/2.12.html#stream-data-on-streamfield-values-is-deprecated) is not really feasible here, as this would change public APIs that expect the JSON representation (e.g. https://wagtailstreamforms.readthedocs.io/en/latest/fields.html) --- .github/workflows/python-test.yml | 15 +++++++++++++++ setup.py | 5 ++++- tox.ini | 6 ++++-- wagtailstreamforms/models/form.py | 8 ++++++-- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/.github/workflows/python-test.yml b/.github/workflows/python-test.yml index a8e22fca..32d23212 100644 --- a/.github/workflows/python-test.yml +++ b/.github/workflows/python-test.yml @@ -31,6 +31,7 @@ jobs: - py36-dj22-wt29 - py36-dj22-wt210 - py36-dj22-wt211 + - py36-dj22-wt212 - py37-dj22-wt25 - py37-dj22-wt26 - py37-dj22-wt27 @@ -38,6 +39,7 @@ jobs: - py37-dj22-wt29 - py37-dj22-wt210 - py37-dj22-wt211 + - py37-dj22-wt212 - py38-dj22-wt25 - py38-dj22-wt26 - py38-dj22-wt27 @@ -45,14 +47,17 @@ jobs: - py38-dj22-wt29 - py38-dj22-wt210 - py38-dj22-wt211 + - py38-dj22-wt212 - py37-dj30-wt28 - py37-dj30-wt29 - py37-dj30-wt210 - py37-dj30-wt211 + - py37-dj30-wt212 - py38-dj30-wt28 - py38-dj30-wt29 - py38-dj30-wt210 - py38-dj30-wt211 + - py38-dj30-wt212 include: - python-version: 3.6 tox_env: py36-dj22-wt25 @@ -68,6 +73,8 @@ jobs: tox_env: py36-dj22-wt210 - python-version: 3.6 tox_env: py36-dj22-wt211 + - python-version: 3.6 + tox_env: py36-dj22-wt212 - python-version: 3.7 tox_env: py37-dj22-wt25 - python-version: 3.7 @@ -82,6 +89,8 @@ jobs: tox_env: py37-dj22-wt210 - python-version: 3.7 tox_env: py37-dj22-wt211 + - python-version: 3.7 + tox_env: py37-dj22-wt212 - python-version: 3.8 tox_env: py38-dj22-wt25 - python-version: 3.8 @@ -96,6 +105,8 @@ jobs: tox_env: py38-dj22-wt210 - python-version: 3.8 tox_env: py38-dj22-wt211 + - python-version: 3.8 + tox_env: py38-dj22-wt212 - python-version: 3.7 tox_env: py37-dj30-wt28 - python-version: 3.7 @@ -104,6 +115,8 @@ jobs: tox_env: py37-dj30-wt210 - python-version: 3.7 tox_env: py37-dj30-wt211 + - python-version: 3.7 + tox_env: py37-dj30-wt212 - python-version: 3.8 tox_env: py38-dj30-wt28 - python-version: 3.8 @@ -112,6 +125,8 @@ jobs: tox_env: py38-dj30-wt210 - python-version: 3.8 tox_env: py38-dj30-wt211 + - python-version: 3.8 + tox_env: py38-dj30-wt212 steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/setup.py b/setup.py index 42738bdf..55afba11 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,10 @@ ] -install_requires = ["wagtail>=2,<2.12"] +install_requires = [ + "wagtail>=2,<2.13", + "Unidecode>=0.04.14,<2.0", +] documentation_extras = [ "sphinxcontrib-spelling>=2.3.0", diff --git a/tox.ini b/tox.ini index f7f92d76..ed47055b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,8 @@ [tox] envlist = flake8 - py{36,37,38}-dj{22}-wt{25,26,27,28,29,210,211} - py{37,38}-dj{30}-wt{28,29,210,211} + py{36,37,38}-dj{22}-wt{25,26,27,28,29,210,211,212} + py{37,38}-dj{30,31}-wt{28,29,210,211,212} [gh-actions] python = @@ -17,6 +17,7 @@ deps = dj22: Django>=2.2.8,<2.3 dj30: Django>=3.0,<3.1 + dj31: Django>=3.1,<3.2 wt23: wagtail>=2.3,<2.4 wt24: wagtail>=2.4,<2.5 wt25: wagtail>=2.5,<2.6 @@ -26,6 +27,7 @@ deps = wt29: wagtail>=2.9,<2.10 wt210: wagtail>=2.10,<2.11 wt211: wagtail>=2.11,<2.12 + wt212: wagtail>=2.12,<2.13 commands = diff --git a/wagtailstreamforms/models/form.py b/wagtailstreamforms/models/form.py index 2c7e8d59..d631e165 100644 --- a/wagtailstreamforms/models/form.py +++ b/wagtailstreamforms/models/form.py @@ -2,6 +2,7 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ +from wagtail import VERSION as WAGTAIL_VERSION from wagtail.admin.edit_handlers import ( FieldPanel, MultiFieldPanel, @@ -162,9 +163,12 @@ def get_form_class(self): return FormBuilder(self.get_form_fields()).get_form_class() def get_form_fields(self): - """ Returns the form fields stream_data. """ + """ Returns the form field's stream data. """ - form_fields = self.fields.stream_data + if WAGTAIL_VERSION >= (2, 12): + form_fields = self.fields.raw_data + else: + form_fields = self.fields.stream_data for fn in hooks.get_hooks("construct_submission_form_fields"): form_fields = fn(form_fields) return form_fields