Coverage for src/jsoncrack_for_sphinx/config/config_parsing.py: 80%
96 statements
« prev ^ index » next coverage.py v7.10.0, created at 2025-07-24 22:26 +0000
« prev ^ index » next coverage.py v7.10.0, created at 2025-07-24 22:26 +0000
1"""
2Configuration parsing functions.
3"""
5from typing import Any, Dict
7from ..search.search_policy import SearchPolicy
8from ..utils.types import Directions, PathSeparator, RenderMode, Theme
9from .config_classes import ContainerConfig, RenderConfig
10from .config_main import JsonCrackConfig
13def parse_config(config_dict: Dict[str, Any]) -> JsonCrackConfig:
14 """Parse configuration dictionary into JsonCrackConfig object."""
16 # Handle Mock objects in tests
17 if not isinstance(config_dict, dict):
18 return JsonCrackConfig()
20 # Parse render config
21 render_config = None
22 if "render" in config_dict:
23 render_obj = config_dict["render"]
24 if isinstance(render_obj, RenderConfig):
25 render_config = render_obj
26 elif isinstance(render_obj, dict) and "mode" in render_obj:
27 # Legacy format support
28 mode_obj = render_obj["mode"]
29 if isinstance(mode_obj, str):
30 # Convert string to RenderMode object
31 if mode_obj == "onclick":
32 mode_obj = RenderMode.OnClick()
33 elif mode_obj == "onload":
34 mode_obj = RenderMode.OnLoad()
35 elif mode_obj == "onscreen":
36 threshold = render_obj.get("threshold", 0.1)
37 margin = render_obj.get("margin", "50px")
38 mode_obj = RenderMode.OnScreen(threshold=threshold, margin=margin)
39 else:
40 # Default to onclick for unknown modes
41 mode_obj = RenderMode.OnClick()
42 elif isinstance(mode_obj, dict) and "type" in mode_obj:
43 # Handle nested mode object
44 mode_type = mode_obj["type"]
45 if mode_type == "onclick":
46 mode_obj = RenderMode.OnClick()
47 elif mode_type == "onload":
48 mode_obj = RenderMode.OnLoad()
49 elif mode_type == "onscreen":
50 threshold = mode_obj.get("threshold", 0.1)
51 margin = mode_obj.get("margin", "50px")
52 mode_obj = RenderMode.OnScreen(threshold=threshold, margin=margin)
53 else:
54 # Default to onclick for unknown modes
55 mode_obj = RenderMode.OnClick()
56 else:
57 # Fallback for any other type
58 mode_obj = RenderMode.OnClick()
59 render_config = RenderConfig(mode_obj)
61 # Parse container config
62 container_config = None
63 if "container" in config_dict:
64 container_obj = config_dict["container"]
65 if isinstance(container_obj, ContainerConfig):
66 container_config = container_obj
67 elif isinstance(container_obj, dict):
68 # Legacy format support
69 direction_str = container_obj.get("direction", "RIGHT")
70 if isinstance(direction_str, str):
71 if direction_str == "LEFT":
72 direction = Directions.LEFT
73 elif direction_str == "RIGHT":
74 direction = Directions.RIGHT
75 elif direction_str == "TOP":
76 direction = Directions.TOP
77 elif direction_str == "DOWN":
78 direction = Directions.DOWN
79 else:
80 # Default to RIGHT for unknown directions
81 direction = Directions.RIGHT
82 else:
83 direction = direction_str
85 container_config = ContainerConfig(
86 direction=direction,
87 height=container_obj.get("height", "500"),
88 width=container_obj.get("width", "100%"),
89 )
91 # Parse search policy
92 search_policy = None
93 if "search_policy" in config_dict:
94 policy_obj = config_dict["search_policy"]
95 if isinstance(policy_obj, SearchPolicy):
96 search_policy = policy_obj
97 elif isinstance(policy_obj, dict):
98 # Parse from dictionary
99 include_package = policy_obj.get("include_package_name", False)
100 include_path = policy_obj.get("include_path_to_file", True)
102 # Parse path separators
103 path_to_file = policy_obj.get("path_to_file_separator", ".")
104 if isinstance(path_to_file, str):
105 if path_to_file == ".":
106 path_to_file = PathSeparator.DOT
107 elif path_to_file == "/":
108 path_to_file = PathSeparator.SLASH
109 elif path_to_file.lower() == "none":
110 path_to_file = PathSeparator.NONE
111 else:
112 path_to_file = PathSeparator.DOT
114 path_to_class = policy_obj.get("path_to_class_separator", ".")
115 if isinstance(path_to_class, str):
116 if path_to_class == ".":
117 path_to_class = PathSeparator.DOT
118 elif path_to_class == "/":
119 path_to_class = PathSeparator.SLASH
120 elif path_to_class.lower() == "none":
121 path_to_class = PathSeparator.NONE
122 else:
123 path_to_class = PathSeparator.DOT
125 custom_patterns = policy_obj.get("custom_patterns", [])
127 search_policy = SearchPolicy(
128 include_package_name=include_package,
129 include_path_to_file=include_path,
130 path_to_file_separator=path_to_file,
131 path_to_class_separator=path_to_class,
132 custom_patterns=custom_patterns,
133 )
135 # Parse theme
136 theme_obj = config_dict.get("theme", Theme.AUTO)
137 if isinstance(theme_obj, str):
138 if theme_obj == "light":
139 theme = Theme.LIGHT
140 elif theme_obj == "dark":
141 theme = Theme.DARK
142 elif theme_obj == "auto":
143 theme = Theme.AUTO
144 else:
145 theme = Theme.AUTO
146 else:
147 theme = theme_obj
149 return JsonCrackConfig(
150 render=render_config or RenderConfig(RenderMode.OnClick()),
151 container=container_config or ContainerConfig(),
152 theme=theme,
153 search_policy=search_policy or SearchPolicy(),
154 disable_autodoc=config_dict.get("disable_autodoc", False),
155 autodoc_ignore=config_dict.get("autodoc_ignore", []),
156 )