You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
3.0 KiB
Python
87 lines
3.0 KiB
Python
"""Event validators."""
|
|
from __future__ import annotations
|
|
|
|
import pathlib
|
|
import warnings
|
|
from typing import Any
|
|
|
|
import jsonschema
|
|
from jsonschema import Draft7Validator, ValidationError
|
|
from referencing import Registry
|
|
from referencing.jsonschema import DRAFT7
|
|
|
|
from . import yaml
|
|
from .utils import JupyterEventsVersionWarning
|
|
|
|
draft7_format_checker = (
|
|
Draft7Validator.FORMAT_CHECKER
|
|
if hasattr(Draft7Validator, "FORMAT_CHECKER")
|
|
else jsonschema.draft7_format_checker
|
|
)
|
|
|
|
|
|
METASCHEMA_PATH = pathlib.Path(__file__).parent.joinpath("schemas")
|
|
|
|
EVENT_METASCHEMA_FILEPATH = METASCHEMA_PATH.joinpath("event-metaschema.yml")
|
|
EVENT_METASCHEMA = yaml.load(EVENT_METASCHEMA_FILEPATH)
|
|
|
|
EVENT_CORE_SCHEMA_FILEPATH = METASCHEMA_PATH.joinpath("event-core-schema.yml")
|
|
EVENT_CORE_SCHEMA = yaml.load(EVENT_CORE_SCHEMA_FILEPATH)
|
|
|
|
PROPERTY_METASCHEMA_FILEPATH = METASCHEMA_PATH.joinpath("property-metaschema.yml")
|
|
PROPERTY_METASCHEMA = yaml.load(PROPERTY_METASCHEMA_FILEPATH)
|
|
|
|
SCHEMA_STORE = {
|
|
EVENT_METASCHEMA["$id"]: EVENT_METASCHEMA,
|
|
PROPERTY_METASCHEMA["$id"]: PROPERTY_METASCHEMA,
|
|
EVENT_CORE_SCHEMA["$id"]: EVENT_CORE_SCHEMA,
|
|
}
|
|
|
|
resources = [
|
|
DRAFT7.create_resource(each)
|
|
for each in (EVENT_METASCHEMA, PROPERTY_METASCHEMA, EVENT_CORE_SCHEMA)
|
|
]
|
|
METASCHEMA_REGISTRY: Registry[Any] = resources @ Registry()
|
|
|
|
JUPYTER_EVENTS_SCHEMA_VALIDATOR = Draft7Validator(
|
|
schema=EVENT_METASCHEMA,
|
|
registry=METASCHEMA_REGISTRY,
|
|
format_checker=draft7_format_checker,
|
|
)
|
|
|
|
JUPYTER_EVENTS_CORE_VALIDATOR = Draft7Validator(
|
|
schema=EVENT_CORE_SCHEMA,
|
|
registry=METASCHEMA_REGISTRY,
|
|
format_checker=draft7_format_checker,
|
|
)
|
|
|
|
|
|
def validate_schema(schema: dict[str, Any]) -> None:
|
|
"""Validate a schema dict."""
|
|
try:
|
|
# If the `version` attribute is an integer, coerce to string.
|
|
# TODO: remove this in a future version.
|
|
if "version" in schema and isinstance(schema["version"], int):
|
|
schema["version"] = str(schema["version"])
|
|
msg = (
|
|
"The `version` property of an event schema must be a string. "
|
|
"It has been type coerced, but in a future version of this "
|
|
"library, it will fail to validate. Please update schema: "
|
|
f"{schema['$id']}"
|
|
)
|
|
warnings.warn(JupyterEventsVersionWarning(msg), stacklevel=2)
|
|
# Validate the schema against Jupyter Events metaschema.
|
|
JUPYTER_EVENTS_SCHEMA_VALIDATOR.validate(schema)
|
|
except ValidationError as err:
|
|
reserved_property_msg = " does not match '^(?!__.*)'"
|
|
if reserved_property_msg in str(err):
|
|
idx = str(err).find(reserved_property_msg)
|
|
bad_property = str(err)[:idx].strip()
|
|
msg = (
|
|
f"{bad_property} is an invalid property name because it "
|
|
"starts with `__`. Properties starting with 'dunder' "
|
|
"are reserved as special meta-fields for Jupyter Events to use."
|
|
)
|
|
raise ValidationError(msg) from err
|
|
raise err
|