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

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 

13 

14from debputy.manifest_parser.declarative_parser import ParserGenerator 

15from debputy.manifest_parser.tagging_types import DebputyParsedContent 

16from debputy.plugin.api.spec import ParserDocumentation 

17 

18_DEBPUTY_DOC_PARSER_GENERATOR = ParserGenerator() 

19 

20 

21class AttributeRefDoc(DebputyParsedContent): 

22 attr: NotRequired[str | list[str]] 

23 description: str 

24 

25 

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] 

34 

35 

36class PMRData(ParserRefDocumentation): 

37 rule_reference: str 

38 documentation: NotRequired[ParserRefDocumentation] 

39 

40 

41class DebputyDocReferenceData(DebputyParsedContent): 

42 pluggable_manifest_rules: NotRequired[list[PMRData]] 

43 

44 

45DEBPUTY_DOC_REFERENCE_DATA_PARSER = _DEBPUTY_DOC_PARSER_GENERATOR.generate_parser( 

46 DebputyDocReferenceData 

47) 

48 

49 

50D = TypeVar("D") 

51 

52 

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 

66 

67 return r 

68 

69 

70@dataclasses.dataclass(slots=True, frozen=True) 

71class DebputyParsedDoc: 

72 pluggable_manifest_rules: Mapping[str, ParserDocumentation] 

73 

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 ) 

86 

87 

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__