1"""
2The ``jsonschema`` command line.
3"""
4from __future__ import absolute_import
5import argparse
6import json
7import sys
8
9from jsonschema import __version__
10from jsonschema._reflect import namedAny
11from jsonschema.validators import validator_for
12
13
14def _namedAnyWithDefault(name):
15    if "." not in name:
16        name = "jsonschema." + name
17    return namedAny(name)
18
19
20def _json_file(path):
21    with open(path) as file:
22        return json.load(file)
23
24
25parser = argparse.ArgumentParser(
26    description="JSON Schema Validation CLI",
27)
28parser.add_argument(
29    "-i", "--instance",
30    action="append",
31    dest="instances",
32    type=_json_file,
33    help=(
34        "a path to a JSON instance (i.e. filename.json) "
35        "to validate (may be specified multiple times)"
36    ),
37)
38parser.add_argument(
39    "-F", "--error-format",
40    default="{error.instance}: {error.message}\n",
41    help=(
42        "the format to use for each error output message, specified in "
43        "a form suitable for passing to str.format, which will be called "
44        "with 'error' for each error"
45    ),
46)
47parser.add_argument(
48    "-V", "--validator",
49    type=_namedAnyWithDefault,
50    help=(
51        "the fully qualified object name of a validator to use, or, for "
52        "validators that are registered with jsonschema, simply the name "
53        "of the class."
54    ),
55)
56parser.add_argument(
57    "--version",
58    action="version",
59    version=__version__,
60)
61parser.add_argument(
62    "schema",
63    help="the JSON Schema to validate with (i.e. schema.json)",
64    type=_json_file,
65)
66
67
68def parse_args(args):
69    arguments = vars(parser.parse_args(args=args or ["--help"]))
70    if arguments["validator"] is None:
71        arguments["validator"] = validator_for(arguments["schema"])
72    return arguments
73
74
75def main(args=sys.argv[1:]):
76    sys.exit(run(arguments=parse_args(args=args)))
77
78
79def run(arguments, stdout=sys.stdout, stderr=sys.stderr):
80    error_format = arguments["error_format"]
81    validator = arguments["validator"](schema=arguments["schema"])
82
83    validator.check_schema(arguments["schema"])
84
85    errored = False
86    for instance in arguments["instances"] or ():
87        for error in validator.iter_errors(instance):
88            stderr.write(error_format.format(error=error))
89            errored = True
90    return errored
91