Coverage for jsonschema_diff/config_maker.py: 40%

55 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-09-15 18:01 +0000

1""" 

2Factory for a ready-to-use :class:`jsonschema_diff.core.Config` instance. 

3 

4All optional switches are enabled by default; pass ``False`` to disable. 

5""" 

6 

7from dataclasses import dataclass 

8from enum import Enum 

9 

10from .core import Compare, Config 

11from .core.custom_compare import CompareList, CompareRange 

12from .core.tools.combine import COMBINE_RULES_TYPE 

13from .core.tools.compare import COMPARE_RULES_TYPE 

14from .core.tools.context import CONTEXT_RULES_TYPE, PAIR_CONTEXT_RULES_TYPE 

15from .core.tools.render import PATH_MAKER_IGNORE_RULES_TYPE 

16 

17 

18@dataclass(frozen=True) 

19class MultilineChars: 

20 START_LINE: str 

21 MIDDLE_LINE: str 

22 END_LINE: str 

23 SINGLE_LINE: str 

24 

25 

26class MultilineListRender(Enum): 

27 Soft = MultilineChars("╭", "│", "╰", " ") 

28 Hard = MultilineChars("┌", "│", "└", " ") 

29 Double = MultilineChars("╔", "║", "╚", " ") 

30 Without = MultilineChars(" ", " ", " ", " ") 

31 

32 

33class ConfigMaker: 

34 """Helper that builds a fully populated :class:`~jsonschema_diff.core.Config`.""" 

35 

36 # pylint: disable=too-many-arguments 

37 @staticmethod 

38 def make( 

39 *, 

40 tab_size: int = 1, 

41 all_for_rendering: bool = False, 

42 crop_path: bool = True, 

43 path_render_with_properies: bool = False, 

44 path_render_with_items: bool = False, 

45 list_comparator: bool = True, 

46 list_multiline_render: MultilineListRender = MultilineListRender.Soft, 

47 range_digit_comparator: bool = True, 

48 range_length_comparator: bool = True, 

49 range_items_comparator: bool = True, 

50 range_properties_comparator: bool = True, 

51 additional_compare_rules: COMPARE_RULES_TYPE = {}, 

52 additional_combine_rules: COMBINE_RULES_TYPE = [], 

53 additional_pair_context_rules: PAIR_CONTEXT_RULES_TYPE = [], 

54 additional_context_rules: CONTEXT_RULES_TYPE = {}, 

55 additional_path_maker_ignore: PATH_MAKER_IGNORE_RULES_TYPE = [], 

56 ) -> Config: 

57 """ 

58 Assemble and return a :class:`~jsonschema_diff.core.Config`. 

59 

60 Parameters 

61 ---------- 

62 tab_size : int 

63 Number of spaces per indentation level. 

64 path_render_with_properies, path_render_with_items : bool 

65 Include these schema service tokens in rendered paths. 

66 list_comparator : bool 

67 Enable :class:`~jsonschema_diff.core.custom_compare.CompareList`. 

68 list_multiline_render : MultilineListRender 

69 How to render multi-line elements of list. 

70 range_*_comparator : bool 

71 Enable :class:`~jsonschema_diff.core.custom_compare.CompareRange` 

72 for numeric/length/items/properties limits. 

73 additional_* : collections 

74 User-supplied rules that override the built-ins. 

75 """ 

76 tab = " " * tab_size 

77 

78 compare_rules: COMPARE_RULES_TYPE = {} 

79 combine_rules: COMBINE_RULES_TYPE = [] 

80 pair_context_rules: list[list[str | type[Compare]]] = [] 

81 context_rules: dict[str | type[Compare], list[str | type[Compare]]] = {} 

82 path_maker_ignore: list[str] = [] 

83 compare_config: dict[type[Compare], dict] = {} 

84 

85 # Built-in comparators 

86 if list_comparator: 

87 compare_rules[list] = CompareList 

88 compare_config[CompareList] = { 

89 field: getattr(list_multiline_render.value, field) 

90 for field in list_multiline_render.value.__dataclass_fields__ 

91 } 

92 

93 def add_rule(keys: list[str], value: type[Compare]) -> None: 

94 combine_rules.append(keys) 

95 for key in keys: 

96 compare_rules[key] = value 

97 

98 ranger = CompareRange 

99 if range_digit_comparator: 

100 add_rule(["minimum", "maximum", "exclusiveMinimum", "exclusiveMaximum"], ranger) 

101 if range_length_comparator: 

102 add_rule(["minLength", "maxLength"], ranger) 

103 if range_items_comparator: 

104 add_rule(["minItems", "maxItems"], ranger) 

105 if range_properties_comparator: 

106 add_rule(["minProperties", "maxProperties"], ranger) 

107 

108 # Path-render filters 

109 if not path_render_with_properies: 

110 path_maker_ignore.append("properties") 

111 if not path_render_with_items: 

112 path_maker_ignore.append("items") 

113 

114 # User additions override defaults 

115 compare_rules.update(additional_compare_rules) 

116 combine_rules.extend(additional_combine_rules) 

117 pair_context_rules.extend([list(r) for r in additional_pair_context_rules]) 

118 context_rules.update({k: list(v) for k, v in additional_context_rules.items()}) 

119 path_maker_ignore.extend(additional_path_maker_ignore) 

120 

121 return Config( 

122 tab=tab, 

123 all_for_rendering=all_for_rendering, 

124 crop_path=crop_path, 

125 compare_rules=compare_rules, 

126 combine_rules=combine_rules, 

127 path_maker_ignore=path_maker_ignore, 

128 pair_context_rules=pair_context_rules, 

129 context_rules=context_rules, 

130 compare_config=compare_config, 

131 )