mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-03-11 09:04:54 +00:00
Helps: #2410. - Ensure that diagnostics methods and parameters are type checked so that we can catch any potential issues. - Move plinth/modules/diagnostics/check.py to plinth/diagnostic_check.py to avoid many circular dependencies created. This is due to plinth.modules.diagnostics automatically imported when plinth.modules.diagnostics.check is imported. Also app.py is already (type) dependent on diagnostic_check due to diagnose() method. To make the Check classes independent of diagnostic module is okay. Tests: - Run make check-type. - Run full diagnostics with following apps installed: torproxy, tor. - Test to netcat to 9051 in tor works. - Test 'port available for internal/external networks' in firewall works. - Test 'Package is latest' works. - Test 'Access url with proxy' in privoxy works. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org> [jvalleroy: Also move tests for diagnostic_check] Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
71 lines
1.9 KiB
Python
71 lines
1.9 KiB
Python
# 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'
|
|
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)
|
|
|
|
@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'])
|
|
|
|
return data
|