Coverage for src/debputy/plugin/api/example_processing.py: 96%

62 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-04-07 12:14 +0200

1import dataclasses 

2from enum import Enum 

3from typing import Set, Tuple, List, cast, Dict, Sequence 

4 

5from debputy.filesystem_scan import build_virtual_fs 

6from debputy.plugin.api import VirtualPath 

7from debputy.plugin.api.impl_types import ( 

8 AutomaticDiscardRuleExample, 

9 PluginProvidedDiscardRule, 

10) 

11from debputy.util import _normalize_path 

12 

13 

14class DiscardVerdict(Enum): 

15 INCONSISTENT_CODE_KEPT = ( 

16 None, 

17 "INCONSISTENT (code kept the path, but should have discarded)", 

18 ) 

19 INCONSISTENT_CODE_DISCARDED = ( 

20 None, 

21 "INCONSISTENT (code discarded the path, but should have kept it)", 

22 ) 

23 KEPT = (False, "Kept") 

24 DISCARDED_BY_CODE = (True, "Discarded (directly by the rule)") 

25 DISCARDED_BY_DIRECTORY = (True, "Discarded (directory was discarded)") 

26 

27 @property 

28 def message(self) -> str: 

29 return cast("str", self.value[1]) 

30 

31 @property 

32 def is_consistent(self) -> bool: 

33 return self.value[0] is not None 

34 

35 @property 

36 def is_discarded(self) -> bool: 

37 return self.value[0] is True 

38 

39 @property 

40 def is_kept(self) -> bool: 

41 return self.value[0] is False 

42 

43 

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

45class ProcessedDiscardRuleExample: 

46 rendered_paths: Sequence[Tuple[VirtualPath, DiscardVerdict]] 

47 inconsistent_paths: Set[VirtualPath] 

48 # To avoid the parents being garbage collected 

49 fs_root: VirtualPath 

50 

51 

52def process_discard_rule_example( 

53 discard_rule: PluginProvidedDiscardRule, 

54 example: AutomaticDiscardRuleExample, 

55) -> ProcessedDiscardRuleExample: 

56 fs_root: VirtualPath = build_virtual_fs([p for p, _ in example.content]) 

57 

58 actual_discarded: Dict[str, bool] = {} 

59 expected_output = { 

60 "/" + _normalize_path(p.path_name, with_prefix=False): v 

61 for p, v in example.content 

62 } 

63 inconsistent_paths = set() 

64 rendered_paths = [] 

65 

66 for p in fs_root.all_paths(): 

67 parent = p.parent_dir 

68 discard_carry_over = False 

69 path_name = p.absolute 

70 if parent and actual_discarded[parent.absolute]: 

71 verdict = True 

72 discard_carry_over = True 

73 else: 

74 verdict = discard_rule.should_discard(p) 

75 

76 actual_discarded[path_name] = verdict 

77 expected = expected_output.get(path_name) 

78 if expected is not None: 

79 inconsistent = expected != verdict 

80 if inconsistent: 

81 inconsistent_paths.add(p) 

82 else: 

83 continue 

84 

85 if inconsistent: 

86 if verdict: 

87 verdict_code = DiscardVerdict.INCONSISTENT_CODE_DISCARDED 

88 else: 

89 verdict_code = DiscardVerdict.INCONSISTENT_CODE_KEPT 

90 elif verdict: 

91 if discard_carry_over: 

92 verdict_code = DiscardVerdict.DISCARDED_BY_DIRECTORY 

93 else: 

94 verdict_code = DiscardVerdict.DISCARDED_BY_CODE 

95 else: 

96 verdict_code = DiscardVerdict.KEPT 

97 rendered_paths.append((p, verdict_code)) 

98 

99 return ProcessedDiscardRuleExample(rendered_paths, inconsistent_paths, fs_root)