Spaces:
Sleeping
Sleeping
| """Minimal output-schema validation for AI generators. | |
| A spec is a dict: field name -> rule dict with keys: | |
| type: "str" | "list" | |
| min_len / max_len: for str, character bounds; for list, item-count bounds | |
| count: exact list length (e.g. exactly 3 DM hooks) | |
| item_min / item_max: character bounds for each list item (str items) | |
| validate() returns a list of human-readable problems (empty = valid). | |
| Deliberately dependency-free so every Space stays light. | |
| """ | |
| def validate(data, spec) -> list[str]: | |
| problems = [] | |
| if not isinstance(data, dict): | |
| return [f"expected a JSON object, got {type(data).__name__}"] | |
| for field, rule in spec.items(): | |
| if field not in data: | |
| problems.append(f"missing field '{field}'") | |
| continue | |
| value = data[field] | |
| ftype = rule.get("type", "str") | |
| if ftype == "str": | |
| if not isinstance(value, str): | |
| problems.append(f"'{field}' must be a string") | |
| continue | |
| v = value.strip() | |
| if rule.get("min_len") and len(v) < rule["min_len"]: | |
| problems.append(f"'{field}' too short (min {rule['min_len']} chars)") | |
| if rule.get("max_len") and len(v) > rule["max_len"]: | |
| problems.append(f"'{field}' too long (max {rule['max_len']} chars)") | |
| elif ftype == "list": | |
| if not isinstance(value, list): | |
| problems.append(f"'{field}' must be a list") | |
| continue | |
| if "count" in rule and len(value) != rule["count"]: | |
| problems.append(f"'{field}' must have exactly {rule['count']} items") | |
| if rule.get("min_len") and len(value) < rule["min_len"]: | |
| problems.append(f"'{field}' needs at least {rule['min_len']} items") | |
| if rule.get("max_len") and len(value) > rule["max_len"]: | |
| problems.append(f"'{field}' allows at most {rule['max_len']} items") | |
| for i, item in enumerate(value): | |
| if not isinstance(item, str): | |
| problems.append(f"'{field}[{i}]' must be a string") | |
| continue | |
| if rule.get("item_min") and len(item.strip()) < rule["item_min"]: | |
| problems.append(f"'{field}[{i}]' too short") | |
| if rule.get("item_max") and len(item.strip()) > rule["item_max"]: | |
| problems.append(f"'{field}[{i}]' too long") | |
| return problems | |