Skip to content

Commit 7374cd5

Browse files
committed
fix(checks): avoid crash when check flag cannot be parsed
Instead make the check failing with a proper description. Fixes #17816
1 parent 52a4752 commit 7374cd5

File tree

3 files changed

+48
-5
lines changed

3 files changed

+48
-5
lines changed

docs/changes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Weblate 5.16
2727
* Adding plural strings with singular matching existing string is now prohibited for bilingual translations (see :ref:`bimono`).
2828
* Automatic :ref:`component-repoweb` URL for common code hosting sites.
2929
* File formats that only differed in encoding (CSV, GWT Properties, Java Properties, iOS Strings) have been merged into single formats.
30+
* Gracefully handle invalid check flags in :ref:`custom-checks`.
3031

3132
.. rubric:: Compatibility
3233

weblate/checks/base.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,12 @@ def check_target_unit(
382382
) -> bool:
383383
"""Check flag value."""
384384
if unit.all_flags.has_value(self.enable_string):
385-
return self.check_target_params(
386-
sources, targets, unit, self.get_value(unit)
387-
)
385+
try:
386+
value = self.get_value(unit)
387+
except ValueError:
388+
# Value is present, but is syntactically invalid
389+
return True
390+
return self.check_target_params(sources, targets, unit, value)
388391
return False
389392

390393
def check_target_params(
@@ -400,6 +403,15 @@ def check_single(self, source: str, target: str, unit: Unit) -> bool:
400403
"""We don't check single phrase here."""
401404
return False
402405

406+
def get_description(self, check_obj: Check) -> StrOrPromise:
407+
try:
408+
self.get_value(check_obj.unit)
409+
except ValueError as error:
410+
return format_html(
411+
gettext("Could not parse {} flag: {}"), self.enable_string, error
412+
)
413+
return super().get_description(check_obj)
414+
403415

404416
class CountingCheck(TargetCheck):
405417
"""Check whether there is same count of given string."""

weblate/checks/tests/test_chars_checks.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
"""Tests for char based quality checks."""
66

7-
from unittest import TestCase
7+
from django.test import SimpleTestCase
88

99
from weblate.checks.chars import (
1010
BeginNewlineCheck,
@@ -28,7 +28,10 @@
2828
PunctuationSpacingCheck,
2929
ZeroWidthSpaceCheck,
3030
)
31+
from weblate.checks.models import Check
3132
from weblate.checks.tests.test_checks import CheckTestCase, MockUnit
33+
from weblate.lang.models import Language
34+
from weblate.trans.models import Component, Project, Translation, Unit
3235

3336

3437
class BeginNewlineCheckTest(CheckTestCase):
@@ -316,7 +319,7 @@ def setUp(self) -> None:
316319
self.test_failure_1 = ("string", "str\u200bing", "")
317320

318321

319-
class MaxLengthCheckTest(TestCase):
322+
class MaxLengthCheckTest(SimpleTestCase):
320323
def setUp(self) -> None:
321324
self.check = MaxLengthCheck()
322325
self.test_good_matching = ("strings", "less than 21", "max-length:12")
@@ -331,6 +334,33 @@ def test_check(self) -> None:
331334
)
332335
)
333336

337+
def test_check_invalid_flag(self) -> None:
338+
self.assertTrue(
339+
self.check.check_target(
340+
[self.test_good_matching[0]],
341+
[self.test_good_matching[1]],
342+
MockUnit(flags="max-length:*"),
343+
)
344+
)
345+
346+
def test_description_invalid_flag(self) -> None:
347+
unit = Unit(
348+
source=self.test_good_matching[0],
349+
target=self.test_good_matching[1],
350+
extra_flags="max-length:*",
351+
translation=Translation(
352+
component=Component(
353+
file_format="po",
354+
source_language=Language(code="en"),
355+
project=Project(),
356+
)
357+
),
358+
)
359+
check = Check(unit=unit)
360+
self.assertIn(
361+
"Could not parse max-length flag:", str(self.check.get_description(check))
362+
)
363+
334364
def test_unicode_check(self) -> None:
335365
self.assertFalse(
336366
self.check.check_target(

0 commit comments

Comments
 (0)