You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

74 lines
2.7 KiB

  1. """ A minimal jsonschema validator.
  2. Supports only a tiny subset of jsonschema.
  3. """
  4. from datetime import datetime
  5. from hc.lib.cronsim import CronSim
  6. from pytz import all_timezones
  7. class ValidationError(Exception):
  8. pass
  9. def validate(obj, schema, obj_name="value"):
  10. if schema.get("type") == "string":
  11. if not isinstance(obj, str):
  12. raise ValidationError("%s is not a string" % obj_name)
  13. if "minLength" in schema and len(obj) < schema["minLength"]:
  14. raise ValidationError("%s is too short" % obj_name)
  15. if "maxLength" in schema and len(obj) > schema["maxLength"]:
  16. raise ValidationError("%s is too long" % obj_name)
  17. if schema.get("format") == "cron":
  18. try:
  19. # Does it have 5 components?
  20. if len(obj.split()) != 5:
  21. raise ValueError()
  22. # Does cronsim accept the schedule?
  23. it = CronSim(obj, datetime(2000, 1, 1))
  24. # Can it calculate the next datetime?
  25. next(it)
  26. except:
  27. raise ValidationError("%s is not a valid cron expression" % obj_name)
  28. if schema.get("format") == "timezone" and obj not in all_timezones:
  29. raise ValidationError("%s is not a valid timezone" % obj_name)
  30. elif schema.get("type") == "number":
  31. if not isinstance(obj, int):
  32. raise ValidationError("%s is not a number" % obj_name)
  33. if "minimum" in schema and obj < schema["minimum"]:
  34. raise ValidationError("%s is too small" % obj_name)
  35. if "maximum" in schema and obj > schema["maximum"]:
  36. raise ValidationError("%s is too large" % obj_name)
  37. elif schema.get("type") == "boolean":
  38. if not isinstance(obj, bool):
  39. raise ValidationError("%s is not a boolean" % obj_name)
  40. elif schema.get("type") == "array":
  41. if not isinstance(obj, list):
  42. raise ValidationError("%s is not an array" % obj_name)
  43. for v in obj:
  44. validate(v, schema["items"], "an item in '%s'" % obj_name)
  45. elif schema.get("type") == "object":
  46. if not isinstance(obj, dict):
  47. raise ValidationError("%s is not an object" % obj_name)
  48. properties = schema.get("properties", {})
  49. for key, spec in properties.items():
  50. if key in obj:
  51. validate(obj[key], spec, obj_name=key)
  52. for key in schema.get("required", []):
  53. if key not in obj:
  54. raise ValidationError("key %s absent in %s" % (key, obj_name))
  55. if "enum" in schema:
  56. if obj not in schema["enum"]:
  57. raise ValidationError("%s has unexpected value" % obj_name)