dnd-initiative-tracker / src /shared /validation.py
Jordancole21's picture
Deploy native Gradio SEO page and tool
73e2d15 verified
Raw
History Blame Contribute Delete
2.47 kB
"""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