Coverage for app/venv/lib/python3.14/site-packages/weblate/machinery/models.py: 45%
34 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 07:15 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 07:15 +0000
1# Copyright © Michal Čihař <michal@weblate.org>
2#
3# SPDX-License-Identifier: GPL-3.0-or-later
5from __future__ import annotations
7import json
8from typing import TYPE_CHECKING, cast
10from appconf import AppConf
12from weblate.utils.classloader import ClassLoader
14from .base import BatchMachineTranslation
16if TYPE_CHECKING: 16 ↛ 17line 16 didn't jump to line 17 because the condition on line 16 was never true
17 from .types import SettingsDict
19MACHINERY = ClassLoader(
20 "WEBLATE_MACHINERY",
21 construct=False,
22 collect_errors=True,
23 base_class=BatchMachineTranslation,
24)
27class WeblateConf(AppConf):
28 """Machine-translation settings."""
30 # List of machinery classes
31 WEBLATE_MACHINERY = (
32 "weblate.machinery.apertium.ApertiumAPYTranslation",
33 "weblate.machinery.aws.AWSTranslation",
34 "weblate.machinery.alibaba.AlibabaTranslation",
35 "weblate.machinery.baidu.BaiduTranslation",
36 "weblate.machinery.deepl.DeepLTranslation",
37 "weblate.machinery.glosbe.GlosbeTranslation",
38 "weblate.machinery.google.GoogleTranslation",
39 "weblate.machinery.googlev3.GoogleV3Translation",
40 "weblate.machinery.libretranslate.LibreTranslateTranslation",
41 "weblate.machinery.microsoft.MicrosoftCognitiveTranslation",
42 "weblate.machinery.modernmt.ModernMTTranslation",
43 "weblate.machinery.mymemory.MyMemoryTranslation",
44 "weblate.machinery.netease.NeteaseSightTranslation",
45 "weblate.machinery.tmserver.TMServerTranslation",
46 "weblate.machinery.yandex.YandexTranslation",
47 "weblate.machinery.yandexv2.YandexV2Translation",
48 "weblate.machinery.saptranslationhub.SAPTranslationHub",
49 "weblate.machinery.youdao.YoudaoTranslation",
50 "weblate.machinery.systran.SystranTranslation",
51 "weblate.machinery.openai.OpenAITranslation",
52 "weblate.machinery.openai.AzureOpenAITranslation",
53 "weblate.machinery.weblatetm.WeblateTranslation",
54 "weblate.memory.machine.WeblateMemory",
55 "weblate.machinery.cyrtranslit.CyrTranslitTranslation",
56 )
58 class Meta:
59 prefix = ""
62def validate_service_configuration(
63 service_name: str,
64 configuration: str | SettingsDict,
65) -> tuple[BatchMachineTranslation | None, SettingsDict, list[str]]:
66 """
67 Validate given service configuration.
69 :param service_name: Name of the service as defined in WEBLATE_MACHINERY
70 :param configuration: JSON encoded configuration for the service
71 :return: A tuple containing the validated service class, configuration
72 and a list of errors
73 :raises ValueError: When service is not found or configuration is invalid
74 """
75 try:
76 service = MACHINERY[service_name]
77 except KeyError:
78 msg = f"Service not found: {service_name}"
79 return None, {}, [msg]
81 service_configuration: SettingsDict
83 if isinstance(configuration, str):
84 try:
85 service_configuration = cast("SettingsDict", json.loads(configuration))
86 except json.JSONDecodeError as error:
87 msg = f"Invalid service configuration ({service_name}): {error}"
88 return service, {}, [msg]
89 else:
90 service_configuration = configuration
92 errors = []
93 if service.settings_form is not None:
94 form = service.settings_form(service, data=service_configuration)
95 # validate form
96 if not form.is_valid():
97 errors.extend([str(error) for error in form.non_field_errors()])
99 for field in form:
100 errors.extend(
101 [
102 f"Error in {field.name} ({service_name}): {error}"
103 for error in field.errors
104 ]
105 )
106 return service, service_configuration, errors