fix: parse dict strings from Robot Framework in ConfigUpdate
Robot Framework's Create Dictionary converts nested dicts like {'enabled': False} to string representation. Parse these strings before Pydantic validation. Also handle Pydantic models passed directly from unit tests.
This commit is contained in:
@@ -289,6 +289,59 @@ class ConfigUpdate(BaseModel):
|
||||
scan_key_overrides: Optional[Dict[str, str]] = None
|
||||
other: Optional[Dict[str, Any]] = None
|
||||
|
||||
@classmethod
|
||||
def _parse_dict_field(cls, v):
|
||||
"""Parse a field that may arrive as a malformed string from Robot Framework.
|
||||
|
||||
Robot Framework's Create Dictionary converts Python-style nested dicts
|
||||
like {'enabled': False} into their string representation. Handle that here
|
||||
before Pydantic's type validation runs. Also handles Pydantic models being
|
||||
passed directly (from unit tests).
|
||||
"""
|
||||
# Pydantic model - convert to dict first
|
||||
if hasattr(v, 'model_dump'):
|
||||
return v.model_dump()
|
||||
if hasattr(v, 'dict'):
|
||||
return v.dict()
|
||||
# Already a dict
|
||||
if isinstance(v, dict):
|
||||
return v
|
||||
# String - try parsing
|
||||
if isinstance(v, str):
|
||||
for parse_fn in (json.loads, ast.literal_eval):
|
||||
try:
|
||||
parsed = parse_fn(v)
|
||||
if isinstance(parsed, dict):
|
||||
return parsed
|
||||
except Exception:
|
||||
pass
|
||||
return v
|
||||
|
||||
@model_validator(mode="before")
|
||||
@classmethod
|
||||
def _pre_validate(cls, data):
|
||||
"""Handle malformed dict strings from Robot Framework and Pydantic models passed directly.
|
||||
|
||||
Robot Framework's Create Dictionary converts Python-style nested dicts
|
||||
like {'enabled': False} into their string representation.
|
||||
Unit tests may pass Pydantic model instances directly.
|
||||
Both cases need conversion before type validation.
|
||||
"""
|
||||
if isinstance(data, dict):
|
||||
data = dict(data) # make mutable
|
||||
for field in ("name", "data_dir", "scheduler", "logging", "backup", "nfo", "scan_key_overrides", "other"):
|
||||
if field in data:
|
||||
v = data[field]
|
||||
# Pydantic model - convert to dict
|
||||
if hasattr(v, "model_dump"):
|
||||
data[field] = v.model_dump()
|
||||
# String from Robot Framework - try parsing
|
||||
elif isinstance(v, str):
|
||||
parsed = cls._parse_dict_field(v)
|
||||
if isinstance(parsed, dict):
|
||||
data[field] = parsed
|
||||
return data
|
||||
|
||||
def apply_to(self, current: AppConfig) -> AppConfig:
|
||||
"""Return a new AppConfig with updates applied to the current config.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user