From 459f88fe887c273a502ef0e32b942fc401e1520b Mon Sep 17 00:00:00 2001 From: zerolab Date: Sun, 1 Oct 2023 19:37:44 +0100 Subject: [PATCH] Lint --- .circleci/report_nightly_build_failure.py | 1 + wagtail_localize/components.py | 2 +- wagtail_localize/locales/views.py | 2 +- wagtail_localize/machine_translators/deepl.py | 2 +- .../tests/test_google_translator.py | 6 +- .../migrations/0002_translation.py | 7 +- .../0003_delete_translation_sources.py | 1 - .../0004_one_source_per_objectlocale.py | 4 +- .../0005_remove_translationsource_object.py | 1 - ...06_create_submit_translation_permission.py | 1 - ...07_stringtranslation_type_and_tool_name.py | 1 - ...08_stringtranslation_last_translated_by.py | 4 +- .../0009_stringtranslation_errors.py | 1 - .../migrations/0010_overridablesegment.py | 4 +- .../migrations/0011_segmentoverride.py | 4 +- .../migrations/0012_localesynchronization.py | 4 +- .../0013_translationsource_schema_version.py | 1 - ...move_translation_source_last_updated_at.py | 1 - .../0015_translationcontext_field_path.py | 1 - wagtail_localize/modeladmin/helpers.py | 1 - wagtail_localize/modeladmin/options.py | 9 +- wagtail_localize/modeladmin/tests.py | 4 +- wagtail_localize/modeladmin/views.py | 8 +- wagtail_localize/models.py | 110 +++++++++++------- wagtail_localize/segments/__init__.py | 2 +- wagtail_localize/segments/ingest.py | 16 ++- wagtail_localize/synctree.py | 7 +- .../test/migrations/0001_initial.py | 10 +- .../0002_header_navigationlink_and_more.py | 12 +- .../0003_wagtail_3_use_json_field.py | 5 +- .../migrations/0004_testparentalsnippet.py | 7 +- wagtail_localize/test/models.py | 33 +++++- wagtail_localize/test/settings.py | 2 +- .../tests/test_translationsource_model.py | 5 +- .../tests/test_update_translations.py | 2 +- wagtail_localize/version.py | 8 +- wagtail_localize/views/convert.py | 4 +- wagtail_localize/views/edit_translation.py | 32 ++--- wagtail_localize/wagtail_hooks.py | 2 +- 39 files changed, 192 insertions(+), 135 deletions(-) diff --git a/.circleci/report_nightly_build_failure.py b/.circleci/report_nightly_build_failure.py index 77a9fbce..bdc33859 100644 --- a/.circleci/report_nightly_build_failure.py +++ b/.circleci/report_nightly_build_failure.py @@ -15,6 +15,7 @@ json={ "text": "A Nightly build failed. See " + os.environ["CIRCLE_BUILD_URL"], }, + timeout=30, ) print("Slack responded with:", response) diff --git a/wagtail_localize/components.py b/wagtail_localize/components.py index b695a7c4..85f0dbc6 100644 --- a/wagtail_localize/components.py +++ b/wagtail_localize/components.py @@ -133,7 +133,7 @@ def __iter__(self): return iter(self.components) -@functools.lru_cache() +@functools.lru_cache def get_translation_component_edit_handler(model): if hasattr(model, "edit_handler"): # use the edit handler specified on the class diff --git a/wagtail_localize/locales/views.py b/wagtail_localize/locales/views.py index cff154e6..ab37c899 100644 --- a/wagtail_localize/locales/views.py +++ b/wagtail_localize/locales/views.py @@ -17,7 +17,7 @@ from .utils import get_locale_usage -@functools.lru_cache() +@functools.lru_cache def get_locale_component_edit_handler(model): if hasattr(model, "edit_handler"): # use the edit handler specified on the class diff --git a/wagtail_localize/machine_translators/deepl.py b/wagtail_localize/machine_translators/deepl.py index 8527dd37..3de38fad 100644 --- a/wagtail_localize/machine_translators/deepl.py +++ b/wagtail_localize/machine_translators/deepl.py @@ -22,7 +22,6 @@ def get_api_endpoint(self): return "https://api.deepl.com/v2/translate" def translate(self, source_locale, target_locale, strings): - response = requests.post( self.get_api_endpoint(), { @@ -34,6 +33,7 @@ def translate(self, source_locale, target_locale, strings): target_locale.language_code, is_target=True ), }, + timeout=30, ) return { diff --git a/wagtail_localize/machine_translators/tests/test_google_translator.py b/wagtail_localize/machine_translators/tests/test_google_translator.py index 6dbbc3bc..67b3ba80 100644 --- a/wagtail_localize/machine_translators/tests/test_google_translator.py +++ b/wagtail_localize/machine_translators/tests/test_google_translator.py @@ -44,7 +44,7 @@ class TestCloudTranslateTranslator(TestCase): def test_no_credentials_option_initialisation(self, translationsserviceclient_init): translator = get_machine_translator() self.assertIsInstance(translator, GoogleCloudTranslator) - translator.client + translator.client # noqa: B018 translationsserviceclient_init.assert_called_once_with() @mock.patch( @@ -61,7 +61,7 @@ def test_credentials_option_initialisation( ): translator = get_machine_translator() self.assertIsInstance(translator, GoogleCloudTranslator) - translator.client + translator.client # noqa: B018 from_service_account_info.assert_called_once_with( SETTINGS_WITH_CREDENTIALS["OPTIONS"]["CREDENTIALS"] ) @@ -83,7 +83,7 @@ def test_credentials_path_option_initialisation( ): translator = get_machine_translator() self.assertIsInstance(translator, GoogleCloudTranslator) - translator.client + translator.client # noqa: B018 from_service_account_file.assert_called_once_with( SETTINGS_WITH_CREDENTIALS_PATH["OPTIONS"]["CREDENTIALS_PATH"] ) diff --git a/wagtail_localize/migrations/0002_translation.py b/wagtail_localize/migrations/0002_translation.py index 28a6af7e..d0948eec 100644 --- a/wagtail_localize/migrations/0002_translation.py +++ b/wagtail_localize/migrations/0002_translation.py @@ -1,12 +1,13 @@ # Generated by Django 3.0.6 on 2020-07-20 17:27 -from django.db import migrations, models -import django.db.models.deletion import uuid +import django.db.models.deletion + +from django.db import migrations, models -class Migration(migrations.Migration): +class Migration(migrations.Migration): dependencies = [ ("wagtailcore", "0057_page_locale_fields_notnull"), ("wagtail_localize", "0001_initial"), diff --git a/wagtail_localize/migrations/0003_delete_translation_sources.py b/wagtail_localize/migrations/0003_delete_translation_sources.py index bc4009a7..04b48b3f 100644 --- a/wagtail_localize/migrations/0003_delete_translation_sources.py +++ b/wagtail_localize/migrations/0003_delete_translation_sources.py @@ -23,7 +23,6 @@ def delete_translation_sources(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ("wagtail_localize", "0002_translation"), ] diff --git a/wagtail_localize/migrations/0004_one_source_per_objectlocale.py b/wagtail_localize/migrations/0004_one_source_per_objectlocale.py index 1daba5af..f48f32e1 100644 --- a/wagtail_localize/migrations/0004_one_source_per_objectlocale.py +++ b/wagtail_localize/migrations/0004_one_source_per_objectlocale.py @@ -1,12 +1,12 @@ # Generated by Django 3.0.8 on 2020-08-05 09:33 -from django.db import migrations, models import django.db.models.deletion import django.utils.timezone +from django.db import migrations, models + class Migration(migrations.Migration): - dependencies = [ ("wagtail_localize", "0003_delete_translation_sources"), ] diff --git a/wagtail_localize/migrations/0005_remove_translationsource_object.py b/wagtail_localize/migrations/0005_remove_translationsource_object.py index 4a2e7aa7..3c0464b4 100644 --- a/wagtail_localize/migrations/0005_remove_translationsource_object.py +++ b/wagtail_localize/migrations/0005_remove_translationsource_object.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("wagtailcore", "0057_page_locale_fields_notnull"), ("wagtail_localize", "0004_one_source_per_objectlocale"), diff --git a/wagtail_localize/migrations/0006_create_submit_translation_permission.py b/wagtail_localize/migrations/0006_create_submit_translation_permission.py index 72b3e7ed..00032098 100644 --- a/wagtail_localize/migrations/0006_create_submit_translation_permission.py +++ b/wagtail_localize/migrations/0006_create_submit_translation_permission.py @@ -41,7 +41,6 @@ def remove_submit_translation_permission(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ("wagtail_localize", "0005_remove_translationsource_object"), ] diff --git a/wagtail_localize/migrations/0007_stringtranslation_type_and_tool_name.py b/wagtail_localize/migrations/0007_stringtranslation_type_and_tool_name.py index a5195663..1377ff85 100644 --- a/wagtail_localize/migrations/0007_stringtranslation_type_and_tool_name.py +++ b/wagtail_localize/migrations/0007_stringtranslation_type_and_tool_name.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("wagtail_localize", "0006_create_submit_translation_permission"), ] diff --git a/wagtail_localize/migrations/0008_stringtranslation_last_translated_by.py b/wagtail_localize/migrations/0008_stringtranslation_last_translated_by.py index 1299910b..f72b2f45 100644 --- a/wagtail_localize/migrations/0008_stringtranslation_last_translated_by.py +++ b/wagtail_localize/migrations/0008_stringtranslation_last_translated_by.py @@ -1,12 +1,12 @@ # Generated by Django 3.0.8 on 2020-08-12 18:34 +import django.db.models.deletion + from django.conf import settings from django.db import migrations, models -import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ("wagtail_localize", "0007_stringtranslation_type_and_tool_name"), diff --git a/wagtail_localize/migrations/0009_stringtranslation_errors.py b/wagtail_localize/migrations/0009_stringtranslation_errors.py index 93b70cf6..5a83f75c 100644 --- a/wagtail_localize/migrations/0009_stringtranslation_errors.py +++ b/wagtail_localize/migrations/0009_stringtranslation_errors.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("wagtail_localize", "0008_stringtranslation_last_translated_by"), ] diff --git a/wagtail_localize/migrations/0010_overridablesegment.py b/wagtail_localize/migrations/0010_overridablesegment.py index ba663b96..a22db15d 100644 --- a/wagtail_localize/migrations/0010_overridablesegment.py +++ b/wagtail_localize/migrations/0010_overridablesegment.py @@ -1,11 +1,11 @@ # Generated by Django 3.1 on 2020-08-28 10:00 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models + class Migration(migrations.Migration): - dependencies = [ ("wagtail_localize", "0009_stringtranslation_errors"), ] diff --git a/wagtail_localize/migrations/0011_segmentoverride.py b/wagtail_localize/migrations/0011_segmentoverride.py index 9aa47b06..69558ff4 100644 --- a/wagtail_localize/migrations/0011_segmentoverride.py +++ b/wagtail_localize/migrations/0011_segmentoverride.py @@ -1,12 +1,12 @@ # Generated by Django 3.1.2 on 2020-10-23 10:24 +import django.db.models.deletion + from django.conf import settings from django.db import migrations, models -import django.db.models.deletion class Migration(migrations.Migration): - dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ("wagtailcore", "0059_apply_collection_ordering"), diff --git a/wagtail_localize/migrations/0012_localesynchronization.py b/wagtail_localize/migrations/0012_localesynchronization.py index 499bc48b..c220905a 100644 --- a/wagtail_localize/migrations/0012_localesynchronization.py +++ b/wagtail_localize/migrations/0012_localesynchronization.py @@ -1,11 +1,11 @@ # Generated by Django 3.1.3 on 2020-11-04 20:25 -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models + class Migration(migrations.Migration): - dependencies = [ ("wagtailcore", "0059_apply_collection_ordering"), ("wagtail_localize", "0011_segmentoverride"), diff --git a/wagtail_localize/migrations/0013_translationsource_schema_version.py b/wagtail_localize/migrations/0013_translationsource_schema_version.py index e3b562e8..f9a57e9a 100644 --- a/wagtail_localize/migrations/0013_translationsource_schema_version.py +++ b/wagtail_localize/migrations/0013_translationsource_schema_version.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("wagtail_localize", "0012_localesynchronization"), ] diff --git a/wagtail_localize/migrations/0014_remove_translation_source_last_updated_at.py b/wagtail_localize/migrations/0014_remove_translation_source_last_updated_at.py index 87f5291e..880f4742 100644 --- a/wagtail_localize/migrations/0014_remove_translation_source_last_updated_at.py +++ b/wagtail_localize/migrations/0014_remove_translation_source_last_updated_at.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("wagtail_localize", "0013_translationsource_schema_version"), ] diff --git a/wagtail_localize/migrations/0015_translationcontext_field_path.py b/wagtail_localize/migrations/0015_translationcontext_field_path.py index 5009e0d0..de850c82 100644 --- a/wagtail_localize/migrations/0015_translationcontext_field_path.py +++ b/wagtail_localize/migrations/0015_translationcontext_field_path.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("wagtail_localize", "0014_remove_translation_source_last_updated_at"), ] diff --git a/wagtail_localize/modeladmin/helpers.py b/wagtail_localize/modeladmin/helpers.py index da23f81c..c730b749 100644 --- a/wagtail_localize/modeladmin/helpers.py +++ b/wagtail_localize/modeladmin/helpers.py @@ -36,7 +36,6 @@ def get_translation_buttons(obj, user, next_url=None, classname=""): if issubclass(model, TranslatableMixin) and user.has_perm( "wagtail_localize.submit_translation" ): - # If there's at least one locale that we haven't translated into yet, show "Translate" button if isinstance(obj, Page): has_locale_to_translate_to = Locale.objects.exclude( diff --git a/wagtail_localize/modeladmin/options.py b/wagtail_localize/modeladmin/options.py index df5e346f..c43770bc 100644 --- a/wagtail_localize/modeladmin/options.py +++ b/wagtail_localize/modeladmin/options.py @@ -50,10 +50,9 @@ def get_templates(self, action="index"): app_label = self.opts.app_label.lower() model_name = self.opts.model_name.lower() return [ - "wagtail_localize/modeladmin/%s/%s/translatable_%s.html" - % (app_label, model_name, action), - "wagtail_localize/modeladmin/{}/translatable_{}.html".format( - app_label, action + "wagtail_localize/modeladmin/{}/{}/translatable_{}.html".format( + app_label, model_name, action ), - "wagtail_localize/modeladmin/translatable_{}.html".format(action), + 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 9f7db9dc..88789319 100644 --- a/wagtail_localize/modeladmin/tests.py +++ b/wagtail_localize/modeladmin/tests.py @@ -152,9 +152,7 @@ def test_edit_view(self): ) self.assertContains( response, - "Translation of TestModel object ({}) into French".format( - self.en_modeladmin.pk - ), + f"Translation of TestModel object ({self.en_modeladmin.pk}) into French", ) def test_inspect_view(self): diff --git a/wagtail_localize/modeladmin/views.py b/wagtail_localize/modeladmin/views.py index 2965bd91..d1718931 100644 --- a/wagtail_localize/modeladmin/views.py +++ b/wagtail_localize/modeladmin/views.py @@ -183,8 +183,8 @@ def get_title(self): def get_object(self): try: model = apps.get_model(self.kwargs["app_label"], self.kwargs["model_name"]) - except LookupError: - raise Http404 + except LookupError as err: + raise Http404 from err if not issubclass(model, TranslatableMixin): raise Http404 return get_object_or_404(model, pk=unquote(self.kwargs["pk"])) @@ -196,8 +196,8 @@ def get_default_success_url(self, translated_object=None): "{app_label}_{model_name}_modeladmin_edit".format(**self.kwargs), args=[pk], ) - except NoReverseMatch: - raise Http404 + except NoReverseMatch as err: + raise Http404 from err def get_success_message(self, locales): return _( diff --git a/wagtail_localize/models.py b/wagtail_localize/models.py index b9eacfbe..7d90485e 100644 --- a/wagtail_localize/models.py +++ b/wagtail_localize/models.py @@ -118,10 +118,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)], ) @@ -183,6 +180,12 @@ class TranslatableObject(models.Model): objects = TranslatableObjectManager() + class Meta: + unique_together = [("content_type", "translation_key")] + + def __str__(self): + return f"TranslatableObject: {self.translation_key}, {self.content_type_id}" + def has_translation(self, locale): """ Returns True if there is an instance of this object in the given Locale. @@ -230,9 +233,6 @@ def get_instance_or_none(self, locale): except self.content_type.model_class().DoesNotExist: pass - class Meta: - unique_together = [("content_type", "translation_key")] - class SourceDeletedError(Exception): pass @@ -330,6 +330,9 @@ class Meta: ("object", "locale"), ] + def __str__(self): + return f"TranslationSource: {self.object_id}, {self.specific_content_type_id}, {self.locale}" + @classmethod def get_or_create_from_instance(cls, instance): """ @@ -521,8 +524,8 @@ def as_instance(self): """ try: instance = self.get_source_instance() - except models.ObjectDoesNotExist: - raise SourceDeletedError + except models.ObjectDoesNotExist as err: + raise SourceDeletedError from err if isinstance(instance, Page): # see https://github.com/wagtail/wagtail/pull/8024 @@ -1072,6 +1075,9 @@ class Meta: ("source", "target_locale"), ] + def __str__(self): + return f"Translation: {self.uuid}, {self.source_id}, {self.target_locale_id}, (enabled: {self.enabled})" + def get_target_instance(self): """ Fetches the translated instance from the database. @@ -1366,6 +1372,9 @@ class TranslationLog(models.Model): related_name="+", ) + def __str__(self): + return f"TranslationLog: {self.source_id}, {self.locale_id}, {self.page_revision_id} " + def get_instance(self): """ Gets the instance of the translated object, if it still exists. @@ -1398,6 +1407,18 @@ class String(models.Model): data_hash = models.UUIDField() data = models.TextField() + class Meta: + unique_together = [("locale", "data_hash")] + + def __str__(self): + return f"String: {self.locale_id}, {self.data_hash}" + + def save(self, *args, **kwargs): + if self.data and self.data_hash is None: + self.data_hash = self._get_data_hash(self.data) + + return super().save(*args, **kwargs) + @classmethod def _get_data_hash(cls, data): """ @@ -1440,15 +1461,6 @@ def as_value(self): """ return StringValue(self.data) - def save(self, *args, **kwargs): - if self.data and self.data_hash is None: - self.data_hash = self._get_data_hash(self.data) - - return super().save(*args, **kwargs) - - class Meta: - unique_together = [("locale", "data_hash")] - class TranslationContext(models.Model): """ @@ -1476,6 +1488,15 @@ class Meta: ("object", "path_id"), ] + def __str__(self): + return f"TranslationContext: {self.object_id}, {self.path_id}, {self.path}, {self.field_path}" + + def save(self, *args, **kwargs): + if self.path and self.path_id is None: + self.path_id = self._get_path_id(self.path) + + return super().save(*args, **kwargs) + @classmethod def _get_path_id(cls, path): """ @@ -1489,12 +1510,6 @@ def _get_path_id(cls, path): """ return uuid.uuid5(uuid.UUID("fcab004a-2b50-11ea-978f-2e728ce88125"), path) - def save(self, *args, **kwargs): - if self.path and self.path_id is None: - self.path_id = self._get_path_id(self.path) - - return super().save(*args, **kwargs) - def get_field_path(self, instance): """ Gets the field path for this context @@ -1641,6 +1656,26 @@ class StringTranslation(models.Model): class Meta: unique_together = [("locale", "translation_of", "context")] + def __str__(self): + return f"StringTranslation: {self.translation_of_id}, {self.locale_id}, {self.context_id}, {self.translation_type}" + + def save(self, *args, **kwargs): + update_fields = kwargs.get("update_fields") + super().save(*args, **kwargs) + + # Set has_error if the string is invalid. + # Since we allow translations to be made by external tools, we need to allow invalid + # HTML in the database so that it can be fixed in Wagtail. However, we do want to know + # if any strings are invalid so we don't use them on a page. + updating_data = update_fields is None or "data" in update_fields + if updating_data and not self.has_error: + try: + StringValue.from_translated_html(self.data) + validate_translation_links(self.translation_of.data, self.data) + except ValueError: + self.has_error = True + self.save(update_fields=["has_error"]) + @classmethod def from_text(cls, translation_of, locale, context, data): """ @@ -1665,24 +1700,6 @@ def from_text(cls, translation_of, locale, context, data): return segment - def save(self, *args, **kwargs): - update_fields = kwargs.get("update_fields") - super().save(*args, **kwargs) - - # Set has_error if the string is invalid. - # Since we allow translations to be made by external tools, we need to allow invalid - # HTML in the database so that it can be fixed in Wagtail. However, we do want to know - # if any strings are invalid so we don't use them on a page. - updating_data = update_fields is None or "data" in update_fields - if updating_data and not self.has_error: - - try: - StringValue.from_translated_html(self.data) - validate_translation_links(self.translation_of.data, self.data) - except ValueError: - self.has_error = True - self.save(update_fields=["has_error"]) - def set_field_error(self, error): """ This sets the `has_error`/`field_error` fields to the value of the given ValidationError instance. @@ -1786,6 +1803,9 @@ class Template(models.Model): template_format = models.CharField(max_length=100) string_count = models.PositiveIntegerField() + def __str__(self): + return f"Template: {self.uuid}, {self.template_format}, {self.string_count}" + @classmethod def from_value(cls, template_value): """ @@ -1859,6 +1879,9 @@ class SegmentOverride(models.Model): field_error = models.TextField(blank=True) + def __str__(self): + return f"SegmentOverride: {self.locale_id}, {self.context_id}" + @property def data(self): return json.loads(self.data_json) @@ -2278,6 +2301,9 @@ class LocaleSynchronization(models.Model): base_form_class = LocaleSynchronizationModelForm + def __str__(self): + return f"LocaleSynchronization: {self.locale_id}, {self.sync_from_id}" + def sync_trees(self, *, page_index=None): from .synctree import synchronize_tree diff --git a/wagtail_localize/segments/__init__.py b/wagtail_localize/segments/__init__.py index 143194b6..c9d2a521 100644 --- a/wagtail_localize/segments/__init__.py +++ b/wagtail_localize/segments/__init__.py @@ -1,4 +1,4 @@ -from .types import ( # noqa +from .types import ( # noqa: F401 OverridableSegmentValue, RelatedObjectSegmentValue, StringSegmentValue, diff --git a/wagtail_localize/segments/ingest.py b/wagtail_localize/segments/ingest.py index 5139c963..1b6274b5 100644 --- a/wagtail_localize/segments/ingest.py +++ b/wagtail_localize/segments/ingest.py @@ -156,8 +156,11 @@ def handle_block(self, block_type, block_value, segments): return segment.render_text() elif isinstance(block_type, blocks.RichTextBlock): - format, template, strings = organise_template_segments(segments) - assert format == "html" + segment_format, template, strings = organise_template_segments(segments) + if segment_format != "html": + raise ValueError( + f"RichTextBlock can only contain HTML segments. Found {segment_format}" + ) return RichText(restore_strings(template, strings)) elif isinstance(block_type, blocks.ChooserBlock): @@ -269,8 +272,13 @@ def ingest_segments(original_obj, translated_obj, src_locale, tgt_locale, segmen setattr(translated_obj, field_name, data) elif isinstance(field, RichTextField): - format, template, strings = organise_template_segments(field_segments) - assert format == "html" + segment_format, template, strings = organise_template_segments( + field_segments + ) + if segment_format != "html": + raise ValueError( + f"RichTextField can only contain HTML segments. Found {segment_format}" + ) html = restore_strings(template, strings) setattr(translated_obj, field_name, html) diff --git a/wagtail_localize/synctree.py b/wagtail_localize/synctree.py index 029b5599..930a7c36 100644 --- a/wagtail_localize/synctree.py +++ b/wagtail_localize/synctree.py @@ -1,3 +1,5 @@ +import logging + from collections import defaultdict from django.utils.functional import cached_property @@ -5,6 +7,9 @@ from wagtail.models import Locale, Page +logger = logging.getLogger(__name__) + + class PageIndex: """ An in-memory index of pages to remove the need to query the database. @@ -124,7 +129,7 @@ def _walk(translation_key): _walk(None) if remaining_pages: - print(f"Warning: {len(remaining_pages)} orphaned pages!") + logger.warning(f"{len(remaining_pages)} orphaned pages!") return PageIndex(new_pages) diff --git a/wagtail_localize/test/migrations/0001_initial.py b/wagtail_localize/test/migrations/0001_initial.py index eff94cad..5d94cb32 100644 --- a/wagtail_localize/test/migrations/0001_initial.py +++ b/wagtail_localize/test/migrations/0001_initial.py @@ -1,21 +1,23 @@ # Generated by Django 4.1.1 on 2022-09-23 14:13 -from django.db import migrations, models +import uuid + import django.db.models.deletion import modelcluster.fields -import uuid import wagtail.blocks import wagtail.blocks.field_block -import wagtail.fields 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): - initial = True core_migration = "0076_modellogentry_revision" diff --git a/wagtail_localize/test/migrations/0002_header_navigationlink_and_more.py b/wagtail_localize/test/migrations/0002_header_navigationlink_and_more.py index 1879eb70..b4352fcf 100644 --- a/wagtail_localize/test/migrations/0002_header_navigationlink_and_more.py +++ b/wagtail_localize/test/migrations/0002_header_navigationlink_and_more.py @@ -1,21 +1,23 @@ # Generated by Django 3.2.16 on 2022-10-17 20:32 -from django.db import migrations, models +import uuid + import django.db.models.deletion import modelcluster.fields -import uuid import wagtail.blocks import wagtail.blocks.field_block -import wagtail.fields 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"), @@ -38,7 +40,7 @@ class Migration(migrations.Migration): "translation_key", models.UUIDField(default=uuid.uuid4, editable=False), ), - ("name", models.CharField(max_length=100, null=True)), + ("name", models.CharField(max_length=100, blank=True)), ( "locale", models.ForeignKey( 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 index 6711a560..45cf9853 100644 --- a/wagtail_localize/test/migrations/0003_wagtail_3_use_json_field.py +++ b/wagtail_localize/test/migrations/0003_wagtail_3_use_json_field.py @@ -1,6 +1,5 @@ # Generated by Django 4.1.9 on 2023-05-24 15:10 -from django.db import migrations import wagtail.blocks import wagtail.blocks.field_block import wagtail.documents.blocks @@ -8,11 +7,13 @@ 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"), ] diff --git a/wagtail_localize/test/migrations/0004_testparentalsnippet.py b/wagtail_localize/test/migrations/0004_testparentalsnippet.py index 265a8f6d..67a628d4 100644 --- a/wagtail_localize/test/migrations/0004_testparentalsnippet.py +++ b/wagtail_localize/test/migrations/0004_testparentalsnippet.py @@ -1,13 +1,14 @@ # Generated by Django 3.2.5 on 2022-05-06 18:53 -from django.db import migrations, models +import uuid + import django.db.models.deletion import modelcluster.fields -import uuid +from django.db import migrations, models -class Migration(migrations.Migration): +class Migration(migrations.Migration): dependencies = [ ("wagtail_localize_test", "0003_wagtail_3_use_json_field"), ] diff --git a/wagtail_localize/test/models.py b/wagtail_localize/test/models.py index 8aa740cc..4ff6fc9d 100644 --- a/wagtail_localize/test/models.py +++ b/wagtail_localize/test/models.py @@ -69,6 +69,9 @@ class TestUUIDModel(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) charfield = models.CharField(max_length=10, blank=True) + def __str__(self): + return f"TestUUIDModel: {self.id}" + @register_snippet class TestUUIDSnippet(TranslatableMixin, models.Model): @@ -76,6 +79,9 @@ class TestUUIDSnippet(TranslatableMixin, models.Model): translatable_fields = [SynchronizedField("field")] + def __str__(self): + return f"TestUUIDModel: {self.field_id}" + @register_snippet class TestParentalSnippet(TranslatableMixin, ClusterableModel): @@ -91,6 +97,9 @@ class TestParentalSnippet(TranslatableMixin, ClusterableModel): class NonTranslatableSnippet(models.Model): field = models.TextField() + def __str__(self): + return self.field + class TestStructBlock(blocks.StructBlock): field_a = blocks.TextBlock() @@ -245,7 +254,7 @@ def get_translatable_segments(self, value): class TestPage(Page): - test_charfield = models.CharField( + test_charfield = models.CharField( # noqa: DJ001 gettext_lazy("char field"), max_length=255, blank=True, null=True, default="" ) test_textfield = models.TextField(blank=True) @@ -403,6 +412,9 @@ class TestModel(TranslatableMixin): class NonTranslatableModel(models.Model): title = models.CharField(max_length=255, blank=True) + def __str__(self): + return self.title + class InheritedTestModel(TestModel): class Meta: @@ -500,6 +512,9 @@ class NonTranslatableChildObject(Orderable): ) field = models.TextField() + def __str__(self): + return f"NonTranslatableChildObject ({self.pk}: {self.page_id}" + class TestModelWithInvalidForeignKey(TranslatableMixin, models.Model): fk = models.ForeignKey("wagtailcore.Site", on_delete=models.CASCADE) @@ -510,6 +525,11 @@ class TestModelWithInvalidForeignKey(TranslatableMixin, models.Model): TranslatableField("fk"), ] + def __str__(self): + return ( + f"TestModelWithInvalidForeignKey ({self.pk}: {self.fk_id}, {self.locale_id}" + ) + class PageWithCustomEditHandler(Page): foo_field = models.TextField() @@ -544,6 +564,9 @@ class PageWithCustomEditHandlerChildObject(TranslatableMixin, Orderable): class Meta(TranslatableMixin.Meta, Orderable.Meta): pass + def __str__(self): + return f"PageWithCustomEditHandlerChildObject ({self.pk}: {self.page_id}" + @register_translation_component( heading="Custom translation view component", @@ -557,6 +580,9 @@ class CustomTranslationData(models.Model): ) custom_text_field = models.CharField(max_length=255) + def __str__(self): + return f"CustomTranslationData ({self.pk}: {self.translation_source_id})" + @classmethod def get_or_create_from_source_and_translation_data( cls, translation_source, translations, **kwargs @@ -576,6 +602,9 @@ def get_or_create_from_source_and_translation_data( class CustomButSimpleTranslationData(models.Model): notes = models.CharField(max_length=255) + def __str__(self): + return f"CustomButSimpleTranslationData ({self.pk})" + class SubNavigationLink(Orderable, TranslatableMixin): sub_nav = ParentalKey( @@ -631,7 +660,7 @@ def __str__(self) -> str: @register_snippet class Header(ClusterableModel, TranslatableMixin): - name = models.CharField(max_length=100, null=True) + name = models.CharField(max_length=100, blank=True) panels = [ FieldPanel("name"), diff --git a/wagtail_localize/test/settings.py b/wagtail_localize/test/settings.py index e5c95c61..016afcce 100644 --- a/wagtail_localize/test/settings.py +++ b/wagtail_localize/test/settings.py @@ -23,7 +23,7 @@ # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = "c6u0-9c!7nilj_ysatsda0(f@e_2mws2f!6m0n^o*4#*q#kzp)" +SECRET_KEY = "not-a-secret-really" # noqa: S105 # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True diff --git a/wagtail_localize/tests/test_translationsource_model.py b/wagtail_localize/tests/test_translationsource_model.py index 38429e77..745a0acc 100644 --- a/wagtail_localize/tests/test_translationsource_model.py +++ b/wagtail_localize/tests/test_translationsource_model.py @@ -418,7 +418,10 @@ def test_update_synchronised_fields(self): ) self.page.save_revision().publish() - (new_page, created,) = source_with_changed_content.create_or_update_translation( + ( + new_page, + created, + ) = source_with_changed_content.create_or_update_translation( self.dest_locale, fallback=True, ) diff --git a/wagtail_localize/tests/test_update_translations.py b/wagtail_localize/tests/test_update_translations.py index 45e43224..9c968431 100644 --- a/wagtail_localize/tests/test_update_translations.py +++ b/wagtail_localize/tests/test_update_translations.py @@ -547,7 +547,7 @@ 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" + restriction_type="password", password="test" # noqa: S106 ) self.client.post( reverse( diff --git a/wagtail_localize/version.py b/wagtail_localize/version.py index 1a13daa0..4191d748 100644 --- a/wagtail_localize/version.py +++ b/wagtail_localize/version.py @@ -35,7 +35,11 @@ def get_complete_version(version=None): if version is None: from wagtail_localize.version import VERSION as version else: - assert len(version) == 5 - assert version[3] in ("dev", "alpha", "beta", "rc", "final") + if len(version) != 5: + raise ValueError("wagtail_localize version number must be a 5-tuple") + if version[3] not in ("dev", "alpha", "beta", "rc", "final"): + raise ValueError( + "wagtail_localize version status must be one of: dev, alpha, beta, rc, or final" + ) return version diff --git a/wagtail_localize/views/convert.py b/wagtail_localize/views/convert.py index d0392400..d3f3ab80 100644 --- a/wagtail_localize/views/convert.py +++ b/wagtail_localize/views/convert.py @@ -27,8 +27,8 @@ def convert_to_alias(request, page_id): ) source_page = translation_source.get_source_instance() - except (Page.DoesNotExist, TranslationSource.DoesNotExist): - raise Http404 + except (Page.DoesNotExist, TranslationSource.DoesNotExist) as err: + raise Http404 from err # prevent self-aliasing if source_page.id == page_id: diff --git a/wagtail_localize/views/edit_translation.py b/wagtail_localize/views/edit_translation.py index d9aab151..123cf766 100644 --- a/wagtail_localize/views/edit_translation.py +++ b/wagtail_localize/views/edit_translation.py @@ -32,9 +32,8 @@ from wagtail import blocks from wagtail.admin import messages from wagtail.admin.navigation import get_explorable_root_page -from wagtail.admin.panels import FieldPanel, InlinePanel, ObjectList +from wagtail.admin.panels import FieldPanel, InlinePanel, ObjectList, TabbedInterface from wagtail.admin.panels import PanelGroup as BaseCompositeEditHandler -from wagtail.admin.panels import TabbedInterface from wagtail.admin.panels import get_edit_handler as get_snippet_edit_handler from wagtail.admin.templatetags.wagtailadmin_tags import avatar_url from wagtail.admin.views.pages.utils import get_valid_next_url_from_request @@ -282,8 +281,8 @@ def get_segment_location_info( # Work out which tab the segment is on from edit handler try: tab = cautious_slugify(tab_helper.get_field_tab(field.name)) - except KeyError: - raise FieldHasNoEditPanelError + except KeyError as err: + raise FieldHasNoEditPanelError from err order = tab_helper.get_field_order(field.name) @@ -300,20 +299,14 @@ def widget_from_field(field): widget_overrides[field.name], "target_models" ): allowed_page_types = [ - "{app}.{model}".format( - app=model._meta.app_label, - model=model._meta.model_name, - ) + f"{model._meta.app_label}.{model._meta.model_name}" for model in widget_overrides[field.name].target_models ] else: from wagtail.admin.forms.models import registry allowed_page_types = [ - "{app}.{model}".format( - app=model._meta.app_label, - model=model._meta.model_name, - ) + f"{model._meta.app_label}.{model._meta.model_name}" for model in registry.foreign_key_lookup(field)[ "widget" ].target_models @@ -331,8 +324,7 @@ def widget_from_field(field): elif issubclass(field.related_model, tuple(get_snippet_models())): chooser_url = reverse( - "wagtailsnippetchoosers_%s_%s:choose" - % ( + "wagtailsnippetchoosers_{}_{}:choose".format( field.related_model._meta.app_label, field.related_model._meta.model_name, ) @@ -363,9 +355,7 @@ def widget_from_block(block, content_components=None): return { "type": "page_chooser", "allowed_page_types": [ - "{app}.{model}".format( - app=model._meta.app_label, model=model._meta.model_name - ) + f"{model._meta.app_label}.{model._meta.model_name}" # Note: Unlike PageChooserPanel, the block doesn't automatically fall back to [Page] for model in block.target_models or [Page] ], @@ -379,8 +369,7 @@ def widget_from_block(block, content_components=None): elif isinstance(block, SnippetChooserBlock): chooser_url = reverse( - "wagtailsnippetchoosers_%s_%s:choose" - % ( + "wagtailsnippetchoosers_{}_{}:choose".format( block.target_model._meta.app_label, block.target_model._meta.model_name, ) @@ -1104,10 +1093,7 @@ def restart_translation(request, translation, instance): ) elif "wagtail_localize.modeladmin" in settings.INSTALLED_APPS: return redirect( - "{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", instance_pk=quote(instance.pk), ) diff --git a/wagtail_localize/wagtail_hooks.py b/wagtail_localize/wagtail_hooks.py index b65bd6d7..0529d2e6 100644 --- a/wagtail_localize/wagtail_hooks.py +++ b/wagtail_localize/wagtail_hooks.py @@ -18,7 +18,7 @@ from wagtail.snippets.widgets import SnippetListingButton # Import synctree so it can register its signal handler -from . import synctree # noqa +from . import synctree # noqa: F401 from .models import Translation, TranslationSource from .views import ( convert,