Coverage for jsonschema_diff/core/parameter_base.py: 91%
46 statements
« prev ^ index » next coverage.py v7.10.5, created at 2025-08-25 07:00 +0000
« prev ^ index » next coverage.py v7.10.5, created at 2025-08-25 07:00 +0000
1from typing import TYPE_CHECKING, Any, TypeAlias
3from .abstraction import Statuses, ToCompare
4from .tools.render import RenderTool
6if TYPE_CHECKING:
7 from .config import Config
9COMPARE_PATH_TYPE: TypeAlias = list[str | int]
10LEGEND_PROCESSOR_TYPE: TypeAlias = dict[str, Any]
11LEGEND_RETURN_TYPE: TypeAlias = dict[
12 str, str | LEGEND_PROCESSOR_TYPE | list[str | LEGEND_PROCESSOR_TYPE]
13]
16class Compare:
17 def __init__(
18 self,
19 config: "Config",
20 schema_path: COMPARE_PATH_TYPE,
21 json_path: COMPARE_PATH_TYPE,
22 to_compare: list[ToCompare],
23 ):
24 self.status = Statuses.UNKNOWN
26 self.config = config
27 self.schema_path = schema_path
28 self.json_path = json_path
30 if len(to_compare) <= 0:
31 raise ValueError("Cannot compare empty list")
32 self.to_compare = to_compare
34 def compare(self) -> Statuses:
35 if len(self.to_compare) > 1:
36 raise ValueError("Unsupported multiple compare for base logic")
38 self.status = self.to_compare[0].status
39 self.key = self.to_compare[0].key
40 self.value = self.to_compare[0].value
41 self.old_value = self.to_compare[0].old_value
42 self.new_value = self.to_compare[0].new_value
43 return self.status
45 def get_name(self) -> str:
46 return self.to_compare[0].key
48 def is_for_rendering(self) -> bool:
49 return self.status in [
50 Statuses.ADDED,
51 Statuses.DELETED,
52 Statuses.REPLACED,
53 Statuses.MODIFIED,
54 ]
56 def _render_start_line(
57 self, tab_level: int = 0, with_path: bool = True, with_key: bool = True
58 ) -> str:
59 to_return = (
60 f"{RenderTool.make_prefix(self.status)} {RenderTool.make_tab(self.config, tab_level)}"
61 )
62 if with_path:
63 to_return += RenderTool.make_path(
64 self.schema_path, self.json_path, ignore=self.config.PATH_MAKER_IGNORE
65 )
67 if with_key:
68 to_return += f".{self.get_name()}"
69 return to_return + ":"
71 def render(self, tab_level: int = 0, with_path: bool = True) -> str:
72 to_return = self._render_start_line(tab_level=tab_level, with_path=with_path)
74 if self.status in [Statuses.ADDED, Statuses.DELETED, Statuses.NO_DIFF]:
75 to_return += f" {self.value}"
76 elif self.status == Statuses.REPLACED:
77 to_return += f" {self.old_value} -> {self.new_value}"
78 else:
79 raise ValueError(f"Unsupported for render status: {self.status}")
81 return to_return
83 @staticmethod
84 def legend() -> LEGEND_RETURN_TYPE:
85 return {
86 "element": [
87 Statuses.ADDED.value,
88 Statuses.DELETED.value,
89 Statuses.REPLACED.value,
90 Statuses.MODIFIED.value,
91 Statuses.NO_DIFF.value,
92 Statuses.UNKNOWN.value,
93 ],
94 "description": [
95 Statuses.ADDED.name,
96 Statuses.DELETED.name,
97 Statuses.REPLACED.name,
98 Statuses.MODIFIED.name,
99 Statuses.NO_DIFF.name,
100 Statuses.UNKNOWN.name,
101 ],
102 "example": [
103 {"old_value": {}, "new_value": {"added_key": "value"}},
104 {"old_value": {"deleted_key": "value"}, "new_value": {}},
105 {
106 "old_value": {"replaced_key": "old-value"},
107 "new_value": {"replaced_key": "new-value"},
108 },
109 {
110 "old_value": {"modified_key": []},
111 "new_value": {"modified_key": ["value"]},
112 },
113 {
114 "old_value": {"no_diff_key": "value"},
115 "new_value": {"no_diff_key": "value"},
116 },
117 ],
118 }