Skip to content

Commit

Permalink
Merge pull request #9 from Zsailer/cli
Browse files Browse the repository at this point in the history
Add a simple CLI tool for validating event schemas
  • Loading branch information
Zsailer authored Aug 29, 2022
2 parents fe79540 + 0101fcb commit 6d22b7d
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 7 deletions.
70 changes: 70 additions & 0 deletions docs/user_guide/defining-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,73 @@ required:
- thing
- user
```
## Checking if a schema is valid
When authoring a schema, how do you check if you schema is following the expected form? Jupyter Events offers a simple command line tool to validate your schema against its Jupyter Events metaschema.
First, install the CLI:
```
pip install jupyter_events[cli]
```

Then, run the CLI against your schema:

```
jupyter events validate path/to/my_schema.json
```

The output will look like this, if it passes:

```
──────────────────────────────────── Validating the following schema ────────────────────────────────────
{
"$id": "http://event.jupyter.org/test",
"version": 1,
"title": "Simple Test Schema",
"description": "A simple schema for testing\n",
"type": "object",
"properties": {
"prop": {
"title": "Test Property",
"description": "Test property.",
"type": "string"
}
}
}
──────────────────────────────────────────────── Results ────────────────────────────────────────────────
✔ Nice work! This schema is valid.
```

or this if fails:

```
──────────────────────────────────── Validating the following schema ────────────────────────────────────
{
"$id": "http://event.jupyter.org/test",
"version": 1,
"title": "Simple Test Schema",
"description": "A simple schema for testing\n",
"type": "object",
"properties": {
"__badName": {
"title": "Test Property",
"description": "Test property.",
"type": "string"
}
}
}
──────────────────────────────────────────────── Results ────────────────────────────────────────────────
❌ The schema failed to validate.
We found the following error with your schema:
'__badName' is an invalid property name because it starts with `__`. Properties starting with
'dunder' are reserved as special meta-fields for Jupyter Events to use.
```
62 changes: 62 additions & 0 deletions jupyter_events/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import json
import pathlib

import click
from jsonschema import ValidationError
from rich.console import Console
from rich.json import JSON
from rich.markup import escape
from rich.padding import Padding
from rich.style import Style

from jupyter_events.schema import EventSchema, EventSchemaLoadingError

console = Console()


@click.group()
def main():
"""A simple CLI tool to quickly validate JSON schemas against
Jupyter Event's custom validator.
You can see Jupyter Event's meta-schema here:
https://raw.githubusercontent.com/jupyter/jupyter_events/main/jupyter_events/schemas/event-metaschema.yml
"""
pass


@click.command()
@click.argument("schema")
def validate(schema):
"""Validate a SCHEMA against Jupyter Event's meta schema.
SCHEMA can be a JSON/YAML string or filepath to a schema.
"""
console.rule("Validating the following schema", style=Style(color="blue"))
# Soft load the schema without validating.
try:
_schema = EventSchema._load_schema(schema)
except EventSchemaLoadingError:
schema_path = pathlib.Path(schema)
_schema = EventSchema._load_schema(schema_path)
# Print what was found.
schema_json = JSON(json.dumps(_schema))
console.print(Padding(schema_json, (1, 0, 1, 4)))
# Now validate this schema against the meta-schema.
try:
EventSchema(_schema)
console.rule("Results", style=Style(color="green"))
out = Padding(
"[green]\u2714[white] Nice work! This schema is valid.", (1, 0, 1, 0)
)
console.print(out)
except ValidationError as err:
console.rule("Results", style=Style(color="red"))
console.print("[red]\u274c [white]The schema failed to validate.\n")
console.print("We found the following error with your schema:")
out = escape(str(err))
console.print(Padding(out, (1, 0, 1, 4)))


main.add_command(validate)
5 changes: 3 additions & 2 deletions jupyter_events/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,11 @@ def add_listener(
Parameters
----------
modified: bool
If True (default), listens to the data after it has been mutated/modified
by the list of modifiers.
schema_id: str
$id of the schema
version: str
The schema version
listener: Callable
A callable function/method that executes when the named event occurs.
"""
Expand Down
4 changes: 1 addition & 3 deletions jupyter_events/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ def __init__(
self._schema = _schema

def __repr__(self):
out = f"Validator class: {self._validator.__class__.__name__}\n"
out += f"Schema: {json.dumps(self._schema, indent=2)}"
return out
return json.dumps(self._schema, indent=2)

@staticmethod
def _load_schema(schema: Union[dict, str, PurePath]) -> dict:
Expand Down
5 changes: 3 additions & 2 deletions jupyter_events/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ def validate_schema(schema: dict):
except ValidationError as err:
reserved_property_msg = " does not match '^(?!__.*)'"
if reserved_property_msg in str(err):
bad_property = str(err)[: -(len(reserved_property_msg))]
idx = str(err).find(reserved_property_msg)
bad_property = str(err)[:idx].strip()
raise ValidationError(
f"{bad_property} is an invalid property name because it "
"starts with `__`. Properties starting with 'dunder' "
"are reserved for Jupyter Events."
"are reserved as special meta-fields for Jupyter Events to use."
)
raise err
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,20 @@ file = 'COPYING.md'
[project.urls]
Homepage = "http://jupyter.org"

[project.scripts]
jupyter-events = "jupyter_events.cli:main"

[project.optional-dependencies]
test = [
"coverage",
"pre-commit",
"pytest-cov",
"pytest>=6.0",
]
cli = [
"click",
"rich"
]

[tool.hatch.version]
path = "jupyter_events/_version.py"
Expand Down

0 comments on commit 6d22b7d

Please sign in to comment.