Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
cli.py293 linesDownload Raw Back to jsonschema
1"""2The ``jsonschema`` command line.3"""4 5from importlib import metadata6from json import JSONDecodeError7from pkgutil import resolve_name8from textwrap import dedent9import argparse10import json11import sys12import traceback13import warnings14 15from attrs import define, field16 17from jsonschema.exceptions import SchemaError18from jsonschema.validators import _RefResolver, validator_for19 20warnings.warn(21    (22        "The jsonschema CLI is deprecated and will be removed in a future "23        "version. Please use check-jsonschema instead, which can be installed "24        "from https://pypi.org/project/check-jsonschema/"25    ),26    DeprecationWarning,27    stacklevel=2,28)29 30 31class _CannotLoadFile(Exception):32    pass33 34 35@define36class _Outputter:37 38    _formatter = field()39    _stdout = field()40    _stderr = field()41 42    @classmethod43    def from_arguments(cls, arguments, stdout, stderr):44        if arguments["output"] == "plain":45            formatter = _PlainFormatter(arguments["error_format"])46        elif arguments["output"] == "pretty":47            formatter = _PrettyFormatter()48        return cls(formatter=formatter, stdout=stdout, stderr=stderr)49 50    def load(self, path):51        try:52            file = open(path)  # noqa: SIM115, PTH12353        except FileNotFoundError as error:54            self.filenotfound_error(path=path, exc_info=sys.exc_info())55            raise _CannotLoadFile() from error56 57        with file:58            try:59                return json.load(file)60            except JSONDecodeError as error:61                self.parsing_error(path=path, exc_info=sys.exc_info())62                raise _CannotLoadFile() from error63 64    def filenotfound_error(self, **kwargs):65        self._stderr.write(self._formatter.filenotfound_error(**kwargs))66 67    def parsing_error(self, **kwargs):68        self._stderr.write(self._formatter.parsing_error(**kwargs))69 70    def validation_error(self, **kwargs):71        self._stderr.write(self._formatter.validation_error(**kwargs))72 73    def validation_success(self, **kwargs):74        self._stdout.write(self._formatter.validation_success(**kwargs))75 76 77@define78class _PrettyFormatter:79 80    _ERROR_MSG = dedent(81        """\82        ===[{type}]===({path})===83 84        {body}85        -----------------------------86        """,87    )88    _SUCCESS_MSG = "===[SUCCESS]===({path})===\n"89 90    def filenotfound_error(self, path, exc_info):91        return self._ERROR_MSG.format(92            path=path,93            type="FileNotFoundError",94            body=f"{path!r} does not exist.",95        )96 97    def parsing_error(self, path, exc_info):98        exc_type, exc_value, exc_traceback = exc_info99        exc_lines = "".join(100            traceback.format_exception(exc_type, exc_value, exc_traceback),101        )102        return self._ERROR_MSG.format(103            path=path,104            type=exc_type.__name__,105            body=exc_lines,106        )107 108    def validation_error(self, instance_path, error):109        return self._ERROR_MSG.format(110            path=instance_path,111            type=error.__class__.__name__,112            body=error,113        )114 115    def validation_success(self, instance_path):116        return self._SUCCESS_MSG.format(path=instance_path)117 118 119@define120class _PlainFormatter:121 122    _error_format = field()123 124    def filenotfound_error(self, path, exc_info):125        return f"{path!r} does not exist.\n"126 127    def parsing_error(self, path, exc_info):128        return "Failed to parse {}: {}\n".format(129            "<stdin>" if path == "<stdin>" else repr(path),130            exc_info[1],131        )132 133    def validation_error(self, instance_path, error):134        return self._error_format.format(file_name=instance_path, error=error)135 136    def validation_success(self, instance_path):137        return ""138 139 140def _resolve_name_with_default(name):141    if "." not in name:142        name = "jsonschema." + name143    return resolve_name(name)144 145 146parser = argparse.ArgumentParser(147    description="JSON Schema Validation CLI",148)149parser.add_argument(150    "-i", "--instance",151    action="append",152    dest="instances",153    help="""154        a path to a JSON instance (i.e. filename.json) to validate (may155        be specified multiple times). If no instances are provided via this156        option, one will be expected on standard input.157    """,158)159parser.add_argument(160    "-F", "--error-format",161    help="""162        the format to use for each validation error message, specified163        in a form suitable for str.format. This string will be passed164        one formatted object named 'error' for each ValidationError.165        Only provide this option when using --output=plain, which is the166        default. If this argument is unprovided and --output=plain is167        used, a simple default representation will be used.168    """,169)170parser.add_argument(171    "-o", "--output",172    choices=["plain", "pretty"],173    default="plain",174    help="""175        an output format to use. 'plain' (default) will produce minimal176        text with one line for each error, while 'pretty' will produce177        more detailed human-readable output on multiple lines.178    """,179)180parser.add_argument(181    "-V", "--validator",182    type=_resolve_name_with_default,183    help="""184        the fully qualified object name of a validator to use, or, for185        validators that are registered with jsonschema, simply the name186        of the class.187    """,188)189parser.add_argument(190    "--base-uri",191    help="""192        a base URI to assign to the provided schema, even if it does not193        declare one (via e.g. $id). This option can be used if you wish to194        resolve relative references to a particular URI (or local path)195    """,196)197parser.add_argument(198    "--version",199    action="version",200    version=metadata.version("jsonschema"),201)202parser.add_argument(203    "schema",204    help="the path to a JSON Schema to validate with (i.e. schema.json)",205)206 207 208def parse_args(args):  # noqa: D103209    arguments = vars(parser.parse_args(args=args or ["--help"]))210    if arguments["output"] != "plain" and arguments["error_format"]:211        raise parser.error(212            "--error-format can only be used with --output plain",213        )214    if arguments["output"] == "plain" and arguments["error_format"] is None:215        arguments["error_format"] = "{error.instance}: {error.message}\n"216    return arguments217 218 219def _validate_instance(instance_path, instance, validator, outputter):220    invalid = False221    for error in validator.iter_errors(instance):222        invalid = True223        outputter.validation_error(instance_path=instance_path, error=error)224 225    if not invalid:226        outputter.validation_success(instance_path=instance_path)227    return invalid228 229 230def main(args=sys.argv[1:]):  # noqa: D103231    sys.exit(run(arguments=parse_args(args=args)))232 233 234def run(arguments, stdout=sys.stdout, stderr=sys.stderr, stdin=sys.stdin):  # noqa: D103235    outputter = _Outputter.from_arguments(236        arguments=arguments,237        stdout=stdout,238        stderr=stderr,239    )240 241    try:242        schema = outputter.load(arguments["schema"])243    except _CannotLoadFile:244        return 1245 246    Validator = arguments["validator"]247    if Validator is None:248        Validator = validator_for(schema)249 250    try:251        Validator.check_schema(schema)252    except SchemaError as error:253        outputter.validation_error(254            instance_path=arguments["schema"],255            error=error,256        )257        return 1258 259    if arguments["instances"]:260        load, instances = outputter.load, arguments["instances"]261    else:262        def load(_):263            try:264                return json.load(stdin)265            except JSONDecodeError as error:266                outputter.parsing_error(267                    path="<stdin>", exc_info=sys.exc_info(),268                )269                raise _CannotLoadFile() from error270        instances = ["<stdin>"]271 272    resolver = _RefResolver(273        base_uri=arguments["base_uri"],274        referrer=schema,275    ) if arguments["base_uri"] is not None else None276 277    validator = Validator(schema, resolver=resolver)278    exit_code = 0279    for each in instances:280        try:281            instance = load(each)282        except _CannotLoadFile:283            exit_code = 1284        else:285            exit_code |= _validate_instance(286                instance_path=each,287                instance=instance,288                validator=validator,289                outputter=outputter,290            )291 292    return exit_code293 
codekingpro/portable-devtools · Team Ai