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
« 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
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
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)")
27 @property
28 def message(self) -> str:
29 return cast("str", self.value[1])
31 @property
32 def is_consistent(self) -> bool:
33 return self.value[0] is not None
35 @property
36 def is_discarded(self) -> bool:
37 return self.value[0] is True
39 @property
40 def is_kept(self) -> bool:
41 return self.value[0] is False
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
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])
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 = []
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)
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
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))
99 return ProcessedDiscardRuleExample(rendered_paths, inconsistent_paths, fs_root)