boilerplate code.
"""
import asyncio
-import jsonschema # type: ignore
+import fastjsonschema # type: ignore
from controlpi.messagebus import (MessageBus, BusException,
Message, MessageTemplate)
def _process_conf(message_bus: MessageBus,
conf: Dict[str, PluginConf]) -> List[Coroutine]:
- jsonschema.Draft7Validator.check_schema(CONF_SCHEMA)
- validator = jsonschema.Draft7Validator(CONF_SCHEMA)
- valid = True
- for error in validator.iter_errors(conf):
- print(error)
- valid = False
- if not valid:
+ try:
+ conf = fastjsonschema.validate(CONF_SCHEMA, conf)
+ except fastjsonschema.JsonSchemaException as e:
+ print(f"Configuration not valid:\n{e.message}")
return []
plugins = PluginRegistry('controlpi_plugins', BasePlugin)
coroutines = [message_bus.run()]
from abc import ABC, abstractmethod
import asyncio
-import jsonschema # type: ignore
+import fastjsonschema # type: ignore
from controlpi.messagebus import MessageBus
-from typing import Union, Dict, List, Any, Optional
+from typing import Union, Dict, List, Any, Optional, Callable
JSONSchema = Union[bool, Dict[str, Union[None, str, int, float, bool,
Dict[str, Any], List[Any]]]]
# Could be more specific.
CONF_SCHEMA: JSONSchema = False
- _validator: Optional[jsonschema.Draft7Validator] = None
+ _validate: Optional[Callable[[PluginConf], PluginConf]] = None
def __init__(self, bus: MessageBus, name: str, conf: PluginConf) -> None:
# noqa: D107
self.bus = bus
self.name = name
- if not type(self)._validator:
- jsonschema.Draft7Validator.check_schema(type(self).CONF_SCHEMA)
- type(self)._validator = \
- jsonschema.Draft7Validator(type(self).CONF_SCHEMA)
- validator = type(self)._validator
- assert isinstance(validator, jsonschema.Draft7Validator)
- valid = True
- for error in validator.iter_errors(conf):
- print(error)
- valid = False
- if not valid:
+ if not type(self)._validate:
+ type(self)._validate = \
+ fastjsonschema.compile(type(self).CONF_SCHEMA)
+ self.conf = {}
+ validate = type(self)._validate
+ assert validate is not None
+ try:
+ self.conf = validate(conf)
+ except fastjsonschema.JsonSchemaException as e:
+ print(e.message)
raise ConfException(f"Configuration for '{self.name}'"
" is not valid.")
- self.conf = conf
self.process_conf()
@abstractmethod
"""
import asyncio
import json
-import jsonschema # type: ignore
+import fastjsonschema # type: ignore
import sys
from typing import Union, Dict, List, Any, Iterable, Callable, Coroutine
MessageCallback = Callable[['Message'], Coroutine[Any, Any, None]]
-# 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.
+# Global cache of JSON schema validation functions:
+_validates: Dict[str, Callable[[MessageValue], MessageValue]] = {}
-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:
+def register_schema(schema: JSONSchema) -> bool:
"""Register the given JSON schema in the global cache."""
- global _validators
+ global _validates
schema_string = json.dumps(schema)
- if schema_string not in _validators:
- _validators[schema_string] = jsonschema.Draft7Validator(schema)
+ if schema_string not in _validates:
+ if not (isinstance(schema, dict) or isinstance(schema, bool)):
+ return False
+ try:
+ _validates[schema_string] = fastjsonschema.compile(schema)
+ except fastjsonschema.JsonSchemaDefinitionException:
+ return False
+ return True
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:
+ global _validates
+ if schema_string not in _validates:
schema = json.loads(schema_string)
- _validators[schema_string] = jsonschema.Draft7Validator(schema)
- validator = _validators[schema_string]
- for error in validator.iter_errors(value):
+ _validates[schema_string] = fastjsonschema.compile(schema)
+ validate = _validates[schema_string]
+ try:
+ validate(value)
+ except fastjsonschema.JsonSchemaException:
return False
return True
...
TypeError: 'schema' is not a valid value in MessageTemplate
(not a valid JSON schema).
+ >>> t['key'] = True
"""
if not isinstance(key, str):
raise TypeError(f"'{key}' is not a valid key in MessageTemplate"
" (not a string).")
- if not check_schema(value):
+ if not register_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:
...
TypeError: 'schema' is not a valid value in MessageTemplate
(not a valid JSON schema).
+ >>> t.update({'key': True})
This is also used in __init__:
>>> t = MessageTemplate({'key 1': {'const': 'value'},
...
TypeError: 'schema' is not a valid value in MessageTemplate
(not a valid JSON schema).
+ >>> t = MessageTemplate({'key': True})
"""
if args:
if len(args) > 1: