Coverage for src/debputy/plugin/api/doc_parsing.py: 96%
44 statements
« prev ^ index » next coverage.py v7.8.2, created at 2026-01-16 17:20 +0000
« prev ^ index » next coverage.py v7.8.2, created at 2026-01-16 17:20 +0000
1import dataclasses
2from typing import NotRequired, Any, Self, TypeVar
3from collections.abc import Mapping, Iterable
5from debputy.manifest_parser.declarative_parser import ParserGenerator
6from debputy.manifest_parser.tagging_types import DebputyParsedContent
7from debputy.plugin.api.spec import ParserDocumentation
9_DEBPUTY_DOC_PARSER_GENERATOR = ParserGenerator()
12class AttributeRefDoc(DebputyParsedContent):
13 attr: NotRequired[str | list[str]]
14 description: str
17class ParserRefDocumentation(DebputyParsedContent):
18 title: str
19 description: NotRequired[str]
20 attributes: NotRequired[list[AttributeRefDoc]]
21 undocumented_attributes: NotRequired[list[str]]
22 non_mapping_description: NotRequired[str]
23 ref_doc_url: NotRequired[str]
24 synopsis: NotRequired[str]
27class PMRData(ParserRefDocumentation):
28 rule_reference: str
29 documentation: NotRequired[ParserRefDocumentation]
32class DebputyDocReferenceData(DebputyParsedContent):
33 pluggable_manifest_rules: NotRequired[list[PMRData]]
36DEBPUTY_DOC_REFERENCE_DATA_PARSER = _DEBPUTY_DOC_PARSER_GENERATOR.generate_parser(
37 DebputyDocReferenceData
38)
41D = TypeVar("D")
44def _unique(
45 topic: str, key_attr_name: str, kd: Iterable[tuple[str, D]]
46) -> Mapping[str, D]:
47 seen = set()
48 r = {}
49 for k, d in kd:
50 if k in seen: 50 ↛ 51line 50 didn't jump to line 51 because the condition on line 50 was never true
51 raise ValueError(
52 f"The multiple instances of the {key_attr_name} attribute in {topic}"
53 f' had the value: "{k}". The value must be unique'
54 )
55 seen.add(k)
56 r[k] = d
58 return r
61@dataclasses.dataclass(slots=True, frozen=True)
62class DebputyParsedDoc:
63 pluggable_manifest_rules: Mapping[str, ParserDocumentation]
65 @classmethod
66 def from_ref_data(cls, docs: DebputyDocReferenceData) -> Self:
67 return cls(
68 pluggable_manifest_rules=_unique(
69 "pluggable-manifest-rules",
70 "rule-reference",
71 (
72 (d["rule_reference"], ParserDocumentation.from_ref_doc(d))
73 for d in docs.get("pluggable_manifest_rules", [])
74 ),
75 )
76 )
79def parser_type_name(v: str | type[Any]) -> str:
80 if isinstance(v, str):
81 return v if v != "<ROOT>" else ""
82 return v.__name__