diagnostics: Add method to translate checks

Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
This commit is contained in:
James Valleroy 2023-11-13 13:08:42 -05:00 committed by Sunil Mohan Adapa
parent 4612df954d
commit a5820bc36d
No known key found for this signature in database
GPG Key ID: 43EA1CFF0AA7C5F2
6 changed files with 72 additions and 27 deletions

View File

@ -4,6 +4,10 @@
from dataclasses import dataclass, field
from enum import StrEnum
from django.utils.translation import gettext
from plinth.utils import SafeFormatter
class Result(StrEnum):
"""The result of a diagnostic check."""
@ -24,3 +28,19 @@ class DiagnosticCheck:
description: str
result: Result = Result.NOT_DONE
parameters: dict = field(default_factory=dict)
def translate(check: DiagnosticCheck) -> DiagnosticCheck:
"""Translate and format description using parameters."""
description = gettext(check.description)
if check.parameters:
description = SafeFormatter().vformat(description, [],
check.parameters)
return DiagnosticCheck(check.check_id, description, check.result,
check.parameters)
def translate_checks(checks: list[DiagnosticCheck]) -> list[DiagnosticCheck]:
"""Translate and format diagnostic checks."""
return [translate(check) for check in checks]

View File

@ -3,7 +3,7 @@
import pytest
from plinth.modules.diagnostics.check import DiagnosticCheck, Result
from plinth.modules.diagnostics.check import DiagnosticCheck, Result, translate
def test_result():
@ -35,3 +35,25 @@ def test_diagnostic_check():
check = DiagnosticCheck('some-check-id', 'sample check', Result.PASSED,
{'key': 'value'})
assert check.parameters['key'] == 'value'
def test_translate():
"""Test formatting the translated description."""
check = DiagnosticCheck('some-check-id', 'sample check', Result.PASSED)
translated = translate(check)
assert translated.check_id == 'some-check-id'
assert translated.description == 'sample check'
assert translated.result == Result.PASSED
assert not translated.parameters
check = DiagnosticCheck('some-check-id', 'sample check {key}',
Result.FAILED, {'key': 'value'})
translated = translate(check)
assert translated.description == 'sample check value'
assert translated.result == Result.FAILED
assert translated.parameters == {'key': 'value'}
check = DiagnosticCheck('some-check-id', 'sample check {missing}',
Result.PASSED, {'key': 'value'})
translated = translate(check)
assert translated.description == 'sample check ?missing?'

View File

@ -3,7 +3,6 @@
import copy
import logging
import string
from django.core.exceptions import ValidationError
from django.db.models import Q
@ -12,6 +11,7 @@ from django.template.response import SimpleTemplateResponse
from django.utils.translation import gettext
from plinth import cfg
from plinth.utils import SafeFormatter
from . import db, models
@ -370,14 +370,3 @@ class Notification(models.StoredNotification):
notes.append(note_context)
return {'notifications': notes, 'max_severity': max_severity}
class SafeFormatter(string.Formatter):
"""A string.format() handler to deal with missing arguments."""
def get_value(self, key, args, kwargs):
"""Retrieve a given field value."""
try:
return super().get_value(key, args, kwargs)
except (IndexError, KeyError):
return f'?{key}?'

View File

@ -10,7 +10,7 @@ import pytest
from django.contrib.auth.models import Group, User
from django.core.exceptions import ValidationError
from plinth.notification import Notification, SafeFormatter
from plinth.notification import Notification
pytestmark = pytest.mark.django_db
@ -413,15 +413,3 @@ def test_display_context_body_template(note, user, load_cfg, rf):
context_note = context['notifications'][0]
assert context_note['body'].content == \
b'Test notification body /plinth/help/about/\n'
@pytest.mark.parametrize('input_, output', (
(('', [], {}), ''),
(('{} {}', [10, 20], {}), '10 20'),
(('{1} {0} {key1}', [10, 20], dict(key1='value1')), '20 10 value1'),
(('{2} {1} {key1}', [10, 20], {}), '?2? 20 ?key1?'),
))
def test_safe_string_formatter(input_, output):
"""Test the safe string formatter."""
formatter = SafeFormatter()
assert output == formatter.vformat(*input_)

View File

@ -11,7 +11,8 @@ import ruamel.yaml
from django.test.client import RequestFactory
from ruamel.yaml.compat import StringIO
from plinth.utils import YAMLFile, is_user_admin, is_valid_user_name
from plinth.utils import (SafeFormatter, YAMLFile, is_user_admin,
is_valid_user_name)
def test_is_valid_user_name():
@ -139,3 +140,17 @@ class TestYAMLFileUtil:
raise ValueError('Test')
assert open(test_file.name, 'r', encoding='utf-8').read() == ''
@pytest.mark.parametrize('input_, output', (
(('', [], {}), ''),
(('{} {}', [10, 20], {}), '10 20'),
(('{1} {0} {key1}', [10, 20], {
'key1': 'value1'
}), '20 10 value1'),
(('{2} {1} {key1}', [10, 20], {}), '?2? 20 ?key1?'),
))
def test_safe_string_formatter(input_, output):
"""Test the safe string formatter."""
formatter = SafeFormatter()
assert output == formatter.vformat(*input_)

View File

@ -174,3 +174,14 @@ def is_authenticated_user(username, password):
import pam # Minimize dependencies for running tests
pam_authenticator = pam.pam()
return bool(pam_authenticator.authenticate(username, password))
class SafeFormatter(string.Formatter):
"""A string.format() handler to deal with missing arguments."""
def get_value(self, key, args, kwargs):
"""Retrieve a given field value."""
try:
return super().get_value(key, args, kwargs)
except (IndexError, KeyError):
return f'?{key}?'