| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- """The cli for jupyter events."""
- from __future__ import annotations
- import json
- import pathlib
- import platform
- 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, EventSchemaFileAbsent, EventSchemaLoadingError
- WIN = platform.system() == "Windows"
- class RC:
- """Return code enum."""
- OK = 0
- INVALID = 1
- UNPARSABLE = 2
- NOT_FOUND = 3
- class EMOJI:
- """Terminal emoji enum"""
- X = "XX" if WIN else "\u274c"
- OK = "OK" if WIN else "\u2714"
- console = Console()
- error_console = Console(stderr=True)
- @click.group()
- @click.version_option()
- def main() -> None:
- """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
- """
- @click.command()
- @click.argument("schema")
- @click.pass_context
- def validate(ctx: click.Context, schema: str) -> int:
- """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"))
- _schema = None
- try:
- # attempt to read schema as a serialized string
- _schema = EventSchema._load_schema(schema)
- except EventSchemaLoadingError:
- # pass here to avoid printing traceback of this exception if next block
- # excepts
- pass
- # if not a serialized schema string, try to interpret it as a path to schema file
- if _schema is None:
- schema_path = pathlib.Path(schema)
- try:
- _schema = EventSchema._load_schema(schema_path)
- except (EventSchemaLoadingError, EventSchemaFileAbsent) as e:
- # no need for full tracestack for user error exceptions. just print
- # the error message and return
- error_console.print(f"[bold red]ERROR[/]: {e}")
- return ctx.exit(RC.UNPARSABLE)
- # 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(f"[green]{EMOJI.OK}[white] Nice work! This schema is valid.", (1, 0, 1, 0))
- console.print(out)
- return ctx.exit(RC.OK)
- except ValidationError as err:
- error_console.rule("Results", style=Style(color="red"))
- error_console.print(f"[red]{EMOJI.X} [white]The schema failed to validate.")
- error_console.print("\nWe found the following error with your schema:")
- out = escape(str(err)) # type:ignore[assignment]
- error_console.print(Padding(out, (1, 0, 1, 4)))
- return ctx.exit(RC.INVALID)
- main.add_command(validate)
|