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