"""jsonschema_diff CLI===================A tiny command-line front-end around :py:mod:`jsonschema_diff`that highlights semantic differences between two JSON-Schemadocuments directly in your terminal.Typical usage------------->>> jsonschema-diff old.schema.json new.schema.json>>> jsonschema-diff --no-color --legend old.json new.json>>> jsonschema-diff --exit-code old.json new.json # useful in CIExit status-----------* **0** – the two schemas are semantically identical* **1** – at least one difference was detected (only when ``--exit-code`` is given)The CLI is intentionally minimal: *all* comparison options are takenfrom :pyclass:`jsonschema_diff.ConfigMaker`, so the behaviour staysin sync with the library defaults."""from__future__importannotationsimportargparseimportjsonimportsysfromjsonschema_diffimportConfigMaker,JsonSchemaDifffromjsonschema_diff.colorimportHighlighterPipelinefromjsonschema_diff.color.stagesimport(MonoLinesHighlighter,PathHighlighter,ReplaceGenericHighlighter,)fromjsonschema_diff.core.parameter_baseimportComparedef_make_highlighter(disable_color:bool)->HighlighterPipeline:""" Create the high-lighting pipeline used to colorise diff output. Parameters ---------- disable_color : When *True* ANSI escape sequences are suppressed even if the invoking TTY advertises color support (e.g. when piping the output into a file). Returns ------- HighlighterPipeline Either an **empty** pipeline (no colour) or the standard three-stage pipeline consisting of :class:`~jsonschema_diff.color.stages.MonoLinesHighlighter`, :class:`~jsonschema_diff.color.stages.ReplaceGenericHighlighter` and :class:`~jsonschema_diff.color.stages.PathHighlighter`. Note ----- The composition of the *default* pipeline mirrors what the core library exposes; duplicating the stages here keeps the CLI fully self-contained while allowing future customisation. Examples -------- >>> _make_highlighter(True) HighlighterPipeline(stages=[]) >>> _make_highlighter(False).stages # doctest: +ELLIPSIS [<jsonschema_diff.color.stages.MonoLinesHighlighter ...>, ...] """ifdisable_color:returnHighlighterPipeline([])returnHighlighterPipeline([MonoLinesHighlighter(),ReplaceGenericHighlighter(),PathHighlighter(),])def_build_parser()->argparse.ArgumentParser:""" Construct the :pyclass:`argparse.ArgumentParser` for the CLI. Returns ------- argparse.ArgumentParser The fully configured parser containing positional arguments for the *old* and *new* schema paths, together with three optional feature flags. See Also -------- * :pyfunc:`main` – where the parser is consumed. * The *argparse* documentation for available formatting options. """p=argparse.ArgumentParser(prog="jsonschema-diff",description="Show the difference between two JSON-Schema files",)# Positional argumentsp.add_argument("old_schema",help="Path to the *old* schema")p.add_argument("new_schema",help="Path to the *new* schema")# Output optionsp.add_argument("--no-color",action="store_true",help="Disable ANSI colors even if the terminal supports them",)p.add_argument("--legend",action="store_true",help="Print a legend explaining diff symbols at the end",)# Exit-code controlp.add_argument("--exit-code",action="store_true",help="Return **1** if differences are detected, otherwise **0**",)returnp
[docs]defmain(argv:list[str]|None=None)->None:# pragma: no cover""" CLI entry-point (invoked by ``python -m jsonschema_diff`` or by the ``jsonschema-diff`` console script). Parameters ---------- argv : Command-line argument vector **excluding** the executable name. When *None* (default) ``sys.argv[1:]`` is used – this is the behaviour required by *setuptools* console-scripts. Note ---- The function performs four sequential steps: 1. Build a :class:`JsonSchemaDiff` instance. 2. Compare the two user-supplied schema files. 3. Print a colourised diff (optionally with a legend). 4. Optionally exit with code 1 if differences are present. """args=_build_parser().parse_args(argv)# 1. Build the wrapper objectdiff=JsonSchemaDiff(config=ConfigMaker.make(),colorize_pipeline=_make_highlighter(args.no_color),legend_ignore=[Compare],# as in the library example)deftry_load(data:str)->dict|str:try:returndict(json.loads(data))exceptjson.JSONDecodeError:returnstr(data)# 2. Compare the filesdiff.compare(old_schema=try_load(args.old_schema),new_schema=try_load(args.new_schema),)# 3. Print the resultdiff.print(with_legend=args.legend,)# 4. Optional special exit codeifargs.exit_code:# ``last_compare_list`` is filled during render/print.sys.exit(1ifdiff.last_compare_listelse0)