Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
test_validators.py2574 linesDownload Raw Back to tests
1from __future__ import annotations2 3from collections import deque, namedtuple4from contextlib import contextmanager5from decimal import Decimal6from io import BytesIO7from typing import Any8from unittest import TestCase, mock9from urllib.request import pathname2url10import json11import os12import sys13import tempfile14import warnings15 16from attrs import define, field17from referencing.jsonschema import DRAFT20201218import referencing.exceptions19 20from jsonschema import (21    FormatChecker,22    TypeChecker,23    exceptions,24    protocols,25    validators,26)27 28 29def fail(validator, errors, instance, schema):30    for each in errors:31        each.setdefault("message", "You told me to fail!")32        yield exceptions.ValidationError(**each)33 34 35class TestCreateAndExtend(TestCase):36    def setUp(self):37        self.addCleanup(38            self.assertEqual,39            validators._META_SCHEMAS,40            dict(validators._META_SCHEMAS),41        )42        self.addCleanup(43            self.assertEqual,44            validators._VALIDATORS,45            dict(validators._VALIDATORS),46        )47 48        self.meta_schema = {"$id": "some://meta/schema"}49        self.validators = {"fail": fail}50        self.type_checker = TypeChecker()51        self.Validator = validators.create(52            meta_schema=self.meta_schema,53            validators=self.validators,54            type_checker=self.type_checker,55        )56 57    def test_attrs(self):58        self.assertEqual(59            (60                self.Validator.VALIDATORS,61                self.Validator.META_SCHEMA,62                self.Validator.TYPE_CHECKER,63            ), (64                self.validators,65                self.meta_schema,66                self.type_checker,67            ),68        )69 70    def test_init(self):71        schema = {"fail": []}72        self.assertEqual(self.Validator(schema).schema, schema)73 74    def test_iter_errors_successful(self):75        schema = {"fail": []}76        validator = self.Validator(schema)77 78        errors = list(validator.iter_errors("hello"))79        self.assertEqual(errors, [])80 81    def test_iter_errors_one_error(self):82        schema = {"fail": [{"message": "Whoops!"}]}83        validator = self.Validator(schema)84 85        expected_error = exceptions.ValidationError(86            "Whoops!",87            instance="goodbye",88            schema=schema,89            validator="fail",90            validator_value=[{"message": "Whoops!"}],91            schema_path=deque(["fail"]),92        )93 94        errors = list(validator.iter_errors("goodbye"))95        self.assertEqual(len(errors), 1)96        self.assertEqual(errors[0]._contents(), expected_error._contents())97 98    def test_iter_errors_multiple_errors(self):99        schema = {100            "fail": [101                {"message": "First"},102                {"message": "Second!", "validator": "asdf"},103                {"message": "Third"},104            ],105        }106        validator = self.Validator(schema)107 108        errors = list(validator.iter_errors("goodbye"))109        self.assertEqual(len(errors), 3)110 111    def test_if_a_version_is_provided_it_is_registered(self):112        Validator = validators.create(113            meta_schema={"$id": "something"},114            version="my version",115        )116        self.addCleanup(validators._META_SCHEMAS.pop, "something")117        self.addCleanup(validators._VALIDATORS.pop, "my version")118        self.assertEqual(Validator.__name__, "MyVersionValidator")119        self.assertEqual(Validator.__qualname__, "MyVersionValidator")120 121    def test_repr(self):122        Validator = validators.create(123            meta_schema={"$id": "something"},124            version="my version",125        )126        self.addCleanup(validators._META_SCHEMAS.pop, "something")127        self.addCleanup(validators._VALIDATORS.pop, "my version")128        self.assertEqual(129            repr(Validator({})),130            "MyVersionValidator(schema={}, format_checker=None)",131        )132 133    def test_long_repr(self):134        Validator = validators.create(135            meta_schema={"$id": "something"},136            version="my version",137        )138        self.addCleanup(validators._META_SCHEMAS.pop, "something")139        self.addCleanup(validators._VALIDATORS.pop, "my version")140        self.assertEqual(141            repr(Validator({"a": list(range(1000))})), (142                "MyVersionValidator(schema={'a': [0, 1, 2, 3, 4, 5, ...]}, "143                "format_checker=None)"144            ),145        )146 147    def test_repr_no_version(self):148        Validator = validators.create(meta_schema={})149        self.assertEqual(150            repr(Validator({})),151            "Validator(schema={}, format_checker=None)",152        )153 154    def test_dashes_are_stripped_from_validator_names(self):155        Validator = validators.create(156            meta_schema={"$id": "something"},157            version="foo-bar",158        )159        self.addCleanup(validators._META_SCHEMAS.pop, "something")160        self.addCleanup(validators._VALIDATORS.pop, "foo-bar")161        self.assertEqual(Validator.__qualname__, "FooBarValidator")162 163    def test_if_a_version_is_not_provided_it_is_not_registered(self):164        original = dict(validators._META_SCHEMAS)165        validators.create(meta_schema={"id": "id"})166        self.assertEqual(validators._META_SCHEMAS, original)167 168    def test_validates_registers_meta_schema_id(self):169        meta_schema_key = "meta schema id"170        my_meta_schema = {"id": meta_schema_key}171 172        validators.create(173            meta_schema=my_meta_schema,174            version="my version",175            id_of=lambda s: s.get("id", ""),176        )177        self.addCleanup(validators._META_SCHEMAS.pop, meta_schema_key)178        self.addCleanup(validators._VALIDATORS.pop, "my version")179 180        self.assertIn(meta_schema_key, validators._META_SCHEMAS)181 182    def test_validates_registers_meta_schema_draft6_id(self):183        meta_schema_key = "meta schema $id"184        my_meta_schema = {"$id": meta_schema_key}185 186        validators.create(187            meta_schema=my_meta_schema,188            version="my version",189        )190        self.addCleanup(validators._META_SCHEMAS.pop, meta_schema_key)191        self.addCleanup(validators._VALIDATORS.pop, "my version")192 193        self.assertIn(meta_schema_key, validators._META_SCHEMAS)194 195    def test_create_default_types(self):196        Validator = validators.create(meta_schema={}, validators=())197        self.assertTrue(198            all(199                Validator({}).is_type(instance=instance, type=type)200                for type, instance in [201                    ("array", []),202                    ("boolean", True),203                    ("integer", 12),204                    ("null", None),205                    ("number", 12.0),206                    ("object", {}),207                    ("string", "foo"),208                ]209            ),210        )211 212    def test_check_schema_with_different_metaschema(self):213        """214        One can create a validator class whose metaschema uses a different215        dialect than itself.216        """217 218        NoEmptySchemasValidator = validators.create(219            meta_schema={220                "$schema": validators.Draft202012Validator.META_SCHEMA["$id"],221                "not": {"const": {}},222            },223        )224        NoEmptySchemasValidator.check_schema({"foo": "bar"})225 226        with self.assertRaises(exceptions.SchemaError):227            NoEmptySchemasValidator.check_schema({})228 229        NoEmptySchemasValidator({"foo": "bar"}).validate("foo")230 231    def test_check_schema_with_different_metaschema_defaults_to_self(self):232        """233        A validator whose metaschema doesn't declare $schema defaults to its234        own validation behavior, not the latest "normal" specification.235        """236 237        NoEmptySchemasValidator = validators.create(238            meta_schema={"fail": [{"message": "Meta schema whoops!"}]},239            validators={"fail": fail},240        )241        with self.assertRaises(exceptions.SchemaError):242            NoEmptySchemasValidator.check_schema({})243 244    def test_extend(self):245        original = dict(self.Validator.VALIDATORS)246        new = object()247 248        Extended = validators.extend(249            self.Validator,250            validators={"new": new},251        )252        self.assertEqual(253            (254                Extended.VALIDATORS,255                Extended.META_SCHEMA,256                Extended.TYPE_CHECKER,257                self.Validator.VALIDATORS,258            ), (259                dict(original, new=new),260                self.Validator.META_SCHEMA,261                self.Validator.TYPE_CHECKER,262                original,263            ),264        )265 266    def test_extend_idof(self):267        """268        Extending a validator preserves its notion of schema IDs.269        """270        def id_of(schema):271            return schema.get("__test__", self.Validator.ID_OF(schema))272        correct_id = "the://correct/id/"273        meta_schema = {274            "$id": "the://wrong/id/",275            "__test__": correct_id,276        }277        Original = validators.create(278            meta_schema=meta_schema,279            validators=self.validators,280            type_checker=self.type_checker,281            id_of=id_of,282        )283        self.assertEqual(Original.ID_OF(Original.META_SCHEMA), correct_id)284 285        Derived = validators.extend(Original)286        self.assertEqual(Derived.ID_OF(Derived.META_SCHEMA), correct_id)287 288    def test_extend_applicable_validators(self):289        """290        Extending a validator preserves its notion of applicable validators.291        """292 293        schema = {294            "$defs": {"test": {"type": "number"}},295            "$ref": "#/$defs/test",296            "maximum": 1,297        }298 299        draft4 = validators.Draft4Validator(schema)300        self.assertTrue(draft4.is_valid(37))  # as $ref ignores siblings301 302        Derived = validators.extend(validators.Draft4Validator)303        self.assertTrue(Derived(schema).is_valid(37))304 305 306class TestValidationErrorMessages(TestCase):307    def message_for(self, instance, schema, *args, **kwargs):308        cls = kwargs.pop("cls", validators._LATEST_VERSION)309        cls.check_schema(schema)310        validator = cls(schema, *args, **kwargs)311        errors = list(validator.iter_errors(instance))312        self.assertTrue(errors, msg=f"No errors were raised for {instance!r}")313        self.assertEqual(314            len(errors),315            1,316            msg=f"Expected exactly one error, found {errors!r}",317        )318        return errors[0].message319 320    def test_single_type_failure(self):321        message = self.message_for(instance=1, schema={"type": "string"})322        self.assertEqual(message, "1 is not of type 'string'")323 324    def test_single_type_list_failure(self):325        message = self.message_for(instance=1, schema={"type": ["string"]})326        self.assertEqual(message, "1 is not of type 'string'")327 328    def test_multiple_type_failure(self):329        types = "string", "object"330        message = self.message_for(instance=1, schema={"type": list(types)})331        self.assertEqual(message, "1 is not of type 'string', 'object'")332 333    def test_object_with_named_type_failure(self):334        schema = {"type": [{"name": "Foo", "minimum": 3}]}335        message = self.message_for(336            instance=1,337            schema=schema,338            cls=validators.Draft3Validator,339        )340        self.assertEqual(message, "1 is not of type 'Foo'")341 342    def test_minimum(self):343        message = self.message_for(instance=1, schema={"minimum": 2})344        self.assertEqual(message, "1 is less than the minimum of 2")345 346    def test_maximum(self):347        message = self.message_for(instance=1, schema={"maximum": 0})348        self.assertEqual(message, "1 is greater than the maximum of 0")349 350    def test_dependencies_single_element(self):351        depend, on = "bar", "foo"352        schema = {"dependencies": {depend: on}}353        message = self.message_for(354            instance={"bar": 2},355            schema=schema,356            cls=validators.Draft3Validator,357        )358        self.assertEqual(message, "'foo' is a dependency of 'bar'")359 360    def test_object_without_title_type_failure_draft3(self):361        type = {"type": [{"minimum": 3}]}362        message = self.message_for(363            instance=1,364            schema={"type": [type]},365            cls=validators.Draft3Validator,366        )367        self.assertEqual(368            message,369            "1 is not of type {'type': [{'minimum': 3}]}",370        )371 372    def test_dependencies_list_draft3(self):373        depend, on = "bar", "foo"374        schema = {"dependencies": {depend: [on]}}375        message = self.message_for(376            instance={"bar": 2},377            schema=schema,378            cls=validators.Draft3Validator,379        )380        self.assertEqual(message, "'foo' is a dependency of 'bar'")381 382    def test_dependencies_list_draft7(self):383        depend, on = "bar", "foo"384        schema = {"dependencies": {depend: [on]}}385        message = self.message_for(386            instance={"bar": 2},387            schema=schema,388            cls=validators.Draft7Validator,389        )390        self.assertEqual(message, "'foo' is a dependency of 'bar'")391 392    def test_additionalItems_single_failure(self):393        message = self.message_for(394            instance=[2],395            schema={"items": [], "additionalItems": False},396            cls=validators.Draft3Validator,397        )398        self.assertIn("(2 was unexpected)", message)399 400    def test_additionalItems_multiple_failures(self):401        message = self.message_for(402            instance=[1, 2, 3],403            schema={"items": [], "additionalItems": False},404            cls=validators.Draft3Validator,405        )406        self.assertIn("(1, 2, 3 were unexpected)", message)407 408    def test_additionalProperties_single_failure(self):409        additional = "foo"410        schema = {"additionalProperties": False}411        message = self.message_for(instance={additional: 2}, schema=schema)412        self.assertIn("('foo' was unexpected)", message)413 414    def test_additionalProperties_multiple_failures(self):415        schema = {"additionalProperties": False}416        message = self.message_for(417            instance=dict.fromkeys(["foo", "bar"]),418            schema=schema,419        )420 421        self.assertIn(repr("foo"), message)422        self.assertIn(repr("bar"), message)423        self.assertIn("were unexpected)", message)424 425    def test_const(self):426        schema = {"const": 12}427        message = self.message_for(428            instance={"foo": "bar"},429            schema=schema,430        )431        self.assertIn("12 was expected", message)432 433    def test_contains_draft_6(self):434        schema = {"contains": {"const": 12}}435        message = self.message_for(436            instance=[2, {}, []],437            schema=schema,438            cls=validators.Draft6Validator,439        )440        self.assertEqual(441            message,442            "None of [2, {}, []] are valid under the given schema",443        )444 445    def test_invalid_format_default_message(self):446        checker = FormatChecker(formats=())447        checker.checks("thing")(lambda value: False)448 449        schema = {"format": "thing"}450        message = self.message_for(451            instance="bla",452            schema=schema,453            format_checker=checker,454        )455 456        self.assertIn(repr("bla"), message)457        self.assertIn(repr("thing"), message)458        self.assertIn("is not a", message)459 460    def test_additionalProperties_false_patternProperties(self):461        schema = {"type": "object",462                  "additionalProperties": False,463                  "patternProperties": {464                      "^abc$": {"type": "string"},465                      "^def$": {"type": "string"},466                  }}467        message = self.message_for(468            instance={"zebra": 123},469            schema=schema,470            cls=validators.Draft4Validator,471        )472        self.assertEqual(473            message,474            "{} does not match any of the regexes: {}, {}".format(475                repr("zebra"), repr("^abc$"), repr("^def$"),476            ),477        )478        message = self.message_for(479            instance={"zebra": 123, "fish": 456},480            schema=schema,481            cls=validators.Draft4Validator,482        )483        self.assertEqual(484            message,485            "{}, {} do not match any of the regexes: {}, {}".format(486                repr("fish"), repr("zebra"), repr("^abc$"), repr("^def$"),487            ),488        )489 490    def test_False_schema(self):491        message = self.message_for(492            instance="something",493            schema=False,494        )495        self.assertEqual(message, "False schema does not allow 'something'")496 497    def test_multipleOf(self):498        message = self.message_for(499            instance=3,500            schema={"multipleOf": 2},501        )502        self.assertEqual(message, "3 is not a multiple of 2")503 504    def test_minItems(self):505        message = self.message_for(instance=[], schema={"minItems": 2})506        self.assertEqual(message, "[] is too short")507 508    def test_maxItems(self):509        message = self.message_for(instance=[1, 2, 3], schema={"maxItems": 2})510        self.assertEqual(message, "[1, 2, 3] is too long")511 512    def test_minItems_1(self):513        message = self.message_for(instance=[], schema={"minItems": 1})514        self.assertEqual(message, "[] should be non-empty")515 516    def test_maxItems_0(self):517        message = self.message_for(instance=[1, 2, 3], schema={"maxItems": 0})518        self.assertEqual(message, "[1, 2, 3] is expected to be empty")519 520    def test_minLength(self):521        message = self.message_for(522            instance="",523            schema={"minLength": 2},524        )525        self.assertEqual(message, "'' is too short")526 527    def test_maxLength(self):528        message = self.message_for(529            instance="abc",530            schema={"maxLength": 2},531        )532        self.assertEqual(message, "'abc' is too long")533 534    def test_minLength_1(self):535        message = self.message_for(instance="", schema={"minLength": 1})536        self.assertEqual(message, "'' should be non-empty")537 538    def test_maxLength_0(self):539        message = self.message_for(instance="abc", schema={"maxLength": 0})540        self.assertEqual(message, "'abc' is expected to be empty")541 542    def test_minProperties(self):543        message = self.message_for(instance={}, schema={"minProperties": 2})544        self.assertEqual(message, "{} does not have enough properties")545 546    def test_maxProperties(self):547        message = self.message_for(548            instance={"a": {}, "b": {}, "c": {}},549            schema={"maxProperties": 2},550        )551        self.assertEqual(552            message,553            "{'a': {}, 'b': {}, 'c': {}} has too many properties",554        )555 556    def test_minProperties_1(self):557        message = self.message_for(instance={}, schema={"minProperties": 1})558        self.assertEqual(message, "{} should be non-empty")559 560    def test_maxProperties_0(self):561        message = self.message_for(562            instance={1: 2},563            schema={"maxProperties": 0},564        )565        self.assertEqual(message, "{1: 2} is expected to be empty")566 567    def test_prefixItems_with_items(self):568        message = self.message_for(569            instance=[1, 2, "foo"],570            schema={"items": False, "prefixItems": [{}, {}]},571        )572        self.assertEqual(573            message,574            "Expected at most 2 items but found 1 extra: 'foo'",575        )576 577    def test_prefixItems_with_multiple_extra_items(self):578        message = self.message_for(579            instance=[1, 2, "foo", 5],580            schema={"items": False, "prefixItems": [{}, {}]},581        )582        self.assertEqual(583            message,584            "Expected at most 2 items but found 2 extra: ['foo', 5]",585        )586 587    def test_pattern(self):588        message = self.message_for(589            instance="bbb",590            schema={"pattern": "^a*$"},591        )592        self.assertEqual(message, "'bbb' does not match '^a*$'")593 594    def test_does_not_contain(self):595        message = self.message_for(596            instance=[],597            schema={"contains": {"type": "string"}},598        )599        self.assertEqual(600            message,601            "[] does not contain items matching the given schema",602        )603 604    def test_contains_too_few(self):605        message = self.message_for(606            instance=["foo", 1],607            schema={"contains": {"type": "string"}, "minContains": 2},608        )609        self.assertEqual(610            message,611            "Too few items match the given schema "612            "(expected at least 2 but only 1 matched)",613        )614 615    def test_contains_too_few_both_constrained(self):616        message = self.message_for(617            instance=["foo", 1],618            schema={619                "contains": {"type": "string"},620                "minContains": 2,621                "maxContains": 4,622            },623        )624        self.assertEqual(625            message,626            "Too few items match the given schema (expected at least 2 but "627            "only 1 matched)",628        )629 630    def test_contains_too_many(self):631        message = self.message_for(632            instance=["foo", "bar", "baz"],633            schema={"contains": {"type": "string"}, "maxContains": 2},634        )635        self.assertEqual(636            message,637            "Too many items match the given schema (expected at most 2)",638        )639 640    def test_contains_too_many_both_constrained(self):641        message = self.message_for(642            instance=["foo"] * 5,643            schema={644                "contains": {"type": "string"},645                "minContains": 2,646                "maxContains": 4,647            },648        )649        self.assertEqual(650            message,651            "Too many items match the given schema (expected at most 4)",652        )653 654    def test_exclusiveMinimum(self):655        message = self.message_for(656            instance=3,657            schema={"exclusiveMinimum": 5},658        )659        self.assertEqual(660            message,661            "3 is less than or equal to the minimum of 5",662        )663 664    def test_exclusiveMaximum(self):665        message = self.message_for(instance=3, schema={"exclusiveMaximum": 2})666        self.assertEqual(667            message,668            "3 is greater than or equal to the maximum of 2",669        )670 671    def test_required(self):672        message = self.message_for(instance={}, schema={"required": ["foo"]})673        self.assertEqual(message, "'foo' is a required property")674 675    def test_dependentRequired(self):676        message = self.message_for(677            instance={"foo": {}},678            schema={"dependentRequired": {"foo": ["bar"]}},679        )680        self.assertEqual(message, "'bar' is a dependency of 'foo'")681 682    def test_oneOf_matches_none(self):683        message = self.message_for(instance={}, schema={"oneOf": [False]})684        self.assertEqual(685            message,686            "{} is not valid under any of the given schemas",687        )688 689    def test_oneOf_matches_too_many(self):690        message = self.message_for(instance={}, schema={"oneOf": [True, True]})691        self.assertEqual(message, "{} is valid under each of True, True")692 693    def test_unevaluated_items(self):694        schema = {"type": "array", "unevaluatedItems": False}695        message = self.message_for(instance=["foo", "bar"], schema=schema)696        self.assertIn(697            message,698            "Unevaluated items are not allowed ('foo', 'bar' were unexpected)",699        )700 701    def test_unevaluated_items_on_invalid_type(self):702        schema = {"type": "array", "unevaluatedItems": False}703        message = self.message_for(instance="foo", schema=schema)704        self.assertEqual(message, "'foo' is not of type 'array'")705 706    def test_unevaluated_properties_invalid_against_subschema(self):707        schema = {708            "properties": {"foo": {"type": "string"}},709            "unevaluatedProperties": {"const": 12},710        }711        message = self.message_for(712            instance={713                "foo": "foo",714                "bar": "bar",715                "baz": 12,716            },717            schema=schema,718        )719        self.assertEqual(720            message,721            "Unevaluated properties are not valid under the given schema "722            "('bar' was unevaluated and invalid)",723        )724 725    def test_unevaluated_properties_disallowed(self):726        schema = {"type": "object", "unevaluatedProperties": False}727        message = self.message_for(728            instance={729                "foo": "foo",730                "bar": "bar",731            },732            schema=schema,733        )734        self.assertEqual(735            message,736            "Unevaluated properties are not allowed "737            "('bar', 'foo' were unexpected)",738        )739 740    def test_unevaluated_properties_on_invalid_type(self):741        schema = {"type": "object", "unevaluatedProperties": False}742        message = self.message_for(instance="foo", schema=schema)743        self.assertEqual(message, "'foo' is not of type 'object'")744 745    def test_single_item(self):746        schema = {"prefixItems": [{}], "items": False}747        message = self.message_for(748            instance=["foo", "bar", "baz"],749            schema=schema,750        )751        self.assertEqual(752            message,753            "Expected at most 1 item but found 2 extra: ['bar', 'baz']",754        )755 756    def test_heterogeneous_additionalItems_with_Items(self):757        schema = {"items": [{}], "additionalItems": False}758        message = self.message_for(759            instance=["foo", "bar", 37],760            schema=schema,761            cls=validators.Draft7Validator,762        )763        self.assertEqual(764            message,765            "Additional items are not allowed ('bar', 37 were unexpected)",766        )767 768    def test_heterogeneous_items_prefixItems(self):769        schema = {"prefixItems": [{}], "items": False}770        message = self.message_for(771            instance=["foo", "bar", 37],772            schema=schema,773        )774        self.assertEqual(775            message,776            "Expected at most 1 item but found 2 extra: ['bar', 37]",777        )778 779    def test_heterogeneous_unevaluatedItems_prefixItems(self):780        schema = {"prefixItems": [{}], "unevaluatedItems": False}781        message = self.message_for(782            instance=["foo", "bar", 37],783            schema=schema,784        )785        self.assertEqual(786            message,787            "Unevaluated items are not allowed ('bar', 37 were unexpected)",788        )789 790    def test_heterogeneous_properties_additionalProperties(self):791        """792        Not valid deserialized JSON, but this should not blow up.793        """794        schema = {"properties": {"foo": {}}, "additionalProperties": False}795        message = self.message_for(796            instance={"foo": {}, "a": "baz", 37: 12},797            schema=schema,798        )799        self.assertEqual(800            message,801            "Additional properties are not allowed (37, 'a' were unexpected)",802        )803 804    def test_heterogeneous_properties_unevaluatedProperties(self):805        """806        Not valid deserialized JSON, but this should not blow up.807        """808        schema = {"properties": {"foo": {}}, "unevaluatedProperties": False}809        message = self.message_for(810            instance={"foo": {}, "a": "baz", 37: 12},811            schema=schema,812        )813        self.assertEqual(814            message,815            "Unevaluated properties are not allowed (37, 'a' were unexpected)",816        )817 818 819class TestValidationErrorDetails(TestCase):820    # TODO: These really need unit tests for each individual keyword, rather821    #       than just these higher level tests.822    def test_anyOf(self):823        instance = 5824        schema = {825            "anyOf": [826                {"minimum": 20},827                {"type": "string"},828            ],829        }830 831        validator = validators.Draft4Validator(schema)832        errors = list(validator.iter_errors(instance))833        self.assertEqual(len(errors), 1)834        e = errors[0]835 836        self.assertEqual(e.validator, "anyOf")837        self.assertEqual(e.validator_value, schema["anyOf"])838        self.assertEqual(e.instance, instance)839        self.assertEqual(e.schema, schema)840        self.assertIsNone(e.parent)841 842        self.assertEqual(e.path, deque([]))843        self.assertEqual(e.relative_path, deque([]))844        self.assertEqual(e.absolute_path, deque([]))845        self.assertEqual(e.json_path, "$")846 847        self.assertEqual(e.schema_path, deque(["anyOf"]))848        self.assertEqual(e.relative_schema_path, deque(["anyOf"]))849        self.assertEqual(e.absolute_schema_path, deque(["anyOf"]))850 851        self.assertEqual(len(e.context), 2)852 853        e1, e2 = sorted_errors(e.context)854 855        self.assertEqual(e1.validator, "minimum")856        self.assertEqual(e1.validator_value, schema["anyOf"][0]["minimum"])857        self.assertEqual(e1.instance, instance)858        self.assertEqual(e1.schema, schema["anyOf"][0])859        self.assertIs(e1.parent, e)860 861        self.assertEqual(e1.path, deque([]))862        self.assertEqual(e1.absolute_path, deque([]))863        self.assertEqual(e1.relative_path, deque([]))864        self.assertEqual(e1.json_path, "$")865 866        self.assertEqual(e1.schema_path, deque([0, "minimum"]))867        self.assertEqual(e1.relative_schema_path, deque([0, "minimum"]))868        self.assertEqual(869            e1.absolute_schema_path, deque(["anyOf", 0, "minimum"]),870        )871 872        self.assertFalse(e1.context)873 874        self.assertEqual(e2.validator, "type")875        self.assertEqual(e2.validator_value, schema["anyOf"][1]["type"])876        self.assertEqual(e2.instance, instance)877        self.assertEqual(e2.schema, schema["anyOf"][1])878        self.assertIs(e2.parent, e)879 880        self.assertEqual(e2.path, deque([]))881        self.assertEqual(e2.relative_path, deque([]))882        self.assertEqual(e2.absolute_path, deque([]))883        self.assertEqual(e2.json_path, "$")884 885        self.assertEqual(e2.schema_path, deque([1, "type"]))886        self.assertEqual(e2.relative_schema_path, deque([1, "type"]))887        self.assertEqual(e2.absolute_schema_path, deque(["anyOf", 1, "type"]))888 889        self.assertEqual(len(e2.context), 0)890 891    def test_type(self):892        instance = {"foo": 1}893        schema = {894            "type": [895                {"type": "integer"},896                {897                    "type": "object",898                    "properties": {"foo": {"enum": [2]}},899                },900            ],901        }902 903        validator = validators.Draft3Validator(schema)904        errors = list(validator.iter_errors(instance))905        self.assertEqual(len(errors), 1)906        e = errors[0]907 908        self.assertEqual(e.validator, "type")909        self.assertEqual(e.validator_value, schema["type"])910        self.assertEqual(e.instance, instance)911        self.assertEqual(e.schema, schema)912        self.assertIsNone(e.parent)913 914        self.assertEqual(e.path, deque([]))915        self.assertEqual(e.relative_path, deque([]))916        self.assertEqual(e.absolute_path, deque([]))917        self.assertEqual(e.json_path, "$")918 919        self.assertEqual(e.schema_path, deque(["type"]))920        self.assertEqual(e.relative_schema_path, deque(["type"]))921        self.assertEqual(e.absolute_schema_path, deque(["type"]))922 923        self.assertEqual(len(e.context), 2)924 925        e1, e2 = sorted_errors(e.context)926 927        self.assertEqual(e1.validator, "type")928        self.assertEqual(e1.validator_value, schema["type"][0]["type"])929        self.assertEqual(e1.instance, instance)930        self.assertEqual(e1.schema, schema["type"][0])931        self.assertIs(e1.parent, e)932 933        self.assertEqual(e1.path, deque([]))934        self.assertEqual(e1.relative_path, deque([]))935        self.assertEqual(e1.absolute_path, deque([]))936        self.assertEqual(e1.json_path, "$")937 938        self.assertEqual(e1.schema_path, deque([0, "type"]))939        self.assertEqual(e1.relative_schema_path, deque([0, "type"]))940        self.assertEqual(e1.absolute_schema_path, deque(["type", 0, "type"]))941 942        self.assertFalse(e1.context)943 944        self.assertEqual(e2.validator, "enum")945        self.assertEqual(e2.validator_value, [2])946        self.assertEqual(e2.instance, 1)947        self.assertEqual(e2.schema, {"enum": [2]})948        self.assertIs(e2.parent, e)949 950        self.assertEqual(e2.path, deque(["foo"]))951        self.assertEqual(e2.relative_path, deque(["foo"]))952        self.assertEqual(e2.absolute_path, deque(["foo"]))953        self.assertEqual(e2.json_path, "$.foo")954 955        self.assertEqual(956            e2.schema_path, deque([1, "properties", "foo", "enum"]),957        )958        self.assertEqual(959            e2.relative_schema_path, deque([1, "properties", "foo", "enum"]),960        )961        self.assertEqual(962            e2.absolute_schema_path,963            deque(["type", 1, "properties", "foo", "enum"]),964        )965 966        self.assertFalse(e2.context)967 968    def test_single_nesting(self):969        instance = {"foo": 2, "bar": [1], "baz": 15, "quux": "spam"}970        schema = {971            "properties": {972                "foo": {"type": "string"},973                "bar": {"minItems": 2},974                "baz": {"maximum": 10, "enum": [2, 4, 6, 8]},975            },976        }977 978        validator = validators.Draft3Validator(schema)979        errors = validator.iter_errors(instance)980        e1, e2, e3, e4 = sorted_errors(errors)981 982        self.assertEqual(e1.path, deque(["bar"]))983        self.assertEqual(e2.path, deque(["baz"]))984        self.assertEqual(e3.path, deque(["baz"]))985        self.assertEqual(e4.path, deque(["foo"]))986 987        self.assertEqual(e1.relative_path, deque(["bar"]))988        self.assertEqual(e2.relative_path, deque(["baz"]))989        self.assertEqual(e3.relative_path, deque(["baz"]))990        self.assertEqual(e4.relative_path, deque(["foo"]))991 992        self.assertEqual(e1.absolute_path, deque(["bar"]))993        self.assertEqual(e2.absolute_path, deque(["baz"]))994        self.assertEqual(e3.absolute_path, deque(["baz"]))995        self.assertEqual(e4.absolute_path, deque(["foo"]))996 997        self.assertEqual(e1.json_path, "$.bar")998        self.assertEqual(e2.json_path, "$.baz")999        self.assertEqual(e3.json_path, "$.baz")1000        self.assertEqual(e4.json_path, "$.foo")1001 1002        self.assertEqual(e1.validator, "minItems")1003        self.assertEqual(e2.validator, "enum")1004        self.assertEqual(e3.validator, "maximum")1005        self.assertEqual(e4.validator, "type")1006 1007    def test_multiple_nesting(self):1008        instance = [1, {"foo": 2, "bar": {"baz": [1]}}, "quux"]1009        schema = {1010            "type": "string",1011            "items": {1012                "type": ["string", "object"],1013                "properties": {1014                    "foo": {"enum": [1, 3]},1015                    "bar": {1016                        "type": "array",1017                        "properties": {1018                            "bar": {"required": True},1019                            "baz": {"minItems": 2},1020                        },1021                    },1022                },1023            },1024        }1025 1026        validator = validators.Draft3Validator(schema)1027        errors = validator.iter_errors(instance)1028        e1, e2, e3, e4, e5, e6 = sorted_errors(errors)1029 1030        self.assertEqual(e1.path, deque([]))1031        self.assertEqual(e2.path, deque([0]))1032        self.assertEqual(e3.path, deque([1, "bar"]))1033        self.assertEqual(e4.path, deque([1, "bar", "bar"]))1034        self.assertEqual(e5.path, deque([1, "bar", "baz"]))1035        self.assertEqual(e6.path, deque([1, "foo"]))1036 1037        self.assertEqual(e1.json_path, "$")1038        self.assertEqual(e2.json_path, "$[0]")1039        self.assertEqual(e3.json_path, "$[1].bar")1040        self.assertEqual(e4.json_path, "$[1].bar.bar")1041        self.assertEqual(e5.json_path, "$[1].bar.baz")1042        self.assertEqual(e6.json_path, "$[1].foo")1043 1044        self.assertEqual(e1.schema_path, deque(["type"]))1045        self.assertEqual(e2.schema_path, deque(["items", "type"]))1046        self.assertEqual(1047            list(e3.schema_path), ["items", "properties", "bar", "type"],1048        )1049        self.assertEqual(1050            list(e4.schema_path),1051            ["items", "properties", "bar", "properties", "bar", "required"],1052        )1053        self.assertEqual(1054            list(e5.schema_path),1055            ["items", "properties", "bar", "properties", "baz", "minItems"],1056        )1057        self.assertEqual(1058            list(e6.schema_path), ["items", "properties", "foo", "enum"],1059        )1060 1061        self.assertEqual(e1.validator, "type")1062        self.assertEqual(e2.validator, "type")1063        self.assertEqual(e3.validator, "type")1064        self.assertEqual(e4.validator, "required")1065        self.assertEqual(e5.validator, "minItems")1066        self.assertEqual(e6.validator, "enum")1067 1068    def test_recursive(self):1069        schema = {1070            "definitions": {1071                "node": {1072                    "anyOf": [{1073                        "type": "object",1074                        "required": ["name", "children"],1075                        "properties": {1076                            "name": {1077                                "type": "string",1078                            },1079                            "children": {1080                                "type": "object",1081                                "patternProperties": {1082                                    "^.*$": {1083                                        "$ref": "#/definitions/node",1084                                    },1085                                },1086                            },1087                        },1088                    }],1089                },1090            },1091            "type": "object",1092            "required": ["root"],1093            "properties": {"root": {"$ref": "#/definitions/node"}},1094        }1095 1096        instance = {1097            "root": {1098                "name": "root",1099                "children": {1100                    "a": {1101                        "name": "a",1102                        "children": {1103                            "ab": {1104                                "name": "ab",1105                                # missing "children"1106                            },1107                        },1108                    },1109                },1110            },1111        }1112        validator = validators.Draft4Validator(schema)1113 1114        e, = validator.iter_errors(instance)1115        self.assertEqual(e.absolute_path, deque(["root"]))1116        self.assertEqual(1117            e.absolute_schema_path, deque(["properties", "root", "anyOf"]),1118        )1119        self.assertEqual(e.json_path, "$.root")1120 1121        e1, = e.context1122        self.assertEqual(e1.absolute_path, deque(["root", "children", "a"]))1123        self.assertEqual(1124            e1.absolute_schema_path, deque(1125                [1126                    "properties",1127                    "root",1128                    "anyOf",1129                    0,1130                    "properties",1131                    "children",1132                    "patternProperties",1133                    "^.*$",1134                    "anyOf",1135                ],1136            ),1137        )1138        self.assertEqual(e1.json_path, "$.root.children.a")1139 1140        e2, = e1.context1141        self.assertEqual(1142            e2.absolute_path, deque(1143                ["root", "children", "a", "children", "ab"],1144            ),1145        )1146        self.assertEqual(1147            e2.absolute_schema_path, deque(1148                [1149                    "properties",1150                    "root",1151                    "anyOf",1152                    0,1153                    "properties",1154                    "children",1155                    "patternProperties",1156                    "^.*$",1157                    "anyOf",1158                    0,1159                    "properties",1160                    "children",1161                    "patternProperties",1162                    "^.*$",1163                    "anyOf",1164                ],1165            ),1166        )1167        self.assertEqual(e2.json_path, "$.root.children.a.children.ab")1168 1169    def test_additionalProperties(self):1170        instance = {"bar": "bar", "foo": 2}1171        schema = {"additionalProperties": {"type": "integer", "minimum": 5}}1172 1173        validator = validators.Draft3Validator(schema)1174        errors = validator.iter_errors(instance)1175        e1, e2 = sorted_errors(errors)1176 1177        self.assertEqual(e1.path, deque(["bar"]))1178        self.assertEqual(e2.path, deque(["foo"]))1179 1180        self.assertEqual(e1.json_path, "$.bar")1181        self.assertEqual(e2.json_path, "$.foo")1182 1183        self.assertEqual(e1.validator, "type")1184        self.assertEqual(e2.validator, "minimum")1185 1186    def test_patternProperties(self):1187        instance = {"bar": 1, "foo": 2}1188        schema = {1189            "patternProperties": {1190                "bar": {"type": "string"},1191                "foo": {"minimum": 5},1192            },1193        }1194 1195        validator = validators.Draft3Validator(schema)1196        errors = validator.iter_errors(instance)1197        e1, e2 = sorted_errors(errors)1198 1199        self.assertEqual(e1.path, deque(["bar"]))1200        self.assertEqual(e2.path, deque(["foo"]))

Showing the first 1,200 of 2574 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai