Gracefully parse options from different formats. Handles: - Dict format (correct): {"key": "value", "key2": "value2"} - String format (common mistake): "key=value,key=value" - None: returns empty dict Args: options: Options in dict format, string format, or
(options: Union[Dict[str, Any], str, None])
| 322 | # --- Internal Helper Functions --- |
| 323 | |
| 324 | def _parse_options_gracefully(options: Union[Dict[str, Any], str, None]) -> Dict[str, Any]: |
| 325 | """ |
| 326 | Gracefully parse options from different formats. |
| 327 | |
| 328 | Handles: |
| 329 | - Dict format (correct): {"key": "value", "key2": "value2"} |
| 330 | - String format (common mistake): "key=value,key=value" |
| 331 | - None: returns empty dict |
| 332 | |
| 333 | Args: |
| 334 | options: Options in dict format, string format, or None |
| 335 | |
| 336 | Returns: |
| 337 | Dictionary of parsed options |
| 338 | |
| 339 | Raises: |
| 340 | ValueError: If string format is malformed |
| 341 | """ |
| 342 | if options is None: |
| 343 | return {} |
| 344 | |
| 345 | if isinstance(options, dict): |
| 346 | # Already correct format |
| 347 | return options |
| 348 | |
| 349 | if isinstance(options, str): |
| 350 | # Handle the common mistake format: "key=value,key=value" |
| 351 | if not options.strip(): |
| 352 | return {} |
| 353 | |
| 354 | logger.info(f"Converting string format options to dict: {options}") |
| 355 | parsed_options = {} |
| 356 | |
| 357 | try: |
| 358 | # Split by comma and then by equals |
| 359 | pairs = [pair.strip() for pair in options.split(',') if pair.strip()] |
| 360 | for pair in pairs: |
| 361 | if '=' not in pair: |
| 362 | raise ValueError(f"Invalid option format: '{pair}' (missing '=')") |
| 363 | |
| 364 | key, value = pair.split('=', 1) # Split only on first '=' |
| 365 | key = key.strip() |
| 366 | value = value.strip() |
| 367 | |
| 368 | # Validate key is not empty |
| 369 | if not key: |
| 370 | raise ValueError(f"Invalid option format: '{pair}' (empty key)") |
| 371 | |
| 372 | # Remove quotes if they wrap the entire value |
| 373 | if (value.startswith('"') and value.endswith('"')) or \ |
| 374 | (value.startswith("'") and value.endswith("'")): |
| 375 | value = value[1:-1] |
| 376 | |
| 377 | # Basic type conversion |
| 378 | if value.lower() in ('true', 'false'): |
| 379 | value = value.lower() == 'true' |
| 380 | elif value.isdigit(): |
| 381 | try: |
no outgoing calls