From f0056012d36c67c2ba415baff0fdc3e87378541f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Braghi=C8=99?= Date: Mon, 11 Mar 2024 09:47:07 +0000 Subject: [PATCH] Tooling updates (#790) * Update ruff version and use for formatting as well * Lint * Remove unused runtime.txt * Move nightly tests to GHA * Tidy up tox config * Ensure we're using coverage >= 7.0 * Add a publish action includes asset build * Tidy up ignore files * Drop the lint step in favour of pre-commit.ci * Tidy up README * Regenerate test migrations as an initial one (speeds up things) --- .circleci/config.yml | 60 -- .circleci/trigger-nightly-build.sh | 8 - .coveragerc | 17 +- .../scripts}/report_nightly_build_failure.py | 1 + .github/workflows/nigthly-tests.yml | 36 + .github/workflows/publish.yml | 62 ++ .github/workflows/ruff.yml | 22 + .github/workflows/test.yml | 29 +- .pre-commit-config.yaml | 14 +- README.md | 14 +- pyproject.toml | 8 +- ruff.toml | 42 +- runtime.txt | 1 - tox.ini | 32 +- wagtail_localize/compat.py | 9 +- wagtail_localize/locales/components.py | 1 - wagtail_localize/machine_translators/deepl.py | 2 +- wagtail_localize/modeladmin/options.py | 4 +- wagtail_localize/modeladmin/tests.py | 8 +- wagtail_localize/models.py | 61 +- wagtail_localize/operations.py | 6 +- wagtail_localize/segments/extract.py | 10 +- wagtail_localize/segments/ingest.py | 20 +- wagtail_localize/segments/types.py | 18 +- wagtail_localize/strings.py | 5 +- wagtail_localize/synctree.py | 5 +- .../test/migrations/0001_initial.py | 478 ++++++++- .../0002_header_navigationlink_and_more.py | 921 ------------------ .../0003_wagtail_3_use_json_field.py | 721 -------------- .../migrations/0004_testparentalsnippet.py | 54 - ..._expire_at_testsnippet_expired_and_more.py | 124 --- wagtail_localize/test/models.py | 2 +- .../tests/test_translationsource_model.py | 4 +- .../tests/test_update_translations.py | 3 +- wagtail_localize/views/edit_translation.py | 39 +- wagtail_localize/views/update_translations.py | 20 +- 36 files changed, 723 insertions(+), 2138 deletions(-) delete mode 100644 .circleci/config.yml delete mode 100755 .circleci/trigger-nightly-build.sh rename {.circleci => .github/scripts}/report_nightly_build_failure.py (99%) create mode 100644 .github/workflows/nigthly-tests.yml create mode 100644 .github/workflows/publish.yml create mode 100644 .github/workflows/ruff.yml delete mode 100644 runtime.txt delete mode 100644 wagtail_localize/test/migrations/0002_header_navigationlink_and_more.py delete mode 100644 wagtail_localize/test/migrations/0003_wagtail_3_use_json_field.py delete mode 100644 wagtail_localize/test/migrations/0004_testparentalsnippet.py delete mode 100644 wagtail_localize/test/migrations/0005_testsnippet_expire_at_testsnippet_expired_and_more.py diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 3470672a..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,60 +0,0 @@ -version: 2 - -jobs: - test: - docker: - - image: cimg/python:3.11 - steps: - - checkout - - - type: cache-restore - keys: - - pip-{{ .Branch }}- - - pip-main- - - - run: pip install flit - - run: flit install --deps production --extras testing - - - type: cache-save - key: pip-{{ .Branch }}-{{ epoch }} - paths: - - '~/.cache/pip' - - - run: python testmanage.py test - - nightly-wagtail-test: - docker: - - image: cimg/python:3.11 - steps: - - checkout - - run: git clone git@github.com:wagtail/wagtail.git - - - run: pip install flit - - run: flit install --deps production --extras testing - - run: | - pip install \ - git+https://github.com/wagtail-nest/wagtail-modeladmin.git@main#egg=wagtail-modeladmin \ - ./wagtail - - - run: python testmanage.py test - - - run: - when: on_fail - command: python ./.circleci/report_nightly_build_failure.py - -workflows: - version: 2 - test: - jobs: - - test - - nightly: - jobs: - - nightly-wagtail-test - triggers: - - schedule: - cron: '0 0 * * *' - filters: - branches: - only: - - main diff --git a/.circleci/trigger-nightly-build.sh b/.circleci/trigger-nightly-build.sh deleted file mode 100755 index ef007897..00000000 --- a/.circleci/trigger-nightly-build.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -# Triggers a test run against the master version of Wagtail - -# This job will is scheduled in the config.yml, this script is here to help test the job - -curl -u ${CIRCLE_API_USER_TOKEN}: \ - -d build_parameters[CIRCLE_JOB]=nightly-wagtail-test \ - https://circleci.com/api/v1.1/project/github/wagtail/wagtail-localize/tree/master diff --git a/.coveragerc b/.coveragerc index ba26293a..36538e64 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,17 +1,23 @@ [run] branch = True include = wagtail_localize/* -omit = */migrations/*,*/tests/* +omit = **/migrations/*,**/tests/* [report] +show_missing = true +ignore_errors = true +skip_empty = true +skip_covered = true + # Regexes for lines to exclude from consideration -exclude_lines = +exclude_also = # Have to re-enable the standard pragma pragma: no cover # Don't complain about missing debug-only code: def __repr__ - if self\.debug + if self.debug + if settings.DEBUG # Don't complain if tests don't hit defensive assertion code: raise AssertionError @@ -21,4 +27,7 @@ exclude_lines = if 0: if __name__ == .__main__.: -ignore_errors = True + # Nor complain about type checking + "if TYPE_CHECKING:", + class .*\bProtocol\): + @(abc\.)?abstractmethod diff --git a/.circleci/report_nightly_build_failure.py b/.github/scripts/report_nightly_build_failure.py similarity index 99% rename from .circleci/report_nightly_build_failure.py rename to .github/scripts/report_nightly_build_failure.py index bdc33859..79685b29 100644 --- a/.circleci/report_nightly_build_failure.py +++ b/.github/scripts/report_nightly_build_failure.py @@ -3,6 +3,7 @@ This reports an error to the #nightly-build-failures Slack channel. """ + import os import requests diff --git a/.github/workflows/nigthly-tests.yml b/.github/workflows/nigthly-tests.yml new file mode 100644 index 00000000..b159ce7d --- /dev/null +++ b/.github/workflows/nigthly-tests.yml @@ -0,0 +1,36 @@ +name: Nightly Wagtail test + +on: + schedule: + # Nightly at 4am. + - cron: '0 4 * * *' + + workflow_dispatch: + +jobs: + nightly-test: + # Cannot check the existence of secrets, so limiting to repository name to prevent all forks to run nightly. + # See: https://github.com/actions/runner/issues/520 + if: ${{ github.repository == 'wagtail/wagtail-localize' }} + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Install dependencies + run: | + python -m pip install --upgrade pip tox + - name: Test + id: test + continue-on-error: true + run: tox -e wagtailmain + + - name: Send Slack notification on failure + if: steps.test.outcome == 'failure' + run: | + python .github/scripts/report_nightly_build_failure.py + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..f04e1cae --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,62 @@ +name: Publish to PyPI + +on: + release: + types: [published] + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read # to fetch code (actions/checkout) + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + + - name: Install Node dependencies + run: npm ci + + - name: Build static files + run: ./node_modules/.bin/webpack --mode production + + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + cache: 'pip' + cache-dependency-path: '**/pyproject.toml' + + - name: ⬇️ Install build dependencies + run: | + python -m pip install -U flit + + - name: 🏗️ Build + run: python -m flit build + + - uses: actions/upload-artifact@v4 + with: + path: ./dist + + # https://docs.pypi.org/trusted-publishers/using-a-publisher/ + pypi-publish: + needs: build + environment: 'publish' + + name: ⬆️ Upload release to PyPI + runs-on: ubuntu-latest + permissions: + # Mandatory for trusted publishing + id-token: write + steps: + - uses: actions/download-artifact@v4 + + - name: 🚀 Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: artifact/ + print-hash: true diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml new file mode 100644 index 00000000..0fec3836 --- /dev/null +++ b/.github/workflows/ruff.yml @@ -0,0 +1,22 @@ +name: Ruff + +on: + push: + branches: + - main + - 'stable/**' + pull_request: + branches: [main] + +jobs: + ruff: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - run: python -Im pip install --user ruff + + - name: Run ruff + working-directory: . + run: ruff --output-format=github wagtail_localize diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3d2b4995..d5bac20c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,23 +23,11 @@ permissions: contents: read # to fetch code (actions/checkout) jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: actions/setup-python@v4 - with: - python-version: ${{env.PYTHON_LATEST}} - - uses: pre-commit/action@v3.0.0 - test-sqlite: runs-on: ubuntu-latest - needs: lint strategy: matrix: - python: ['3.8', '3.9', '3.10', '3.11', '3.12'] + python: ['3.10', '3.11', '3.12'] database: ['sqlite'] steps: @@ -59,7 +47,6 @@ jobs: test-postgres: runs-on: ubuntu-latest - needs: lint strategy: matrix: python: ['3.8', '3.9', '3.10', '3.11', '3.12'] @@ -92,10 +79,8 @@ jobs: - name: Install dependencies id: install-dependencies run: | - python -m pip install --upgrade pip - python -m pip install tox tox-gh-actions + python -m pip install --upgrade pip tox tox-gh-actions - name: Test with tox - id: test-with-tox run: tox -- -v1 env: DATABASE_URL: postgres://postgres:postgres@localhost:5432/postgres @@ -103,10 +88,12 @@ jobs: coverage: runs-on: ubuntu-latest - needs: lint + needs: + - test-sqlite + - test-postgres strategy: matrix: - python: ['3.8'] + python: ['3.11'] steps: - uses: actions/checkout@v4 @@ -116,9 +103,9 @@ jobs: python-version: ${{ matrix.python }} - name: Install dependencies run: | - pip install flit + python -Im pip install -U flit + python -Im pip install "coverage>=7.0,<8.0" flit install --deps production --extras testing - pip install coverage==5.4 - name: Test run: | coverage run testmanage.py test diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dd265a87..b113f7fb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: check-added-large-files - id: check-case-conflict @@ -12,20 +12,12 @@ repos: args: ['--unsafe'] - id: end-of-file-fixer - id: trailing-whitespace - - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.11.0 - hooks: - - id: black - - repo: https://github.com/adamchainz/blacken-docs - rev: 1.16.0 - hooks: - - id: blacken-docs - additional_dependencies: [black==23.11.0] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: 'v0.1.5' + rev: 'v0.3.2' hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] + - id: ruff-format - repo: https://github.com/pre-commit/mirrors-prettier rev: 'v2.7.1' hooks: diff --git a/README.md b/README.md index a2e2f534..11ee77e1 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ [![Version](https://img.shields.io/pypi/v/wagtail-localize.svg?style=flat)](https://pypi.python.org/pypi/wagtail-localize/) [![License](https://img.shields.io/badge/license-BSD-blue.svg?style=flat)](https://opensource.org/licenses/BSD-3-Clause) [![codecov](https://img.shields.io/codecov/c/github/wagtail/wagtail-localize?style=flat)](https://codecov.io/gh/wagtail/wagtail-localize) -[![black](https://img.shields.io/badge/code%20style-black-000000.svg?style=flat)](https://github.com/psf/black) -[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=flat)](https://github.com/pre-commit/pre-commit) +[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) +[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/wagtail/wagtail-localize/main.svg)](https://results.pre-commit.ci/latest/github/wagtail/wagtail-localize/main) Wagtail Localize is a translation plugin for the [Wagtail CMS](https://wagtail.org). It allows pages or snippets to be translated within Wagtail's admin interface. It also provides integrations with external translations services such as [Pontoon](https://pontoon.mozilla.org/) or [DeepL](https://www.deepl.com/), and importing/exporting translations with PO files. @@ -25,9 +25,9 @@ We'll be at Wagtail Space US this year! The Call for Participation and Registrat Wagtail Localize requires the following: - Python (3.8, 3.9, 3.10, 3.11) -- Django (3.2, 4.1, 4.2) -- Wagtail (4.1, 5.1, 5.2) with [internationalisation enabled](https://docs.wagtail.org/en/stable/advanced_topics/i18n.html#configuration) -- [wagtail-modeladmin](https://pypi.org/project/wagtail-modeladmin/) if `using wagtail_localize.modeladmin` and Wagtail >= 5.0 +- Django (3.2, 4.2, 5.0) +- Wagtail (5.2, 6.0) with [internationalisation enabled](https://docs.wagtail.org/en/stable/advanced_topics/i18n.html#configuration) +- [wagtail-modeladmin](https://pypi.org/project/wagtail-modeladmin/) if `using wagtail_localize.modeladmin` and Wagtail >= 5.2 ## Installation @@ -105,8 +105,8 @@ Now you can run tests as shown below: tox ``` -or, you can run them for a specific environment `tox -e python3.8-django3.2-wagtail4.1` or specific test -`tox -e python3.9-django3.2-wagtail4.1-sqlite -- wagtail_localize.tests.test_edit_translation.TestGetEditTranslationView` +or, you can run them for a specific environment `tox -e python3.11-django4.2-wagtail5.2` or specific test +`tox -e python3.11-django4.2-wagtail5.2-sqlite -- wagtail_localize.tests.test_edit_translation.TestGetEditTranslationView` To run the test app interactively, use `tox -e interactive`, visit `http://127.0.0.1:8020/admin/` and log in with `admin`/`changeme`. diff --git a/pyproject.toml b/pyproject.toml index f1d2bfaf..d4660fa2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,6 @@ classifiers = [ "Programming Language :: Python :: 3.12", "Framework :: Django", "Framework :: Django :: 3.2", - "Framework :: Django :: 4.1", "Framework :: Django :: 4.2", "Framework :: Django :: 5.0", "Framework :: Wagtail", @@ -80,10 +79,13 @@ exclude = [ "scripts", "docs", ".*", + "*.db", "*.js", "*.json", "*.ini", + "*.sqlite3", "*.yml", + "*.yaml", "netlify.toml", "ruff.toml", "testmanage.py", @@ -91,7 +93,3 @@ exclude = [ include = [ "wagtail_localize/static" ] - - -[tool.black] -target-version = ["py38"] diff --git a/ruff.toml b/ruff.toml index 2b37ede4..b055d0d1 100644 --- a/ruff.toml +++ b/ruff.toml @@ -1,34 +1,40 @@ -target-version = "py38" +[lint] -exclude = ["dist","build","venv",".venv",".tox",".git", "__pycache__", "node_modules", "LC_MESSAGES", "locale"] - -select = [ - "B", # flake8-bugbear - "BLE", # flake8-blind-except - "C4", # flake8-comprehensions - "DJ", # flake8-django - "E", # pycodestyle errors - "F", # pyflakes +extend-select = [ + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "DJ", # flake8-django + "E", # pycodestyle errors + "F", # pyflakes "I", # isort + "INT", # flake8-gettext + "PIE", # flake8-pie "PGH", # pygrep-hooks - "RUF100", # unused noqa "S", # flake8-bandit - "T20", # flake8-print - "UP", # pyupgrade - "W", # pycodestyle warnings + "SIM", # flake8-simplify + "W", # pycodestyle warnings "YTT", # flake8-2020 + "UP", # pyupgrade + "RUF100", # unused noqa +] + +extend-ignore = [ + "E501", # no line length errors + "B028" ] fixable = ["C4", "E", "F", "I", "UP"] -# E501: Line too long -ignore = ["E501","B028"] +exclude = ["dist","build","venv",".venv",".tox",".git", "__pycache__", "node_modules", "LC_MESSAGES", "locale"] -[per-file-ignores] +[lint.per-file-ignores] "tests/**.py" = ["DJ008"] "**/report_nightly_build_failure.py" = ["T201"] -[isort] +[lint.isort] known-first-party = ["wagtail_localize"] lines-between-types = 1 lines-after-imports = 2 + +[format] +docstring-code-format = true diff --git a/runtime.txt b/runtime.txt deleted file mode 100644 index cc1923a4..00000000 --- a/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -3.8 diff --git a/tox.ini b/tox.ini index e53b8865..9fcd5cc8 100644 --- a/tox.ini +++ b/tox.ini @@ -1,11 +1,14 @@ [tox] -skipsdist = True -usedevelop = True +min_version = 4.0 envlist = - python{3.10}-django{3.2}-wagtail{5.2}-{sqlite,postgres15} - python{3.8,3.9,3.10,3.11,3.12}-django{4.2}-wagtail{5.2,6.0}-{sqlite,postgres15} - python{3.10,3.11,3.12}-django{5.0}-wagtail{5.2,6.0}-{sqlite,postgres15} + python3.10-django3.2-wagtail5.2-postgres15 + python{3.8,3.9,3.10,3.11,3.12}-django{4.2}-wagtail{5.2,6.0}-postgres15 + python{3.10,3.11,3.12}-django{5.0}-wagtail{5.2,6.0}-postgres15 + # note: we're running a subset of the test with sqlite + python3.10-django3.2-wagtail5.2-sqlite + python3.11-django4.2-wagtail{5.2,6.0}-sqlite + python3.12-django5.0-wagtail{5.2,6.0}-sqlite [gh-actions] python = @@ -21,6 +24,7 @@ DATABASE = sqlite: sqlite [testenv] +package = editable pass_env = FORCE_COLOR NO_COLOR @@ -32,9 +36,10 @@ setenv = postgres: DATABASE_URL={env:DATABASE_URL:postgres:///wagtail_localize} PYTHONDEVMODE = 1 +extras = testing + deps = - coverage - typing_extensions>=4.0 + coverage>=7.0,<8.0 django3.2: Django>=3.2,<3.3 django4.2: Django>=4.2,<5.0 @@ -46,8 +51,6 @@ deps = postgres: psycopg2>=2.9 - .[testing] - install_command = python -Im pip install --upgrade {opts} {packages} commands = python -Im coverage run testmanage.py test --deprecation all {posargs: -v 2} @@ -60,8 +63,15 @@ deps = commands = python -Im coverage report -m +[testenv:wagtailmain] +description = Test with latest Wagtail main branch +base_python = python3.12 +deps = + wagtailmain: git+https://github.com/wagtail/wagtail.git@main#egg=Wagtail + [testenv:interactive] +description = An interactive environment for local testing purposes basepython = python3.11 commands_pre = @@ -77,11 +87,11 @@ setenv = INTERACTIVE = 1 [testenv:migrations] -basepython = python3.9 +basepython = python3.11 # always generate with the min supported versions deps = - Django~=3.2 + Django>=3.2,<3.3 wagtail>=5.2,<6.0 commands = diff --git a/wagtail_localize/compat.py b/wagtail_localize/compat.py index 4eb164d4..6fc2e851 100644 --- a/wagtail_localize/compat.py +++ b/wagtail_localize/compat.py @@ -1,9 +1,6 @@ import os -if os.name == "nt": - # Windows has a different strftime format for dates without leading 0 - # https://stackoverflow.com/questions/904928/python-strftime-date-without-leading-0 - DATE_FORMAT = "%#d %B %Y" -else: - DATE_FORMAT = "%-d %B %Y" +# Windows has a different strftime format for dates without leading 0 +# https://stackoverflow.com/questions/904928/python-strftime-date-without-leading-0 +DATE_FORMAT = "%#d %B %Y" if os.name == "nt" else "%-d %B %Y" diff --git a/wagtail_localize/locales/components.py b/wagtail_localize/locales/components.py index b0142a7b..dfa498f5 100644 --- a/wagtail_localize/locales/components.py +++ b/wagtail_localize/locales/components.py @@ -32,4 +32,3 @@ def validate_with_locale(self, locale): """ Validates the locale component against the given locale. """ - pass diff --git a/wagtail_localize/machine_translators/deepl.py b/wagtail_localize/machine_translators/deepl.py index cfad1ad0..ba29318a 100644 --- a/wagtail_localize/machine_translators/deepl.py +++ b/wagtail_localize/machine_translators/deepl.py @@ -10,7 +10,7 @@ SUPPORTED_FORMALITY_OPTIONS = {"default", "prefer_less", "prefer_more"} -def language_code(code, is_target=False): +def language_code(code, *, is_target=False): # DeepL supports targeting Brazilian Portuguese and requires to specifically request American or British English. # @see https://www.deepl.com/en/docs-api/translate-text/translate-text upper_code = code.upper() diff --git a/wagtail_localize/modeladmin/options.py b/wagtail_localize/modeladmin/options.py index a431c124..db60ca29 100644 --- a/wagtail_localize/modeladmin/options.py +++ b/wagtail_localize/modeladmin/options.py @@ -55,9 +55,7 @@ def get_templates(self, action="index"): app_label = self.opts.app_label.lower() model_name = self.opts.model_name.lower() return [ - "wagtail_localize/modeladmin/{}/{}/translatable_{}.html".format( - app_label, model_name, action - ), + f"wagtail_localize/modeladmin/{app_label}/{model_name}/translatable_{action}.html", f"wagtail_localize/modeladmin/{app_label}/translatable_{action}.html", f"wagtail_localize/modeladmin/translatable_{action}.html", ] diff --git a/wagtail_localize/modeladmin/tests.py b/wagtail_localize/modeladmin/tests.py index d3c16ff7..d3103849 100644 --- a/wagtail_localize/modeladmin/tests.py +++ b/wagtail_localize/modeladmin/tests.py @@ -109,9 +109,7 @@ def test_edit_view(self): ) self.assertContains( response, - ' 1: raise ValueError( - "Related object field can only have a single segment. Found {}".format( - len(segments) - ) + f"Related object field can only have a single segment. Found {len(segments)}" ) segment = segments[0] @@ -123,9 +121,7 @@ def handle_block(self, block_type, block_value, segments): if isinstance(block_type, EmbedBlock): if len(segments) > 1: raise ValueError( - "EmbedBlock can only have a single segment. Found {}".format( - len(segments) - ) + f"EmbedBlock can only have a single segment. Found {len(segments)}" ) segment = segments[0] @@ -142,9 +138,7 @@ def handle_block(self, block_type, block_value, segments): ): if len(segments) > 1: raise ValueError( - "TextBlock/CharBlock can only have a single segment. Found {}".format( - len(segments) - ) + f"TextBlock/CharBlock can only have a single segment. Found {len(segments)}" ) segment = segments[0] @@ -177,9 +171,7 @@ def handle_block(self, block_type, block_value, segments): else: raise Exception( - "Unrecognised StreamField block type '{}'. Have you implemented restore_translated_segments() on this class?".format( - block_type.__class__.__name__ - ) + f"Unrecognised StreamField block type '{block_type.__class__.__name__}'. Have you implemented restore_translated_segments() on this class?" ) def handle_related_object_block(self, related_object, segments): @@ -285,9 +277,7 @@ def ingest_segments(original_obj, translated_obj, src_locale, tgt_locale, segmen elif isinstance(field, (models.TextField, models.CharField)): if len(field_segments) > 1: raise ValueError( - "TextField/CharField can only have a single segment. Found {}".format( - len(field_segments) - ) + f"TextField/CharField can only have a single segment. Found {len(field_segments)}" ) segment = field_segments[0] diff --git a/wagtail_localize/segments/types.py b/wagtail_localize/segments/types.py index 5bf13b88..e69b2afc 100644 --- a/wagtail_localize/segments/types.py +++ b/wagtail_localize/segments/types.py @@ -28,8 +28,8 @@ def wrap(self, base_path): For example: - >>> s = StringSegmentValue('field', 'foo') - >>> s.wrap('wrapped') + >>> s = StringSegmentValue("field", "foo") + >>> s.wrap("wrapped") StringSegmentValue('wrapped.field', 'foo') """ new_path = base_path @@ -47,7 +47,7 @@ def unwrap(self): For example: - >>> s = StringSegmentValue('wrapped.field', 'foo') + >>> s = StringSegmentValue("wrapped.field", "foo") >>> s.unwrap() 'wrapped', StringSegmentValue('field', 'foo') """ @@ -88,9 +88,7 @@ def __init__(self, path, string, attrs=None, **kwargs): else: raise TypeError( - "`string` must be either a `StringValue` or a `str`. Got `{}`".format( - type(string).__name__ - ) + f"`string` must be either a `StringValue` or a `str`. Got `{type(string).__name__}`" ) self.string = string @@ -228,9 +226,7 @@ def __eq__(self, other): ) def __repr__(self): - return "".format( - self.path, self.format, self.string_count - ) + return f"" class RelatedObjectSegmentValue(BaseValue): @@ -329,9 +325,7 @@ def __eq__(self, other): ) def __repr__(self): - return "".format( - self.path, self.content_type, self.translation_key - ) + return f"" class OverridableSegmentValue(BaseValue): diff --git a/wagtail_localize/strings.py b/wagtail_localize/strings.py index 7071cb9b..0d86f8ff 100644 --- a/wagtail_localize/strings.py +++ b/wagtail_localize/strings.py @@ -491,9 +491,8 @@ def extract_ids(template): if not isinstance(element, Tag): continue - if element.name == "a": - if "id" in element.attrs: - ids.add(element.attrs["id"]) + if element.name == "a" and "id" in element.attrs: + ids.add(element.attrs["id"]) return ids diff --git a/wagtail_localize/synctree.py b/wagtail_localize/synctree.py index 930a7c36..fcda05cd 100644 --- a/wagtail_localize/synctree.py +++ b/wagtail_localize/synctree.py @@ -69,10 +69,7 @@ def from_page_instance(cls, page): """ # Get parent, but only if the parent is not the root page. We consider the # homepage of each langauge tree to be the roots - if page.depth > 2: - parent_page = page.get_parent() - else: - parent_page = None + parent_page = page.get_parent() if page.depth > 2 else None return cls( page.content_type, diff --git a/wagtail_localize/test/migrations/0001_initial.py b/wagtail_localize/test/migrations/0001_initial.py index 5d94cb32..3cac1764 100644 --- a/wagtail_localize/test/migrations/0001_initial.py +++ b/wagtail_localize/test/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.1.1 on 2022-09-23 14:13 +# Generated by Django 3.2.25 on 2024-03-10 17:20 import uuid @@ -20,12 +20,11 @@ class Migration(migrations.Migration): initial = True - core_migration = "0076_modellogentry_revision" dependencies = [ - ("wagtailcore", "0059_apply_collection_ordering"), - ("wagtaildocs", "0010_document_file_hash"), - ("wagtailimages", "0022_uploadedimage"), - ("wagtail_localize", "0015_translationcontext_field_path"), + ("wagtaildocs", "0012_uploadeddocument"), + ("wagtailimages", "0025_alter_image_file_alter_rendition_file"), + ("wagtailcore", "0089_log_entry_data_json_null_to_object"), + ("wagtail_localize", "0016_rename_page_revision_translationlog_revision"), ] operations = [ @@ -44,6 +43,92 @@ class Migration(migrations.Migration): ("notes", models.CharField(max_length=255)), ], ), + migrations.CreateModel( + name="Header", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "translation_key", + models.UUIDField(default=uuid.uuid4, editable=False), + ), + ("name", models.CharField(blank=True, max_length=100)), + ( + "locale", + models.ForeignKey( + editable=False, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="wagtailcore.locale", + ), + ), + ], + options={ + "abstract": False, + "unique_together": {("translation_key", "locale")}, + }, + ), + migrations.CreateModel( + name="NavigationLink", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "translation_key", + models.UUIDField(default=uuid.uuid4, editable=False), + ), + ( + "sort_order", + models.IntegerField(blank=True, editable=False, null=True), + ), + ("label", models.CharField(max_length=255)), + ( + "locale", + models.ForeignKey( + editable=False, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="wagtailcore.locale", + ), + ), + ( + "page", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + ), + ), + ( + "snippet", + modelcluster.fields.ParentalKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="navigation_links", + to="wagtail_localize_test.header", + ), + ), + ], + options={ + "abstract": False, + "unique_together": {("translation_key", "locale")}, + }, + ), migrations.CreateModel( name="NonTranslatableModel", fields=[ @@ -139,10 +224,7 @@ class Migration(migrations.Migration): ("test_urlblock", wagtail.blocks.URLBlock()), ("test_richtextblock", wagtail.blocks.RichTextBlock()), ("test_rawhtmlblock", wagtail.blocks.RawHTMLBlock()), - ( - "test_blockquoteblock", - wagtail.blocks.BlockQuoteBlock(), - ), + ("test_blockquoteblock", wagtail.blocks.BlockQuoteBlock()), ( "test_structblock", wagtail.blocks.StructBlock( @@ -208,10 +290,7 @@ class Migration(migrations.Migration): wagtail.blocks.CharBlock() ), ), - ( - "chooser", - wagtail.blocks.PageChooserBlock(), - ), + ("chooser", wagtail.blocks.PageChooserBlock()), ( "chooser_in_struct", wagtail.blocks.StructBlock( @@ -332,8 +411,60 @@ class Migration(migrations.Migration): ] ), ), + ( + "test_chooser_in_struct_in_listblock", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "page", + wagtail.blocks.PageChooserBlock( + required=False + ), + ) + ] + ) + ), + ), + ( + "test_image_chooser_in_listblock", + wagtail.blocks.ListBlock( + wagtail.images.blocks.ImageChooserBlock() + ), + ), + ( + "test_document_chooser_in_listblock", + wagtail.blocks.ListBlock( + wagtail.documents.blocks.DocumentChooserBlock() + ), + ), + ( + "test_chooser_in_struct_in_list_in_stream_in_listblock", + wagtail.blocks.ListBlock( + wagtail.blocks.StreamBlock( + [ + ( + "list", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "page", + wagtail.blocks.PageChooserBlock( + required=False + ), + ) + ] + ) + ), + ) + ] + ) + ), + ), ], blank=True, + use_json_field=True, ), ), ( @@ -460,10 +591,7 @@ class Migration(migrations.Migration): ("test_urlblock", wagtail.blocks.URLBlock()), ("test_richtextblock", wagtail.blocks.RichTextBlock()), ("test_rawhtmlblock", wagtail.blocks.RawHTMLBlock()), - ( - "test_blockquoteblock", - wagtail.blocks.BlockQuoteBlock(), - ), + ("test_blockquoteblock", wagtail.blocks.BlockQuoteBlock()), ( "test_structblock", wagtail.blocks.StructBlock( @@ -529,10 +657,7 @@ class Migration(migrations.Migration): wagtail.blocks.CharBlock() ), ), - ( - "chooser", - wagtail.blocks.PageChooserBlock(), - ), + ("chooser", wagtail.blocks.PageChooserBlock()), ( "chooser_in_struct", wagtail.blocks.StructBlock( @@ -653,8 +778,60 @@ class Migration(migrations.Migration): ] ), ), + ( + "test_chooser_in_struct_in_listblock", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "page", + wagtail.blocks.PageChooserBlock( + required=False + ), + ) + ] + ) + ), + ), + ( + "test_image_chooser_in_listblock", + wagtail.blocks.ListBlock( + wagtail.images.blocks.ImageChooserBlock() + ), + ), + ( + "test_document_chooser_in_listblock", + wagtail.blocks.ListBlock( + wagtail.documents.blocks.DocumentChooserBlock() + ), + ), + ( + "test_chooser_in_struct_in_list_in_stream_in_listblock", + wagtail.blocks.ListBlock( + wagtail.blocks.StreamBlock( + [ + ( + "list", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "page", + wagtail.blocks.PageChooserBlock( + required=False + ), + ) + ] + ) + ), + ) + ] + ) + ), + ), ], blank=True, + use_json_field=True, ), ), ( @@ -696,10 +873,7 @@ class Migration(migrations.Migration): ("test_urlblock", wagtail.blocks.URLBlock()), ("test_richtextblock", wagtail.blocks.RichTextBlock()), ("test_rawhtmlblock", wagtail.blocks.RawHTMLBlock()), - ( - "test_blockquoteblock", - wagtail.blocks.BlockQuoteBlock(), - ), + ("test_blockquoteblock", wagtail.blocks.BlockQuoteBlock()), ( "test_structblock", wagtail.blocks.StructBlock( @@ -765,10 +939,7 @@ class Migration(migrations.Migration): wagtail.blocks.CharBlock() ), ), - ( - "chooser", - wagtail.blocks.PageChooserBlock(), - ), + ("chooser", wagtail.blocks.PageChooserBlock()), ( "chooser_in_struct", wagtail.blocks.StructBlock( @@ -889,8 +1060,60 @@ class Migration(migrations.Migration): ] ), ), + ( + "test_chooser_in_struct_in_listblock", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "page", + wagtail.blocks.PageChooserBlock( + required=False + ), + ) + ] + ) + ), + ), + ( + "test_image_chooser_in_listblock", + wagtail.blocks.ListBlock( + wagtail.images.blocks.ImageChooserBlock() + ), + ), + ( + "test_document_chooser_in_listblock", + wagtail.blocks.ListBlock( + wagtail.documents.blocks.DocumentChooserBlock() + ), + ), + ( + "test_chooser_in_struct_in_list_in_stream_in_listblock", + wagtail.blocks.ListBlock( + wagtail.blocks.StreamBlock( + [ + ( + "list", + wagtail.blocks.ListBlock( + wagtail.blocks.StructBlock( + [ + ( + "page", + wagtail.blocks.PageChooserBlock( + required=False + ), + ) + ] + ) + ), + ) + ] + ) + ), + ), ], blank=True, + use_json_field=True, ), ), ( @@ -949,8 +1172,79 @@ class Migration(migrations.Migration): "translation_key", models.UUIDField(default=uuid.uuid4, editable=False), ), + ( + "live", + models.BooleanField( + default=True, editable=False, verbose_name="live" + ), + ), + ( + "has_unpublished_changes", + models.BooleanField( + default=False, + editable=False, + verbose_name="has unpublished changes", + ), + ), + ( + "first_published_at", + models.DateTimeField( + blank=True, + db_index=True, + null=True, + verbose_name="first published at", + ), + ), + ( + "last_published_at", + models.DateTimeField( + editable=False, null=True, verbose_name="last published at" + ), + ), + ( + "go_live_at", + models.DateTimeField( + blank=True, null=True, verbose_name="go live date/time" + ), + ), + ( + "expire_at", + models.DateTimeField( + blank=True, null=True, verbose_name="expiry date/time" + ), + ), + ( + "expired", + models.BooleanField( + default=False, editable=False, verbose_name="expired" + ), + ), ("field", models.TextField(verbose_name="field")), ("small_charfield", models.CharField(blank=True, max_length=10)), + ( + "latest_revision", + models.ForeignKey( + blank=True, + editable=False, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.revision", + verbose_name="latest revision", + ), + ), + ( + "live_revision", + models.ForeignKey( + blank=True, + editable=False, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.revision", + verbose_name="live revision", + ), + ), ( "locale", models.ForeignKey( @@ -1333,6 +1627,43 @@ class Migration(migrations.Migration): "unique_together": {("translation_key", "locale")}, }, ), + migrations.CreateModel( + name="TestParentalSnippet", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "translation_key", + models.UUIDField(default=uuid.uuid4, editable=False), + ), + ( + "field", + modelcluster.fields.ParentalManyToManyField( + blank=True, to="wagtail_localize_test.TestUUIDModel" + ), + ), + ( + "locale", + models.ForeignKey( + editable=False, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="wagtailcore.locale", + ), + ), + ], + options={ + "abstract": False, + "unique_together": {("translation_key", "locale")}, + }, + ), migrations.CreateModel( name="TestNonParentalChildObject", fields=[ @@ -1377,6 +1708,38 @@ class Migration(migrations.Migration): "unique_together": {("translation_key", "locale")}, }, ), + migrations.CreateModel( + name="TestNoDraftModel", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "translation_key", + models.UUIDField(default=uuid.uuid4, editable=False), + ), + ("field", models.CharField(blank=True, max_length=20)), + ( + "locale", + models.ForeignKey( + editable=False, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="wagtailcore.locale", + ), + ), + ], + options={ + "abstract": False, + "unique_together": {("translation_key", "locale")}, + }, + ), migrations.CreateModel( name="TestModelWithInvalidForeignKey", fields=[ @@ -1460,6 +1823,61 @@ class Migration(migrations.Migration): "unique_together": {("translation_key", "locale")}, }, ), + migrations.CreateModel( + name="SubNavigationLink", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "translation_key", + models.UUIDField(default=uuid.uuid4, editable=False), + ), + ( + "sort_order", + models.IntegerField(blank=True, editable=False, null=True), + ), + ("label", models.CharField(max_length=255)), + ( + "locale", + models.ForeignKey( + editable=False, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="wagtailcore.locale", + ), + ), + ( + "page", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="wagtailcore.page", + ), + ), + ( + "sub_nav", + modelcluster.fields.ParentalKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="sub_navigation_links", + to="wagtail_localize_test.navigationlink", + ), + ), + ], + options={ + "abstract": False, + "unique_together": {("translation_key", "locale")}, + }, + ), migrations.CreateModel( name="PageWithCustomEditHandlerChildObject", fields=[ diff --git a/wagtail_localize/test/migrations/0002_header_navigationlink_and_more.py b/wagtail_localize/test/migrations/0002_header_navigationlink_and_more.py deleted file mode 100644 index b4352fcf..00000000 --- a/wagtail_localize/test/migrations/0002_header_navigationlink_and_more.py +++ /dev/null @@ -1,921 +0,0 @@ -# Generated by Django 3.2.16 on 2022-10-17 20:32 - -import uuid - -import django.db.models.deletion -import modelcluster.fields -import wagtail.blocks -import wagtail.blocks.field_block -import wagtail.documents.blocks -import wagtail.embeds.blocks -import wagtail.fields -import wagtail.images.blocks -import wagtail.snippets.blocks - -from django.db import migrations, models - -import wagtail_localize.test.models - - -class Migration(migrations.Migration): - dependencies = [ - ("wagtailcore", "0066_collection_management_permissions"), - ("wagtail_localize_test", "0001_initial"), - ] - - operations = [ - migrations.CreateModel( - name="Header", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ( - "translation_key", - models.UUIDField(default=uuid.uuid4, editable=False), - ), - ("name", models.CharField(max_length=100, blank=True)), - ( - "locale", - models.ForeignKey( - editable=False, - on_delete=django.db.models.deletion.PROTECT, - related_name="+", - to="wagtailcore.locale", - ), - ), - ], - options={ - "abstract": False, - "unique_together": {("translation_key", "locale")}, - }, - ), - migrations.CreateModel( - name="NavigationLink", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ( - "translation_key", - models.UUIDField(default=uuid.uuid4, editable=False), - ), - ( - "sort_order", - models.IntegerField(blank=True, editable=False, null=True), - ), - ("label", models.CharField(max_length=255)), - ( - "locale", - models.ForeignKey( - editable=False, - on_delete=django.db.models.deletion.PROTECT, - related_name="+", - to="wagtailcore.locale", - ), - ), - ( - "page", - models.ForeignKey( - blank=True, - null=True, - on_delete=django.db.models.deletion.SET_NULL, - related_name="+", - to="wagtailcore.page", - ), - ), - ( - "snippet", - modelcluster.fields.ParentalKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="navigation_links", - to="wagtail_localize_test.header", - ), - ), - ], - options={ - "abstract": False, - "unique_together": {("translation_key", "locale")}, - }, - ), - migrations.AlterField( - model_name="testgeneratetranslatablefieldspage", - name="test_streamfield", - field=wagtail.fields.StreamField( - [ - ("test_charblock", wagtail.blocks.CharBlock(max_length=255)), - ( - "test_textblock", - wagtail.blocks.TextBlock(label="text block"), - ), - ("test_emailblock", wagtail.blocks.EmailBlock()), - ("test_urlblock", wagtail.blocks.URLBlock()), - ("test_richtextblock", wagtail.blocks.RichTextBlock()), - ("test_rawhtmlblock", wagtail.blocks.RawHTMLBlock()), - ("test_blockquoteblock", wagtail.blocks.BlockQuoteBlock()), - ( - "test_structblock", - wagtail.blocks.StructBlock( - [ - ("field_a", wagtail.blocks.TextBlock()), - ("field_b", wagtail.blocks.TextBlock()), - ] - ), - ), - ( - "test_listblock", - wagtail.blocks.ListBlock(wagtail.blocks.TextBlock()), - ), - ( - "test_listblock_in_structblock", - wagtail.blocks.StructBlock( - [ - ( - "title", - wagtail.blocks.CharBlock(required=False), - ), - ( - "items", - wagtail.blocks.ListBlock( - wagtail.blocks.field_block.CharBlock - ), - ), - ( - "links_list", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "heading", - wagtail.blocks.CharBlock( - blank=True, - label="List Heading", - required=False, - ), - ), - ( - "pages", - wagtail.blocks.ListBlock( - wagtail.blocks.PageChooserBlock() - ), - ), - ] - ) - ), - ), - ] - ), - ), - ( - "test_nestedstreamblock", - wagtail.blocks.StreamBlock( - [ - ("block_a", wagtail.blocks.TextBlock()), - ("block_b", wagtail.blocks.TextBlock()), - ( - "block_l", - wagtail.blocks.ListBlock( - wagtail.blocks.CharBlock() - ), - ), - ("chooser", wagtail.blocks.PageChooserBlock()), - ( - "chooser_in_struct", - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(), - ) - ] - ), - ), - ( - "chooser_in_list", - wagtail.blocks.ListBlock( - wagtail.blocks.PageChooserBlock() - ), - ), - ] - ), - ), - ( - "test_streamblock_in_structblock", - wagtail.blocks.StructBlock( - [ - ( - "nested_stream", - wagtail.blocks.StreamBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(), - ), - ( - "checklist", - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(), - ) - ] - ), - ), - ] - ), - ) - ] - ), - ), - ( - "test_customstructblock", - wagtail.blocks.StructBlock( - [ - ("field_a", wagtail.blocks.TextBlock()), - ("field_b", wagtail.blocks.TextBlock()), - ] - ), - ), - ( - "test_customblockwithoutextractmethod", - wagtail_localize.test.models.CustomBlockWithoutExtractMethod(), - ), - ("test_pagechooserblock", wagtail.blocks.PageChooserBlock()), - ( - "test_pagechooserblock_with_restricted_types", - wagtail.blocks.PageChooserBlock( - [ - "wagtail_localize_test.TestHomePage", - "wagtail_localize_test.TestPage", - ] - ), - ), - ( - "test_imagechooserblock", - wagtail.images.blocks.ImageChooserBlock(), - ), - ( - "test_documentchooserblock", - wagtail.documents.blocks.DocumentChooserBlock(), - ), - ( - "test_snippetchooserblock", - wagtail.snippets.blocks.SnippetChooserBlock( - wagtail_localize.test.models.TestSnippet - ), - ), - ( - "test_nontranslatablesnippetchooserblock", - wagtail.snippets.blocks.SnippetChooserBlock( - wagtail_localize.test.models.NonTranslatableSnippet - ), - ), - ("test_embedblock", wagtail.embeds.blocks.EmbedBlock()), - ( - "test_chooserstructblock", - wagtail.blocks.StructBlock( - [("page", wagtail.blocks.PageChooserBlock())] - ), - ), - ( - "test_nestedchooserstructblock", - wagtail.blocks.StructBlock( - [ - ( - "nested_page", - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(), - ) - ] - ), - ) - ] - ), - ), - ( - "test_chooser_in_struct_in_listblock", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(required=False), - ) - ] - ) - ), - ), - ( - "test_image_chooser_in_listblock", - wagtail.blocks.ListBlock( - wagtail.images.blocks.ImageChooserBlock() - ), - ), - ( - "test_document_chooser_in_listblock", - wagtail.blocks.ListBlock( - wagtail.documents.blocks.DocumentChooserBlock() - ), - ), - ( - "test_chooser_in_struct_in_list_in_stream_in_listblock", - wagtail.blocks.ListBlock( - wagtail.blocks.StreamBlock( - [ - ( - "list", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock( - required=False - ), - ) - ] - ) - ), - ) - ] - ) - ), - ), - ], - blank=True, - ), - ), - migrations.AlterField( - model_name="testpage", - name="test_streamfield", - field=wagtail.fields.StreamField( - [ - ("test_charblock", wagtail.blocks.CharBlock(max_length=255)), - ( - "test_textblock", - wagtail.blocks.TextBlock(label="text block"), - ), - ("test_emailblock", wagtail.blocks.EmailBlock()), - ("test_urlblock", wagtail.blocks.URLBlock()), - ("test_richtextblock", wagtail.blocks.RichTextBlock()), - ("test_rawhtmlblock", wagtail.blocks.RawHTMLBlock()), - ("test_blockquoteblock", wagtail.blocks.BlockQuoteBlock()), - ( - "test_structblock", - wagtail.blocks.StructBlock( - [ - ("field_a", wagtail.blocks.TextBlock()), - ("field_b", wagtail.blocks.TextBlock()), - ] - ), - ), - ( - "test_listblock", - wagtail.blocks.ListBlock(wagtail.blocks.TextBlock()), - ), - ( - "test_listblock_in_structblock", - wagtail.blocks.StructBlock( - [ - ( - "title", - wagtail.blocks.CharBlock(required=False), - ), - ( - "items", - wagtail.blocks.ListBlock( - wagtail.blocks.field_block.CharBlock - ), - ), - ( - "links_list", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "heading", - wagtail.blocks.CharBlock( - blank=True, - label="List Heading", - required=False, - ), - ), - ( - "pages", - wagtail.blocks.ListBlock( - wagtail.blocks.PageChooserBlock() - ), - ), - ] - ) - ), - ), - ] - ), - ), - ( - "test_nestedstreamblock", - wagtail.blocks.StreamBlock( - [ - ("block_a", wagtail.blocks.TextBlock()), - ("block_b", wagtail.blocks.TextBlock()), - ( - "block_l", - wagtail.blocks.ListBlock( - wagtail.blocks.CharBlock() - ), - ), - ("chooser", wagtail.blocks.PageChooserBlock()), - ( - "chooser_in_struct", - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(), - ) - ] - ), - ), - ( - "chooser_in_list", - wagtail.blocks.ListBlock( - wagtail.blocks.PageChooserBlock() - ), - ), - ] - ), - ), - ( - "test_streamblock_in_structblock", - wagtail.blocks.StructBlock( - [ - ( - "nested_stream", - wagtail.blocks.StreamBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(), - ), - ( - "checklist", - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(), - ) - ] - ), - ), - ] - ), - ) - ] - ), - ), - ( - "test_customstructblock", - wagtail.blocks.StructBlock( - [ - ("field_a", wagtail.blocks.TextBlock()), - ("field_b", wagtail.blocks.TextBlock()), - ] - ), - ), - ( - "test_customblockwithoutextractmethod", - wagtail_localize.test.models.CustomBlockWithoutExtractMethod(), - ), - ("test_pagechooserblock", wagtail.blocks.PageChooserBlock()), - ( - "test_pagechooserblock_with_restricted_types", - wagtail.blocks.PageChooserBlock( - [ - "wagtail_localize_test.TestHomePage", - "wagtail_localize_test.TestPage", - ] - ), - ), - ( - "test_imagechooserblock", - wagtail.images.blocks.ImageChooserBlock(), - ), - ( - "test_documentchooserblock", - wagtail.documents.blocks.DocumentChooserBlock(), - ), - ( - "test_snippetchooserblock", - wagtail.snippets.blocks.SnippetChooserBlock( - wagtail_localize.test.models.TestSnippet - ), - ), - ( - "test_nontranslatablesnippetchooserblock", - wagtail.snippets.blocks.SnippetChooserBlock( - wagtail_localize.test.models.NonTranslatableSnippet - ), - ), - ("test_embedblock", wagtail.embeds.blocks.EmbedBlock()), - ( - "test_chooserstructblock", - wagtail.blocks.StructBlock( - [("page", wagtail.blocks.PageChooserBlock())] - ), - ), - ( - "test_nestedchooserstructblock", - wagtail.blocks.StructBlock( - [ - ( - "nested_page", - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(), - ) - ] - ), - ) - ] - ), - ), - ( - "test_chooser_in_struct_in_listblock", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(required=False), - ) - ] - ) - ), - ), - ( - "test_image_chooser_in_listblock", - wagtail.blocks.ListBlock( - wagtail.images.blocks.ImageChooserBlock() - ), - ), - ( - "test_document_chooser_in_listblock", - wagtail.blocks.ListBlock( - wagtail.documents.blocks.DocumentChooserBlock() - ), - ), - ( - "test_chooser_in_struct_in_list_in_stream_in_listblock", - wagtail.blocks.ListBlock( - wagtail.blocks.StreamBlock( - [ - ( - "list", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock( - required=False - ), - ) - ] - ) - ), - ) - ] - ) - ), - ), - ], - blank=True, - ), - ), - migrations.AlterField( - model_name="testpage", - name="test_synchronized_streamfield", - field=wagtail.fields.StreamField( - [ - ("test_charblock", wagtail.blocks.CharBlock(max_length=255)), - ( - "test_textblock", - wagtail.blocks.TextBlock(label="text block"), - ), - ("test_emailblock", wagtail.blocks.EmailBlock()), - ("test_urlblock", wagtail.blocks.URLBlock()), - ("test_richtextblock", wagtail.blocks.RichTextBlock()), - ("test_rawhtmlblock", wagtail.blocks.RawHTMLBlock()), - ("test_blockquoteblock", wagtail.blocks.BlockQuoteBlock()), - ( - "test_structblock", - wagtail.blocks.StructBlock( - [ - ("field_a", wagtail.blocks.TextBlock()), - ("field_b", wagtail.blocks.TextBlock()), - ] - ), - ), - ( - "test_listblock", - wagtail.blocks.ListBlock(wagtail.blocks.TextBlock()), - ), - ( - "test_listblock_in_structblock", - wagtail.blocks.StructBlock( - [ - ( - "title", - wagtail.blocks.CharBlock(required=False), - ), - ( - "items", - wagtail.blocks.ListBlock( - wagtail.blocks.field_block.CharBlock - ), - ), - ( - "links_list", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "heading", - wagtail.blocks.CharBlock( - blank=True, - label="List Heading", - required=False, - ), - ), - ( - "pages", - wagtail.blocks.ListBlock( - wagtail.blocks.PageChooserBlock() - ), - ), - ] - ) - ), - ), - ] - ), - ), - ( - "test_nestedstreamblock", - wagtail.blocks.StreamBlock( - [ - ("block_a", wagtail.blocks.TextBlock()), - ("block_b", wagtail.blocks.TextBlock()), - ( - "block_l", - wagtail.blocks.ListBlock( - wagtail.blocks.CharBlock() - ), - ), - ("chooser", wagtail.blocks.PageChooserBlock()), - ( - "chooser_in_struct", - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(), - ) - ] - ), - ), - ( - "chooser_in_list", - wagtail.blocks.ListBlock( - wagtail.blocks.PageChooserBlock() - ), - ), - ] - ), - ), - ( - "test_streamblock_in_structblock", - wagtail.blocks.StructBlock( - [ - ( - "nested_stream", - wagtail.blocks.StreamBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(), - ), - ( - "checklist", - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(), - ) - ] - ), - ), - ] - ), - ) - ] - ), - ), - ( - "test_customstructblock", - wagtail.blocks.StructBlock( - [ - ("field_a", wagtail.blocks.TextBlock()), - ("field_b", wagtail.blocks.TextBlock()), - ] - ), - ), - ( - "test_customblockwithoutextractmethod", - wagtail_localize.test.models.CustomBlockWithoutExtractMethod(), - ), - ("test_pagechooserblock", wagtail.blocks.PageChooserBlock()), - ( - "test_pagechooserblock_with_restricted_types", - wagtail.blocks.PageChooserBlock( - [ - "wagtail_localize_test.TestHomePage", - "wagtail_localize_test.TestPage", - ] - ), - ), - ( - "test_imagechooserblock", - wagtail.images.blocks.ImageChooserBlock(), - ), - ( - "test_documentchooserblock", - wagtail.documents.blocks.DocumentChooserBlock(), - ), - ( - "test_snippetchooserblock", - wagtail.snippets.blocks.SnippetChooserBlock( - wagtail_localize.test.models.TestSnippet - ), - ), - ( - "test_nontranslatablesnippetchooserblock", - wagtail.snippets.blocks.SnippetChooserBlock( - wagtail_localize.test.models.NonTranslatableSnippet - ), - ), - ("test_embedblock", wagtail.embeds.blocks.EmbedBlock()), - ( - "test_chooserstructblock", - wagtail.blocks.StructBlock( - [("page", wagtail.blocks.PageChooserBlock())] - ), - ), - ( - "test_nestedchooserstructblock", - wagtail.blocks.StructBlock( - [ - ( - "nested_page", - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(), - ) - ] - ), - ) - ] - ), - ), - ( - "test_chooser_in_struct_in_listblock", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(required=False), - ) - ] - ) - ), - ), - ( - "test_image_chooser_in_listblock", - wagtail.blocks.ListBlock( - wagtail.images.blocks.ImageChooserBlock() - ), - ), - ( - "test_document_chooser_in_listblock", - wagtail.blocks.ListBlock( - wagtail.documents.blocks.DocumentChooserBlock() - ), - ), - ( - "test_chooser_in_struct_in_list_in_stream_in_listblock", - wagtail.blocks.ListBlock( - wagtail.blocks.StreamBlock( - [ - ( - "list", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock( - required=False - ), - ) - ] - ) - ), - ) - ] - ) - ), - ), - ], - blank=True, - ), - ), - migrations.CreateModel( - name="SubNavigationLink", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ( - "translation_key", - models.UUIDField(default=uuid.uuid4, editable=False), - ), - ( - "sort_order", - models.IntegerField(blank=True, editable=False, null=True), - ), - ("label", models.CharField(max_length=255)), - ( - "locale", - models.ForeignKey( - editable=False, - on_delete=django.db.models.deletion.PROTECT, - related_name="+", - to="wagtailcore.locale", - ), - ), - ( - "page", - models.ForeignKey( - blank=True, - null=True, - on_delete=django.db.models.deletion.SET_NULL, - related_name="+", - to="wagtailcore.page", - ), - ), - ( - "sub_nav", - modelcluster.fields.ParentalKey( - null=True, - on_delete=django.db.models.deletion.CASCADE, - related_name="sub_navigation_links", - to="wagtail_localize_test.navigationlink", - ), - ), - ], - options={ - "abstract": False, - "unique_together": {("translation_key", "locale")}, - }, - ), - ] diff --git a/wagtail_localize/test/migrations/0003_wagtail_3_use_json_field.py b/wagtail_localize/test/migrations/0003_wagtail_3_use_json_field.py deleted file mode 100644 index 45cf9853..00000000 --- a/wagtail_localize/test/migrations/0003_wagtail_3_use_json_field.py +++ /dev/null @@ -1,721 +0,0 @@ -# Generated by Django 4.1.9 on 2023-05-24 15:10 - -import wagtail.blocks -import wagtail.blocks.field_block -import wagtail.documents.blocks -import wagtail.embeds.blocks -import wagtail.fields -import wagtail.images.blocks -import wagtail.snippets.blocks - -from django.db import migrations - -import wagtail_localize.test.models - - -class Migration(migrations.Migration): - dependencies = [ - ("wagtail_localize_test", "0002_header_navigationlink_and_more"), - ] - - operations = [ - migrations.AlterField( - model_name="testgeneratetranslatablefieldspage", - name="test_streamfield", - field=wagtail.fields.StreamField( - [ - ("test_charblock", wagtail.blocks.CharBlock(max_length=255)), - ("test_textblock", wagtail.blocks.TextBlock(label="text block")), - ("test_emailblock", wagtail.blocks.EmailBlock()), - ("test_urlblock", wagtail.blocks.URLBlock()), - ("test_richtextblock", wagtail.blocks.RichTextBlock()), - ("test_rawhtmlblock", wagtail.blocks.RawHTMLBlock()), - ("test_blockquoteblock", wagtail.blocks.BlockQuoteBlock()), - ( - "test_structblock", - wagtail.blocks.StructBlock( - [ - ("field_a", wagtail.blocks.TextBlock()), - ("field_b", wagtail.blocks.TextBlock()), - ] - ), - ), - ( - "test_listblock", - wagtail.blocks.ListBlock(wagtail.blocks.TextBlock()), - ), - ( - "test_listblock_in_structblock", - wagtail.blocks.StructBlock( - [ - ("title", wagtail.blocks.CharBlock(required=False)), - ( - "items", - wagtail.blocks.ListBlock( - wagtail.blocks.field_block.CharBlock - ), - ), - ( - "links_list", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "heading", - wagtail.blocks.CharBlock( - blank=True, - label="List Heading", - required=False, - ), - ), - ( - "pages", - wagtail.blocks.ListBlock( - wagtail.blocks.PageChooserBlock() - ), - ), - ] - ) - ), - ), - ] - ), - ), - ( - "test_nestedstreamblock", - wagtail.blocks.StreamBlock( - [ - ("block_a", wagtail.blocks.TextBlock()), - ("block_b", wagtail.blocks.TextBlock()), - ( - "block_l", - wagtail.blocks.ListBlock( - wagtail.blocks.CharBlock() - ), - ), - ("chooser", wagtail.blocks.PageChooserBlock()), - ( - "chooser_in_struct", - wagtail.blocks.StructBlock( - [("page", wagtail.blocks.PageChooserBlock())] - ), - ), - ( - "chooser_in_list", - wagtail.blocks.ListBlock( - wagtail.blocks.PageChooserBlock() - ), - ), - ] - ), - ), - ( - "test_streamblock_in_structblock", - wagtail.blocks.StructBlock( - [ - ( - "nested_stream", - wagtail.blocks.StreamBlock( - [ - ("page", wagtail.blocks.PageChooserBlock()), - ( - "checklist", - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(), - ) - ] - ), - ), - ] - ), - ) - ] - ), - ), - ( - "test_customstructblock", - wagtail.blocks.StructBlock( - [ - ("field_a", wagtail.blocks.TextBlock()), - ("field_b", wagtail.blocks.TextBlock()), - ] - ), - ), - ( - "test_customblockwithoutextractmethod", - wagtail_localize.test.models.CustomBlockWithoutExtractMethod(), - ), - ("test_pagechooserblock", wagtail.blocks.PageChooserBlock()), - ( - "test_pagechooserblock_with_restricted_types", - wagtail.blocks.PageChooserBlock( - [ - "wagtail_localize_test.TestHomePage", - "wagtail_localize_test.TestPage", - ] - ), - ), - ( - "test_imagechooserblock", - wagtail.images.blocks.ImageChooserBlock(), - ), - ( - "test_documentchooserblock", - wagtail.documents.blocks.DocumentChooserBlock(), - ), - ( - "test_snippetchooserblock", - wagtail.snippets.blocks.SnippetChooserBlock( - wagtail_localize.test.models.TestSnippet - ), - ), - ( - "test_nontranslatablesnippetchooserblock", - wagtail.snippets.blocks.SnippetChooserBlock( - wagtail_localize.test.models.NonTranslatableSnippet - ), - ), - ("test_embedblock", wagtail.embeds.blocks.EmbedBlock()), - ( - "test_chooserstructblock", - wagtail.blocks.StructBlock( - [("page", wagtail.blocks.PageChooserBlock())] - ), - ), - ( - "test_nestedchooserstructblock", - wagtail.blocks.StructBlock( - [ - ( - "nested_page", - wagtail.blocks.StructBlock( - [("page", wagtail.blocks.PageChooserBlock())] - ), - ) - ] - ), - ), - ( - "test_chooser_in_struct_in_listblock", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(required=False), - ) - ] - ) - ), - ), - ( - "test_image_chooser_in_listblock", - wagtail.blocks.ListBlock( - wagtail.images.blocks.ImageChooserBlock() - ), - ), - ( - "test_document_chooser_in_listblock", - wagtail.blocks.ListBlock( - wagtail.documents.blocks.DocumentChooserBlock() - ), - ), - ( - "test_chooser_in_struct_in_list_in_stream_in_listblock", - wagtail.blocks.ListBlock( - wagtail.blocks.StreamBlock( - [ - ( - "list", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock( - required=False - ), - ) - ] - ) - ), - ) - ] - ) - ), - ), - ], - blank=True, - use_json_field=True, - ), - ), - migrations.AlterField( - model_name="testpage", - name="test_streamfield", - field=wagtail.fields.StreamField( - [ - ("test_charblock", wagtail.blocks.CharBlock(max_length=255)), - ("test_textblock", wagtail.blocks.TextBlock(label="text block")), - ("test_emailblock", wagtail.blocks.EmailBlock()), - ("test_urlblock", wagtail.blocks.URLBlock()), - ("test_richtextblock", wagtail.blocks.RichTextBlock()), - ("test_rawhtmlblock", wagtail.blocks.RawHTMLBlock()), - ("test_blockquoteblock", wagtail.blocks.BlockQuoteBlock()), - ( - "test_structblock", - wagtail.blocks.StructBlock( - [ - ("field_a", wagtail.blocks.TextBlock()), - ("field_b", wagtail.blocks.TextBlock()), - ] - ), - ), - ( - "test_listblock", - wagtail.blocks.ListBlock(wagtail.blocks.TextBlock()), - ), - ( - "test_listblock_in_structblock", - wagtail.blocks.StructBlock( - [ - ("title", wagtail.blocks.CharBlock(required=False)), - ( - "items", - wagtail.blocks.ListBlock( - wagtail.blocks.field_block.CharBlock - ), - ), - ( - "links_list", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "heading", - wagtail.blocks.CharBlock( - blank=True, - label="List Heading", - required=False, - ), - ), - ( - "pages", - wagtail.blocks.ListBlock( - wagtail.blocks.PageChooserBlock() - ), - ), - ] - ) - ), - ), - ] - ), - ), - ( - "test_nestedstreamblock", - wagtail.blocks.StreamBlock( - [ - ("block_a", wagtail.blocks.TextBlock()), - ("block_b", wagtail.blocks.TextBlock()), - ( - "block_l", - wagtail.blocks.ListBlock( - wagtail.blocks.CharBlock() - ), - ), - ("chooser", wagtail.blocks.PageChooserBlock()), - ( - "chooser_in_struct", - wagtail.blocks.StructBlock( - [("page", wagtail.blocks.PageChooserBlock())] - ), - ), - ( - "chooser_in_list", - wagtail.blocks.ListBlock( - wagtail.blocks.PageChooserBlock() - ), - ), - ] - ), - ), - ( - "test_streamblock_in_structblock", - wagtail.blocks.StructBlock( - [ - ( - "nested_stream", - wagtail.blocks.StreamBlock( - [ - ("page", wagtail.blocks.PageChooserBlock()), - ( - "checklist", - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(), - ) - ] - ), - ), - ] - ), - ) - ] - ), - ), - ( - "test_customstructblock", - wagtail.blocks.StructBlock( - [ - ("field_a", wagtail.blocks.TextBlock()), - ("field_b", wagtail.blocks.TextBlock()), - ] - ), - ), - ( - "test_customblockwithoutextractmethod", - wagtail_localize.test.models.CustomBlockWithoutExtractMethod(), - ), - ("test_pagechooserblock", wagtail.blocks.PageChooserBlock()), - ( - "test_pagechooserblock_with_restricted_types", - wagtail.blocks.PageChooserBlock( - [ - "wagtail_localize_test.TestHomePage", - "wagtail_localize_test.TestPage", - ] - ), - ), - ( - "test_imagechooserblock", - wagtail.images.blocks.ImageChooserBlock(), - ), - ( - "test_documentchooserblock", - wagtail.documents.blocks.DocumentChooserBlock(), - ), - ( - "test_snippetchooserblock", - wagtail.snippets.blocks.SnippetChooserBlock( - wagtail_localize.test.models.TestSnippet - ), - ), - ( - "test_nontranslatablesnippetchooserblock", - wagtail.snippets.blocks.SnippetChooserBlock( - wagtail_localize.test.models.NonTranslatableSnippet - ), - ), - ("test_embedblock", wagtail.embeds.blocks.EmbedBlock()), - ( - "test_chooserstructblock", - wagtail.blocks.StructBlock( - [("page", wagtail.blocks.PageChooserBlock())] - ), - ), - ( - "test_nestedchooserstructblock", - wagtail.blocks.StructBlock( - [ - ( - "nested_page", - wagtail.blocks.StructBlock( - [("page", wagtail.blocks.PageChooserBlock())] - ), - ) - ] - ), - ), - ( - "test_chooser_in_struct_in_listblock", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(required=False), - ) - ] - ) - ), - ), - ( - "test_image_chooser_in_listblock", - wagtail.blocks.ListBlock( - wagtail.images.blocks.ImageChooserBlock() - ), - ), - ( - "test_document_chooser_in_listblock", - wagtail.blocks.ListBlock( - wagtail.documents.blocks.DocumentChooserBlock() - ), - ), - ( - "test_chooser_in_struct_in_list_in_stream_in_listblock", - wagtail.blocks.ListBlock( - wagtail.blocks.StreamBlock( - [ - ( - "list", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock( - required=False - ), - ) - ] - ) - ), - ) - ] - ) - ), - ), - ], - blank=True, - use_json_field=True, - ), - ), - migrations.AlterField( - model_name="testpage", - name="test_synchronized_streamfield", - field=wagtail.fields.StreamField( - [ - ("test_charblock", wagtail.blocks.CharBlock(max_length=255)), - ("test_textblock", wagtail.blocks.TextBlock(label="text block")), - ("test_emailblock", wagtail.blocks.EmailBlock()), - ("test_urlblock", wagtail.blocks.URLBlock()), - ("test_richtextblock", wagtail.blocks.RichTextBlock()), - ("test_rawhtmlblock", wagtail.blocks.RawHTMLBlock()), - ("test_blockquoteblock", wagtail.blocks.BlockQuoteBlock()), - ( - "test_structblock", - wagtail.blocks.StructBlock( - [ - ("field_a", wagtail.blocks.TextBlock()), - ("field_b", wagtail.blocks.TextBlock()), - ] - ), - ), - ( - "test_listblock", - wagtail.blocks.ListBlock(wagtail.blocks.TextBlock()), - ), - ( - "test_listblock_in_structblock", - wagtail.blocks.StructBlock( - [ - ("title", wagtail.blocks.CharBlock(required=False)), - ( - "items", - wagtail.blocks.ListBlock( - wagtail.blocks.field_block.CharBlock - ), - ), - ( - "links_list", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "heading", - wagtail.blocks.CharBlock( - blank=True, - label="List Heading", - required=False, - ), - ), - ( - "pages", - wagtail.blocks.ListBlock( - wagtail.blocks.PageChooserBlock() - ), - ), - ] - ) - ), - ), - ] - ), - ), - ( - "test_nestedstreamblock", - wagtail.blocks.StreamBlock( - [ - ("block_a", wagtail.blocks.TextBlock()), - ("block_b", wagtail.blocks.TextBlock()), - ( - "block_l", - wagtail.blocks.ListBlock( - wagtail.blocks.CharBlock() - ), - ), - ("chooser", wagtail.blocks.PageChooserBlock()), - ( - "chooser_in_struct", - wagtail.blocks.StructBlock( - [("page", wagtail.blocks.PageChooserBlock())] - ), - ), - ( - "chooser_in_list", - wagtail.blocks.ListBlock( - wagtail.blocks.PageChooserBlock() - ), - ), - ] - ), - ), - ( - "test_streamblock_in_structblock", - wagtail.blocks.StructBlock( - [ - ( - "nested_stream", - wagtail.blocks.StreamBlock( - [ - ("page", wagtail.blocks.PageChooserBlock()), - ( - "checklist", - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(), - ) - ] - ), - ), - ] - ), - ) - ] - ), - ), - ( - "test_customstructblock", - wagtail.blocks.StructBlock( - [ - ("field_a", wagtail.blocks.TextBlock()), - ("field_b", wagtail.blocks.TextBlock()), - ] - ), - ), - ( - "test_customblockwithoutextractmethod", - wagtail_localize.test.models.CustomBlockWithoutExtractMethod(), - ), - ("test_pagechooserblock", wagtail.blocks.PageChooserBlock()), - ( - "test_pagechooserblock_with_restricted_types", - wagtail.blocks.PageChooserBlock( - [ - "wagtail_localize_test.TestHomePage", - "wagtail_localize_test.TestPage", - ] - ), - ), - ( - "test_imagechooserblock", - wagtail.images.blocks.ImageChooserBlock(), - ), - ( - "test_documentchooserblock", - wagtail.documents.blocks.DocumentChooserBlock(), - ), - ( - "test_snippetchooserblock", - wagtail.snippets.blocks.SnippetChooserBlock( - wagtail_localize.test.models.TestSnippet - ), - ), - ( - "test_nontranslatablesnippetchooserblock", - wagtail.snippets.blocks.SnippetChooserBlock( - wagtail_localize.test.models.NonTranslatableSnippet - ), - ), - ("test_embedblock", wagtail.embeds.blocks.EmbedBlock()), - ( - "test_chooserstructblock", - wagtail.blocks.StructBlock( - [("page", wagtail.blocks.PageChooserBlock())] - ), - ), - ( - "test_nestedchooserstructblock", - wagtail.blocks.StructBlock( - [ - ( - "nested_page", - wagtail.blocks.StructBlock( - [("page", wagtail.blocks.PageChooserBlock())] - ), - ) - ] - ), - ), - ( - "test_chooser_in_struct_in_listblock", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock(required=False), - ) - ] - ) - ), - ), - ( - "test_image_chooser_in_listblock", - wagtail.blocks.ListBlock( - wagtail.images.blocks.ImageChooserBlock() - ), - ), - ( - "test_document_chooser_in_listblock", - wagtail.blocks.ListBlock( - wagtail.documents.blocks.DocumentChooserBlock() - ), - ), - ( - "test_chooser_in_struct_in_list_in_stream_in_listblock", - wagtail.blocks.ListBlock( - wagtail.blocks.StreamBlock( - [ - ( - "list", - wagtail.blocks.ListBlock( - wagtail.blocks.StructBlock( - [ - ( - "page", - wagtail.blocks.PageChooserBlock( - required=False - ), - ) - ] - ) - ), - ) - ] - ) - ), - ), - ], - blank=True, - use_json_field=True, - ), - ), - ] diff --git a/wagtail_localize/test/migrations/0004_testparentalsnippet.py b/wagtail_localize/test/migrations/0004_testparentalsnippet.py deleted file mode 100644 index 67a628d4..00000000 --- a/wagtail_localize/test/migrations/0004_testparentalsnippet.py +++ /dev/null @@ -1,54 +0,0 @@ -# Generated by Django 3.2.5 on 2022-05-06 18:53 - -import uuid - -import django.db.models.deletion -import modelcluster.fields - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ("wagtail_localize_test", "0003_wagtail_3_use_json_field"), - ] - - operations = [ - migrations.CreateModel( - name="TestParentalSnippet", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ( - "translation_key", - models.UUIDField(default=uuid.uuid4, editable=False), - ), - ( - "field", - modelcluster.fields.ParentalManyToManyField( - blank=True, to="wagtail_localize_test.TestUUIDModel" - ), - ), - ( - "locale", - models.ForeignKey( - editable=False, - on_delete=django.db.models.deletion.PROTECT, - related_name="+", - to="wagtailcore.locale", - ), - ), - ], - options={ - "abstract": False, - "unique_together": {("translation_key", "locale")}, - }, - ), - ] diff --git a/wagtail_localize/test/migrations/0005_testsnippet_expire_at_testsnippet_expired_and_more.py b/wagtail_localize/test/migrations/0005_testsnippet_expire_at_testsnippet_expired_and_more.py deleted file mode 100644 index 0f6d3705..00000000 --- a/wagtail_localize/test/migrations/0005_testsnippet_expire_at_testsnippet_expired_and_more.py +++ /dev/null @@ -1,124 +0,0 @@ -# Generated by Django 4.2.9 on 2024-01-06 13:20 - -import uuid - -import django.db.models.deletion - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ("wagtailcore", "0077_alter_revision_user"), - ("wagtail_localize_test", "0004_testparentalsnippet"), - ] - - operations = [ - migrations.AddField( - model_name="testsnippet", - name="expire_at", - field=models.DateTimeField( - blank=True, null=True, verbose_name="expiry date/time" - ), - ), - migrations.AddField( - model_name="testsnippet", - name="expired", - field=models.BooleanField( - default=False, editable=False, verbose_name="expired" - ), - ), - migrations.AddField( - model_name="testsnippet", - name="first_published_at", - field=models.DateTimeField( - blank=True, db_index=True, null=True, verbose_name="first published at" - ), - ), - migrations.AddField( - model_name="testsnippet", - name="go_live_at", - field=models.DateTimeField( - blank=True, null=True, verbose_name="go live date/time" - ), - ), - migrations.AddField( - model_name="testsnippet", - name="has_unpublished_changes", - field=models.BooleanField( - default=False, editable=False, verbose_name="has unpublished changes" - ), - ), - migrations.AddField( - model_name="testsnippet", - name="last_published_at", - field=models.DateTimeField( - editable=False, null=True, verbose_name="last published at" - ), - ), - migrations.AddField( - model_name="testsnippet", - name="latest_revision", - field=models.ForeignKey( - blank=True, - editable=False, - null=True, - on_delete=django.db.models.deletion.SET_NULL, - related_name="+", - to="wagtailcore.revision", - verbose_name="latest revision", - ), - ), - migrations.AddField( - model_name="testsnippet", - name="live", - field=models.BooleanField( - default=True, editable=False, verbose_name="live" - ), - ), - migrations.AddField( - model_name="testsnippet", - name="live_revision", - field=models.ForeignKey( - blank=True, - editable=False, - null=True, - on_delete=django.db.models.deletion.SET_NULL, - related_name="+", - to="wagtailcore.revision", - verbose_name="live revision", - ), - ), - migrations.CreateModel( - name="TestNoDraftModel", - fields=[ - ( - "id", - models.AutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ( - "translation_key", - models.UUIDField(default=uuid.uuid4, editable=False), - ), - ("field", models.CharField(blank=True, max_length=10)), - ( - "locale", - models.ForeignKey( - editable=False, - on_delete=django.db.models.deletion.PROTECT, - related_name="+", - to="wagtailcore.locale", - ), - ), - ], - options={ - "abstract": False, - "unique_together": {("translation_key", "locale")}, - }, - ), - ] diff --git a/wagtail_localize/test/models.py b/wagtail_localize/test/models.py index 8340d2b7..bd84561c 100644 --- a/wagtail_localize/test/models.py +++ b/wagtail_localize/test/models.py @@ -52,7 +52,7 @@ class TestSnippet(TranslatableMixin, DraftStateMixin, RevisionMixin, Clusterable class TestNoDraftModel(TranslatableMixin): - field = models.CharField(max_length=10, blank=True) + field = models.CharField(max_length=20, blank=True) translatable_fields = [ TranslatableField("field"), diff --git a/wagtail_localize/tests/test_translationsource_model.py b/wagtail_localize/tests/test_translationsource_model.py index e9ba1475..1baee3a9 100644 --- a/wagtail_localize/tests/test_translationsource_model.py +++ b/wagtail_localize/tests/test_translationsource_model.py @@ -745,9 +745,7 @@ def setUp(self): locale=self.dest_locale, context=TranslationContext.objects.get( object_id=self.page.translation_key, - path="test_childobjects.{}.field".format( - self.page.test_childobjects.get().translation_key - ), + path=f"test_childobjects.{self.page.test_childobjects.get().translation_key}.field", ), data="Ceci est un objet enfant de test", ) diff --git a/wagtail_localize/tests/test_update_translations.py b/wagtail_localize/tests/test_update_translations.py index c676956c..c828aae0 100644 --- a/wagtail_localize/tests/test_update_translations.py +++ b/wagtail_localize/tests/test_update_translations.py @@ -542,7 +542,8 @@ def test_post_update_page_translation_after_source_privacy_changed(self): # change the restriction for the source self.en_blog_post.view_restrictions.all().update( - restriction_type="password", password="test" # noqa: S106 + restriction_type="password", + password="test", # noqa: S106 ) self.client.post( reverse( diff --git a/wagtail_localize/views/edit_translation.py b/wagtail_localize/views/edit_translation.py index d7af70c9..4f2ff023 100644 --- a/wagtail_localize/views/edit_translation.py +++ b/wagtail_localize/views/edit_translation.py @@ -1,3 +1,4 @@ +import contextlib import json import os import tempfile @@ -325,10 +326,7 @@ def widget_from_field(field): elif issubclass(field.related_model, tuple(get_snippet_models())): chooser_url = reverse( - "wagtailsnippetchoosers_{}_{}:choose".format( - field.related_model._meta.app_label, - field.related_model._meta.model_name, - ) + f"wagtailsnippetchoosers_{field.related_model._meta.app_label}_{field.related_model._meta.model_name}:choose" ) return { "type": "snippet_chooser", @@ -370,10 +368,7 @@ def widget_from_block(block, content_components=None): elif isinstance(block, SnippetChooserBlock): chooser_url = reverse( - "wagtailsnippetchoosers_{}_{}:choose".format( - block.target_model._meta.app_label, - block.target_model._meta.model_name, - ) + f"wagtailsnippetchoosers_{block.target_model._meta.app_label}_{block.target_model._meta.model_name}:choose" ) return { "type": "snippet_chooser", @@ -499,10 +494,7 @@ def edit_translation(request, translation: Translation, instance): last_published_at = instance.last_published_at last_published_by = None - if instance.live: - live_url = instance.full_url - else: - live_url = None + live_url = instance.full_url if instance.live else None can_publish = page_perms.can_publish() can_unpublish = page_perms.can_unpublish() @@ -660,10 +652,8 @@ def edit_translation(request, translation: Translation, instance): # Set to the ID of a string segment that represents the title. # If this segment has a translation, the title will be replaced with that translation. - try: + with contextlib.suppress(StringSegment.DoesNotExist): title_segment_id = string_segments.get(context__path="title").id - except StringSegment.DoesNotExist: - pass machine_translator = None translator = get_machine_translator() @@ -748,10 +738,7 @@ def get_edit_url(instance): elif "wagtail_localize.modeladmin" in settings.INSTALLED_APPS: return reverse( - "{app_label}_{model_name}_modeladmin_edit".format( - app_label=instance._meta.app_label, - model_name=instance._meta.model_name, - ), + f"{instance._meta.app_label}_{instance._meta.model_name}_modeladmin_edit", args=[quote(instance.pk)], ) @@ -766,10 +753,7 @@ def get_delete_url(instance): elif "wagtail_localize.modeladmin" in settings.INSTALLED_APPS: return reverse( - "{app_label}_{model_name}_modeladmin_delete".format( - app_label=instance._meta.app_label, - model_name=instance._meta.model_name, - ), + f"{instance._meta.app_label}_{instance._meta.model_name}_modeladmin_delete", args=[quote(instance.pk)], ) @@ -1322,9 +1306,8 @@ def download_pofile(request, translation_id): response = HttpResponse( str(translation.export_po()), content_type="text/x-gettext-translation" ) - response["Content-Disposition"] = "attachment; filename={}-{}.po".format( - slugify(translation.source.object_repr), - translation.target_locale.language_code, + response["Content-Disposition"] = ( + f"attachment; filename={slugify(translation.source.object_repr)}-{translation.target_locale.language_code}.po" ) return response @@ -1375,10 +1358,8 @@ def upload_pofile(request, translation_id): messages.success(request, _("Successfully imported translations from PO File.")) # Delete the created tempfile - try: + with contextlib.suppress(OSError): os.unlink(f.name) - except OSError: - pass # Work out where to redirect to next_url = get_valid_next_url_from_request(request) diff --git a/wagtail_localize/views/update_translations.py b/wagtail_localize/views/update_translations.py index 9d19eb95..09093da6 100644 --- a/wagtail_localize/views/update_translations.py +++ b/wagtail_localize/views/update_translations.py @@ -1,3 +1,5 @@ +import contextlib + from django import forms from django.conf import settings from django.contrib import messages @@ -72,10 +74,7 @@ def get_default_success_url(self): elif "wagtail_localize.modeladmin" in settings.INSTALLED_APPS: return reverse( - "{app_label}_{model_name}_modeladmin_index".format( - app_label=instance._meta.app_label, - model_name=instance._meta.model_name, - ) + f"{instance._meta.app_label}_{instance._meta.model_name}_modeladmin_index" ) def get_edit_url(self, instance): @@ -90,10 +89,7 @@ def get_edit_url(self, instance): elif "wagtail_localize.modeladmin" in settings.INSTALLED_APPS: return reverse( - "{app_label}_{model_name}_modeladmin_edit".format( - app_label=instance._meta.app_label, - model_name=instance._meta.model_name, - ), + f"{instance._meta.app_label}_{instance._meta.model_name}_modeladmin_edit", args=[quote(instance.pk)], ) @@ -140,20 +136,16 @@ def form_valid(self, form): if form.cleaned_data["publish_translations"]: for translation in enabled_translations.select_related("target_locale"): - try: + with contextlib.suppress(ValidationError): translation.save_target(user=self.request.user, publish=True) - except ValidationError: - pass else: for translation in enabled_translations.select_related( "source", "target_locale" ): - try: + with contextlib.suppress(ValidationError): translation.source.update_target_view_restrictions( translation.target_locale ) - except ValidationError: - pass self.components.save( self.object,