From de0380ab8c6f61b1cacd1d12256bbf36bc75dee6 Mon Sep 17 00:00:00 2001 From: Nikos Vasileiou Date: Thu, 16 Feb 2023 12:36:21 +0200 Subject: [PATCH 1/2] Add support for Django 4.x --- .github/workflows/ci.yml | 15 +++++ Makefile | 56 ++++++++++++++++++- .../native/django/management/utils/push.py | 7 ++- .../django/tools/migrations/templatetags.py | 10 +++- transifex/native/django/utils/templates.py | 7 ++- 5 files changed, 89 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d8fd51..84c9c28 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,6 +27,7 @@ jobs: docker run -e CODECOV_TOKEN=$CODECOV_TOKEN --rm native sh -c 'pytest --cov --cov-report=term-missing && codecov' env: CODECOV_TOKEN: ${{secrets.codecov_token}} + python3_6-django2_0-tests: runs-on: ubuntu-latest steps: @@ -37,6 +38,7 @@ jobs: docker run -e CODECOV_TOKEN=$CODECOV_TOKEN --rm native sh -c 'pytest --cov --cov-report=term-missing && codecov' env: CODECOV_TOKEN: ${{secrets.codecov_token}} + python3_7-django2_2-tests: runs-on: ubuntu-latest steps: @@ -47,6 +49,7 @@ jobs: docker run -e CODECOV_TOKEN=$CODECOV_TOKEN --rm native sh -c 'pytest --cov --cov-report=term-missing && codecov' env: CODECOV_TOKEN: ${{secrets.codecov_token}} + python3_8-django2_2-tests: runs-on: ubuntu-latest steps: @@ -57,6 +60,7 @@ jobs: docker run -e CODECOV_TOKEN=$CODECOV_TOKEN --rm native sh -c 'pytest --cov --cov-report=term-missing && codecov' env: CODECOV_TOKEN: ${{secrets.codecov_token}} + python3_9-django3_2-tests: runs-on: ubuntu-latest steps: @@ -68,6 +72,17 @@ jobs: env: CODECOV_TOKEN: ${{secrets.codecov_token}} + python3_11-django4_1-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Test py3.11-dj4.1 + run: | + docker build --build-arg PYTHON_VERSION=3.11 --build-arg DJANGO_VERSION=4.1 -t native -f Dockerfile-tmpl . + docker run -e CODECOV_TOKEN=$CODECOV_TOKEN --rm native sh -c 'pytest --cov --cov-report=term-missing && codecov' + env: + CODECOV_TOKEN: ${{secrets.codecov_token}} + publish-pypi: needs: [ quality-checks, python3_6-django1_11-tests, diff --git a/Makefile b/Makefile index b6fc3ba..88d04aa 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,16 @@ CUR_PATH=$(shell pwd) FILES=$(shell git ls-files transifex* tests*) -build: +# --- Build --- + +build: \ + build_dj1.11_py3.6 \ + build_dj2.0_py3.6 \ + build_dj2.2_py3.8 \ + build_dj3.2_py3.9 \ + build_dj4.1_py3.11 + +build_dj1.11_py3.6: DOCKER_BUILDKIT=1 docker build \ --no-cache \ --progress=plain \ @@ -9,6 +18,8 @@ build: --build-arg DJANGO_VERSION=1.11 \ -t native:3.6-1.11-latest \ -f Dockerfile-tmpl . + +build_dj2.0_py3.6: DOCKER_BUILDKIT=1 docker build \ --no-cache \ --progress=plain \ @@ -16,6 +27,8 @@ build: --build-arg DJANGO_VERSION=2.0 \ -t native:3.6-2.0-latest \ -f Dockerfile-tmpl . + +build_dj2.2_py3.8: DOCKER_BUILDKIT=1 docker build \ --no-cache \ --progress=plain \ @@ -23,6 +36,8 @@ build: --build-arg DJANGO_VERSION=2.2 \ -t native:3.8-2.2-latest \ -f Dockerfile-tmpl . + +build_dj3.2_py3.9: DOCKER_BUILDKIT=1 docker build \ --no-cache \ --progress=plain \ @@ -31,6 +46,17 @@ build: -t native:3.9-3.2-latest \ -f Dockerfile-tmpl . +build_dj4.1_py3.11: + DOCKER_BUILDKIT=1 docker build \ + --no-cache \ + --progress=plain \ + --build-arg PYTHON_VERSION=3.11 \ + --build-arg DJANGO_VERSION=4.1 \ + -t native:3.11-4.1-latest \ + -f Dockerfile-tmpl . + +# --- Code quality --- + code_quality: git diff origin/devel..$(git rev-parse HEAD) --name-only | \ xargs docker run --rm \ @@ -38,6 +64,8 @@ code_quality: --mount src="$$(pwd)",target=/src,type=bind \ transifex/txlint --files +# --- Shell --- + shell_dj1.11_py3.6: # Django 1.11 (3.6) docker run --rm -it --entrypoint bash native:3.6-1.11-latest @@ -54,27 +82,51 @@ shell_dj3.2_py3.9: # Django 3.2 (Python 3.9) docker run --rm -it --entrypoint bash native:3.9-3.2-latest -localtests: +shell_dj4.1_py3.11: + # Django 4.1 (Python 3.11) + docker run --rm -it --entrypoint bash native:3.11-4.1-latest + +# --- Tests --- + +localtests: \ + tests_dj1.11_py3.6 \ + tests_dj2.0_py3.6 \ + tests_dj2.2_py3.8 \ + tests_dj3.2_py3.9 \ + tests_dj4.1_py3.11 \ + tests_coverage + +tests_dj1.11_py3.6: # Django 1.11 (3.6) docker run -v $(CUR_PATH):/usr/app \ --rm native:3.6-1.11-latest\ pytest --cov --cov-append --cov-report=term-missing +tests_dj2.0_py3.6: # Django 2.0 (Python 3.6) docker run -v $(CUR_PATH):/usr/app \ --rm native:3.6-2.0-latest\ pytest --cov --cov-append --cov-report=term-missing +tests_dj2.2_py3.8: # Django 2.2 (Python 3.8) docker run -v $(CUR_PATH):/usr/app \ --rm native:3.8-2.2-latest\ pytest --cov --cov-append --cov-report=term-missing +tests_dj3.2_py3.9: # Django 3.2 (Python 3.9) docker run -v $(CUR_PATH):/usr/app \ --rm native:3.9-3.2-latest\ pytest --cov --cov-append --cov-report=term-missing +tests_dj4.1_py3.11: + # Django 4.1 (Python 3.11) + docker run -v $(CUR_PATH):/usr/app \ + --rm native:3.11-4.1-latest\ + pytest --cov --cov-append --cov-report=term-missing + +tests_coverage: # Coverage report docker run -v $(CUR_PATH):/usr/app \ --rm native:3.6-1.11-latest \ diff --git a/transifex/native/django/management/utils/push.py b/transifex/native/django/management/utils/push.py index d33fdc3..2e0cb11 100644 --- a/transifex/native/django/management/utils/push.py +++ b/transifex/native/django/management/utils/push.py @@ -4,9 +4,9 @@ import sys import time +from django import VERSION as DJANGO_VERSION from django.conf import settings from django.core.management.utils import handle_extensions -from django.utils.encoding import force_text from transifex.common.console import Color from transifex.common.utils import generate_hashed_key, generate_key from transifex.native import tx @@ -16,6 +16,11 @@ extract_transifex_template_strings from transifex.native.parsing import Extractor +if DJANGO_VERSION[0] >= 4: + from django.utils.encoding import force_str as force_text +else: + from django.utils.encoding import force_text + class Push(CommandMixin): def add_arguments(self, subparsers): diff --git a/transifex/native/django/tools/migrations/templatetags.py b/transifex/native/django/tools/migrations/templatetags.py index 4c51fdd..de06499 100644 --- a/transifex/native/django/tools/migrations/templatetags.py +++ b/transifex/native/django/tools/migrations/templatetags.py @@ -7,10 +7,9 @@ from __future__ import unicode_literals from django import VERSION as DJANGO_VERSION -from django.template.base import TRANSLATOR_COMMENT_MARK, DebugLexer, Parser +from django.template.base import DebugLexer, Parser from django.template.defaulttags import token_kwargs from django.templatetags.i18n import do_block_translate, do_translate -from django.utils.encoding import force_text from django.utils.html import escape as escape_html from transifex.common._compat import string_types, text_type from transifex.native.django.compat import (TOKEN_BLOCK, TOKEN_COMMENT, @@ -21,6 +20,13 @@ FileMigration, StringMigration) +if DJANGO_VERSION[0] >= 4: + from django.utils.translation.template import TRANSLATOR_COMMENT_MARK + from django.utils.encoding import force_str as force_text +else: + from django.template.base import TRANSLATOR_COMMENT_MARK + from django.utils.encoding import force_text + COMMENT_FOUND = object() diff --git a/transifex/native/django/utils/templates.py b/transifex/native/django/utils/templates.py index b14d051..75d24a8 100644 --- a/transifex/native/django/utils/templates.py +++ b/transifex/native/django/utils/templates.py @@ -1,7 +1,7 @@ from __future__ import unicode_literals +from django import VERSION as DJANGO_VERSION from django.template.base import Lexer, Parser -from django.utils.encoding import force_text from transifex.common._compat import string_types from transifex.common.utils import generate_key from transifex.native.consts import KEY_CONTEXT @@ -9,6 +9,11 @@ from transifex.native.django.templatetags.transifex import do_t from transifex.native.parsing import SourceString +if DJANGO_VERSION[0] >= 4: + from django.utils.encoding import force_str as force_text +else: + from django.utils.encoding import force_text + # Django template consts LOAD_TAG = 'load' WITH_TAG = 'with' From e0658740d571692d12aa7a74b6f40d67273a1687 Mon Sep 17 00:00:00 2001 From: Konstantinos Bairaktaris Date: Tue, 28 Feb 2023 14:39:30 +0200 Subject: [PATCH 2/2] Fix outstanding issues with Django-4 - Version comparison - Issue with FilterExpressions --- transifex/native/django/templatetags/transifex.py | 9 +++++++++ transifex/native/django/tools/migrations/templatetags.py | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/transifex/native/django/templatetags/transifex.py b/transifex/native/django/templatetags/transifex.py index fdd5340..67f2030 100644 --- a/transifex/native/django/templatetags/transifex.py +++ b/transifex/native/django/templatetags/transifex.py @@ -259,6 +259,10 @@ def render(self, context): # it back in place before returning from render. # https://docs.djangoproject.com/en/1.11/howto/custom-template-tags/#thread-safety-considerations # noqa old_source_string_var = self.source_string.var + try: + old_is_var = self.source_string.is_var + except AttributeError: + old_is_var = None # Now we resolve the full source filter expression, after having # replaced its text with the outcome of the translation, in order to @@ -266,8 +270,13 @@ def render(self, context): # marked as safe in order to prevent further escaping attempts that # would introduce the danger of double escaping (eg `<` => `&lt;`) self.source_string.var = mark_safe(result) + self.source_string.is_var = False + result = self.source_string.resolve(context) + self.source_string.var = old_source_string_var + if old_is_var is not None: + self.source_string.is_var = old_is_var if self.asvar is not None: # Save the translation outcome to a context variable diff --git a/transifex/native/django/tools/migrations/templatetags.py b/transifex/native/django/tools/migrations/templatetags.py index de06499..658d178 100644 --- a/transifex/native/django/tools/migrations/templatetags.py +++ b/transifex/native/django/tools/migrations/templatetags.py @@ -58,7 +58,8 @@ def _get_ordered_tokens(parser): This method is useful when we want to iterate all the remaining tokens of the parser in the correct order. """ - if DJANGO_VERSION[0] >= 3 and DJANGO_VERSION[1] > 1: + major, minor = DJANGO_VERSION[:2] + if major == 3 and minor > 1 or major > 3: return reversed(parser.tokens) return parser.tokens