Coverage for app/venv/lib/python3.14/site-packages/weblate/checks/parser.py: 43%
52 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 re
8import threading
9from typing import TYPE_CHECKING
11from pyparsing import Optional, QuotedString, Regex, ZeroOrMore
13if TYPE_CHECKING: 13 ↛ 14line 13 didn't jump to line 14 because the condition on line 13 was never true
14 from pyparsing import ParserElement
17def single_value_flag(func, validation=None):
18 def parse_values(val):
19 if not val:
20 msg = "Missing required parameter"
21 raise ValueError(msg)
22 if len(val) > 1:
23 msg = "Too many parameters"
24 raise ValueError(msg)
25 result = func(val[0])
26 if validation is not None:
27 validation(result)
28 return result
30 return parse_values
33def length_validation(length: int):
34 def validate_length(val) -> None:
35 if len(val) > length:
36 msg = "String too long"
37 raise ValueError(msg)
39 return validate_length
42def multi_value_flag(
43 func, minimum: int = 1, maximum: int | None = None, modulo: int | None = None
44):
45 def parse_values(val):
46 if modulo and len(val) % modulo != 0:
47 msg = "Number of parameter is not even"
48 raise ValueError(msg)
49 if minimum and len(val) < minimum:
50 msg = "Missing required parameter"
51 raise ValueError(msg)
52 if maximum and len(val) > maximum:
53 msg = "Too many parameters"
54 raise ValueError(msg)
55 return [func(x) for x in val]
57 return parse_values
60class RawQuotedString(QuotedString):
61 def __init__(self, quote_char: str, esc_char: str = "\\") -> None:
62 super().__init__(quote_char, esc_char=esc_char, convert_whitespace_escapes=True)
63 # unlike the QuotedString this replaces only escaped quotes and not all chars
64 self.unquote_scan_re = re.compile(
65 rf"({'|'.join(re.escape(k) for k in self.ws_map)})|({re.escape(self.esc_char)}[{re.escape(quote_char)}{re.escape(esc_char)}])|(\n|.)",
66 flags=self.re_flags,
67 )
70SYNTAXCHARS = {",", ":", '"', "'", "\\"}
73def get_flags_parser() -> ParserElement:
74 flag_name = Regex(r"""[^,:"' \r\n\t]([^,:"']*[^,:"' \r\n\t])?""")
76 regex_string = "r" + RawQuotedString('"')
78 flag_param = Optional(
79 regex_string | flag_name | RawQuotedString("'") | RawQuotedString('"')
80 )
82 flag = flag_name + ZeroOrMore(":" + flag_param)
84 return Optional(flag) + ZeroOrMore("," + Optional(flag))
87FLAGS_PARSER: ParserElement = get_flags_parser()
88FLAGS_PARSER_LOCK = threading.Lock()