Coverage for src/debputy/lsp/ref_models/deb822_reference_parse_models.py: 84%
92 statements
« prev ^ index » next coverage.py v7.6.0, created at 2025-01-27 13:59 +0000
« prev ^ index » next coverage.py v7.6.0, created at 2025-01-27 13:59 +0000
1import re
2import sys
3from enum import Enum
4from typing import (
5 NotRequired,
6 List,
7 Any,
8 Optional,
9 Iterable,
10 Literal,
11 Dict,
12)
14from debputy.lsp.vendoring._deb822_repro import (
15 LIST_SPACE_SEPARATED_INTERPRETATION,
16 LIST_COMMA_SEPARATED_INTERPRETATION,
17)
18from debputy.lsp.vendoring._deb822_repro.parsing import (
19 LIST_UPLOADERS_INTERPRETATION,
20 Deb822ParsedTokenList,
21 Interpretation,
22 _parse_whitespace_list_value,
23 Deb822ParsedValueElement,
24 _parsed_value_render_factory,
25 ListInterpretation,
26)
27from debputy.lsp.vendoring._deb822_repro.tokens import (
28 Deb822SpaceSeparatorToken,
29 _value_line_tokenizer,
30 _RE_WHITESPACE_SEPARATED_WORD_LIST,
31 Deb822ValueToken,
32 Deb822Token,
33)
34from debputy.manifest_parser.declarative_parser import ParserGenerator
35from debputy.manifest_parser.tagging_types import DebputyParsedContent
37_DEB822_REFERENCE_DATA_PARSER_GENERATOR = ParserGenerator()
39# FIXME: should go into python3-debian
40_RE_COMMA = re.compile("([^,]*),([^,]*)")
42UsageHint = Literal["rare",]
45@_value_line_tokenizer
46def comma_or_space_split_tokenizer(v: str) -> Iterable[Deb822Token]:
47 assert "\n" not in v
48 for match in _RE_WHITESPACE_SEPARATED_WORD_LIST.finditer(v):
49 space_before, word, space_after = match.groups()
50 if space_before: 50 ↛ 52line 50 didn't jump to line 52 because the condition on line 50 was always true
51 yield Deb822SpaceSeparatorToken(sys.intern(space_before))
52 if "," in word: 52 ↛ 53line 52 didn't jump to line 53 because the condition on line 52 was never true
53 for m in _RE_COMMA.finditer(word):
54 word_before, word_after = m.groups()
55 if word_before:
56 yield Deb822ValueToken(word_before)
57 # ... not quite a whitespace, but it is too much pain to make it a non-whitespace token.
58 yield Deb822SpaceSeparatorToken(",")
59 if word_after:
60 yield Deb822ValueToken(word_after)
61 else:
62 yield Deb822ValueToken(word)
63 if space_after: 63 ↛ 64line 63 didn't jump to line 64 because the condition on line 63 was never true
64 yield Deb822SpaceSeparatorToken(sys.intern(space_after))
67# FIXME: should go into python3-debian
68LIST_COMMA_OR_SPACE_SEPARATED_INTERPRETATION = ListInterpretation( 68 ↛ exitline 68 didn't jump to the function exit
69 comma_or_space_split_tokenizer,
70 _parse_whitespace_list_value,
71 Deb822ParsedValueElement,
72 Deb822SpaceSeparatorToken,
73 lambda: Deb822SpaceSeparatorToken(","),
74 _parsed_value_render_factory,
75)
77_KEY2FIELD_VALUE_CLASS: Dict[str, "FieldValueClass"]
80class FieldValueClass(Enum):
81 SINGLE_VALUE = "single-value", LIST_SPACE_SEPARATED_INTERPRETATION
82 SPACE_SEPARATED_LIST = "space-separated-list", LIST_SPACE_SEPARATED_INTERPRETATION
83 BUILD_PROFILES_LIST = "build-profiles-list", None # TODO
84 COMMA_SEPARATED_LIST = "comma-separated-list", LIST_COMMA_SEPARATED_INTERPRETATION
85 COMMA_SEPARATED_EMAIL_LIST = (
86 "comma-separated-email-list",
87 LIST_UPLOADERS_INTERPRETATION,
88 )
89 COMMA_OR_SPACE_SEPARATED_LIST = (
90 "comma-or-space-separated-list",
91 LIST_COMMA_OR_SPACE_SEPARATED_INTERPRETATION,
92 )
93 FREE_TEXT_FIELD = "free-text", None
94 DEP5_FILE_LIST = "dep5-file-list", LIST_SPACE_SEPARATED_INTERPRETATION
96 @classmethod
97 def from_key(cls, key: str) -> "FieldValueClass":
98 return _KEY2FIELD_VALUE_CLASS[key]
100 @property
101 def key(self) -> str:
102 return self.value[0]
104 def interpreter(self) -> Optional[Interpretation[Deb822ParsedTokenList[Any, Any]]]:
105 return self.value[1]
108# TODO: Have the parser generator support enums better than this hack.
109FieldValueType = Literal[tuple(x.key for x in FieldValueClass)]
110_KEY2FIELD_VALUE_CLASS = {x.key: x for x in FieldValueClass}
113class Documentation(DebputyParsedContent):
114 synopsis: NotRequired[str]
115 long_description: NotRequired[str]
116 uris: NotRequired[List[str]]
119class DCtrlSubstvar(DebputyParsedContent):
120 name: str
121 defined_by: str
122 dh_sequence: NotRequired[str]
123 documentation: NotRequired[Documentation]
126class DctrlSubstvarsReferenceData(DebputyParsedContent):
127 substvars: List[DCtrlSubstvar]
130class StaticValue(DebputyParsedContent):
131 value: str
132 documentation: NotRequired[Documentation]
133 sort_key: NotRequired[str]
134 usage_hint: NotRequired[UsageHint]
137class Deb822Field(DebputyParsedContent):
138 canonical_name: str
139 field_value_type: FieldValueType
140 unknown_value_authority: NotRequired[str]
141 missing_field_authority: NotRequired[str]
142 default_value: NotRequired[str]
143 usage_hint: NotRequired[UsageHint]
144 documentation: NotRequired[Documentation]
145 values: NotRequired[List[StaticValue]]
146 replaced_by: NotRequired[str]
147 is_obsolete_without_replacement: NotRequired[Literal[True]]
148 spellcheck_value: NotRequired[Literal[True]]
151class StanzaType(DebputyParsedContent):
152 stanza_name: str
153 fields: List[Deb822Field]
156class ReferenceVariable(DebputyParsedContent):
157 name: str
158 fallback: str
161class ReferenceDefinition(DebputyParsedContent):
162 variables: NotRequired[List[ReferenceVariable]]
165class Deb822ReferenceData(DebputyParsedContent):
166 definitions: NotRequired[ReferenceDefinition]
167 stanza_types: List[StanzaType]
170DEB822_REFERENCE_DATA_PARSER = _DEB822_REFERENCE_DATA_PARSER_GENERATOR.generate_parser(
171 Deb822ReferenceData
172)
175DCTRL_SUBSTVARS_REFERENCE_DATA_PARSER = (
176 _DEB822_REFERENCE_DATA_PARSER_GENERATOR.generate_parser(DctrlSubstvarsReferenceData)
177)