# Global cache of JSON schema validators:
_validators: Dict[str, jsonschema.Draft7Validator] = {}
+# Draft7Validator is hardcoded, because _LATEST_VERSION is non-public in
+# jsonschema and we also perhaps do not want to upgrade automatically.
+
+
+def check_schema(schema: JSONSchema) -> bool:
+ """Check if the given JSON schema is valid."""
+ try:
+ jsonschema.Draft7Validator.check_schema(schema)
+ except jsonschema.exceptions.SchemaError:
+ return False
+ return True
+
+
+def register_schema(schema: JSONSchema) -> None:
+ """Register the given JSON schema in the global cache."""
+ global _validators
+ schema_string = json.dumps(schema)
+ if schema_string not in _validators:
+ _validators[schema_string] = jsonschema.Draft7Validator(schema)
+
+
+def validate(schema_string: str, value: MessageValue) -> bool:
+ """Validate the given MessageValue against the given JSON schema string."""
+ global _validators
+ if schema_string not in _validators:
+ schema = json.loads(schema_string)
+ _validators[schema_string] = jsonschema.Draft7Validator(schema)
+ validator = _validators[schema_string]
+ for error in validator.iter_errors(value):
+ return False
+ return True
class Message(Dict[str, MessageValue]):
TypeError: 'schema' is not a valid value in MessageTemplate
(not a valid JSON schema).
"""
- global _validators
if not isinstance(key, str):
raise TypeError(f"'{key}' is not a valid key in MessageTemplate"
" (not a string).")
- schema_string = json.dumps(value)
- if schema_string not in _validators:
- try:
- jsonschema.Draft7Validator.check_schema(value)
- # Draft7Validator is hardcoded, because _LATEST_VERSION is
- # non-public in jsonschema and we also perhaps do not want
- # to upgrade automatically.
- except jsonschema.exceptions.SchemaError:
- raise TypeError(f"'{value}' is not a valid value in"
- " MessageTemplate (not a valid JSON schema).")
- _validators[schema_string] = jsonschema.Draft7Validator(value)
+ if not check_schema(value):
+ raise TypeError(f"'{value}' is not a valid value in"
+ " MessageTemplate (not a valid JSON schema).")
+ register_schema(value)
super().__setitem__(key, value)
def update(self, *args, **kwargs) -> None:
return False
else:
schema_string = json.dumps(self[key])
- validator = _validators[schema_string]
- for error in validator.iter_errors(message[key]):
+ if not validate(schema_string, message[key]):
return False
return True
{'k1': 'v2', 'k2': 'v1'}: False
{'k1': 'v2', 'k2': 'v2'}: True
"""
- global _validators
if client in self._clients:
return True
for key in self._children:
if key in message:
for schema_string in self._children[key]:
- if schema_string not in _validators:
- schema = json.loads(schema_string)
- _validators[schema_string] = \
- jsonschema.Draft7Validator(schema)
- validator = _validators[schema_string]
- validated = True
- for error in validator.iter_errors(message[key]):
- validated = False
- if validated:
+ if validate(schema_string, message[key]):
child = self._children[key][schema_string]
if child.check(client, message):
return True
{'k1': 'v2', 'k2': 'v1'}: []
{'k1': 'v2', 'k2': 'v2'}: ['Client 2']
"""
- global _validators
result = []
for client in self._clients:
if client not in result:
for key in self._children:
if key in message:
for schema_string in self._children[key]:
- if schema_string not in _validators:
- schema = json.loads(schema_string)
- _validators[schema_string] = \
- jsonschema.Draft7Validator(schema)
- validator = _validators[schema_string]
- validated = True
- for error in validator.iter_errors(message[key]):
- validated = False
- if validated:
+ if validate(schema_string, message[key]):
child = self._children[key][schema_string]
for client in child.get(message):
if client not in result: