diff --git a/.github/workflows/nightly-tests.yml b/.github/workflows/nightly-tests.yml index 852c7feb..3403d0f1 100644 --- a/.github/workflows/nightly-tests.yml +++ b/.github/workflows/nightly-tests.yml @@ -25,10 +25,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python 3.8 + - name: Set up Python 3.12 uses: actions/setup-python@v1 with: - python-version: 3.8 + python-version: 3.12 - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/python-release.yml b/.github/workflows/python-release.yml index e4f19036..55e81c04 100644 --- a/.github/workflows/python-release.yml +++ b/.github/workflows/python-release.yml @@ -10,10 +10,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Set up Python 3.8 + - name: Set up Python 3.12 uses: actions/setup-python@v1 with: - python-version: 3.8 + python-version: 3.12 - name: Install build requirements run: python -m pip install wheel - name: Build package diff --git a/.github/workflows/python-test.yml b/.github/workflows/python-test.yml index 304d4e69..3952e6fe 100644 --- a/.github/workflows/python-test.yml +++ b/.github/workflows/python-test.yml @@ -1,4 +1,3 @@ ---- name: Python Tests on: [push] @@ -7,13 +6,15 @@ jobs: format: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Python 3.8 - uses: actions/setup-python@v1 + - uses: actions/checkout@v3 + - name: Set up Python 3.12 + uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: "3.12" - name: Install dependencies - run: pip install tox + run: | + python -m pip install --upgrade pip + pip install tox - name: Validate formatting run: tox -e format @@ -22,58 +23,18 @@ jobs: strategy: max-parallel: 4 matrix: + python-version: ["3.12"] tox_env: - - py311-dj41-wt41 - - py311-dj41-wt50 - - py311-dj41-wt51 - - py311-dj41-wt52 - include: - - python-version: "3.11" - tox_env: py311-dj41-wt41 - - python-version: "3.11" - tox_env: py311-dj41-wt50 - - python-version: "3.11" - tox_env: py311-dj41-wt51 - - python-version: "3.11" - tox_env: py311-dj41-wt52 - + - py312-dj51-wt63 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip pip install tox tox-gh-actions - - name: Test with tox + - name: Run tests with tox run: tox -e ${{ matrix.tox_env }} -- index-url=https://pypi.python.org/simple/ - - name: Prepare artifacts - run: mkdir -p .coverage-data && mv .coverage.* .coverage-data/ - - uses: actions/upload-artifact@master - with: - name: coverage-data - path: .coverage-data/ - - coverage: - runs-on: ubuntu-latest - needs: [test] - steps: - - uses: actions/checkout@v2 - - uses: actions/download-artifact@master - with: - name: coverage-data - path: . - - name: Set up Python 3.8 - uses: actions/setup-python@v1 - with: - python-version: 3.8 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install tox - - name: Prepare Coverage report - run: tox -e coverage-report - - name: Upload to codecov - uses: codecov/codecov-action@v1.0.6 diff --git a/docker-compose.yml b/docker-compose.yml index 5b919e96..3410c4ab 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,7 +24,7 @@ services: ports: - 8000:8000 db: - image: postgres:9.6 + image: postgres:11 environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=password diff --git a/example/migrations/0001_initial.py b/example/migrations/0001_initial.py index f623c26a..ed939d89 100644 --- a/example/migrations/0001_initial.py +++ b/example/migrations/0001_initial.py @@ -2,8 +2,8 @@ from django.db import migrations, models import django.db.models.deletion -import wagtail.core.blocks -import wagtail.core.fields +import wagtail.blocks +import wagtail.fields import wagtailstreamforms.blocks @@ -20,7 +20,7 @@ class Migration(migrations.Migration): name='BasicPage', fields=[ ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')), - ('body', wagtail.core.fields.StreamField((('rich_text', wagtail.core.blocks.RichTextBlock()), ('form', wagtail.core.blocks.StructBlock((('form', wagtailstreamforms.blocks.FormChooserBlock()), ('form_action', wagtail.core.blocks.CharBlock(help_text='The form post action. "" or "." for the current page or a url', required=False)), ('form_reference', wagtailstreamforms.blocks.InfoBlock(help_text='This form will be given a unique reference once saved', required=False)))))))), + ('body', wagtail.fields.StreamField((('rich_text', wagtail.blocks.RichTextBlock()), ('form', wagtail.blocks.StructBlock((('form', wagtailstreamforms.blocks.FormChooserBlock()), ('form_action', wagtail.blocks.CharBlock(help_text='The form post action. "" or "." for the current page or a url', required=False)), ('form_reference', wagtailstreamforms.blocks.InfoBlock(help_text='This form will be given a unique reference once saved', required=False)))))))), ], options={ 'abstract': False, diff --git a/example/models.py b/example/models.py index 9bc38212..f69b28cb 100644 --- a/example/models.py +++ b/example/models.py @@ -1,7 +1,7 @@ from django.db import models -from wagtail.admin.panels import StreamFieldPanel from wagtail import blocks +from wagtail.admin.panels import FieldPanel from wagtail.fields import StreamField from wagtail.models import Page from wagtailstreamforms.blocks import WagtailFormBlock @@ -23,5 +23,5 @@ class BasicPage(Page): show_in_menus_default = True content_panels = Page.content_panels + [ - StreamFieldPanel('body'), + FieldPanel('body'), ] diff --git a/example/settings.py b/example/settings.py index 56241b04..b69b27d6 100644 --- a/example/settings.py +++ b/example/settings.py @@ -8,7 +8,7 @@ # Security -SECRET_KEY = environ.get('SECRET_KEY', '') +SECRET_KEY = environ.get('SECRET_KEY', 's3cr3t') DEBUG = True @@ -37,12 +37,11 @@ 'wagtail.search', 'wagtail.contrib.redirects', 'wagtail.sites', - 'wagtail.contrib.modeladmin', - 'wagtail.contrib.postgres_search', + 'wagtail_modeladmin', 'wagtail.contrib.settings', 'wagtail.contrib.search_promotions', - 'captcha', + 'django_recaptcha', 'taggit', # app specific @@ -90,14 +89,14 @@ DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'HOST': environ.get('RDS_HOSTNAME'), - 'PORT': environ.get('RDS_PORT'), - 'NAME': environ.get('RDS_DB_NAME'), - 'USER': environ.get('RDS_USERNAME'), - 'PASSWORD': environ.get('RDS_PASSWORD'), + 'HOST': environ.get('DB_HOSTNAME'), + 'PORT': environ.get('DB_PORT'), + 'NAME': environ.get('DB_NAME'), + 'USER': environ.get('DB_USERNAME'), + 'PASSWORD': environ.get('DB_PASSWORD'), } } - +DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' # Email @@ -143,7 +142,7 @@ # Wagtail WAGTAIL_SITE_NAME = 'example.com' - +WAGTAILADMIN_BASE_URL = "/" # Forms @@ -156,4 +155,5 @@ RECAPTCHA_PUBLIC_KEY = '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI' RECAPTCHA_PRIVATE_KEY = '6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe' NOCAPTCHA = True -SILENCED_SYSTEM_CHECKS = ['captcha.recaptcha_test_key_error'] +SILENCED_SYSTEM_CHECKS = ['django_recaptcha.recaptcha_test_key_error'] + diff --git a/example/wagtailstreamforms_fields.py b/example/wagtailstreamforms_fields.py index 73d5c5b5..d3f8900a 100644 --- a/example/wagtailstreamforms_fields.py +++ b/example/wagtailstreamforms_fields.py @@ -1,7 +1,7 @@ from django import forms from django.contrib.auth.models import User +from django_recaptcha.fields import ReCaptchaField -from captcha.fields import ReCaptchaField from wagtail import blocks from wagtailstreamforms.fields import BaseField, register @@ -19,11 +19,26 @@ def get_options(self, block_value): }) return options + def get_form_block_class(self): + return blocks.StructBlock + + def get_local_blocks(self): + return [ + ("label", blocks.CharBlock()), + ("help_text", blocks.CharBlock(required=False)), + ] + + def get_form_block_kwargs(self): + return { + "icon": self.icon, + "label": self.label, + } + def get_form_block(self): - return blocks.StructBlock([ - ('label', blocks.CharBlock()), - ('help_text', blocks.CharBlock(required=False)), - ], icon=self.icon, label=self.label) + return self.get_form_block_class()( + self.get_local_blocks(), + **self.get_form_block_kwargs(), + ) @register('regex_validated') @@ -45,15 +60,21 @@ def get_regex_choices(self): ('^[a-zA-Z0-9]+$', 'Letters and numbers only'), ) - def get_form_block(self): - return blocks.StructBlock([ + def get_local_blocks(self): + return [ ('label', blocks.CharBlock()), ('help_text', blocks.CharBlock(required=False)), ('required', blocks.BooleanBlock(required=False)), ('regex', blocks.ChoiceBlock(choices=self.get_regex_choices())), ('error_message', blocks.CharBlock()), ('default_value', blocks.CharBlock(required=False)), - ], icon=self.icon, label=self.label) + ] + + def get_form_block(self): + return self.get_form_block_class()( + self.get_local_blocks(), + **self.get_form_block_kwargs() + ) @register('user') @@ -71,9 +92,15 @@ def get_options(self, block_value): options.update({'queryset': self.get_queryset()}) return options - def get_form_block(self): - return blocks.StructBlock([ + def get_local_blocks(self): + return [ ('label', blocks.CharBlock()), ('help_text', blocks.CharBlock(required=False)), ('required', blocks.BooleanBlock(required=False)), - ], icon=self.icon, label=self.label) + ] + + def get_form_block(self): + return self.get_form_block_class()( + self.get_local_blocks(), + **self.get_form_block_kwargs() + ) diff --git a/pyproject.toml b/pyproject.toml index c8c642a5..cb8deba6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,77 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "wagtailstreamforms" +dynamic = ["version"] +description = "Wagtail forms in a streamfield" +readme = "README.rst" +license = "MIT" +authors = [ + { name = "Stuart George", email = "stuart@accentdesign.co.uk" }, +] +keywords = [ + "accent", + "design", + "forms", + "streamfield", + "wagtail", +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Framework :: Django", + "Framework :: Django :: 5.0", + "Framework :: Wagtail", + "Framework :: Wagtail :: 5", + "Framework :: Wagtail :: 6", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Internet :: WWW/HTTP :: Site Management", +] +dependencies = [ + "Unidecode>=0.04.14,<2.0", + "wagtail-modeladmin", + "wagtail>6.0,<=6.3", +] + +[project.optional-dependencies] +docs = [ + "karma_sphinx_theme>=0.0.6", + "sphinx-autobuild>=0.6.0", + "Sphinx>=1.5.2", + "sphinxcontrib-spelling>=2.3.0", +] +test = [ + "flake8-blind-except==0.1.1", + "flake8-debugger==3.1.0", + "flake8==3.7.9", + "isort[pyproject]==4.3.21", + "mock==4.0.2", + "pytest-django==4.7.0", + "pytest==7.3.2", +] + +[project.urls] +Download = "https://pypi.python.org/pypi/wagtailstreamforms" +Homepage = "https://github.com/AccentDesign/wagtailstreamforms/" + +[tool.hatch.version] +path = "wagtailstreamforms/__init__.py" + +[tool.hatch.build.targets.sdist] +include = [ + "/wagtailstreamforms", +] + [tool.black] line-length=99 -target-version=["py39"] +target-version=["py312"] exclude = ''' /( \.git diff --git a/readthedocs.yml b/readthedocs.yml index 06897971..2264ed84 100644 --- a/readthedocs.yml +++ b/readthedocs.yml @@ -1,5 +1,5 @@ --- python: - version: 3.5 + version: 3.12 pip_install: true requirements_file: docs/requirements.txt diff --git a/requirements.txt b/requirements.txt index 1f7ad04c..722a9c9b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,10 @@ # The app itself -e . -Django>=3.2 +Django>=5 mock psycopg2-binary # example site django-recaptcha +wagtail-modeladmin \ No newline at end of file diff --git a/setup.py b/setup.py deleted file mode 100644 index 87ec759e..00000000 --- a/setup.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python - -from codecs import open -from os import path - -from setuptools import setup - -from wagtailstreamforms import __version__ - -tests_require = [ - "mock==4.0.2", - "pytest-django==4.7.0", - "pytest==7.3.2", - # Linting - "isort[pyproject]==4.3.21", - "flake8==3.7.9", - "flake8-blind-except==0.1.1", - "flake8-debugger==3.1.0", -] - - -install_requires = [ - "wagtail>=4.1,<5.3", - "Unidecode>=0.04.14,<2.0", - "wagtail-generic-chooser>=0.5.0,<0.7", -] - -documentation_extras = [ - "sphinxcontrib-spelling>=2.3.0", - "Sphinx>=1.5.2", - "sphinx-autobuild>=0.6.0", - "karma_sphinx_theme>=0.0.6", -] - -here = path.abspath(path.dirname(__file__)) - -with open(path.join(here, "README.rst"), encoding="utf-8") as f: - long_description = f.read() - -setup( - name="wagtailstreamforms", - version=__version__, - description="Wagtail forms in a streamfield", - long_description=long_description, - author="Stuart George", - author_email="stuart@accentdesign.co.uk", - url="https://github.com/AccentDesign/wagtailstreamforms/", - download_url="https://pypi.python.org/pypi/wagtailstreamforms", - license="MIT", - packages=["wagtailstreamforms"], - install_requires=install_requires, - extras_require={ - "docs": documentation_extras, - "test": tests_require, - }, - include_package_data=True, - keywords=["wagtail", "streamfield", "forms", "accent", "design"], - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "Operating System :: OS Independent", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Framework :: Django", - "Framework :: Django :: 3.2", - "Framework :: Django :: 4", - "Framework :: Django :: 4.0", - "Framework :: Django :: 4.1", - "Framework :: Django :: 4.2", - "Framework :: Wagtail", - "Framework :: Wagtail :: 4", - "Topic :: Internet :: WWW/HTTP :: Site Management", - ], -) diff --git a/tests/blocks/test_form_block.py b/tests/blocks/test_form_block.py index c1b72d7f..addef28f 100644 --- a/tests/blocks/test_form_block.py +++ b/tests/blocks/test_form_block.py @@ -1,5 +1,3 @@ -from django.conf import settings - from wagtailstreamforms.blocks import WagtailFormBlock from wagtailstreamforms.models import Form @@ -25,98 +23,87 @@ def test_render(self): expected_html = "\n".join( [ "