# SPDX-License-Identifier: AGPL-3.0-or-later """Diagnostic check data type.""" import dataclasses import json from dataclasses import dataclass, field from enum import StrEnum from typing import TypeAlias from django.utils.translation import gettext from plinth.utils import SafeFormatter DiagnosticCheckParameters: TypeAlias = dict[str, str | int | bool | None] class Result(StrEnum): """The result of a diagnostic check.""" NOT_DONE = 'not_done' SKIPPED = 'skipped' PASSED = 'passed' WARNING = 'warning' FAILED = 'failed' ERROR = 'error' @dataclass class DiagnosticCheck: """A diagnostic check and optional result and parameters.""" check_id: str description: str result: Result = Result.NOT_DONE parameters: DiagnosticCheckParameters = field(default_factory=dict) component_id: str | None = None @property def translated_description(self): """Return translated string for description.""" description = gettext(self.description) if self.parameters: return SafeFormatter().vformat(description, [], self.parameters) return description class CheckJSONEncoder(json.JSONEncoder): """Encode objects that include DiagnosticChecks.""" def default(self, o): """Add class tag to DiagnosticChecks.""" if isinstance(o, DiagnosticCheck): o = dataclasses.asdict(o) o.update({'__class__': 'DiagnosticCheck'}) return o return super().default(o) class CheckJSONDecoder(json.JSONDecoder): """Decode objects that include DiagnosticChecks.""" def __init__(self): json.JSONDecoder.__init__(self, object_hook=CheckJSONDecoder.from_dict) @staticmethod def from_dict(data): """Convert tagged data to DiagnosticCheck.""" if data.get('__class__') == 'DiagnosticCheck': return DiagnosticCheck(data['check_id'], data['description'], data['result'], data['parameters'], data.get('component_id')) return data