diff options
-rw-r--r-- | .coveragerc | 10 | ||||
-rw-r--r-- | .flake8 | 10 | ||||
-rw-r--r-- | .github/CODEOWNERS (renamed from json/.github/CODEOWNERS) | 0 | ||||
-rw-r--r-- | .github/FUNDING.yml | 4 | ||||
-rw-r--r-- | .github/SECURITY.md | 21 | ||||
-rw-r--r-- | .github/workflows/ci.yml | 227 | ||||
-rw-r--r-- | .github/workflows/coverage.yml | 25 | ||||
-rw-r--r-- | .github/workflows/fuzz.yml | 30 | ||||
-rw-r--r-- | .gitignore | 17 | ||||
-rw-r--r-- | .pre-commit-config.yaml | 22 | ||||
-rw-r--r-- | .pre-commit-hooks.yaml | 6 | ||||
-rw-r--r-- | .readthedocs.yml | 15 | ||||
-rw-r--r-- | CHANGELOG.rst | 369 | ||||
-rw-r--r-- | CONTRIBUTING.rst | 60 | ||||
-rw-r--r-- | COPYING | 19 | ||||
-rw-r--r-- | LICENSE (renamed from json/LICENSE) | 0 | ||||
-rw-r--r-- | README.md (renamed from json/README.md) | 0 | ||||
-rw-r--r-- | README.rst | 148 | ||||
-rwxr-xr-x | bin/jsonschema_suite (renamed from json/bin/jsonschema_suite) | 136 | ||||
-rw-r--r-- | codecov.yml | 5 | ||||
-rw-r--r-- | docs/Makefile | 227 | ||||
-rw-r--r-- | docs/conf.py | 254 | ||||
-rw-r--r-- | docs/creating.rst | 34 | ||||
-rw-r--r-- | docs/errors.rst | 406 | ||||
-rw-r--r-- | docs/faq.rst | 291 | ||||
-rw-r--r-- | docs/index.rst | 22 | ||||
-rw-r--r-- | docs/jsonschema_role.py | 146 | ||||
-rw-r--r-- | docs/make.bat | 190 | ||||
-rw-r--r-- | docs/references.rst | 13 | ||||
-rw-r--r-- | docs/requirements.in | 6 | ||||
-rw-r--r-- | docs/requirements.txt | 81 | ||||
-rw-r--r-- | docs/spelling-wordlist.txt | 45 | ||||
-rw-r--r-- | docs/validate.rst | 288 | ||||
-rw-r--r-- | json/.github/workflows/ci.yml | 25 | ||||
-rw-r--r-- | json/.gitignore | 160 | ||||
-rw-r--r-- | json/tests/draft3/optional/bignum.json | 107 | ||||
-rw-r--r-- | json/tests/draft6/optional/format/date-time.json | 133 | ||||
-rw-r--r-- | json/tests/draft6/optional/format/ipv4.json | 84 | ||||
-rw-r--r-- | json/tests/draft6/optional/format/ipv6.json | 208 | ||||
-rw-r--r-- | json/tests/draft7/anyOf.json | 215 | ||||
-rw-r--r-- | json/tests/draft7/optional/bignum.json | 93 | ||||
-rw-r--r-- | json/tests/draft7/optional/format/date-time.json | 133 | ||||
-rw-r--r-- | json/tests/draft7/optional/format/ipv4.json | 84 | ||||
-rw-r--r-- | json/tests/draft7/optional/format/ipv6.json | 208 | ||||
-rw-r--r-- | json/tox.ini | 9 | ||||
-rw-r--r-- | jsonschema/__init__.py | 58 | ||||
-rw-r--r-- | jsonschema/__main__.py | 3 | ||||
-rw-r--r-- | jsonschema/_format.py | 498 | ||||
-rw-r--r-- | jsonschema/_legacy_validators.py | 228 | ||||
-rw-r--r-- | jsonschema/_types.py | 217 | ||||
-rw-r--r-- | jsonschema/_utils.py | 348 | ||||
-rw-r--r-- | jsonschema/_validators.py | 467 | ||||
-rw-r--r-- | jsonschema/benchmarks/__init__.py | 5 | ||||
-rw-r--r-- | jsonschema/benchmarks/issue232.py | 25 | ||||
-rw-r--r-- | jsonschema/benchmarks/issue232/issue.json | 2653 | ||||
-rw-r--r-- | jsonschema/benchmarks/json_schema_test_suite.py | 12 | ||||
-rw-r--r-- | jsonschema/cli.py | 288 | ||||
-rw-r--r-- | jsonschema/exceptions.py | 393 | ||||
-rw-r--r-- | jsonschema/protocols.py | 171 | ||||
-rw-r--r-- | jsonschema/schemas/draft2019-09.json | 42 | ||||
-rw-r--r-- | jsonschema/schemas/draft2020-12.json | 58 | ||||
-rw-r--r-- | jsonschema/schemas/draft3.json | 177 | ||||
-rw-r--r-- | jsonschema/schemas/draft4.json | 149 | ||||
-rw-r--r-- | jsonschema/schemas/draft6.json | 153 | ||||
-rw-r--r-- | jsonschema/schemas/draft7.json | 166 | ||||
-rw-r--r-- | jsonschema/schemas/vocabularies.json | 1 | ||||
-rw-r--r-- | jsonschema/tests/__init__.py | 0 | ||||
-rw-r--r-- | jsonschema/tests/_helpers.py | 5 | ||||
-rw-r--r-- | jsonschema/tests/_suite.py | 231 | ||||
-rw-r--r-- | jsonschema/tests/fuzz_validate.py | 50 | ||||
-rw-r--r-- | jsonschema/tests/test_cli.py | 911 | ||||
-rw-r--r-- | jsonschema/tests/test_deprecations.py | 123 | ||||
-rw-r--r-- | jsonschema/tests/test_exceptions.py | 588 | ||||
-rw-r--r-- | jsonschema/tests/test_format.py | 107 | ||||
-rw-r--r-- | jsonschema/tests/test_jsonschema_test_suite.py | 446 | ||||
-rw-r--r-- | jsonschema/tests/test_types.py | 217 | ||||
-rw-r--r-- | jsonschema/tests/test_utils.py | 124 | ||||
-rw-r--r-- | jsonschema/tests/test_validators.py | 2183 | ||||
-rw-r--r-- | jsonschema/validators.py | 1099 | ||||
-rw-r--r-- | package.json (renamed from json/package.json) | 0 | ||||
-rw-r--r-- | pyproject.toml | 99 | ||||
-rw-r--r-- | remotes/baseUriChange/folderInteger.json (renamed from json/remotes/baseUriChange/folderInteger.json) | 0 | ||||
-rw-r--r-- | remotes/baseUriChangeFolder/folderInteger.json (renamed from json/remotes/baseUriChangeFolder/folderInteger.json) | 0 | ||||
-rw-r--r-- | remotes/baseUriChangeFolderInSubschema/folderInteger.json (renamed from json/remotes/baseUriChangeFolderInSubschema/folderInteger.json) | 0 | ||||
-rw-r--r-- | remotes/draft-next/format-assertion-false.json (renamed from json/remotes/draft-next/format-assertion-false.json) | 0 | ||||
-rw-r--r-- | remotes/draft-next/format-assertion-true.json (renamed from json/remotes/draft-next/format-assertion-true.json) | 0 | ||||
-rw-r--r-- | remotes/draft-next/metaschema-no-validation.json (renamed from json/remotes/draft-next/metaschema-no-validation.json) | 0 | ||||
-rw-r--r-- | remotes/draft2019-09/metaschema-no-validation.json (renamed from json/remotes/draft2019-09/metaschema-no-validation.json) | 0 | ||||
-rw-r--r-- | remotes/draft2020-12/format-assertion-false.json (renamed from json/remotes/draft2020-12/format-assertion-false.json) | 0 | ||||
-rw-r--r-- | remotes/draft2020-12/format-assertion-true.json (renamed from json/remotes/draft2020-12/format-assertion-true.json) | 0 | ||||
-rw-r--r-- | remotes/draft2020-12/metaschema-no-validation.json (renamed from json/remotes/draft2020-12/metaschema-no-validation.json) | 0 | ||||
-rw-r--r-- | remotes/extendible-dynamic-ref.json (renamed from json/remotes/extendible-dynamic-ref.json) | 0 | ||||
-rw-r--r-- | remotes/integer.json (renamed from json/remotes/integer.json) | 0 | ||||
-rw-r--r-- | remotes/locationIndependentIdentifier.json (renamed from json/remotes/locationIndependentIdentifier.json) | 0 | ||||
-rw-r--r-- | remotes/locationIndependentIdentifierDraft4.json (renamed from json/remotes/locationIndependentIdentifierDraft4.json) | 0 | ||||
-rw-r--r-- | remotes/locationIndependentIdentifierPre2019.json (renamed from json/remotes/locationIndependentIdentifierPre2019.json) | 0 | ||||
-rw-r--r-- | remotes/name-defs.json (renamed from json/remotes/name-defs.json) | 0 | ||||
-rw-r--r-- | remotes/name.json (renamed from json/remotes/name.json) | 0 | ||||
-rw-r--r-- | remotes/nested/foo-ref-string.json (renamed from json/remotes/nested/foo-ref-string.json) | 0 | ||||
-rw-r--r-- | remotes/nested/string.json (renamed from json/remotes/nested/string.json) | 0 | ||||
-rw-r--r-- | remotes/ref-and-definitions.json (renamed from json/remotes/ref-and-definitions.json) | 0 | ||||
-rw-r--r-- | remotes/ref-and-defs.json (renamed from json/remotes/ref-and-defs.json) | 0 | ||||
-rw-r--r-- | remotes/subSchemas-defs.json (renamed from json/remotes/subSchemas-defs.json) | 0 | ||||
-rw-r--r-- | remotes/subSchemas.json (renamed from json/remotes/subSchemas.json) | 0 | ||||
-rw-r--r-- | remotes/tree.json (renamed from json/remotes/tree.json) | 0 | ||||
-rw-r--r-- | test-schema.json (renamed from json/test-schema.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/additionalProperties.json (renamed from json/tests/draft-next/additionalProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/allOf.json (renamed from json/tests/draft-next/allOf.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/anchor.json (renamed from json/tests/draft-next/anchor.json) | 4 | ||||
-rw-r--r-- | tests/draft-next/anyOf.json (renamed from json/tests/draft-next/anyOf.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/boolean_schema.json (renamed from json/tests/draft-next/boolean_schema.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/const.json (renamed from json/tests/draft-next/const.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/contains.json (renamed from json/tests/draft-next/contains.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/content.json (renamed from json/tests/draft-next/content.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/default.json (renamed from json/tests/draft-next/default.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/defs.json (renamed from json/tests/draft-next/defs.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/dependentRequired.json (renamed from json/tests/draft-next/dependentRequired.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/dependentSchemas.json (renamed from json/tests/draft-next/dependentSchemas.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/dynamicRef.json (renamed from json/tests/draft-next/dynamicRef.json) | 4 | ||||
-rw-r--r-- | tests/draft-next/enum.json (renamed from json/tests/draft-next/enum.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/exclusiveMaximum.json (renamed from json/tests/draft-next/exclusiveMaximum.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/exclusiveMinimum.json (renamed from json/tests/draft-next/exclusiveMinimum.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/format.json (renamed from json/tests/draft-next/format.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/id.json (renamed from json/tests/draft-next/id.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/if-then-else.json (renamed from json/tests/draft-next/if-then-else.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/infinite-loop-detection.json (renamed from json/tests/draft-next/infinite-loop-detection.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/items.json (renamed from json/tests/draft-next/items.json) | 10 | ||||
-rw-r--r-- | tests/draft-next/maxContains.json (renamed from json/tests/draft-next/maxContains.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/maxItems.json (renamed from json/tests/draft-next/maxItems.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/maxLength.json (renamed from json/tests/draft-next/maxLength.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/maxProperties.json (renamed from json/tests/draft-next/maxProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/maximum.json (renamed from json/tests/draft-next/maximum.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/minContains.json (renamed from json/tests/draft-next/minContains.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/minItems.json (renamed from json/tests/draft-next/minItems.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/minLength.json (renamed from json/tests/draft-next/minLength.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/minProperties.json (renamed from json/tests/draft-next/minProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/minimum.json (renamed from json/tests/draft-next/minimum.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/multipleOf.json (renamed from json/tests/draft-next/multipleOf.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/not.json (renamed from json/tests/draft-next/not.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/oneOf.json (renamed from json/tests/draft-next/oneOf.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/bignum.json (renamed from json/tests/draft2020-12/optional/bignum.json) | 4 | ||||
-rw-r--r-- | tests/draft-next/optional/dependencies-compatibility.json (renamed from json/tests/draft-next/optional/dependencies-compatibility.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/ecmascript-regex.json (renamed from json/tests/draft-next/optional/ecmascript-regex.json) | 12 | ||||
-rw-r--r-- | tests/draft-next/optional/float-overflow.json (renamed from json/tests/draft-next/optional/float-overflow.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/format-assertion.json (renamed from json/tests/draft-next/optional/format-assertion.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/format/date-time.json (renamed from json/tests/draft2020-12/optional/format/date-time.json) | 4 | ||||
-rw-r--r-- | tests/draft-next/optional/format/date.json (renamed from json/tests/draft2019-09/optional/format/date.json) | 2 | ||||
-rw-r--r-- | tests/draft-next/optional/format/duration.json (renamed from json/tests/draft2019-09/optional/format/duration.json) | 2 | ||||
-rw-r--r-- | tests/draft-next/optional/format/email.json (renamed from json/tests/draft-next/optional/format/email.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/format/hostname.json (renamed from json/tests/draft-next/optional/format/hostname.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/format/idn-email.json (renamed from json/tests/draft-next/optional/format/idn-email.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/format/idn-hostname.json (renamed from json/tests/draft-next/optional/format/idn-hostname.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/format/ipv4.json (renamed from json/tests/draft2019-09/optional/format/ipv4.json) | 4 | ||||
-rw-r--r-- | tests/draft-next/optional/format/ipv6.json (renamed from json/tests/draft-next/optional/format/ipv6.json) | 4 | ||||
-rw-r--r-- | tests/draft-next/optional/format/iri-reference.json (renamed from json/tests/draft-next/optional/format/iri-reference.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/format/iri.json (renamed from json/tests/draft-next/optional/format/iri.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/format/json-pointer.json (renamed from json/tests/draft-next/optional/format/json-pointer.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/format/regex.json (renamed from json/tests/draft-next/optional/format/regex.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/format/relative-json-pointer.json (renamed from json/tests/draft-next/optional/format/relative-json-pointer.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/format/time.json (renamed from json/tests/draft2020-12/optional/format/time.json) | 2 | ||||
-rw-r--r-- | tests/draft-next/optional/format/uri-reference.json (renamed from json/tests/draft-next/optional/format/uri-reference.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/format/uri-template.json (renamed from json/tests/draft-next/optional/format/uri-template.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/format/uri.json (renamed from json/tests/draft-next/optional/format/uri.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/format/uuid.json (renamed from json/tests/draft-next/optional/format/uuid.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/non-bmp-regex.json (renamed from json/tests/draft-next/optional/non-bmp-regex.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/optional/refOfUnknownKeyword.json (renamed from json/tests/draft-next/optional/refOfUnknownKeyword.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/pattern.json (renamed from json/tests/draft-next/pattern.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/patternProperties.json (renamed from json/tests/draft-next/patternProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/prefixItems.json (renamed from json/tests/draft2020-12/prefixItems.json) | 2 | ||||
-rw-r--r-- | tests/draft-next/properties.json (renamed from json/tests/draft-next/properties.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/propertyNames.json (renamed from json/tests/draft-next/propertyNames.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/ref.json (renamed from json/tests/draft-next/ref.json) | 4 | ||||
-rw-r--r-- | tests/draft-next/refRemote.json (renamed from json/tests/draft-next/refRemote.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/required.json (renamed from json/tests/draft-next/required.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/type.json (renamed from json/tests/draft-next/type.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/unevaluatedItems.json (renamed from json/tests/draft-next/unevaluatedItems.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/unevaluatedProperties.json (renamed from json/tests/draft-next/unevaluatedProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/uniqueItems.json (renamed from json/tests/draft-next/uniqueItems.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/unknownKeyword.json (renamed from json/tests/draft-next/unknownKeyword.json) | 0 | ||||
-rw-r--r-- | tests/draft-next/vocabulary.json (renamed from json/tests/draft-next/vocabulary.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/additionalItems.json (renamed from json/tests/draft2019-09/additionalItems.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/additionalProperties.json (renamed from json/tests/draft2019-09/additionalProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/allOf.json (renamed from json/tests/draft2019-09/allOf.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/anchor.json (renamed from json/tests/draft2019-09/anchor.json) | 4 | ||||
-rw-r--r-- | tests/draft2019-09/anyOf.json (renamed from json/tests/draft2019-09/anyOf.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/boolean_schema.json (renamed from json/tests/draft2019-09/boolean_schema.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/const.json (renamed from json/tests/draft2019-09/const.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/contains.json (renamed from json/tests/draft2019-09/contains.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/content.json (renamed from json/tests/draft2019-09/content.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/default.json (renamed from json/tests/draft2019-09/default.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/defs.json (renamed from json/tests/draft2019-09/defs.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/dependentRequired.json (renamed from json/tests/draft2019-09/dependentRequired.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/dependentSchemas.json (renamed from json/tests/draft2019-09/dependentSchemas.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/enum.json (renamed from json/tests/draft2019-09/enum.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/exclusiveMaximum.json (renamed from json/tests/draft2019-09/exclusiveMaximum.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/exclusiveMinimum.json (renamed from json/tests/draft2019-09/exclusiveMinimum.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/format.json (renamed from json/tests/draft2019-09/format.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/id.json (renamed from json/tests/draft2019-09/id.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/if-then-else.json (renamed from json/tests/draft2019-09/if-then-else.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/infinite-loop-detection.json (renamed from json/tests/draft2019-09/infinite-loop-detection.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/items.json (renamed from json/tests/draft2019-09/items.json) | 4 | ||||
-rw-r--r-- | tests/draft2019-09/maxContains.json (renamed from json/tests/draft2019-09/maxContains.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/maxItems.json (renamed from json/tests/draft2019-09/maxItems.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/maxLength.json (renamed from json/tests/draft2019-09/maxLength.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/maxProperties.json (renamed from json/tests/draft2019-09/maxProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/maximum.json (renamed from json/tests/draft2019-09/maximum.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/minContains.json (renamed from json/tests/draft2019-09/minContains.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/minItems.json (renamed from json/tests/draft2019-09/minItems.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/minLength.json (renamed from json/tests/draft2019-09/minLength.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/minProperties.json (renamed from json/tests/draft2019-09/minProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/minimum.json (renamed from json/tests/draft2019-09/minimum.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/multipleOf.json (renamed from json/tests/draft2019-09/multipleOf.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/not.json (renamed from json/tests/draft2019-09/not.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/oneOf.json (renamed from json/tests/draft2019-09/oneOf.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/bignum.json (renamed from json/tests/draft2019-09/optional/bignum.json) | 4 | ||||
-rw-r--r-- | tests/draft2019-09/optional/dependencies-compatibility.json (renamed from json/tests/draft2019-09/optional/dependencies-compatibility.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/ecmascript-regex.json (renamed from json/tests/draft2019-09/optional/ecmascript-regex.json) | 12 | ||||
-rw-r--r-- | tests/draft2019-09/optional/float-overflow.json (renamed from json/tests/draft2019-09/optional/float-overflow.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/date-time.json (renamed from json/tests/draft2019-09/optional/format/date-time.json) | 4 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/date.json (renamed from json/tests/draft2020-12/optional/format/date.json) | 2 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/duration.json (renamed from json/tests/draft2020-12/optional/format/duration.json) | 2 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/email.json (renamed from json/tests/draft2019-09/optional/format/email.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/hostname.json (renamed from json/tests/draft2019-09/optional/format/hostname.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/idn-email.json (renamed from json/tests/draft2019-09/optional/format/idn-email.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/idn-hostname.json (renamed from json/tests/draft2019-09/optional/format/idn-hostname.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/ipv4.json (renamed from json/tests/draft2020-12/optional/format/ipv4.json) | 4 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/ipv6.json (renamed from json/tests/draft2020-12/optional/format/ipv6.json) | 4 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/iri-reference.json (renamed from json/tests/draft2019-09/optional/format/iri-reference.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/iri.json (renamed from json/tests/draft2019-09/optional/format/iri.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/json-pointer.json (renamed from json/tests/draft2019-09/optional/format/json-pointer.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/regex.json (renamed from json/tests/draft2019-09/optional/format/regex.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/relative-json-pointer.json (renamed from json/tests/draft2019-09/optional/format/relative-json-pointer.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/time.json (renamed from json/tests/draft7/optional/format/time.json) | 2 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/unknown.json (renamed from json/tests/draft2019-09/optional/format/unknown.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/uri-reference.json (renamed from json/tests/draft2019-09/optional/format/uri-reference.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/uri-template.json (renamed from json/tests/draft2019-09/optional/format/uri-template.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/uri.json (renamed from json/tests/draft2019-09/optional/format/uri.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/format/uuid.json (renamed from json/tests/draft2019-09/optional/format/uuid.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/non-bmp-regex.json (renamed from json/tests/draft2019-09/optional/non-bmp-regex.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/optional/refOfUnknownKeyword.json (renamed from json/tests/draft2019-09/optional/refOfUnknownKeyword.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/pattern.json (renamed from json/tests/draft2019-09/pattern.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/patternProperties.json (renamed from json/tests/draft2019-09/patternProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/properties.json (renamed from json/tests/draft2019-09/properties.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/propertyNames.json (renamed from json/tests/draft2019-09/propertyNames.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/recursiveRef.json (renamed from json/tests/draft2019-09/recursiveRef.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/ref.json (renamed from json/tests/draft2019-09/ref.json) | 4 | ||||
-rw-r--r-- | tests/draft2019-09/refRemote.json (renamed from json/tests/draft2019-09/refRemote.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/required.json (renamed from json/tests/draft2019-09/required.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/type.json (renamed from json/tests/draft2019-09/type.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/unevaluatedItems.json (renamed from json/tests/draft2019-09/unevaluatedItems.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/unevaluatedProperties.json (renamed from json/tests/draft2019-09/unevaluatedProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/uniqueItems.json (renamed from json/tests/draft2019-09/uniqueItems.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/unknownKeyword.json (renamed from json/tests/draft2019-09/unknownKeyword.json) | 0 | ||||
-rw-r--r-- | tests/draft2019-09/vocabulary.json (renamed from json/tests/draft2019-09/vocabulary.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/additionalProperties.json (renamed from json/tests/draft2020-12/additionalProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/allOf.json (renamed from json/tests/draft2020-12/allOf.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/anchor.json (renamed from json/tests/draft2020-12/anchor.json) | 4 | ||||
-rw-r--r-- | tests/draft2020-12/anyOf.json (renamed from json/tests/draft2020-12/anyOf.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/boolean_schema.json (renamed from json/tests/draft2020-12/boolean_schema.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/const.json (renamed from json/tests/draft2020-12/const.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/contains.json (renamed from json/tests/draft2020-12/contains.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/content.json (renamed from json/tests/draft2020-12/content.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/default.json (renamed from json/tests/draft2020-12/default.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/defs.json (renamed from json/tests/draft2020-12/defs.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/dependentRequired.json (renamed from json/tests/draft2020-12/dependentRequired.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/dependentSchemas.json (renamed from json/tests/draft2020-12/dependentSchemas.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/dynamicRef.json (renamed from json/tests/draft2020-12/dynamicRef.json) | 4 | ||||
-rw-r--r-- | tests/draft2020-12/enum.json (renamed from json/tests/draft2020-12/enum.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/exclusiveMaximum.json (renamed from json/tests/draft2020-12/exclusiveMaximum.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/exclusiveMinimum.json (renamed from json/tests/draft2020-12/exclusiveMinimum.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/format.json (renamed from json/tests/draft2020-12/format.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/id.json (renamed from json/tests/draft2020-12/id.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/if-then-else.json (renamed from json/tests/draft2020-12/if-then-else.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/infinite-loop-detection.json (renamed from json/tests/draft2020-12/infinite-loop-detection.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/items.json (renamed from json/tests/draft2020-12/items.json) | 10 | ||||
-rw-r--r-- | tests/draft2020-12/maxContains.json (renamed from json/tests/draft2020-12/maxContains.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/maxItems.json (renamed from json/tests/draft2020-12/maxItems.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/maxLength.json (renamed from json/tests/draft2020-12/maxLength.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/maxProperties.json (renamed from json/tests/draft2020-12/maxProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/maximum.json (renamed from json/tests/draft2020-12/maximum.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/minContains.json (renamed from json/tests/draft2020-12/minContains.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/minItems.json (renamed from json/tests/draft2020-12/minItems.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/minLength.json (renamed from json/tests/draft2020-12/minLength.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/minProperties.json (renamed from json/tests/draft2020-12/minProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/minimum.json (renamed from json/tests/draft2020-12/minimum.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/multipleOf.json (renamed from json/tests/draft2020-12/multipleOf.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/not.json (renamed from json/tests/draft2020-12/not.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/oneOf.json (renamed from json/tests/draft2020-12/oneOf.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/bignum.json (renamed from json/tests/draft6/optional/bignum.json) | 4 | ||||
-rw-r--r-- | tests/draft2020-12/optional/dependencies-compatibility.json (renamed from json/tests/draft2020-12/optional/dependencies-compatibility.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/ecmascript-regex.json (renamed from json/tests/draft2020-12/optional/ecmascript-regex.json) | 12 | ||||
-rw-r--r-- | tests/draft2020-12/optional/float-overflow.json (renamed from json/tests/draft2020-12/optional/float-overflow.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format-assertion.json (renamed from json/tests/draft2020-12/optional/format-assertion.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/date-time.json (renamed from json/tests/draft-next/optional/format/date-time.json) | 4 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/date.json (renamed from json/tests/draft7/optional/format/date.json) | 2 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/duration.json (renamed from json/tests/draft-next/optional/format/duration.json) | 2 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/email.json (renamed from json/tests/draft2020-12/optional/format/email.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/hostname.json (renamed from json/tests/draft2020-12/optional/format/hostname.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/idn-email.json (renamed from json/tests/draft2020-12/optional/format/idn-email.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/idn-hostname.json (renamed from json/tests/draft2020-12/optional/format/idn-hostname.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/ipv4.json (renamed from json/tests/draft4/optional/format/ipv4.json) | 4 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/ipv6.json (renamed from json/tests/draft2019-09/optional/format/ipv6.json) | 4 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/iri-reference.json (renamed from json/tests/draft2020-12/optional/format/iri-reference.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/iri.json (renamed from json/tests/draft2020-12/optional/format/iri.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/json-pointer.json (renamed from json/tests/draft2020-12/optional/format/json-pointer.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/regex.json (renamed from json/tests/draft2020-12/optional/format/regex.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/relative-json-pointer.json (renamed from json/tests/draft2020-12/optional/format/relative-json-pointer.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/time.json (renamed from json/tests/draft2019-09/optional/format/time.json) | 2 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/unknown.json (renamed from json/tests/draft2020-12/optional/format/unknown.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/uri-reference.json (renamed from json/tests/draft2020-12/optional/format/uri-reference.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/uri-template.json (renamed from json/tests/draft2020-12/optional/format/uri-template.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/uri.json (renamed from json/tests/draft2020-12/optional/format/uri.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/format/uuid.json (renamed from json/tests/draft2020-12/optional/format/uuid.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/non-bmp-regex.json (renamed from json/tests/draft2020-12/optional/non-bmp-regex.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/optional/refOfUnknownKeyword.json (renamed from json/tests/draft2020-12/optional/refOfUnknownKeyword.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/pattern.json (renamed from json/tests/draft2020-12/pattern.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/patternProperties.json (renamed from json/tests/draft2020-12/patternProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/prefixItems.json (renamed from json/tests/draft-next/prefixItems.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/properties.json (renamed from json/tests/draft2020-12/properties.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/propertyNames.json (renamed from json/tests/draft2020-12/propertyNames.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/ref.json (renamed from json/tests/draft2020-12/ref.json) | 4 | ||||
-rw-r--r-- | tests/draft2020-12/refRemote.json (renamed from json/tests/draft2020-12/refRemote.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/required.json (renamed from json/tests/draft2020-12/required.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/type.json (renamed from json/tests/draft2020-12/type.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/unevaluatedItems.json (renamed from json/tests/draft2020-12/unevaluatedItems.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/unevaluatedProperties.json (renamed from json/tests/draft2020-12/unevaluatedProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/uniqueItems.json (renamed from json/tests/draft2020-12/uniqueItems.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/unknownKeyword.json (renamed from json/tests/draft2020-12/unknownKeyword.json) | 0 | ||||
-rw-r--r-- | tests/draft2020-12/vocabulary.json (renamed from json/tests/draft2020-12/vocabulary.json) | 0 | ||||
-rw-r--r-- | tests/draft3/additionalItems.json (renamed from json/tests/draft3/additionalItems.json) | 0 | ||||
-rw-r--r-- | tests/draft3/additionalProperties.json (renamed from json/tests/draft3/additionalProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft3/default.json (renamed from json/tests/draft3/default.json) | 0 | ||||
-rw-r--r-- | tests/draft3/dependencies.json (renamed from json/tests/draft3/dependencies.json) | 0 | ||||
-rw-r--r-- | tests/draft3/disallow.json (renamed from json/tests/draft3/disallow.json) | 0 | ||||
-rw-r--r-- | tests/draft3/divisibleBy.json (renamed from json/tests/draft3/divisibleBy.json) | 0 | ||||
-rw-r--r-- | tests/draft3/enum.json (renamed from json/tests/draft3/enum.json) | 0 | ||||
-rw-r--r-- | tests/draft3/extends.json (renamed from json/tests/draft3/extends.json) | 0 | ||||
-rw-r--r-- | tests/draft3/format.json (renamed from json/tests/draft3/format.json) | 0 | ||||
-rw-r--r-- | tests/draft3/infinite-loop-detection.json (renamed from json/tests/draft3/infinite-loop-detection.json) | 0 | ||||
-rw-r--r-- | tests/draft3/items.json (renamed from json/tests/draft3/items.json) | 0 | ||||
-rw-r--r-- | tests/draft3/maxItems.json (renamed from json/tests/draft3/maxItems.json) | 0 | ||||
-rw-r--r-- | tests/draft3/maxLength.json (renamed from json/tests/draft3/maxLength.json) | 0 | ||||
-rw-r--r-- | tests/draft3/maximum.json (renamed from json/tests/draft3/maximum.json) | 0 | ||||
-rw-r--r-- | tests/draft3/minItems.json (renamed from json/tests/draft3/minItems.json) | 0 | ||||
-rw-r--r-- | tests/draft3/minLength.json (renamed from json/tests/draft3/minLength.json) | 0 | ||||
-rw-r--r-- | tests/draft3/minimum.json (renamed from json/tests/draft3/minimum.json) | 0 | ||||
-rw-r--r-- | tests/draft3/optional/bignum.json (renamed from json/tests/draft4/optional/bignum.json) | 4 | ||||
-rw-r--r-- | tests/draft3/optional/ecmascript-regex.json (renamed from json/tests/draft3/optional/ecmascript-regex.json) | 0 | ||||
-rw-r--r-- | tests/draft3/optional/format/color.json (renamed from json/tests/draft3/optional/format/color.json) | 0 | ||||
-rw-r--r-- | tests/draft3/optional/format/date-time.json (renamed from json/tests/draft3/optional/format/date-time.json) | 0 | ||||
-rw-r--r-- | tests/draft3/optional/format/date.json (renamed from json/tests/draft3/optional/format/date.json) | 0 | ||||
-rw-r--r-- | tests/draft3/optional/format/email.json (renamed from json/tests/draft3/optional/format/email.json) | 0 | ||||
-rw-r--r-- | tests/draft3/optional/format/host-name.json (renamed from json/tests/draft3/optional/format/host-name.json) | 0 | ||||
-rw-r--r-- | tests/draft3/optional/format/ip-address.json (renamed from json/tests/draft3/optional/format/ip-address.json) | 0 | ||||
-rw-r--r-- | tests/draft3/optional/format/ipv6.json (renamed from json/tests/draft3/optional/format/ipv6.json) | 0 | ||||
-rw-r--r-- | tests/draft3/optional/format/regex.json (renamed from json/tests/draft3/optional/format/regex.json) | 0 | ||||
-rw-r--r-- | tests/draft3/optional/format/time.json (renamed from json/tests/draft3/optional/format/time.json) | 0 | ||||
-rw-r--r-- | tests/draft3/optional/format/uri.json (renamed from json/tests/draft3/optional/format/uri.json) | 0 | ||||
-rw-r--r-- | tests/draft3/optional/non-bmp-regex.json (renamed from json/tests/draft3/optional/non-bmp-regex.json) | 0 | ||||
-rw-r--r-- | tests/draft3/optional/zeroTerminatedFloats.json (renamed from json/tests/draft3/optional/zeroTerminatedFloats.json) | 0 | ||||
-rw-r--r-- | tests/draft3/pattern.json (renamed from json/tests/draft3/pattern.json) | 0 | ||||
-rw-r--r-- | tests/draft3/patternProperties.json (renamed from json/tests/draft3/patternProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft3/properties.json (renamed from json/tests/draft3/properties.json) | 0 | ||||
-rw-r--r-- | tests/draft3/ref.json (renamed from json/tests/draft3/ref.json) | 0 | ||||
-rw-r--r-- | tests/draft3/refRemote.json (renamed from json/tests/draft3/refRemote.json) | 0 | ||||
-rw-r--r-- | tests/draft3/required.json (renamed from json/tests/draft3/required.json) | 0 | ||||
-rw-r--r-- | tests/draft3/type.json (renamed from json/tests/draft3/type.json) | 0 | ||||
-rw-r--r-- | tests/draft3/uniqueItems.json (renamed from json/tests/draft3/uniqueItems.json) | 0 | ||||
-rw-r--r-- | tests/draft4/additionalItems.json (renamed from json/tests/draft4/additionalItems.json) | 0 | ||||
-rw-r--r-- | tests/draft4/additionalProperties.json (renamed from json/tests/draft4/additionalProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft4/allOf.json (renamed from json/tests/draft4/allOf.json) | 0 | ||||
-rw-r--r-- | tests/draft4/anyOf.json (renamed from json/tests/draft4/anyOf.json) | 26 | ||||
-rw-r--r-- | tests/draft4/default.json (renamed from json/tests/draft4/default.json) | 0 | ||||
-rw-r--r-- | tests/draft4/definitions.json (renamed from json/tests/draft4/definitions.json) | 0 | ||||
-rw-r--r-- | tests/draft4/dependencies.json (renamed from json/tests/draft4/dependencies.json) | 0 | ||||
-rw-r--r-- | tests/draft4/enum.json (renamed from json/tests/draft4/enum.json) | 0 | ||||
-rw-r--r-- | tests/draft4/format.json (renamed from json/tests/draft4/format.json) | 0 | ||||
-rw-r--r-- | tests/draft4/id.json (renamed from json/tests/draft4/id.json) | 0 | ||||
-rw-r--r-- | tests/draft4/infinite-loop-detection.json (renamed from json/tests/draft4/infinite-loop-detection.json) | 0 | ||||
-rw-r--r-- | tests/draft4/items.json (renamed from json/tests/draft4/items.json) | 0 | ||||
-rw-r--r-- | tests/draft4/maxItems.json (renamed from json/tests/draft4/maxItems.json) | 0 | ||||
-rw-r--r-- | tests/draft4/maxLength.json (renamed from json/tests/draft4/maxLength.json) | 0 | ||||
-rw-r--r-- | tests/draft4/maxProperties.json (renamed from json/tests/draft4/maxProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft4/maximum.json (renamed from json/tests/draft4/maximum.json) | 0 | ||||
-rw-r--r-- | tests/draft4/minItems.json (renamed from json/tests/draft4/minItems.json) | 0 | ||||
-rw-r--r-- | tests/draft4/minLength.json (renamed from json/tests/draft4/minLength.json) | 0 | ||||
-rw-r--r-- | tests/draft4/minProperties.json (renamed from json/tests/draft4/minProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft4/minimum.json (renamed from json/tests/draft4/minimum.json) | 0 | ||||
-rw-r--r-- | tests/draft4/multipleOf.json (renamed from json/tests/draft4/multipleOf.json) | 0 | ||||
-rw-r--r-- | tests/draft4/not.json (renamed from json/tests/draft4/not.json) | 0 | ||||
-rw-r--r-- | tests/draft4/oneOf.json (renamed from json/tests/draft4/oneOf.json) | 0 | ||||
-rw-r--r-- | tests/draft4/optional/bignum.json | 95 | ||||
-rw-r--r-- | tests/draft4/optional/ecmascript-regex.json (renamed from json/tests/draft4/optional/ecmascript-regex.json) | 12 | ||||
-rw-r--r-- | tests/draft4/optional/float-overflow.json (renamed from json/tests/draft4/optional/float-overflow.json) | 0 | ||||
-rw-r--r-- | tests/draft4/optional/format/date-time.json (renamed from json/tests/draft4/optional/format/date-time.json) | 4 | ||||
-rw-r--r-- | tests/draft4/optional/format/email.json (renamed from json/tests/draft4/optional/format/email.json) | 0 | ||||
-rw-r--r-- | tests/draft4/optional/format/hostname.json (renamed from json/tests/draft4/optional/format/hostname.json) | 0 | ||||
-rw-r--r-- | tests/draft4/optional/format/ipv4.json (renamed from json/tests/draft-next/optional/format/ipv4.json) | 4 | ||||
-rw-r--r-- | tests/draft4/optional/format/ipv6.json (renamed from json/tests/draft4/optional/format/ipv6.json) | 4 | ||||
-rw-r--r-- | tests/draft4/optional/format/unknown.json (renamed from json/tests/draft4/optional/format/unknown.json) | 0 | ||||
-rw-r--r-- | tests/draft4/optional/format/uri.json (renamed from json/tests/draft4/optional/format/uri.json) | 0 | ||||
-rw-r--r-- | tests/draft4/optional/non-bmp-regex.json (renamed from json/tests/draft4/optional/non-bmp-regex.json) | 0 | ||||
-rw-r--r-- | tests/draft4/optional/zeroTerminatedFloats.json (renamed from json/tests/draft4/optional/zeroTerminatedFloats.json) | 0 | ||||
-rw-r--r-- | tests/draft4/pattern.json (renamed from json/tests/draft4/pattern.json) | 0 | ||||
-rw-r--r-- | tests/draft4/patternProperties.json (renamed from json/tests/draft4/patternProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft4/properties.json (renamed from json/tests/draft4/properties.json) | 0 | ||||
-rw-r--r-- | tests/draft4/ref.json (renamed from json/tests/draft4/ref.json) | 4 | ||||
-rw-r--r-- | tests/draft4/refRemote.json (renamed from json/tests/draft4/refRemote.json) | 0 | ||||
-rw-r--r-- | tests/draft4/required.json (renamed from json/tests/draft4/required.json) | 0 | ||||
-rw-r--r-- | tests/draft4/type.json (renamed from json/tests/draft4/type.json) | 0 | ||||
-rw-r--r-- | tests/draft4/uniqueItems.json (renamed from json/tests/draft4/uniqueItems.json) | 0 | ||||
-rw-r--r-- | tests/draft6/additionalItems.json (renamed from json/tests/draft6/additionalItems.json) | 0 | ||||
-rw-r--r-- | tests/draft6/additionalProperties.json (renamed from json/tests/draft6/additionalProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft6/allOf.json (renamed from json/tests/draft6/allOf.json) | 0 | ||||
-rw-r--r-- | tests/draft6/anyOf.json (renamed from json/tests/draft6/anyOf.json) | 26 | ||||
-rw-r--r-- | tests/draft6/boolean_schema.json (renamed from json/tests/draft6/boolean_schema.json) | 0 | ||||
-rw-r--r-- | tests/draft6/const.json (renamed from json/tests/draft6/const.json) | 0 | ||||
-rw-r--r-- | tests/draft6/contains.json (renamed from json/tests/draft6/contains.json) | 0 | ||||
-rw-r--r-- | tests/draft6/default.json (renamed from json/tests/draft6/default.json) | 0 | ||||
-rw-r--r-- | tests/draft6/definitions.json (renamed from json/tests/draft6/definitions.json) | 0 | ||||
-rw-r--r-- | tests/draft6/dependencies.json (renamed from json/tests/draft6/dependencies.json) | 0 | ||||
-rw-r--r-- | tests/draft6/enum.json (renamed from json/tests/draft6/enum.json) | 0 | ||||
-rw-r--r-- | tests/draft6/exclusiveMaximum.json (renamed from json/tests/draft6/exclusiveMaximum.json) | 0 | ||||
-rw-r--r-- | tests/draft6/exclusiveMinimum.json (renamed from json/tests/draft6/exclusiveMinimum.json) | 0 | ||||
-rw-r--r-- | tests/draft6/format.json (renamed from json/tests/draft6/format.json) | 0 | ||||
-rw-r--r-- | tests/draft6/id.json (renamed from json/tests/draft6/id.json) | 0 | ||||
-rw-r--r-- | tests/draft6/infinite-loop-detection.json (renamed from json/tests/draft6/infinite-loop-detection.json) | 0 | ||||
-rw-r--r-- | tests/draft6/items.json (renamed from json/tests/draft6/items.json) | 0 | ||||
-rw-r--r-- | tests/draft6/maxItems.json (renamed from json/tests/draft6/maxItems.json) | 0 | ||||
-rw-r--r-- | tests/draft6/maxLength.json (renamed from json/tests/draft6/maxLength.json) | 0 | ||||
-rw-r--r-- | tests/draft6/maxProperties.json (renamed from json/tests/draft6/maxProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft6/maximum.json (renamed from json/tests/draft6/maximum.json) | 0 | ||||
-rw-r--r-- | tests/draft6/minItems.json (renamed from json/tests/draft6/minItems.json) | 0 | ||||
-rw-r--r-- | tests/draft6/minLength.json (renamed from json/tests/draft6/minLength.json) | 0 | ||||
-rw-r--r-- | tests/draft6/minProperties.json (renamed from json/tests/draft6/minProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft6/minimum.json (renamed from json/tests/draft6/minimum.json) | 0 | ||||
-rw-r--r-- | tests/draft6/multipleOf.json (renamed from json/tests/draft6/multipleOf.json) | 0 | ||||
-rw-r--r-- | tests/draft6/not.json (renamed from json/tests/draft6/not.json) | 0 | ||||
-rw-r--r-- | tests/draft6/oneOf.json (renamed from json/tests/draft6/oneOf.json) | 0 | ||||
-rw-r--r-- | tests/draft6/optional/bignum.json (renamed from json/tests/draft-next/optional/bignum.json) | 4 | ||||
-rw-r--r-- | tests/draft6/optional/ecmascript-regex.json (renamed from json/tests/draft7/optional/ecmascript-regex.json) | 12 | ||||
-rw-r--r-- | tests/draft6/optional/float-overflow.json (renamed from json/tests/draft6/optional/float-overflow.json) | 0 | ||||
-rw-r--r-- | tests/draft6/optional/format/date-time.json | 133 | ||||
-rw-r--r-- | tests/draft6/optional/format/email.json (renamed from json/tests/draft6/optional/format/email.json) | 0 | ||||
-rw-r--r-- | tests/draft6/optional/format/hostname.json (renamed from json/tests/draft6/optional/format/hostname.json) | 0 | ||||
-rw-r--r-- | tests/draft6/optional/format/ipv4.json | 84 | ||||
-rw-r--r-- | tests/draft6/optional/format/ipv6.json | 208 | ||||
-rw-r--r-- | tests/draft6/optional/format/json-pointer.json (renamed from json/tests/draft6/optional/format/json-pointer.json) | 0 | ||||
-rw-r--r-- | tests/draft6/optional/format/unknown.json (renamed from json/tests/draft6/optional/format/unknown.json) | 0 | ||||
-rw-r--r-- | tests/draft6/optional/format/uri-reference.json (renamed from json/tests/draft6/optional/format/uri-reference.json) | 0 | ||||
-rw-r--r-- | tests/draft6/optional/format/uri-template.json (renamed from json/tests/draft6/optional/format/uri-template.json) | 0 | ||||
-rw-r--r-- | tests/draft6/optional/format/uri.json (renamed from json/tests/draft6/optional/format/uri.json) | 0 | ||||
-rw-r--r-- | tests/draft6/optional/non-bmp-regex.json (renamed from json/tests/draft6/optional/non-bmp-regex.json) | 0 | ||||
-rw-r--r-- | tests/draft6/pattern.json (renamed from json/tests/draft6/pattern.json) | 0 | ||||
-rw-r--r-- | tests/draft6/patternProperties.json (renamed from json/tests/draft6/patternProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft6/properties.json (renamed from json/tests/draft6/properties.json) | 0 | ||||
-rw-r--r-- | tests/draft6/propertyNames.json (renamed from json/tests/draft6/propertyNames.json) | 0 | ||||
-rw-r--r-- | tests/draft6/ref.json (renamed from json/tests/draft6/ref.json) | 0 | ||||
-rw-r--r-- | tests/draft6/refRemote.json (renamed from json/tests/draft6/refRemote.json) | 0 | ||||
-rw-r--r-- | tests/draft6/required.json (renamed from json/tests/draft6/required.json) | 0 | ||||
-rw-r--r-- | tests/draft6/type.json (renamed from json/tests/draft6/type.json) | 0 | ||||
-rw-r--r-- | tests/draft6/uniqueItems.json (renamed from json/tests/draft6/uniqueItems.json) | 0 | ||||
-rw-r--r-- | tests/draft6/unknownKeyword.json (renamed from json/tests/draft6/unknownKeyword.json) | 0 | ||||
-rw-r--r-- | tests/draft7/additionalItems.json (renamed from json/tests/draft7/additionalItems.json) | 0 | ||||
-rw-r--r-- | tests/draft7/additionalProperties.json (renamed from json/tests/draft7/additionalProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft7/allOf.json (renamed from json/tests/draft7/allOf.json) | 0 | ||||
-rw-r--r-- | tests/draft7/anyOf.json | 189 | ||||
-rw-r--r-- | tests/draft7/boolean_schema.json (renamed from json/tests/draft7/boolean_schema.json) | 0 | ||||
-rw-r--r-- | tests/draft7/const.json (renamed from json/tests/draft7/const.json) | 0 | ||||
-rw-r--r-- | tests/draft7/contains.json (renamed from json/tests/draft7/contains.json) | 0 | ||||
-rw-r--r-- | tests/draft7/default.json (renamed from json/tests/draft7/default.json) | 0 | ||||
-rw-r--r-- | tests/draft7/definitions.json (renamed from json/tests/draft7/definitions.json) | 0 | ||||
-rw-r--r-- | tests/draft7/dependencies.json (renamed from json/tests/draft7/dependencies.json) | 0 | ||||
-rw-r--r-- | tests/draft7/enum.json (renamed from json/tests/draft7/enum.json) | 0 | ||||
-rw-r--r-- | tests/draft7/exclusiveMaximum.json (renamed from json/tests/draft7/exclusiveMaximum.json) | 0 | ||||
-rw-r--r-- | tests/draft7/exclusiveMinimum.json (renamed from json/tests/draft7/exclusiveMinimum.json) | 0 | ||||
-rw-r--r-- | tests/draft7/format.json (renamed from json/tests/draft7/format.json) | 0 | ||||
-rw-r--r-- | tests/draft7/id.json (renamed from json/tests/draft7/id.json) | 0 | ||||
-rw-r--r-- | tests/draft7/if-then-else.json (renamed from json/tests/draft7/if-then-else.json) | 0 | ||||
-rw-r--r-- | tests/draft7/infinite-loop-detection.json (renamed from json/tests/draft7/infinite-loop-detection.json) | 0 | ||||
-rw-r--r-- | tests/draft7/items.json (renamed from json/tests/draft7/items.json) | 0 | ||||
-rw-r--r-- | tests/draft7/maxItems.json (renamed from json/tests/draft7/maxItems.json) | 0 | ||||
-rw-r--r-- | tests/draft7/maxLength.json (renamed from json/tests/draft7/maxLength.json) | 0 | ||||
-rw-r--r-- | tests/draft7/maxProperties.json (renamed from json/tests/draft7/maxProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft7/maximum.json (renamed from json/tests/draft7/maximum.json) | 0 | ||||
-rw-r--r-- | tests/draft7/minItems.json (renamed from json/tests/draft7/minItems.json) | 0 | ||||
-rw-r--r-- | tests/draft7/minLength.json (renamed from json/tests/draft7/minLength.json) | 0 | ||||
-rw-r--r-- | tests/draft7/minProperties.json (renamed from json/tests/draft7/minProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft7/minimum.json (renamed from json/tests/draft7/minimum.json) | 0 | ||||
-rw-r--r-- | tests/draft7/multipleOf.json (renamed from json/tests/draft7/multipleOf.json) | 0 | ||||
-rw-r--r-- | tests/draft7/not.json (renamed from json/tests/draft7/not.json) | 0 | ||||
-rw-r--r-- | tests/draft7/oneOf.json (renamed from json/tests/draft7/oneOf.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/bignum.json | 93 | ||||
-rw-r--r-- | tests/draft7/optional/content.json (renamed from json/tests/draft7/optional/content.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/ecmascript-regex.json (renamed from json/tests/draft6/optional/ecmascript-regex.json) | 12 | ||||
-rw-r--r-- | tests/draft7/optional/float-overflow.json (renamed from json/tests/draft7/optional/float-overflow.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/format/date-time.json | 133 | ||||
-rw-r--r-- | tests/draft7/optional/format/date.json (renamed from json/tests/draft-next/optional/format/date.json) | 2 | ||||
-rw-r--r-- | tests/draft7/optional/format/email.json (renamed from json/tests/draft7/optional/format/email.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/format/hostname.json (renamed from json/tests/draft7/optional/format/hostname.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/format/idn-email.json (renamed from json/tests/draft7/optional/format/idn-email.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/format/idn-hostname.json (renamed from json/tests/draft7/optional/format/idn-hostname.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/format/ipv4.json | 84 | ||||
-rw-r--r-- | tests/draft7/optional/format/ipv6.json | 208 | ||||
-rw-r--r-- | tests/draft7/optional/format/iri-reference.json (renamed from json/tests/draft7/optional/format/iri-reference.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/format/iri.json (renamed from json/tests/draft7/optional/format/iri.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/format/json-pointer.json (renamed from json/tests/draft7/optional/format/json-pointer.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/format/regex.json (renamed from json/tests/draft7/optional/format/regex.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/format/relative-json-pointer.json (renamed from json/tests/draft7/optional/format/relative-json-pointer.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/format/time.json (renamed from json/tests/draft-next/optional/format/time.json) | 2 | ||||
-rw-r--r-- | tests/draft7/optional/format/unknown.json (renamed from json/tests/draft7/optional/format/unknown.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/format/uri-reference.json (renamed from json/tests/draft7/optional/format/uri-reference.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/format/uri-template.json (renamed from json/tests/draft7/optional/format/uri-template.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/format/uri.json (renamed from json/tests/draft7/optional/format/uri.json) | 0 | ||||
-rw-r--r-- | tests/draft7/optional/non-bmp-regex.json (renamed from json/tests/draft7/optional/non-bmp-regex.json) | 0 | ||||
-rw-r--r-- | tests/draft7/pattern.json (renamed from json/tests/draft7/pattern.json) | 0 | ||||
-rw-r--r-- | tests/draft7/patternProperties.json (renamed from json/tests/draft7/patternProperties.json) | 0 | ||||
-rw-r--r-- | tests/draft7/properties.json (renamed from json/tests/draft7/properties.json) | 0 | ||||
-rw-r--r-- | tests/draft7/propertyNames.json (renamed from json/tests/draft7/propertyNames.json) | 0 | ||||
-rw-r--r-- | tests/draft7/ref.json (renamed from json/tests/draft7/ref.json) | 4 | ||||
-rw-r--r-- | tests/draft7/refRemote.json (renamed from json/tests/draft7/refRemote.json) | 0 | ||||
-rw-r--r-- | tests/draft7/required.json (renamed from json/tests/draft7/required.json) | 0 | ||||
-rw-r--r-- | tests/draft7/type.json (renamed from json/tests/draft7/type.json) | 0 | ||||
-rw-r--r-- | tests/draft7/uniqueItems.json (renamed from json/tests/draft7/uniqueItems.json) | 0 | ||||
-rw-r--r-- | tests/draft7/unknownKeyword.json (renamed from json/tests/draft7/unknownKeyword.json) | 0 | ||||
l--------- | tests/latest (renamed from json/tests/latest) | 0 | ||||
-rw-r--r-- | tox.ini | 121 |
527 files changed, 1467 insertions, 17042 deletions
diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 5c6eb7e..0000000 --- a/.coveragerc +++ /dev/null @@ -1,10 +0,0 @@ -# vim: filetype=dosini: -[run] -branch = True -source = jsonschema -omit = */jsonschema/_reflect.py,*/jsonschema/__main__.py,*/jsonschema/benchmarks/*,*/jsonschema/tests/fuzz_validate.py - -[report] -exclude_lines = - pragma: no cover - if TYPE_CHECKING: diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 6a6b5cf..0000000 --- a/.flake8 +++ /dev/null @@ -1,10 +0,0 @@ -[flake8] -ban-relative-imports = true -inline-quotes = " -exclude = - jsonschema/__init__.py - jsonschema/_reflect.py -ignore = - B008, # Barring function calls in default args. Ha, no. - B306, # See https://github.com/PyCQA/flake8-bugbear/issues/131 - W503, # (flake8 default) old PEP8 boolean operator line breaks diff --git a/json/.github/CODEOWNERS b/.github/CODEOWNERS index 15f4a2d..15f4a2d 100644 --- a/json/.github/CODEOWNERS +++ b/.github/CODEOWNERS diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 39a1618..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,4 +0,0 @@ -# These are supported funding model platforms - -github: "Julian" -tidelift: "pypi/jsonschema" diff --git a/.github/SECURITY.md b/.github/SECURITY.md deleted file mode 100644 index fd524e9..0000000 --- a/.github/SECURITY.md +++ /dev/null @@ -1,21 +0,0 @@ -# Security Policy - -## Supported Versions - -In general, only the latest released ``jsonschema`` version is supported -and will receive updates. - -## Reporting a Vulnerability - -To report a security vulnerability, please send an email to -``Julian+Security@GrayVines.com`` with subject line ``SECURITY -(jsonschema)``. - -I will do my best to respond within 48 hours to acknowledge the message -and discuss further steps. - -If the vulnerability is accepted, an advisory will be sent out via -GitHub's security advisory functionality. - -For non-sensitive discussion related to this policy itself, feel free to -open an issue on the issue tracker. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e77123f..a826069 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: CI +name: Test Suite Sanity Checking on: push: @@ -6,229 +6,20 @@ on: release: types: [published] schedule: - # Daily at 3:21 - - cron: '21 3 * * *' + # Daily at 6:42, arbitrarily as a time that's possibly non-busy + - cron: '42 6 * * *' jobs: - pre-commit: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 - - uses: pre-commit/action@v2.0.3 - ci: - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [macos-latest, ubuntu-latest, windows-latest] - python-version: - - name: pypy-3.8 - toxenv: pypy3-noextra-build - - name: pypy-3.8 - toxenv: pypy3-noextra-tests - - name: pypy-3.8 - toxenv: pypy3-format-build - - name: pypy-3.8 - toxenv: pypy3-format-tests - - name: pypy-3.8 - toxenv: pypy3-formatnongpl-build - - name: pypy-3.8 - toxenv: pypy3-formatnongpl-tests - - name: 3.7 - toxenv: py37-noextra-build - - name: 3.7 - toxenv: py37-noextra-tests - - name: 3.7 - toxenv: py37-format-build - - name: 3.7 - toxenv: py37-format-tests - - name: 3.7 - toxenv: py37-formatnongpl-build - - name: 3.7 - toxenv: py37-formatnongpl-tests - - name: 3.8 - toxenv: py38-noextra-build - - name: 3.8 - toxenv: py38-noextra-tests - - name: 3.8 - toxenv: py38-format-build - - name: 3.8 - toxenv: py38-format-tests - - name: 3.8 - toxenv: py38-formatnongpl-build - - name: 3.8 - toxenv: py38-formatnongpl-tests - - name: 3.9 - toxenv: py39-noextra-build - - name: 3.9 - toxenv: py39-noextra-tests - - name: 3.9 - toxenv: py39-format-build - - name: 3.9 - toxenv: py39-format-tests - - name: 3.9 - toxenv: py39-formatnongpl-build - - name: 3.9 - toxenv: py39-formatnongpl-tests - - name: "3.10" - toxenv: py310-noextra-build - - name: "3.10" - toxenv: py310-noextra-tests - - name: "3.10" - toxenv: py310-format-build - - name: "3.10" - toxenv: py310-format-tests - - name: "3.10" - toxenv: py310-formatnongpl-build - - name: "3.10" - toxenv: py310-formatnongpl-tests - - name: "3.11.0-beta - 3.11.0" - toxenv: py311-noextra-build - - name: "3.11.0-beta - 3.11.0" - toxenv: py311-noextra-tests - - name: "3.11.0-beta - 3.11.0" - toxenv: py311-format-build - - name: "3.11.0-beta - 3.11.0" - toxenv: py311-format-tests - - name: "3.11.0-beta - 3.11.0" - toxenv: py311-formatnongpl-build - - name: "3.11.0-beta - 3.11.0" - toxenv: py311-formatnongpl-tests - - name: "3.10" - toxenv: docs-dirhtml - - name: "3.10" - toxenv: docs-doctest - - name: "3.10" - toxenv: docs-linkcheck - - name: "3.10" - toxenv: docs-spelling - - name: "3.10" - toxenv: docs-style - - name: "3.10" - toxenv: readme - - name: "3.10" - toxenv: safety - - name: "3.10" - toxenv: secrets - - name: "3.10" - toxenv: style - - name: "3.10" - toxenv: typing - exclude: - - os: windows-latest - python-version: - name: pypy-3.8 - toxenv: pypy3-noextra-build - - os: windows-latest - python-version: - name: pypy-3.8 - toxenv: pypy3-noextra-tests - - os: windows-latest - python-version: - name: pypy-3.8 - toxenv: pypy3-format-build - - os: windows-latest - python-version: - name: pypy-3.8 - toxenv: pypy3-format-tests - - os: windows-latest - python-version: - name: pypy-3.8 - toxenv: pypy3-formatnongpl-build - - os: windows-latest - python-version: - name: pypy-3.8 - toxenv: pypy3-formatnongpl-tests - - os: windows-latest - python-version: - name: "3.10" - toxenv: py310-noextra-tests - - os: windows-latest - python-version: - name: "3.10" - toxenv: py310-format-tests - - os: windows-latest - python-version: - name: "3.10" - toxenv: py310-formatnongpl-tests - - os: windows-latest - python-version: - name: "3.11.0-alpha - 3.11.0" - toxenv: py311-noextra-tests - - os: windows-latest - python-version: - name: "3.11.0-alpha - 3.11.0" - toxenv: py311-format-tests - - os: windows-latest - python-version: - name: "3.11.0-alpha - 3.11.0" - toxenv: py311-formatnongpl-tests - - os: windows-latest - python-version: - name: "3.10" - toxenv: readme - - os: windows-latest - python-version: - name: "3.10" - toxenv: docs-linkcheck - - os: windows-latest - python-version: - name: "3.10" - toxenv: docs-style + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version.name }} - uses: actions/setup-python@v3 + - name: Set up Python + uses: actions/setup-python@v4 with: - python-version: ${{ matrix.python-version.name }} - - name: Install dependencies - run: > - sudo apt-get update && - sudo apt-get install -y libenchant-dev libxml2-dev libxslt-dev - if: runner.os == 'Linux' && startsWith(matrix.python-version.toxenv, 'docs-') - - name: Install dependencies - run: brew install enchant - if: runner.os == 'macOS' && startsWith(matrix.python-version.toxenv, 'docs-') + python-version: '3.x' - name: Install tox run: python -m pip install tox - - name: Run tox - run: python -m tox -e "${{ matrix.python-version.toxenv }}" - - packaging: - needs: ci - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - uses: actions/setup-python@v3 - with: - python-version: "3.10" - - name: Install dependencies - run: python -m pip install build - - name: Create packages - run: python -m build . - - uses: actions/upload-artifact@v3 - with: - name: dist - path: dist - - name: Publish package - if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') - uses: pypa/gh-action-pypi-publish@master - with: - user: __token__ - password: ${{ secrets.pypi_password }} - - name: Create Release Notes - if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') - uses: actions/github-script@v6 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - await github.request(`POST /repos/${{ github.repository }}/releases`, { - tag_name: "${{ github.ref }}", - generate_release_notes: true - }); + - name: Run the sanity checks + run: python -m tox diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml deleted file mode 100644 index 3edc627..0000000 --- a/.github/workflows/coverage.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Coverage - -on: - push: - pull_request: - release: - types: [published] - -jobs: - coverage: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v3 - with: - python-version: "3.10" - - name: Install tox - run: python -m pip install tox - - name: Collect & Upload Coverage - # codecov.io is too flaky to fail for this right now - continue-on-error: true - run: python -m tox -e py39-format-codecov - env: - CODECOV_TOKEN: 2b38dae1-41c4-4435-a29d-79a1299e5617 diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml deleted file mode 100644 index dcc49a3..0000000 --- a/.github/workflows/fuzz.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: CIFuzz - -on: - pull_request: - branches: - - main - -jobs: - Fuzzing: - runs-on: ubuntu-latest - steps: - - name: Build Fuzzers - id: build - uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master - with: - oss-fuzz-project-name: 'jsonschema' - language: python - continue-on-error: true - - name: Run Fuzzers - if: steps.build.outcome == 'success' - uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master - with: - oss-fuzz-project-name: 'jsonschema' - fuzz-seconds: 30 - - name: Upload Crash - uses: actions/upload-artifact@v3 - if: failure() && steps.build.outcome == 'success' - with: - name: artifacts - path: ./out/artifacts @@ -101,7 +101,15 @@ ipython_config.py # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control #poetry.lock -# PEP 582; used by e.g. github.com/David-OConnor/pyflow +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm __pypackages__/ # Celery stuff @@ -145,13 +153,8 @@ dmypy.json cython_debug/ # PyCharm -# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ - -# User defined -_cache -_static -_templates diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index 5cec24c..0000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,22 +0,0 @@ -exclude: json/ - -repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.3.0 - hooks: - - id: check-ast - - id: check-docstring-first - - id: check-json - - id: check-toml - - id: check-vcs-permalinks - - id: check-yaml - - id: debug-statements - exclude: '^jsonschema/tests/_suite.py$' - - id: end-of-file-fixer - - id: mixed-line-ending - args: [--fix, lf] - - id: trailing-whitespace - - repo: https://github.com/PyCQA/isort - rev: 5.10.1 - hooks: - - id: isort diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml deleted file mode 100644 index f806715..0000000 --- a/.pre-commit-hooks.yaml +++ /dev/null @@ -1,6 +0,0 @@ -- id: jsonschema - name: jsonschema - description: json schema validation - language: python - pass_filenames: false - entry: jsonschema diff --git a/.readthedocs.yml b/.readthedocs.yml deleted file mode 100644 index 5750166..0000000 --- a/.readthedocs.yml +++ /dev/null @@ -1,15 +0,0 @@ -version: 2 - -sphinx: - builder: dirhtml - configuration: docs/conf.py - fail_on_warning: true - -formats: all - -python: - version: 3.8 - install: - - requirements: docs/requirements.txt - - method: pip - path: . diff --git a/CHANGELOG.rst b/CHANGELOG.rst deleted file mode 100644 index 986c0f4..0000000 --- a/CHANGELOG.rst +++ /dev/null @@ -1,369 +0,0 @@ -v4.9.1 ------- - -* Update some documentation examples to use newer validator releases in their - sample code. - -v4.9.0 ------- - -* Fix relative ``$ref`` resolution when the base URI is a URN or other scheme - (#544). -* ``pkgutil.resolve_name`` is now used to retrieve validators - provided on the command line. This function is only available on - 3.9+, so 3.7 and 3.8 (which are still supported) now rely on the - `pkgutil_resolve_name <https://pypi.org/project/pkgutil_resolve_name/>`_ - backport package. Note however that the CLI itself is due - to be deprecated shortly in favor of `check-jsonschema - <https://github.com/python-jsonschema/check-jsonschema>`_. - -v4.8.0 ------- - -* ``best_match`` no longer traverses into ``anyOf`` and ``oneOf`` when all of - the errors within them seem equally applicable. This should lead to clearer - error messages in some cases where no branches were matched. - -v4.7.2 ------- - -* Also have ``best_match`` handle cases where the ``type`` validator is an - array. - -v4.7.1 ------- - -* Minor tweak of the PyPI hyperlink names - -v4.7.0 ------- - -* Enhance ``best_match`` to prefer errors from branches of the schema which - match the instance's type (#728) - -v4.6.2 ------- - -* Fix a number of minor typos in docstrings, mostly private ones (#969) - -v4.6.1 ------- - -* Gut the (incomplete) implementation of ``recursiveRef`` on draft 2019. It - needs completing, but for now can lead to recursion errors (e.g. #847). - -v4.6.0 ------- - -* Fix ``unevaluatedProperties`` and ``unevaluatedItems`` for types they should - ignore (#949) -* ``jsonschema`` now uses `hatch <https://hatch.pypa.io/>`_ for its build - process. This should be completely transparent to end-users (and only matters - to contributors). - -v4.5.1 ------- - -* Revert changes to ``$dynamicRef`` which caused a performance regression - in v4.5.0 - -v4.5.0 ------- - -* Validator classes for each version now maintain references to the correct - corresponding format checker (#905) -* Development has moved to a `GitHub organization - <https://github.com/python-jsonschema/>`_. - No functional behavior changes are expected from the change. - -v4.4.0 ------- - -* Add ``mypy`` support (#892) -* Add support for Python 3.11 - -v4.3.3 ------- - -* Properly report deprecation warnings at the right stack level (#899) - -v4.3.2 ------- - -* Additional performance improvements for resolving refs (#896) - -v4.3.1 ------- - -* Resolving refs has had performance improvements (#893) - -v4.3.0 ------- - -* Fix undesired fallback to brute force container uniqueness check on - certain input types (#893) -* Implement a PEP544 Protocol for validator classes (#890) - -v4.2.1 ------- - -* Pin ``importlib.resources`` from below (#877) - -v4.2.0 ------- - -* Use ``importlib.resources`` to load schemas (#873) -* Ensure all elements of arrays are verified for uniqueness by ``uniqueItems`` - (#866) - -v4.1.2 ------- - -* Fix ``dependentSchemas`` to properly consider non-object instances to be - valid (#850) - -v4.1.1 ------- - -* Fix ``prefixItems`` not indicating which item was invalid within the instance - path (#862) - -v4.1.0 ------- - -* Add Python 3.10 to the list of supported Python versions - -v4.0.1 ------- - -* Fix the declaration of minimum supported Python version (#846) - -v4.0.0 ------- - -* Partial support for Draft 2020-12 (as well as 2019-09). - Thanks to Thomas Schmidt and Harald Nezbeda. -* ``False`` and ``0`` are now properly considered non-equal even - recursively within a container (#686). As part of this change, - ``uniqueItems`` validation may be *slower* in some cases. Please feel - free to report any significant performance regressions, though in - some cases they may be difficult to address given the specification - requirement. -* The CLI has been improved, and in particular now supports a ``--output`` - option (with ``plain`` (default) or ``pretty`` arguments) to control the - output format. Future work may add additional machine-parsable output - formats. -* Code surrounding ``DEFAULT_TYPES`` and the legacy mechanism for - specifying types to validators have been removed, as per the deprecation - policy. Validators should use the ``TypeChecker`` object to customize - the set of Python types corresponding to JSON Schema types. -* Validation errors now have a ``json_path`` attribute, describing their - location in JSON path format -* Support for the IP address and domain name formats has been improved -* Support for Python 2 and 3.6 has been dropped, with ``python_requires`` - properly set. -* ``multipleOf`` could overflow when given sufficiently large numbers. Now, - when an overflow occurs, ``jsonschema`` will fall back to using fraction - division (#746). -* ``jsonschema.__version__``, ``jsonschema.validators.validators``, - ``jsonschema.validators.meta_schemas`` and - ``jsonschema.RefResolver.in_scope`` have been deprecated, as has - passing a second-argument schema to ``Validator.iter_errors`` and - ``Validator.is_valid``. - -v3.2.0 ------- - -* Added a ``format_nongpl`` setuptools extra, which installs only ``format`` - dependencies that are non-GPL (#619). - -v3.1.1 ------- - -* Temporarily revert the switch to ``js-regex`` until #611 and #612 are - resolved. - -v3.1.0 ------- - -* Regular expressions throughout schemas now respect the ECMA 262 dialect, as - recommended by the specification (#609). - -v3.0.2 ------- - -* Fixed a bug where ``0`` and ``False`` were considered equal by - ``const`` and ``enum`` (#575). - -v3.0.1 ------- - -* Fixed a bug where extending validators did not preserve their notion - of which validator property contains ``$id`` information. - -v3.0.0 ------- - -* Support for Draft 6 and Draft 7 -* Draft 7 is now the default -* New ``TypeChecker`` object for more complex type definitions (and overrides) -* Falling back to isodate for the date-time format checker is no longer - attempted, in accordance with the specification - -v2.6.0 ------- - -* Support for Python 2.6 has been dropped. -* Improve a few error messages for ``uniqueItems`` (#224) and - ``additionalProperties`` (#317) -* Fixed an issue with ``ErrorTree``'s handling of multiple errors (#288) - -v2.5.0 ------- - -* Improved performance on CPython by adding caching around ref resolution - (#203) - -v2.4.0 ------- - -* Added a CLI (#134) -* Added absolute path and absolute schema path to errors (#120) -* Added ``relevance`` -* Meta-schemas are now loaded via ``pkgutil`` - -v2.3.0 ------- - -* Added ``by_relevance`` and ``best_match`` (#91) -* Fixed ``format`` to allow adding formats for non-strings (#125) -* Fixed the ``uri`` format to reject URI references (#131) - -v2.2.0 ------- - -* Compile the host name regex (#127) -* Allow arbitrary objects to be types (#129) - -v2.1.0 ------- - -* Support RFC 3339 datetimes in conformance with the spec -* Fixed error paths for additionalItems + items (#122) -* Fixed wording for min / maxProperties (#117) - - -v2.0.0 ------- - -* Added ``create`` and ``extend`` to ``jsonschema.validators`` -* Removed ``ValidatorMixin`` -* Fixed array indices ref resolution (#95) -* Fixed unknown scheme defragmenting and handling (#102) - - -v1.3.0 ------- - -* Better error tracebacks (#83) -* Raise exceptions in ``ErrorTree``\s for keys not in the instance (#92) -* __cause__ (#93) - - -v1.2.0 ------- - -* More attributes for ValidationError (#86) -* Added ``ValidatorMixin.descend`` -* Fixed bad ``RefResolutionError`` message (#82) - - -v1.1.0 ------- - -* Canonicalize URIs (#70) -* Allow attaching exceptions to ``format`` errors (#77) - - -v1.0.0 ------- - -* Support for Draft 4 -* Support for format -* Longs are ints too! -* Fixed a number of issues with ``$ref`` support (#66) -* Draft4Validator is now the default -* ``ValidationError.path`` is now in sequential order -* Added ``ValidatorMixin`` - - -v0.8.0 ------- - -* Full support for JSON References -* ``validates`` for registering new validators -* Documentation -* Bugfixes - - * uniqueItems not so unique (#34) - * Improper any (#47) - - -v0.7 ----- - -* Partial support for (JSON Pointer) ``$ref`` -* Deprecations - - * ``Validator`` is replaced by ``Draft3Validator`` with a slightly different - interface - * ``validator(meta_validate=False)`` - - -v0.6 ----- - -* Bugfixes - - * Issue #30 - Wrong behavior for the dependencies property validation - * Fixed a miswritten test - - -v0.5 ----- - -* Bugfixes - - * Issue #17 - require path for error objects - * Issue #18 - multiple type validation for non-objects - - -v0.4 ----- - -* Preliminary support for programmatic access to error details (Issue #5). - There are certainly some corner cases that don't do the right thing yet, but - this works mostly. - - In order to make this happen (and also to clean things up a bit), a number - of deprecations are necessary: - - * ``stop_on_error`` is deprecated in ``Validator.__init__``. Use - ``Validator.iter_errors()`` instead. - * ``number_types`` and ``string_types`` are deprecated there as well. - Use ``types={"number" : ..., "string" : ...}`` instead. - * ``meta_validate`` is also deprecated, and instead is now accepted as - an argument to ``validate``, ``iter_errors`` and ``is_valid``. - -* A bugfix or two - - -v0.3 ----- - -* Default for unknown types and properties is now to *not* error (consistent - with the schema). -* Python 3 support -* Removed dependency on SecureTypes now that the hash bug has been resolved. -* "Numerous bug fixes" -- most notably, a divisibleBy error for floats and a - bunch of missing typechecks for irrelevant properties. diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index c051d56..0000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,60 +0,0 @@ -============================ -Contributing to `jsonschema` -============================ - -Found a bug? ------------- - -If you suspect you may have found a security-related vulnerability, please follow the instructions in `the security policy <https://github.com/python-jsonschema/jsonschema/blob/main/.github/SECURITY.md>`_. - -Otherwise, it is extremely helpful if you first search to see whether your bug has been `previously reported on the Issues tab <https://github.com/python-jsonschema/jsonschema/issues?q=is%3Aissue+is%3Aopen+label%3ABug>`_. - -If it doesn't appear to be a known issue, please `file a new one <https://github.com/python-jsonschema/jsonschema/issues/new>`_, and include a **title and clear description**, along with as much relevant information as possible. -Including a *minimal*, *self-sufficient* bit of code (often an instance and schema) is the fastest way to get attention, along with a description of the behavior you expect, and if you're able, a link to where in the specification contains the behavior you're noticing is incorrect. - -Pull requests to fix your issue are of course very welcome. - - -Fixing a Bug? -------------- - -Please open a new GitHub pull request with the change, along with new tests. - -Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable. - -Continuous integration via GitHub actions should run to indicate whether your change passes both the test suite as well as linters. -Please ensure it passes, or indicate in a comment if you believe it fails spuriously. - - -Adding New Functionality? -------------------------- - -Please discuss any larger changes ahead of time for the sake of your own time! - -Improvements are very welcome, but large pull requests, disruptive ones, or backwards incompatible ones, can lead to long back and forth discussions. - -You're welcome to suggest a change in an issue and thereby get some initial feedback before embarking on an effort that may not get merged. - - -Improving the Documentation? ----------------------------- - -Writing good documentation is challenging both to prioritize and to do well. - -Any help you may have would be great, especially if you're a beginner who's struggled to understand a part of the library. - -Documentation is written in `Sphinx-flavored reStructuredText <https://www.sphinx-doc.org>`_, so you'll want to familiarize yourself a bit with Sphinx. - -Feel free to file issues or pull requests. - - -Have a Question? ----------------- - -Please do not use the issue tracker for questions, it's reserved for things believed to be bugs, or new functionality. - -There is a `discussions tab <https://github.com/python-jsonschema/jsonschema/discussions>`_ where general questions can be asked. - -Answers on it are best-effort. - -Any help you can offer to answer others' questions is of course very welcome as well. diff --git a/COPYING b/COPYING deleted file mode 100644 index af9cfbd..0000000 --- a/COPYING +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2013 Julian Berman - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/json/README.md b/README.md index d9cc165..d9cc165 100644 --- a/json/README.md +++ b/README.md diff --git a/README.rst b/README.rst deleted file mode 100644 index 0003c50..0000000 --- a/README.rst +++ /dev/null @@ -1,148 +0,0 @@ -========== -jsonschema -========== - -|PyPI| |Pythons| |CI| |ReadTheDocs| |Precommit| |Zenodo| - -.. |PyPI| image:: https://img.shields.io/pypi/v/jsonschema.svg - :alt: PyPI version - :target: https://pypi.org/project/jsonschema/ - -.. |Pythons| image:: https://img.shields.io/pypi/pyversions/jsonschema.svg - :alt: Supported Python versions - :target: https://pypi.org/project/jsonschema/ - -.. |CI| image:: https://github.com/python-jsonschema/jsonschema/workflows/CI/badge.svg - :alt: Build status - :target: https://github.com/python-jsonschema/jsonschema/actions?query=workflow%3ACI - -.. |ReadTheDocs| image:: https://readthedocs.org/projects/python-jsonschema/badge/?version=stable&style=flat - :alt: ReadTheDocs status - :target: https://python-jsonschema.readthedocs.io/en/stable/ - -.. |Precommit| image:: https://results.pre-commit.ci/badge/github/python-jsonschema/jsonschema/main.svg - :alt: pre-commit.ci status - :target: https://results.pre-commit.ci/latest/github/python-jsonschema/jsonschema/main - -.. |Zenodo| image:: https://zenodo.org/badge/3072629.svg - :target: https://zenodo.org/badge/latestdoi/3072629 - - -``jsonschema`` is an implementation of the `JSON Schema -<https://json-schema.org>`_ specification for Python. - -.. code-block:: python - - >>> from jsonschema import validate - - >>> # A sample schema, like what we'd get from json.load() - >>> schema = { - ... "type" : "object", - ... "properties" : { - ... "price" : {"type" : "number"}, - ... "name" : {"type" : "string"}, - ... }, - ... } - - >>> # If no exception is raised by validate(), the instance is valid. - >>> validate(instance={"name" : "Eggs", "price" : 34.99}, schema=schema) - - >>> validate( - ... instance={"name" : "Eggs", "price" : "Invalid"}, schema=schema, - ... ) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - ValidationError: 'Invalid' is not of type 'number' - -It can also be used from console: - -.. code-block:: bash - - $ jsonschema --instance sample.json sample.schema - -Features --------- - -* Partial support for - `Draft 2020-12 <https://python-jsonschema.readthedocs.io/en/latest/validate/#jsonschema.Draft202012Validator>`_ and - `Draft 2019-09 <https://python-jsonschema.readthedocs.io/en/latest/validate/#jsonschema.Draft201909Validator>`_, - except for ``dynamicRef`` / ``recursiveRef`` and ``$vocabulary`` (in-progress). - Full support for - `Draft 7 <https://python-jsonschema.readthedocs.io/en/latest/validate/#jsonschema.Draft7Validator>`_, - `Draft 6 <https://python-jsonschema.readthedocs.io/en/latest/validate/#jsonschema.Draft6Validator>`_, - `Draft 4 <https://python-jsonschema.readthedocs.io/en/latest/validate/#jsonschema.Draft4Validator>`_ - and - `Draft 3 <https://python-jsonschema.readthedocs.io/en/latest/validate/#jsonschema.Draft3Validator>`_ - -* `Lazy validation <https://python-jsonschema.readthedocs.io/en/latest/validate/#jsonschema.protocols.Validator.iter_errors>`_ - that can iteratively report *all* validation errors. - -* `Programmatic querying <https://python-jsonschema.readthedocs.io/en/latest/errors/>`_ - of which properties or items failed validation. - - -Installation ------------- - -``jsonschema`` is available on `PyPI <https://pypi.org/project/jsonschema/>`_. You can install using `pip <https://pip.pypa.io/en/stable/>`_: - -.. code-block:: bash - - $ pip install jsonschema - - -Running the Test Suite ----------------------- - -If you have ``tox`` installed (perhaps via ``pip install tox`` or your -package manager), running ``tox`` in the directory of your source -checkout will run ``jsonschema``'s test suite on all of the versions -of Python ``jsonschema`` supports. If you don't have all of the -versions that ``jsonschema`` is tested under, you'll likely want to run -using ``tox``'s ``--skip-missing-interpreters`` option. - -Of course you're also free to just run the tests on a single version with your -favorite test runner. The tests live in the ``jsonschema.tests`` package. - - -Benchmarks ----------- - -``jsonschema``'s benchmarks make use of `pyperf -<https://pyperf.readthedocs.io>`_. Running them can be done via:: - - $ tox -e perf - - -Community ---------- - -The JSON Schema specification has `a Slack -<https://json-schema.slack.com>`_, with an `invite link on its home page -<https://json-schema.org/>`_. Many folks knowledgeable on authoring -schemas can be found there. - -Otherwise, asking questions on Stack Overflow is another means of -getting help if you're stuck. - - -About ------ - -I'm Julian Berman. - -``jsonschema`` is on `GitHub <https://github.com/python-jsonschema/jsonschema>`_. - -Get in touch, via GitHub or otherwise, if you've got something to contribute, -it'd be most welcome! - -You can also generally find me on Libera (nick: ``Julian``) in various -channels, including ``#python``. - -If you feel overwhelmingly grateful, you can also `sponsor me -<https://github.com/sponsors/Julian/>`_. - -And for companies who appreciate ``jsonschema`` and its continued support -and growth, ``jsonschema`` is also now supportable via `TideLift -<https://tidelift.com/subscription/pkg/pypi-jsonschema?utm_source=pypi-j -sonschema&utm_medium=referral&utm_campaign=readme>`_. diff --git a/json/bin/jsonschema_suite b/bin/jsonschema_suite index a859dcf..bd77ee4 100755 --- a/json/bin/jsonschema_suite +++ b/bin/jsonschema_suite @@ -40,14 +40,14 @@ def files(paths): Each test file in the provided paths, as an array of test cases. """ for path in paths: - yield json.loads(path.read_text()) + yield path, json.loads(path.read_text()) def cases(paths): """ Each test case within each file in the provided paths. """ - for test_file in files(paths): + for _, test_file in files(paths): yield from test_file @@ -82,52 +82,115 @@ class SanityTests(unittest.TestCase): assert cls.remote_files, "Didn't find the remote files!" print(f"Found {len(cls.remote_files)} remote files") + def assertUnique(self, iterable): + """ + Assert that the elements of an iterable are unique. + """ + + seen, duplicated = set(), set() + for each in iterable: + if each in seen: + duplicated.add(each) + seen.add(each) + self.assertFalse(duplicated, "Elements are not unique.") + def test_all_test_files_are_valid_json(self): """ All test files contain valid JSON. """ for path in self.test_files: - try: - json.loads(path.read_text()) - except ValueError as error: - self.fail(f"{path} contains invalid JSON ({error})") + with self.subTest(path=path): + try: + json.loads(path.read_text()) + except ValueError as error: + self.fail(f"{path} contains invalid JSON ({error})") def test_all_remote_files_are_valid_json(self): """ All remote files contain valid JSON. """ for path in self.remote_files: - try: - json.loads(path.read_text()) - except ValueError as error: - self.fail(f"{path} contains invalid JSON ({error})") + with self.subTest(path=path): + try: + json.loads(path.read_text()) + except ValueError as error: + self.fail(f"{path} contains invalid JSON ({error})") - def test_all_descriptions_have_reasonable_length(self): + def test_all_case_descriptions_have_reasonable_length(self): + """ + All cases have reasonably long descriptions. + """ + for case in cases(self.test_files): + with self.subTest(description=case["description"]): + self.assertLess( + len(case["description"]), + 150, + "Description is too long (keep it to less than 150 chars)." + ) + + def test_all_test_descriptions_have_reasonable_length(self): """ All tests have reasonably long descriptions. """ for count, test in enumerate(tests(self.test_files)): - description = test["description"] - self.assertLess( - len(description), - 70, - f"{description!r} is too long! (keep it to less than 70 chars)" - ) + with self.subTest(description=test["description"]): + self.assertLess( + len(test["description"]), + 70, + "Description is too long (keep it to less than 70 chars)." + ) print(f"Found {count} tests.") - def test_all_descriptions_are_unique(self): + def test_all_case_descriptions_are_unique(self): + """ + All cases have unique descriptions in their files. + """ + for path, cases in files(self.test_files): + with self.subTest(path=path): + self.assertUnique(case["description"] for case in cases) + + def test_all_test_descriptions_are_unique(self): """ All test cases have unique test descriptions in their tests. """ for count, case in enumerate(cases(self.test_files)): - descriptions = set(test["description"] for test in case["tests"]) - self.assertEqual( - len(descriptions), - len(case["tests"]), - f"{case!r} contains a duplicate description", - ) + with self.subTest(description=case["description"]): + self.assertUnique( + test["description"] for test in case["tests"] + ) print(f"Found {count} test cases.") + def test_descriptions_do_not_use_modal_verbs(self): + """ + Instead of saying "test that X frobs" or "X should frob" use "X frobs". + + See e.g. https://jml.io/pages/test-docstrings.html + + This test isn't comprehensive (it doesn't catch all the extra + verbiage there), but it's just to catch whatever it manages to + cover. + """ + + message = ( + "In descriptions, don't say 'Test that X frobs' or 'X should " + "frob' or 'X should be valid'. Just say 'X frobs' or 'X is " + "valid'. It's shorter, and the test suite is entirely about " + "what *should* be already. " + "See https://jml.io/pages/test-docstrings.html for help." + ) + for test in tests(self.test_files): + with self.subTest(description=test["description"]): + self.assertNotRegex( + test["description"], + r"\bshould\b", + message, + ) + self.assertNotRegex( + test["description"], + r"(?i)\btest(s)? that\b", + message, + ) + @unittest.skipIf(jsonschema is None, "Validation library not present!") def test_all_schemas_are_valid(self): """ @@ -141,12 +204,14 @@ class SanityTests(unittest.TestCase): if Validator is not None: test_files = collect(version) for case in cases(test_files): - try: - Validator.check_schema(case["schema"]) - except jsonschema.SchemaError as error: - self.fail( - f"{case} contains an invalid schema ({error})", - ) + with self.subTest(case=case): + try: + Validator.check_schema(case["schema"]) + except jsonschema.SchemaError: + self.fail( + "Found an invalid schema." + "See the traceback for details on why." + ) else: warnings.warn(f"No schema validator for {version.name}") @@ -157,11 +222,12 @@ class SanityTests(unittest.TestCase): """ Validator = jsonschema.validators.validator_for(TESTSUITE_SCHEMA) validator = Validator(TESTSUITE_SCHEMA) - for tests in files(self.test_files): - try: - validator.validate(tests) - except jsonschema.ValidationError as error: - self.fail(str(error)) + for path, cases in files(self.test_files): + with self.subTest(path=path): + try: + validator.validate(cases) + except jsonschema.ValidationError as error: + self.fail(str(error)) def main(arguments): diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index 640bd89..0000000 --- a/codecov.yml +++ /dev/null @@ -1,5 +0,0 @@ -coverage: - status: - patch: - default: - target: 100% diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index f6315df..0000000 --- a/docs/Makefile +++ /dev/null @@ -1,227 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -PYTHON = python -PAPER = -BUILDDIR = _build -SOURCEDIR = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCEDIR) -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help -help: - @echo "Please use \`make <target>' where <target> is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " applehelp to make an Apple Help Book" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " epub3 to make an epub3" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " xml to make Docutils-native XML files" - @echo " pseudoxml to make pseudoxml-XML files for display purposes" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation" - @echo " coverage to run coverage check of the documentation (if enabled)" - @echo " spelling to run a spell check of the documentation" - @echo " dummy to check syntax errors of document sources" - -.PHONY: clean -clean: - rm -rf $(BUILDDIR)/* - -.PHONY: html -html: - $(PYTHON) -m sphinx -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -.PHONY: dirhtml -dirhtml: - $(PYTHON) -m sphinx -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -.PHONY: singlehtml -singlehtml: - $(PYTHON) -m sphinx -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -.PHONY: json -json: - $(PYTHON) -m sphinx -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -.PHONY: htmlhelp -htmlhelp: - $(PYTHON) -m sphinx -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -.PHONY: qthelp -qthelp: - $(PYTHON) -m sphinx -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/jsonschema.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/jsonschema.qhc" - -.PHONY: applehelp -applehelp: - $(PYTHON) -m sphinx -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp - @echo - @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." - @echo "N.B. You won't be able to view it unless you put it in" \ - "~/Library/Documentation/Help or install it in your application" \ - "bundle." - -.PHONY: devhelp -devhelp: - $(PYTHON) -m sphinx -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/jsonschema" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/jsonschema" - @echo "# devhelp" - -.PHONY: epub -epub: - $(PYTHON) -m sphinx -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -.PHONY: epub3 -epub3: - $(PYTHON) -m sphinx -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 - @echo - @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." - -.PHONY: latex -latex: - $(PYTHON) -m sphinx -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -.PHONY: latexpdf -latexpdf: - $(PYTHON) -m sphinx -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -.PHONY: latexpdfja -latexpdfja: - $(PYTHON) -m sphinx -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through platex and dvipdfmx..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -.PHONY: text -text: - $(PYTHON) -m sphinx -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -.PHONY: man -man: - $(PYTHON) -m sphinx -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -.PHONY: texinfo -texinfo: - $(PYTHON) -m sphinx -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -.PHONY: info -info: - $(PYTHON) -m sphinx -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -.PHONY: gettext -gettext: - $(PYTHON) -m sphinx -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -.PHONY: changes -changes: - $(PYTHON) -m sphinx -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -.PHONY: linkcheck -linkcheck: - $(PYTHON) -m sphinx -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -.PHONY: doctest -doctest: - $(PYTHON) -m sphinx -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -.PHONY: coverage -coverage: - $(PYTHON) -m sphinx -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage - @echo "Testing of coverage in the sources finished, look at the " \ - "results in $(BUILDDIR)/coverage/python.txt." - -.PHONY: xml -xml: - $(PYTHON) -m sphinx -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml - @echo - @echo "Build finished. The XML files are in $(BUILDDIR)/xml." - -.PHONY: pseudoxml -pseudoxml: - $(PYTHON) -m sphinx -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml - @echo - @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." - -.PHONY: spelling -spelling: - $(PYTHON) -m sphinx -b spelling $(ALLSPHINXOPTS) $(BUILDDIR)/spelling - @echo - @echo "Build finished. The spelling files are in $(BUILDDIR)/spelling." - -.PHONY: dummy -dummy: - $(PYTHON) -m sphinx -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy - @echo - @echo "Build finished. Dummy builder generates no files." diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100644 index f595f16..0000000 --- a/docs/conf.py +++ /dev/null @@ -1,254 +0,0 @@ -from importlib import metadata -import os -import re -import sys - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -ext_paths = [os.path.abspath(os.path.pardir), os.path.dirname(__file__)] -sys.path = ext_paths + sys.path - -# -- General configuration ------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = "1.0" - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named "sphinx.ext.*") or your custom -# ones. -extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.autosectionlabel", - "sphinx.ext.coverage", - "sphinx.ext.doctest", - "sphinx.ext.intersphinx", - "sphinx.ext.napoleon", - "sphinx.ext.viewcode", - "sphinx_autodoc_typehints", - "sphinxcontrib.spelling", - "jsonschema_role", -] - -cache_path = "_cache" - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# The suffix of source filenames. -source_suffix = ".rst" - -# The encoding of source files. -# source_encoding = "utf-8-sig" - -# The master toctree document. -master_doc = "index" - -# General information about the project. -project = "jsonschema" -author = "Julian Berman" -copyright = "2013, " + author - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# version: The short X.Y version -# release: The full version, including alpha/beta/rc tags. -release = metadata.version("jsonschema") -version = release.partition("-")[0] - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = "" -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = "%B %d, %Y" - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ["_build", "_cache", "_static", "_templates"] - -# The reST default role (used for this markup: `text`) to use for all documents -default_role = "any" - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -doctest_global_setup = """ -from jsonschema import * -""" - -intersphinx_mapping = { - "python": ("https://docs.python.org/3", None), -} - - -# -- Options for HTML output ----------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = "furo" - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -# html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ["_static"] - -# If not "", a "Last updated on:" timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = "%b %d, %Y" - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = "" - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = "jsonschemadoc" - - -# -- Options for LaTeX output ---------------------------------------------- - -# Grouping the document tree into LaTeX files. List of tuples (source -# start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ("index", "jsonschema.tex", "jsonschema Documentation", author, "manual"), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output ---------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [("index", "jsonschema", "jsonschema Documentation", [author], 1)] - -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- Options for Texinfo output -------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ( - "index", - "jsonschema", - "jsonschema Documentation", - author, - "jsonschema", - "One line description of project.", - "Miscellaneous", - ), -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: "footnote", "no", or "inline". -# texinfo_show_urls = "footnote" - -# -- Options for the linkcheck builder ------------------------------------ - - -def entire_domain(host): - return r"http.?://" + re.escape(host) + r"($|/.*)" - - -linkcheck_ignore = [ - entire_domain("img.shields.io"), - "https://github.com/python-jsonschema/jsonschema/actions", - "https://github.com/python-jsonschema/jsonschema/workflows/CI/badge.svg", -] - -# -- Options for sphinxcontrib-autosectionlabel --------------------------- - -autosectionlabel_prefix_document = True - -# -- Options for sphinxcontrib-spelling ----------------------------------- - -spelling_word_list_filename = "spelling-wordlist.txt" diff --git a/docs/creating.rst b/docs/creating.rst deleted file mode 100644 index 810293f..0000000 --- a/docs/creating.rst +++ /dev/null @@ -1,34 +0,0 @@ -.. currentmodule:: jsonschema.validators - -.. _creating-validators: - -======================================= -Creating or Extending Validator Classes -======================================= - -.. autofunction:: create - -.. autofunction:: extend - -.. autofunction:: validator_for - -.. autofunction:: validates - - -Creating Validation Errors --------------------------- - -Any validating function that validates against a subschema should call -``descend``, rather than ``iter_errors``. If it recurses into the -instance, or schema, it should pass one or both of the ``path`` or -``schema_path`` arguments to ``descend`` in order to properly maintain -where in the instance or schema respectively the error occurred. - -The Validator Protocol ----------------------- - -``jsonschema`` defines a `protocol <typing.Protocol>`, -`jsonschema.protocols.Validator` which can be used in type annotations to -describe the type of a validator object. - -For full details, see `validator-protocol`. diff --git a/docs/errors.rst b/docs/errors.rst deleted file mode 100644 index 4ca11d1..0000000 --- a/docs/errors.rst +++ /dev/null @@ -1,406 +0,0 @@ -========================== -Handling Validation Errors -========================== - -.. currentmodule:: jsonschema.exceptions - -When an invalid instance is encountered, a `ValidationError` will be -raised or returned, depending on which method or function is used. - -.. autoexception:: ValidationError - - The information carried by an error roughly breaks down into: - - =============== ================= ======================== - What Happened Why Did It Happen What Was Being Validated - =============== ================= ======================== - `message` `context` `instance` - - `cause` `json_path` - - `path` - - `schema` - - `schema_path` - - `validator` - - `validator_value` - =============== ================= ======================== - - - .. attribute:: message - - A human readable message explaining the error. - - .. attribute:: validator - - The name of the failed `validator - <https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-structural>`_. - - .. attribute:: validator_value - - The value for the failed validator in the schema. - - .. attribute:: schema - - The full schema that this error came from. This is potentially a - subschema from within the schema that was passed in originally, - or even an entirely different schema if a :validator:`$ref` was - followed. - - .. attribute:: relative_schema_path - - A `collections.deque` containing the path to the failed - validator within the schema. - - .. attribute:: absolute_schema_path - - A `collections.deque` containing the path to the failed - validator within the schema, but always relative to the - *original* schema as opposed to any subschema (i.e. the one - originally passed into a validator class, *not* `schema`\). - - .. attribute:: schema_path - - Same as `relative_schema_path`. - - .. attribute:: relative_path - - A `collections.deque` containing the path to the - offending element within the instance. The deque can be empty if - the error happened at the root of the instance. - - .. attribute:: absolute_path - - A `collections.deque` containing the path to the - offending element within the instance. The absolute path - is always relative to the *original* instance that was - validated (i.e. the one passed into a validation method, *not* - `instance`\). The deque can be empty if the error happened - at the root of the instance. - - .. attribute:: json_path - - A `JSON path <https://goessner.net/articles/JsonPath/index.html>`_ - to the offending element within the instance. - - .. attribute:: path - - Same as `relative_path`. - - .. attribute:: instance - - The instance that was being validated. This will differ from - the instance originally passed into ``validate`` if the - validator object was in the process of validating a (possibly - nested) element within the top-level instance. The path within - the top-level instance (i.e. `ValidationError.path`) could - be used to find this object, but it is provided for convenience. - - .. attribute:: context - - If the error was caused by errors in subschemas, the list of errors - from the subschemas will be available on this property. The - `schema_path` and `path` of these errors will be relative - to the parent error. - - .. attribute:: cause - - If the error was caused by a *non*-validation error, the - exception object will be here. Currently this is only used - for the exception raised by a failed format checker in - `jsonschema.FormatChecker.check`. - - .. attribute:: parent - - A validation error which this error is the `context` of. - ``None`` if there wasn't one. - - -In case an invalid schema itself is encountered, a `SchemaError` is -raised. - -.. autoexception:: SchemaError - - The same attributes are present as for `ValidationError`\s. - - -These attributes can be clarified with a short example: - -.. testcode:: - - schema = { - "items": { - "anyOf": [ - {"type": "string", "maxLength": 2}, - {"type": "integer", "minimum": 5} - ] - } - } - instance = [{}, 3, "foo"] - v = Draft202012Validator(schema) - errors = sorted(v.iter_errors(instance), key=lambda e: e.path) - -The error messages in this situation are not very helpful on their own. - -.. testcode:: - - for error in errors: - print(error.message) - -outputs: - -.. testoutput:: - - {} is not valid under any of the given schemas - 3 is not valid under any of the given schemas - 'foo' is not valid under any of the given schemas - -If we look at `ValidationError.path` on each of the errors, we can find -out which elements in the instance correspond to each of the errors. In -this example, `ValidationError.path` will have only one element, which -will be the index in our list. - -.. testcode:: - - for error in errors: - print(list(error.path)) - -.. testoutput:: - - [0] - [1] - [2] - -Since our schema contained nested subschemas, it can be helpful to look at -the specific part of the instance and subschema that caused each of the errors. -This can be seen with the `ValidationError.instance` and -`ValidationError.schema` attributes. - -With validators like :validator:`anyOf`, the `ValidationError.context` -attribute can be used to see the sub-errors which caused the failure. Since -these errors actually came from two separate subschemas, it can be helpful to -look at the `ValidationError.schema_path` attribute as well to see where -exactly in the schema each of these errors come from. In the case of sub-errors -from the `ValidationError.context` attribute, this path will be relative -to the `ValidationError.schema_path` of the parent error. - -.. testcode:: - - for error in errors: - for suberror in sorted(error.context, key=lambda e: e.schema_path): - print(list(suberror.schema_path), suberror.message, sep=", ") - -.. testoutput:: - - [0, 'type'], {} is not of type 'string' - [1, 'type'], {} is not of type 'integer' - [0, 'type'], 3 is not of type 'string' - [1, 'minimum'], 3 is less than the minimum of 5 - [0, 'maxLength'], 'foo' is too long - [1, 'type'], 'foo' is not of type 'integer' - -The string representation of an error combines some of these attributes for -easier debugging. - -.. testcode:: - - print(errors[1]) - -.. testoutput:: - - 3 is not valid under any of the given schemas - - Failed validating 'anyOf' in schema['items']: - {'anyOf': [{'maxLength': 2, 'type': 'string'}, - {'minimum': 5, 'type': 'integer'}]} - - On instance[1]: - 3 - - -ErrorTrees ----------- - -If you want to programmatically be able to query which properties or validators -failed when validating a given instance, you probably will want to do so using -`jsonschema.exceptions.ErrorTree` objects. - -.. autoclass:: jsonschema.exceptions.ErrorTree - :members: - :special-members: - :exclude-members: __dict__,__weakref__ - - .. attribute:: errors - - The mapping of validator names to the error objects (usually - `jsonschema.exceptions.ValidationError`\s) at this level - of the tree. - -Consider the following example: - -.. testcode:: - - schema = { - "type" : "array", - "items" : {"type" : "number", "enum" : [1, 2, 3]}, - "minItems" : 3, - } - instance = ["spam", 2] - -For clarity's sake, the given instance has three errors under this schema: - -.. testcode:: - - v = Draft202012Validator(schema) - for error in sorted(v.iter_errors(["spam", 2]), key=str): - print(error.message) - -.. testoutput:: - - 'spam' is not of type 'number' - 'spam' is not one of [1, 2, 3] - ['spam', 2] is too short - -Let's construct an `jsonschema.exceptions.ErrorTree` so that we -can query the errors a bit more easily than by just iterating over the -error objects. - -.. testcode:: - - tree = ErrorTree(v.iter_errors(instance)) - -As you can see, `jsonschema.exceptions.ErrorTree` takes an -iterable of `ValidationError`\s when constructing a tree so -you can directly pass it the return value of a validator object's -`jsonschema.protocols.Validator.iter_errors` method. - -`ErrorTree`\s support a number of useful operations. The first one we -might want to perform is to check whether a given element in our instance -failed validation. We do so using the :keyword:`in` operator: - -.. doctest:: - - >>> 0 in tree - True - - >>> 1 in tree - False - -The interpretation here is that the 0th index into the instance (``"spam"``) -did have an error (in fact it had 2), while the 1th index (``2``) did not (i.e. -it was valid). - -If we want to see which errors a child had, we index into the tree and look at -the `ErrorTree.errors` attribute. - -.. doctest:: - - >>> sorted(tree[0].errors) - ['enum', 'type'] - -Here we see that the :validator:`enum` and :validator:`type` validators failed -for index ``0``. In fact `ErrorTree.errors` is a dict, whose values are -the `ValidationError`\s, so we can get at those directly if we want -them. - -.. doctest:: - - >>> print(tree[0].errors["type"].message) - 'spam' is not of type 'number' - -Of course this means that if we want to know if a given named -validator failed for a given index, we check for its presence in -`ErrorTree.errors`: - -.. doctest:: - - >>> "enum" in tree[0].errors - True - - >>> "minimum" in tree[0].errors - False - -Finally, if you were paying close enough attention, you'll notice that we -haven't seen our :validator:`minItems` error appear anywhere yet. This is -because :validator:`minItems` is an error that applies globally to the instance -itself. So it appears in the root node of the tree. - -.. doctest:: - - >>> "minItems" in tree.errors - True - -That's all you need to know to use error trees. - -To summarize, each tree contains child trees that can be accessed by -indexing the tree to get the corresponding child tree for a given index -into the instance. Each tree and child has a `ErrorTree.errors` -attribute, a dict, that maps the failed validator name to the -corresponding validation error. - - -best_match and relevance ------------------------- - -The `best_match` function is a simple but useful function for attempting -to guess the most relevant error in a given bunch. - -.. doctest:: - - >>> from jsonschema import Draft202012Validator - >>> from jsonschema.exceptions import best_match - - >>> schema = { - ... "type": "array", - ... "minItems": 3, - ... } - >>> print(best_match(Draft202012Validator(schema).iter_errors(11)).message) - 11 is not of type 'array' - - -.. autofunction:: best_match - - -.. function:: relevance(validation_error) - - A key function that sorts errors based on heuristic relevance. - - If you want to sort a bunch of errors entirely, you can use - this function to do so. Using this function as a key to e.g. - `sorted` or `max` will cause more relevant errors to be - considered greater than less relevant ones. - - Within the different validators that can fail, this function - considers :validator:`anyOf` and :validator:`oneOf` to be *weak* - validation errors, and will sort them lower than other validators at - the same level in the instance. - - If you want to change the set of weak [or strong] validators you can create - a custom version of this function with `by_relevance` and provide a - different set of each. - -.. doctest:: - - >>> schema = { - ... "properties": { - ... "name": {"type": "string"}, - ... "phones": { - ... "properties": { - ... "home": {"type": "string"} - ... }, - ... }, - ... }, - ... } - >>> instance = {"name": 123, "phones": {"home": [123]}} - >>> errors = Draft202012Validator(schema).iter_errors(instance) - >>> [ - ... e.path[-1] - ... for e in sorted(errors, key=exceptions.relevance) - ... ] - ['home', 'name'] - - -.. autofunction:: by_relevance diff --git a/docs/faq.rst b/docs/faq.rst deleted file mode 100644 index 62b3d4b..0000000 --- a/docs/faq.rst +++ /dev/null @@ -1,291 +0,0 @@ -========================== -Frequently Asked Questions -========================== - - -My schema specifies format validation. Why do invalid instances seem valid? ---------------------------------------------------------------------------- - -The :validator:`format` validator can be a bit of a stumbling block for new -users working with JSON Schema. - -In a schema such as: - -.. code-block:: json - - {"type": "string", "format": "date"} - -JSON Schema specifications have historically differentiated between the -:validator:`format` validator and other validators. In particular, the -:validator:`format` validator was specified to be *informational* as much -as it may be used for validation. - -In other words, for many use cases, schema authors may wish to use -values for the :validator:`format` validator but have no expectation -they be validated alongside other required assertions in a schema. - -Of course this does not represent all or even most use cases -- many -schema authors *do* wish to assert that instances conform fully, even to -the specific format mentioned. - -In drafts prior to ``draft2019-09``, the decision on whether to -automatically enable :validator:`format` validation was left up to -validation implementations such as this one. - -This library made the choice to leave it off by default, for two reasons: - - * for forward compatibility and implementation complexity reasons - -- if :validator:`format` validation were on by default, and a - future draft of JSON Schema introduced a hard-to-implement format, - either the implementation of that format would block releases of - this library until it were implemented, or the behavior surrounding - :validator:`format` would need to be even more complex than simply - defaulting to be on. It therefore was safer to start with it off, - and defend against the expectation that a given format would always - automatically work. - - * given that a common use of JSON Schema is for portability across - languages (and therefore implementations of JSON Schema), so that - users be aware of this point itself regarding :validator:`format` - validation, and therefore remember to check any *other* - implementations they were using to ensure they too were explicitly - enabled for :validator:`format` validation. - -As of ``draft2019-09`` however, the opt-out by default behavior -mentioned here is now *required* for all validators. - -Difficult as this may sound for new users, at this point it at least -means they should expect the same behavior that has always been -implemented here, across any other implementation they encounter. - -.. seealso:: - - `Draft 2019-09's release notes on format <https://json-schema.org/draft/2019-09/release-notes.html#format-vocabulary>`_ - - for upstream details on the behavior of format and how it has changed - in ``draft2019-09`` - - `validating formats` - - for details on how to enable format validation - - `jsonschema.FormatChecker` - - the object which implements format validation - - -How do I configure a base URI for ``$ref`` resolution using local files? ------------------------------------------------------------------------- - -`jsonschema` supports loading schemas from the filesystem. - -The most common mistake when configuring a :class:`~jsonschema.RefResolver` -to retrieve schemas from the local filesystem is to give it a base URI -which points to a directory, but forget to add a trailing slash. - -For example, given a directory ``/tmp/foo/`` with ``bar/schema.json`` -within it, you should use something like: - -.. code-block:: python - - from pathlib import Path - - import jsonschema.validators - - path = Path("/tmp/foo") - resolver = jsonschema.validators.RefResolver( - base_uri=f"{path.as_uri()}/", - referrer=True, - ) - jsonschema.validate( - instance={}, - schema={"$ref": "bar/schema.json"}, - resolver=resolver, - ) - -where note: - - * the base URI has a trailing slash, even though - `pathlib.PurePath.as_uri` does not add it! - * any relative refs are now given relative to the provided directory - -If you forget the trailing slash, you'll find references are resolved a -directory too high. - -You're likely familiar with this behavior from your browser. If you -visit a page at ``https://example.com/foo``, then links on it like -``<a href="./bar">`` take you to ``https://example.com/bar``, not -``https://example.com/foo/bar``. For this reason many sites will -redirect ``https://example.com/foo`` to ``https://example.com/foo/``, -i.e. add the trailing slash, so that relative links on the page will keep the -last path component. - -There are, in summary, 2 ways to do this properly: - -* Remember to include a trailing slash, so your base URI is - ``file:///foo/bar/`` rather than ``file:///foo/bar``, as shown above -* Use a file within the directory as your base URI rather than the - directory itself, i.e. ``file://foo/bar/baz.json``, which will of course - cause ``baz.json`` to be removed while resolving relative URIs - -Why doesn't my schema's default property set the default on my instance? ------------------------------------------------------------------------- - -The basic answer is that the specification does not require that -:validator:`default` actually do anything. - -For an inkling as to *why* it doesn't actually do anything, consider -that none of the other validators modify the instance either. More -importantly, having :validator:`default` modify the instance can produce -quite peculiar things. It's perfectly valid (and perhaps even useful) -to have a default that is not valid under the schema it lives in! So an -instance modified by the default would pass validation the first time, -but fail the second! - -Still, filling in defaults is a thing that is useful. `jsonschema` -allows you to `define your own validator classes and callables -<creating>`, so you can easily create an `jsonschema.protocols.Validator` -that does do default setting. Here's some code to get you started. (In -this code, we add the default properties to each object *before* the -properties are validated, so the default values themselves will need to -be valid under the schema.) - - .. testcode:: - - from jsonschema import Draft202012Validator, validators - - - def extend_with_default(validator_class): - validate_properties = validator_class.VALIDATORS["properties"] - - def set_defaults(validator, properties, instance, schema): - for property, subschema in properties.items(): - if "default" in subschema: - instance.setdefault(property, subschema["default"]) - - for error in validate_properties( - validator, properties, instance, schema, - ): - yield error - - return validators.extend( - validator_class, {"properties" : set_defaults}, - ) - - - DefaultValidatingValidator = extend_with_default(Draft202012Validator) - - - # Example usage: - obj = {} - schema = {'properties': {'foo': {'default': 'bar'}}} - # Note jsonschem.validate(obj, schema, cls=DefaultValidatingValidator) - # will not work because the metaschema contains `default` directives. - DefaultValidatingValidator(schema).validate(obj) - assert obj == {'foo': 'bar'} - - -See the above-linked document for more info on how this works, but -basically, it just extends the :validator:`properties` validator on -a `jsonschema.Draft202012Validator` to then go ahead and update all the -defaults. - -.. note:: - - If you're interested in a more interesting solution to a larger - class of these types of transformations, keep an eye on `Seep - <https://github.com/Julian/Seep>`_, which is an experimental - data transformation and extraction library written on top of - `jsonschema`. - - -.. hint:: - - The above code can provide default values for an entire object and - all of its properties, but only if your schema provides a default - value for the object itself, like so: - - .. testcode:: - - schema = { - "type": "object", - "properties": { - "outer-object": { - "type": "object", - "properties" : { - "inner-object": { - "type": "string", - "default": "INNER-DEFAULT" - } - }, - "default": {} # <-- MUST PROVIDE DEFAULT OBJECT - } - } - } - - obj = {} - DefaultValidatingValidator(schema).validate(obj) - assert obj == {'outer-object': {'inner-object': 'INNER-DEFAULT'}} - - ...but if you don't provide a default value for your object, then - it won't be instantiated at all, much less populated with default - properties. - - .. testcode:: - - del schema["properties"]["outer-object"]["default"] - obj2 = {} - DefaultValidatingValidator(schema).validate(obj2) - assert obj2 == {} # whoops - - -How do jsonschema version numbers work? ---------------------------------------- - -``jsonschema`` tries to follow the `Semantic Versioning -<https://semver.org/>`_ specification. - -This means broadly that no backwards-incompatible changes should be made -in minor releases (and certainly not in dot releases). - -The full picture requires defining what constitutes a -backwards-incompatible change. - -The following are simple examples of things considered public API, -and therefore should *not* be changed without bumping a major version -number: - - * module names and contents, when not marked private by Python - convention (a single leading underscore) - - * function and object signature (parameter order and name) - -The following are *not* considered public API and may change without -notice: - - * the exact wording and contents of error messages; typical reasons - to rely on this seem to involve downstream tests in packages using - `jsonschema`. These use cases are encouraged to use the extensive - introspection provided in `jsonschema.exceptions.ValidationError`\s - instead to make meaningful assertions about what failed rather than - relying on *how* what failed is explained to a human. - - * the order in which validation errors are returned or raised - - * the contents of the ``jsonschema.tests`` package - - * the contents of the ``jsonschema.benchmarks`` package - - * the specific non-zero error codes presented by the command line - interface - - * the exact representation of errors presented by the command line - interface, other than that errors represented by the plain outputter - will be reported one per line - - * anything marked private - -With the exception of the last two of those, flippant changes are -avoided, but changes can and will be made if there is improvement to be -had. Feel free to open an issue ticket if there is a specific issue or -question worth raising. diff --git a/docs/index.rst b/docs/index.rst deleted file mode 100644 index e4d7252..0000000 --- a/docs/index.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. module:: jsonschema -.. include:: ../README.rst - - -Contents --------- - -.. toctree:: - :maxdepth: 2 - - validate - errors - references - creating - faq - - -Indices and tables -================== - -* `genindex` -* `search` diff --git a/docs/jsonschema_role.py b/docs/jsonschema_role.py deleted file mode 100644 index 7610c06..0000000 --- a/docs/jsonschema_role.py +++ /dev/null @@ -1,146 +0,0 @@ -from contextlib import suppress -from datetime import datetime -from importlib import metadata -from urllib.parse import urljoin -import os -import urllib.request - -from docutils import nodes -from lxml import html -import certifi - -__version__ = "1.2.0" - -BASE_URL = "https://json-schema.org/draft-07/" -VALIDATION_SPEC = urljoin(BASE_URL, "json-schema-validation.html") -REF_URL = urljoin(BASE_URL, "json-schema-core.html#rfc.section.8.3") -SCHEMA_URL = urljoin(BASE_URL, "json-schema-core.html#rfc.section.7") - - -def setup(app): - """ - Install the plugin. - - Arguments: - - app (sphinx.application.Sphinx): - - the Sphinx application context - """ - - app.add_config_value("cache_path", "_cache", "") - - os.makedirs(app.config.cache_path, exist_ok=True) - - path = os.path.join(app.config.cache_path, "spec.html") - spec = fetch_or_load(path) - app.add_role("validator", docutils_does_not_allow_using_classes(spec)) - - return dict(version=__version__, parallel_read_safe=True) - - -def fetch_or_load(spec_path): - """ - Fetch a new specification or use the cache if it's current. - - Arguments: - - cache_path: - - the path to a cached specification - """ - - headers = { - "User-Agent": "python-jsonschema v{} - documentation build v{}".format( - metadata.version("jsonschema"), - __version__, - ), - } - - with suppress(FileNotFoundError): - modified = datetime.utcfromtimestamp(os.path.getmtime(spec_path)) - date = modified.strftime("%a, %d %b %Y %I:%M:%S UTC") - headers["If-Modified-Since"] = date - - request = urllib.request.Request(VALIDATION_SPEC, headers=headers) - response = urllib.request.urlopen(request, cafile=certifi.where()) - - if response.code == 200: - with open(spec_path, "w+b") as spec: - spec.writelines(response) - spec.seek(0) - return html.parse(spec) - - with open(spec_path) as spec: - return html.parse(spec) - - -def docutils_does_not_allow_using_classes(spec): - """ - Yeah. - - It doesn't allow using a class because it does annoying stuff like - try to set attributes on the callable object rather than just - keeping a dict. - """ - - def validator(name, raw_text, text, lineno, inliner): - """ - Link to the JSON Schema documentation for a validator. - - Arguments: - - name (str): - - the name of the role in the document - - raw_source (str): - - the raw text (role with argument) - - text (str): - - the argument given to the role - - lineno (int): - - the line number - - inliner (docutils.parsers.rst.states.Inliner): - - the inliner - - Returns: - - tuple: - - a 2-tuple of nodes to insert into the document and an - iterable of system messages, both possibly empty - """ - - if text == "$ref": - return [nodes.reference(raw_text, text, refuri=REF_URL)], [] - elif text == "$schema": - return [nodes.reference(raw_text, text, refuri=SCHEMA_URL)], [] - - # find the header in the validation spec containing matching text - header = spec.xpath("//h1[contains(text(), '{0}')]".format(text)) - - if len(header) == 0: - inliner.reporter.warning( - "Didn't find a target for {0}".format(text), - ) - uri = VALIDATION_SPEC - else: - if len(header) > 1: - inliner.reporter.info( - "Found multiple targets for {0}".format(text), - ) - - # get the href from link in the header - uri = urljoin(VALIDATION_SPEC, header[0].find("a").attrib["href"]) - - reference = nodes.reference(raw_text, text, refuri=uri) - return [reference], [] - - return validator diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index fcb914f..0000000 --- a/docs/make.bat +++ /dev/null @@ -1,190 +0,0 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set BUILDDIR=_build -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . -set I18NSPHINXOPTS=%SPHINXOPTS% . -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% - set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^<target^>` where ^<target^> is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. singlehtml to make a single large HTML file - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. devhelp to make HTML files and a Devhelp project - echo. epub to make an epub - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. text to make text files - echo. man to make manual pages - echo. texinfo to make Texinfo files - echo. gettext to make PO message catalogs - echo. changes to make an overview over all changed/added/deprecated items - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end -) - -if "%1" == "singlehtml" ( - %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\jsonschema.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\jsonschema.ghc - goto end -) - -if "%1" == "devhelp" ( - %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. - goto end -) - -if "%1" == "epub" ( - %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The epub file is in %BUILDDIR%/epub. - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "text" ( - %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The text files are in %BUILDDIR%/text. - goto end -) - -if "%1" == "man" ( - %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The manual pages are in %BUILDDIR%/man. - goto end -) - -if "%1" == "texinfo" ( - %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. - goto end -) - -if "%1" == "gettext" ( - %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The message catalogs are in %BUILDDIR%/locale. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - if errorlevel 1 exit /b 1 - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - if errorlevel 1 exit /b 1 - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - if errorlevel 1 exit /b 1 - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. - goto end -) - -:end diff --git a/docs/references.rst b/docs/references.rst deleted file mode 100644 index 9f24299..0000000 --- a/docs/references.rst +++ /dev/null @@ -1,13 +0,0 @@ -========================= -Resolving JSON References -========================= - - -.. currentmodule:: jsonschema - -.. autoclass:: RefResolver - :members: - -.. autoexception:: RefResolutionError - - A JSON reference failed to resolve. diff --git a/docs/requirements.in b/docs/requirements.in deleted file mode 100644 index 06623c0..0000000 --- a/docs/requirements.in +++ /dev/null @@ -1,6 +0,0 @@ -file:.#egg=jsonschema -furo -lxml -sphinx -sphinx-autodoc-typehints -sphinxcontrib-spelling diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index d35464c..0000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,81 +0,0 @@ -# -# This file is autogenerated by pip-compile with python 3.10 -# To update, run: -# -# pip-compile docs/requirements.in -# -alabaster==0.7.12 - # via sphinx -attrs==22.1.0 - # via jsonschema -babel==2.10.3 - # via sphinx -beautifulsoup4==4.11.1 - # via furo -certifi==2022.6.15 - # via requests -charset-normalizer==2.1.0 - # via requests -docutils==0.19 - # via sphinx -furo==2022.6.21 - # via -r docs/requirements.in -idna==3.3 - # via requests -imagesize==1.4.1 - # via sphinx -jinja2==3.1.2 - # via sphinx -file:.#egg=jsonschema - # via -r docs/requirements.in -lxml==4.9.1 - # via -r docs/requirements.in -markupsafe==2.1.1 - # via jinja2 -packaging==21.3 - # via sphinx -pyenchant==3.2.2 - # via sphinxcontrib-spelling -pygments==2.12.0 - # via - # furo - # sphinx -pyparsing==3.0.9 - # via packaging -pyrsistent==0.18.1 - # via jsonschema -pytz==2022.1 - # via babel -requests==2.28.1 - # via sphinx -snowballstemmer==2.2.0 - # via sphinx -soupsieve==2.3.2.post1 - # via beautifulsoup4 -sphinx==5.1.1 - # via - # -r docs/requirements.in - # furo - # sphinx-autodoc-typehints - # sphinx-basic-ng - # sphinxcontrib-spelling -sphinx-autodoc-typehints==1.19.0 - # via -r docs/requirements.in -sphinx-basic-ng==0.0.1a12 - # via furo -sphinxcontrib-applehelp==1.0.2 - # via sphinx -sphinxcontrib-devhelp==1.0.2 - # via sphinx -sphinxcontrib-htmlhelp==2.0.0 - # via sphinx -sphinxcontrib-jsmath==1.0.1 - # via sphinx -sphinxcontrib-qthelp==1.0.3 - # via sphinx -sphinxcontrib-serializinghtml==1.1.5 - # via sphinx -sphinxcontrib-spelling==7.6.0 - # via -r docs/requirements.in -urllib3==1.26.11 - # via requests diff --git a/docs/spelling-wordlist.txt b/docs/spelling-wordlist.txt deleted file mode 100644 index ab42031..0000000 --- a/docs/spelling-wordlist.txt +++ /dev/null @@ -1,45 +0,0 @@ -# this appears to be misinterpreting Napoleon types as prose, sigh... -Validator -TypeChecker -UnknownType -ValidationError - -# 0th, sigh... -th -callables -deque -dereferences -filesystem -hostname -implementers -indices -# ipv4/6, sigh... -ipv -iterable -iteratively -jsonschema -majorly -metaschema -online -outputter -pre -programmatically -recurses -regex -repr -sensical -subschema -subschemas -subscopes -uri -validator -validators -versioned -schemas - -Zac -HD - -Berman -Libera -GPL diff --git a/docs/validate.rst b/docs/validate.rst deleted file mode 100644 index 744ea8a..0000000 --- a/docs/validate.rst +++ /dev/null @@ -1,288 +0,0 @@ -================= -Schema Validation -================= - - -.. currentmodule:: jsonschema - - -The Basics ----------- - -The simplest way to validate an instance under a given schema is to use the -:func:`validate` function. - -.. autofunction:: validate - -.. [#] For information on creating JSON schemas to validate - your data, there is a good introduction to JSON Schema - fundamentals underway at `Understanding JSON Schema - <https://json-schema.org/understanding-json-schema/>`_ - -.. _validator-protocol: - -The Validator Protocol ------------------------ - -`jsonschema` defines a protocol that all validator -classes should adhere to. - -.. autoclass:: jsonschema.protocols.Validator - :members: - -All of the `versioned validators <versioned-validators>` that are included with -`jsonschema` adhere to the protocol, and implementers of validator classes -that extend or complement the ones included should adhere to it as well. For -more information see `creating-validators`. - -Type Checking -------------- - -To handle JSON Schema's :validator:`type` property, a `Validator` uses -an associated `TypeChecker`. The type checker provides an immutable -mapping between names of types and functions that can test if an instance is -of that type. The defaults are suitable for most users - each of the -`versioned validators <versioned-validators>` that are included with -`jsonschema` have a `TypeChecker` that can correctly handle their respective -versions. - -.. seealso:: `validating-types` - - For an example of providing a custom type check. - -.. autoclass:: TypeChecker - :members: - -.. autoexception:: jsonschema.exceptions.UndefinedTypeCheck - - Raised when trying to remove a type check that is not known to this - TypeChecker, or when calling `jsonschema.TypeChecker.is_type` - directly. - -.. _validating-types: - -Validating With Additional Types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Occasionally it can be useful to provide additional or alternate types when -validating the JSON Schema's :validator:`type` property. - -`jsonschema` tries to strike a balance between performance in the common -case and generality. For instance, JSON Schema defines a ``number`` type, which -can be validated with a schema such as ``{"type" : "number"}``. By default, -this will accept instances of Python `numbers.Number`. This includes in -particular `int`\s and `float`\s, along with -`decimal.Decimal` objects, `complex` numbers etc. For -``integer`` and ``object``, however, rather than checking for -`numbers.Integral` and `collections.abc.Mapping`, -`jsonschema` simply checks for `int` and `dict`, since the -more general instance checks can introduce significant slowdown, especially -given how common validating these types are. - -If you *do* want the generality, or just want to add a few specific additional -types as being acceptable for a validator object, then you should update an -existing `TypeChecker` or create a new one. You may then create a new -`Validator` via `jsonschema.validators.extend`. - -.. testcode:: - - from jsonschema import validators - - class MyInteger(object): - pass - - def is_my_int(checker, instance): - return ( - Draft202012Validator.TYPE_CHECKER.is_type(instance, "number") or - isinstance(instance, MyInteger) - ) - - type_checker = Draft202012Validator.TYPE_CHECKER.redefine( - "number", is_my_int, - ) - - CustomValidator = validators.extend( - Draft202012Validator, - type_checker=type_checker, - ) - validator = CustomValidator(schema={"type" : "number"}) - - -.. autoexception:: jsonschema.exceptions.UnknownType - -.. _versioned-validators: - -Versioned Validators --------------------- - -`jsonschema` ships with validator classes for various versions of -the JSON Schema specification. For details on the methods and attributes -that each validator class provides see the `Validator` protocol, -which each included validator class implements. - -.. autoclass:: Draft202012Validator - -.. autoclass:: Draft201909Validator - -.. autoclass:: Draft7Validator - -.. autoclass:: Draft6Validator - -.. autoclass:: Draft4Validator - -.. autoclass:: Draft3Validator - - -For example, if you wanted to validate a schema you created against the -Draft 2020-12 meta-schema, you could use: - -.. testcode:: - - from jsonschema import Draft202012Validator - - schema = { - "$schema": Draft202012Validator.META_SCHEMA["$id"], - - "type": "object", - "properties": { - "name": {"type": "string"}, - "email": {"type": "string"}, - }, - "required": ["email"] - } - Draft202012Validator.check_schema(schema) - - -.. _validating formats: - -Validating Formats ------------------- - -JSON Schema defines the :validator:`format` property which can be used to check -if primitive types (``string``\s, ``number``\s, ``boolean``\s) conform to -well-defined formats. By default, no validation is enforced, but optionally, -validation can be enabled by hooking in a format-checking object into an -`Validator`. - -.. doctest:: - - >>> validate("127.0.0.1", {"format" : "ipv4"}) - >>> validate( - ... instance="-12", - ... schema={"format" : "ipv4"}, - ... format_checker=draft202012_format_checker, - ... ) - Traceback (most recent call last): - ... - ValidationError: "-12" is not a "ipv4" - -.. autoclass:: FormatChecker - :members: - :exclude-members: cls_checks - - .. attribute:: checkers - - A mapping of currently known formats to tuple of functions that - validate them and errors that should be caught. New checkers can be - added and removed either per-instance or globally for all checkers - using the `FormatChecker.checks` or `FormatChecker.cls_checks` - decorators respectively. - - .. classmethod:: cls_checks(format, raises=()) - - Register a decorated function as *globally* validating a new format. - - Any instance created after this function is called will pick up the - supplied checker. - - :argument str format: the format that the decorated function will check - :argument Exception raises: the exception(s) raised - by the decorated function when an invalid instance is - found. The exception object will be accessible as the - `jsonschema.exceptions.ValidationError.cause` attribute - of the resulting validation error. - - -.. autoexception:: FormatError - :members: - - -There are a number of default checkers that `FormatChecker`\s know how -to validate. Their names can be viewed by inspecting the -`FormatChecker.checkers` attribute. Certain checkers will only be -available if an appropriate package is available for use. The easiest way to -ensure you have what is needed is to install ``jsonschema`` using the -``format`` or ``format_nongpl`` collection of optional dependencies -- e.g. - -.. code-block:: sh - - $ pip install jsonschema[format] - -which will install all of the below dependencies for all formats. - -Or if you want to install MIT-license compatible dependencies only: - -.. code-block:: sh - - $ pip install jsonschema[format_nongpl] - -The non-GPL extra is intended to not install any direct dependencies -that are GPL (but that of course end-users should do their own verification). -At the moment, it supports all the available checkers except for ``iri`` and -``iri-reference``. - -The more specific list of available checkers, along with their requirement -(if any,) are listed below. - -.. note:: - - If the following packages are not installed when using a checker - that requires it, validation will succeed without throwing an error, - as specified by the JSON Schema specification. - -========================= ==================== -Checker Notes -========================= ==================== -``color`` requires webcolors_ -``date`` -``date-time`` requires rfc3339-validator_ -``duration`` requires isoduration_ -``email`` -``hostname`` requires fqdn_ -``idn-hostname`` requires idna_ -``ipv4`` -``ipv6`` OS must have `socket.inet_pton` function -``iri`` requires rfc3987_ -``iri-reference`` requires rfc3987_ -``json-pointer`` requires jsonpointer_ -``regex`` -``relative-json-pointer`` requires jsonpointer_ -``time`` requires rfc3339-validator_ -``uri`` requires rfc3987_ or rfc3986-validator_ -``uri-reference`` requires rfc3987_ or rfc3986-validator_ -``uri-template`` requires uri-template_ -========================= ==================== - - -.. _fqdn: https://pypi.org/pypi/fqdn/ -.. _idna: https://pypi.org/pypi/idna/ -.. _isoduration: https://pypi.org/pypi/isoduration/ -.. _jsonpointer: https://pypi.org/pypi/jsonpointer/ -.. _rfc3339-validator: https://pypi.org/project/rfc3339-validator/ -.. _rfc3986-validator: https://pypi.org/project/rfc3986-validator/ -.. _rfc3987: https://pypi.org/pypi/rfc3987/ -.. _rfc5322: https://tools.ietf.org/html/rfc5322#section-3.4.1 -.. _uri-template: https://pypi.org/pypi/uri-template/ -.. _webcolors: https://pypi.org/pypi/webcolors/ - -.. note:: - - Since in most cases "validating" an email address is an attempt - instead to confirm that mail sent to it will deliver to a recipient, - and that that recipient is the correct one the email is intended - for, and since many valid email addresses are in many places - incorrectly rejected, and many invalid email addresses are in many - places incorrectly accepted, the ``email`` format validator only - provides a sanity check, not full rfc5322_ validation. - - The same applies to the ``idn-email`` format. diff --git a/json/.github/workflows/ci.yml b/json/.github/workflows/ci.yml deleted file mode 100644 index a826069..0000000 --- a/json/.github/workflows/ci.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Test Suite Sanity Checking - -on: - push: - pull_request: - release: - types: [published] - schedule: - # Daily at 6:42, arbitrarily as a time that's possibly non-busy - - cron: '42 6 * * *' - -jobs: - ci: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.x' - - name: Install tox - run: python -m pip install tox - - name: Run the sanity checks - run: python -m tox diff --git a/json/.gitignore b/json/.gitignore deleted file mode 100644 index 68bc17f..0000000 --- a/json/.gitignore +++ /dev/null @@ -1,160 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/#use-with-ide -.pdm.toml - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ diff --git a/json/tests/draft3/optional/bignum.json b/json/tests/draft3/optional/bignum.json deleted file mode 100644 index ccc7c17..0000000 --- a/json/tests/draft3/optional/bignum.json +++ /dev/null @@ -1,107 +0,0 @@ -[ - { - "description": "integer", - "schema": {"type": "integer"}, - "tests": [ - { - "description": "a bignum is an integer", - "data": 12345678910111213141516171819202122232425262728293031, - "valid": true - } - ] - }, - { - "description": "number", - "schema": {"type": "number"}, - "tests": [ - { - "description": "a bignum is a number", - "data": 98249283749234923498293171823948729348710298301928331, - "valid": true - } - ] - }, - { - "description": "integer", - "schema": {"type": "integer"}, - "tests": [ - { - "description": "a negative bignum is an integer", - "data": -12345678910111213141516171819202122232425262728293031, - "valid": true - } - ] - }, - { - "description": "number", - "schema": {"type": "number"}, - "tests": [ - { - "description": "a negative bignum is a number", - "data": -98249283749234923498293171823948729348710298301928331, - "valid": true - } - ] - }, - { - "description": "string", - "schema": {"type": "string"}, - "tests": [ - { - "description": "a bignum is not a string", - "data": 98249283749234923498293171823948729348710298301928331, - "valid": false - } - ] - }, - { - "description": "integer comparison", - "schema": {"maximum": 18446744073709551615}, - "tests": [ - { - "description": "comparison works for high numbers", - "data": 18446744073709551600, - "valid": true - } - ] - }, - { - "description": "float comparison with high precision", - "schema": { - "maximum": 972783798187987123879878123.18878137, - "exclusiveMaximum": true - }, - "tests": [ - { - "description": "comparison works for high numbers", - "data": 972783798187987123879878123.188781371, - "valid": false - } - ] - }, - { - "description": "integer comparison", - "schema": {"minimum": -18446744073709551615}, - "tests": [ - { - "description": "comparison works for very negative numbers", - "data": -18446744073709551600, - "valid": true - } - ] - }, - { - "description": "float comparison with high precision on negative numbers", - "schema": { - "minimum": -972783798187987123879878123.18878137, - "exclusiveMinimum": true - }, - "tests": [ - { - "description": "comparison works for very negative numbers", - "data": -972783798187987123879878123.188781371, - "valid": false - } - ] - } -] diff --git a/json/tests/draft6/optional/format/date-time.json b/json/tests/draft6/optional/format/date-time.json deleted file mode 100644 index f4f9933..0000000 --- a/json/tests/draft6/optional/format/date-time.json +++ /dev/null @@ -1,133 +0,0 @@ -[ - { - "description": "validation of date-time strings", - "schema": { "format": "date-time" }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true - }, - { - "description": "a valid date-time string", - "data": "1963-06-19T08:30:06.283185Z", - "valid": true - }, - { - "description": "a valid date-time string without second fraction", - "data": "1963-06-19T08:30:06Z", - "valid": true - }, - { - "description": "a valid date-time string with plus offset", - "data": "1937-01-01T12:00:27.87+00:20", - "valid": true - }, - { - "description": "a valid date-time string with minus offset", - "data": "1990-12-31T15:59:50.123-08:00", - "valid": true - }, - { - "description": "a valid date-time with a leap second, UTC", - "data": "1998-12-31T23:59:60Z", - "valid": true - }, - { - "description": "a valid date-time with a leap second, with minus offset", - "data": "1998-12-31T15:59:60.123-08:00", - "valid": true - }, - { - "description": "an invalid date-time past leap second, UTC", - "data": "1998-12-31T23:59:61Z", - "valid": false - }, - { - "description": "an invalid date-time with leap second on a wrong minute, UTC", - "data": "1998-12-31T23:58:60Z", - "valid": false - }, - { - "description": "an invalid date-time with leap second on a wrong hour, UTC", - "data": "1998-12-31T22:59:60Z", - "valid": false - }, - { - "description": "an invalid day in date-time string", - "data": "1990-02-31T15:59:59.123-08:00", - "valid": false - }, - { - "description": "an invalid offset in date-time string", - "data": "1990-12-31T15:59:59-24:00", - "valid": false - }, - { - "description": "an invalid closing Z after time-zone offset", - "data": "1963-06-19T08:30:06.28123+01:00Z", - "valid": false - }, - { - "description": "an invalid date-time string", - "data": "06/19/1963 08:30:06 PST", - "valid": false - }, - { - "description": "case-insensitive T and Z", - "data": "1963-06-19t08:30:06.283185z", - "valid": true - }, - { - "description": "only RFC3339 not all of ISO 8601 are valid", - "data": "2013-350T01:01:01", - "valid": false - }, - { - "description": "invalid non-padded month dates", - "data": "1963-6-19T08:30:06.283185Z", - "valid": false - }, - { - "description": "invalid non-padded day dates", - "data": "1963-06-1T08:30:06.283185Z", - "valid": false - }, - { - "description": "non-ascii digits should be rejected in the date portion", - "data": "1963-06-1৪T00:00:00Z", - "valid": false - }, - { - "description": "non-ascii digits should be rejected in the time portion", - "data": "1963-06-11T0৪:00:00Z", - "valid": false - } - ] - } -] diff --git a/json/tests/draft6/optional/format/ipv4.json b/json/tests/draft6/optional/format/ipv4.json deleted file mode 100644 index 6b166c7..0000000 --- a/json/tests/draft6/optional/format/ipv4.json +++ /dev/null @@ -1,84 +0,0 @@ -[ - { - "description": "validation of IP addresses", - "schema": { "format": "ipv4" }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true - }, - { - "description": "a valid IP address", - "data": "192.168.0.1", - "valid": true - }, - { - "description": "an IP address with too many components", - "data": "127.0.0.0.1", - "valid": false - }, - { - "description": "an IP address with out-of-range values", - "data": "256.256.256.256", - "valid": false - }, - { - "description": "an IP address without 4 components", - "data": "127.0", - "valid": false - }, - { - "description": "an IP address as an integer", - "data": "0x7f000001", - "valid": false - }, - { - "description": "an IP address as an integer (decimal)", - "data": "2130706433", - "valid": false - }, - { - "description": "leading zeroes should be rejected, as they are treated as octals", - "comment": "see https://sick.codes/universal-netmask-npm-package-used-by-270000-projects-vulnerable-to-octal-input-data-server-side-request-forgery-remote-file-inclusion-local-file-inclusion-and-more-cve-2021-28918/", - "data": "087.10.0.1", - "valid": false - }, - { - "description": "value without leading zero is valid", - "data": "87.10.0.1", - "valid": true - }, - { - "description": "non-ascii digits should be rejected", - "data": "1২7.0.0.1", - "valid": false - } - ] - } -] diff --git a/json/tests/draft6/optional/format/ipv6.json b/json/tests/draft6/optional/format/ipv6.json deleted file mode 100644 index 6379927..0000000 --- a/json/tests/draft6/optional/format/ipv6.json +++ /dev/null @@ -1,208 +0,0 @@ -[ - { - "description": "validation of IPv6 addresses", - "schema": { "format": "ipv6" }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true - }, - { - "description": "a valid IPv6 address", - "data": "::1", - "valid": true - }, - { - "description": "an IPv6 address with out-of-range values", - "data": "12345::", - "valid": false - }, - { - "description": "trailing 4 hex symbols is valid", - "data": "::abef", - "valid": true - }, - { - "description": "trailing 5 hex symbols is invalid", - "data": "::abcef", - "valid": false - }, - { - "description": "an IPv6 address with too many components", - "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", - "valid": false - }, - { - "description": "an IPv6 address containing illegal characters", - "data": "::laptop", - "valid": false - }, - { - "description": "no digits is valid", - "data": "::", - "valid": true - }, - { - "description": "leading colons is valid", - "data": "::42:ff:1", - "valid": true - }, - { - "description": "trailing colons is valid", - "data": "d6::", - "valid": true - }, - { - "description": "missing leading octet is invalid", - "data": ":2:3:4:5:6:7:8", - "valid": false - }, - { - "description": "missing trailing octet is invalid", - "data": "1:2:3:4:5:6:7:", - "valid": false - }, - { - "description": "missing leading octet with omitted octets later", - "data": ":2:3:4::8", - "valid": false - }, - { - "description": "single set of double colons in the middle is valid", - "data": "1:d6::42", - "valid": true - }, - { - "description": "two sets of double colons is invalid", - "data": "1::d6::42", - "valid": false - }, - { - "description": "mixed format with the ipv4 section as decimal octets", - "data": "1::d6:192.168.0.1", - "valid": true - }, - { - "description": "mixed format with double colons between the sections", - "data": "1:2::192.168.0.1", - "valid": true - }, - { - "description": "mixed format with ipv4 section with octet out of range", - "data": "1::2:192.168.256.1", - "valid": false - }, - { - "description": "mixed format with ipv4 section with a hex octet", - "data": "1::2:192.168.ff.1", - "valid": false - }, - { - "description": "mixed format with leading double colons (ipv4-mapped ipv6 address)", - "data": "::ffff:192.168.0.1", - "valid": true - }, - { - "description": "triple colons is invalid", - "data": "1:2:3:4:5:::8", - "valid": false - }, - { - "description": "8 octets", - "data": "1:2:3:4:5:6:7:8", - "valid": true - }, - { - "description": "insufficient octets without double colons", - "data": "1:2:3:4:5:6:7", - "valid": false - }, - { - "description": "no colons is invalid", - "data": "1", - "valid": false - }, - { - "description": "ipv4 is not ipv6", - "data": "127.0.0.1", - "valid": false - }, - { - "description": "ipv4 segment must have 4 octets", - "data": "1:2:3:4:1.2.3", - "valid": false - }, - { - "description": "leading whitespace is invalid", - "data": " ::1", - "valid": false - }, - { - "description": "trailing whitespace is invalid", - "data": "::1 ", - "valid": false - }, - { - "description": "netmask is not a part of ipv6 address", - "data": "fe80::/64", - "valid": false - }, - { - "description": "zone id is not a part of ipv6 address", - "data": "fe80::a%eth1", - "valid": false - }, - { - "description": "a long valid ipv6", - "data": "1000:1000:1000:1000:1000:1000:255.255.255.255", - "valid": true - }, - { - "description": "a long invalid ipv6, below length limit, first", - "data": "100:100:100:100:100:100:255.255.255.255.255", - "valid": false - }, - { - "description": "a long invalid ipv6, below length limit, second", - "data": "100:100:100:100:100:100:100:255.255.255.255", - "valid": false - }, - { - "description": "non-ascii digits should be rejected", - "data": "1:2:3:4:5:6:7:৪", - "valid": false - }, - { - "description": "non-ascii digits should be rejected in the ipv4 portion also", - "data": "1:2::192.16৪.0.1", - "valid": false - } - ] - } -] diff --git a/json/tests/draft7/anyOf.json b/json/tests/draft7/anyOf.json deleted file mode 100644 index b720afa..0000000 --- a/json/tests/draft7/anyOf.json +++ /dev/null @@ -1,215 +0,0 @@ -[ - { - "description": "anyOf", - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "minimum": 2 - } - ] - }, - "tests": [ - { - "description": "first anyOf valid", - "data": 1, - "valid": true - }, - { - "description": "second anyOf valid", - "data": 2.5, - "valid": true - }, - { - "description": "both anyOf valid", - "data": 3, - "valid": true - }, - { - "description": "neither anyOf valid", - "data": 1.5, - "valid": false - } - ] - }, - { - "description": "anyOf with base schema", - "schema": { - "type": "string", - "anyOf" : [ - { - "maxLength": 2 - }, - { - "minLength": 4 - } - ] - }, - "tests": [ - { - "description": "mismatch base schema", - "data": 3, - "valid": false - }, - { - "description": "one anyOf valid", - "data": "foobar", - "valid": true - }, - { - "description": "both anyOf invalid", - "data": "foo", - "valid": false - } - ] - }, - { - "description": "anyOf with boolean schemas, all true", - "schema": {"anyOf": [true, true]}, - "tests": [ - { - "description": "any value is valid", - "data": "foo", - "valid": true - } - ] - }, - { - "description": "anyOf with boolean schemas, some true", - "schema": {"anyOf": [true, false]}, - "tests": [ - { - "description": "any value is valid", - "data": "foo", - "valid": true - } - ] - }, - { - "description": "anyOf with boolean schemas, all false", - "schema": {"anyOf": [false, false]}, - "tests": [ - { - "description": "any value is invalid", - "data": "foo", - "valid": false - } - ] - }, - { - "description": "anyOf complex types", - "schema": { - "anyOf": [ - { - "properties": { - "bar": {"type": "integer"} - }, - "required": ["bar"] - }, - { - "properties": { - "foo": {"type": "string"} - }, - "required": ["foo"] - } - ] - }, - "tests": [ - { - "description": "first anyOf valid (complex)", - "data": {"bar": 2}, - "valid": true - }, - { - "description": "second anyOf valid (complex)", - "data": {"foo": "baz"}, - "valid": true - }, - { - "description": "both anyOf valid (complex)", - "data": {"foo": "baz", "bar": 2}, - "valid": true - }, - { - "description": "neither anyOf valid (complex)", - "data": {"foo": 2, "bar": "quux"}, - "valid": false - } - ] - }, - { - "description": "anyOf with one empty schema", - "schema": { - "anyOf": [ - { "type": "number" }, - {} - ] - }, - "tests": [ - { - "description": "string is valid", - "data": "foo", - "valid": true - }, - { - "description": "number is valid", - "data": 123, - "valid": true - } - ] - }, - { - "description": "nested anyOf, to check validation semantics", - "schema": { - "anyOf": [ - { - "anyOf": [ - { - "type": "null" - } - ] - } - ] - }, - "tests": [ - { - "description": "null is valid", - "data": null, - "valid": true - }, - { - "description": "anything non-null is invalid", - "data": 123, - "valid": false - } - ] - }, - { - "description": "nested anyOf, to check validation semantics", - "schema": { - "anyOf": [ - { - "anyOf": [ - { - "type": "null" - } - ] - } - ] - }, - "tests": [ - { - "description": "null is valid", - "data": null, - "valid": true - }, - { - "description": "anything non-null is invalid", - "data": 123, - "valid": false - } - ] - } -] diff --git a/json/tests/draft7/optional/bignum.json b/json/tests/draft7/optional/bignum.json deleted file mode 100644 index 3f49226..0000000 --- a/json/tests/draft7/optional/bignum.json +++ /dev/null @@ -1,93 +0,0 @@ -[ - { - "description": "integer", - "schema": { "type": "integer" }, - "tests": [ - { - "description": "a bignum is an integer", - "data": 12345678910111213141516171819202122232425262728293031, - "valid": true - }, - { - "description": "a negative bignum is an integer", - "data": -12345678910111213141516171819202122232425262728293031, - "valid": true - } - ] - }, - { - "description": "number", - "schema": { "type": "number" }, - "tests": [ - { - "description": "a bignum is a number", - "data": 98249283749234923498293171823948729348710298301928331, - "valid": true - }, - { - "description": "a negative bignum is a number", - "data": -98249283749234923498293171823948729348710298301928331, - "valid": true - } - ] - }, - { - "description": "string", - "schema": { "type": "string" }, - "tests": [ - { - "description": "a bignum is not a string", - "data": 98249283749234923498293171823948729348710298301928331, - "valid": false - } - ] - }, - { - "description": "integer comparison", - "schema": { "maximum": 18446744073709551615 }, - "tests": [ - { - "description": "comparison works for high numbers", - "data": 18446744073709551600, - "valid": true - } - ] - }, - { - "description": "float comparison with high precision", - "schema": { - "exclusiveMaximum": 972783798187987123879878123.18878137 - }, - "tests": [ - { - "description": "comparison works for high numbers", - "data": 972783798187987123879878123.188781371, - "valid": false - } - ] - }, - { - "description": "integer comparison", - "schema": { "minimum": -18446744073709551615 }, - "tests": [ - { - "description": "comparison works for very negative numbers", - "data": -18446744073709551600, - "valid": true - } - ] - }, - { - "description": "float comparison with high precision on negative numbers", - "schema": { - "exclusiveMinimum": -972783798187987123879878123.18878137 - }, - "tests": [ - { - "description": "comparison works for very negative numbers", - "data": -972783798187987123879878123.188781371, - "valid": false - } - ] - } -] diff --git a/json/tests/draft7/optional/format/date-time.json b/json/tests/draft7/optional/format/date-time.json deleted file mode 100644 index f4f9933..0000000 --- a/json/tests/draft7/optional/format/date-time.json +++ /dev/null @@ -1,133 +0,0 @@ -[ - { - "description": "validation of date-time strings", - "schema": { "format": "date-time" }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true - }, - { - "description": "a valid date-time string", - "data": "1963-06-19T08:30:06.283185Z", - "valid": true - }, - { - "description": "a valid date-time string without second fraction", - "data": "1963-06-19T08:30:06Z", - "valid": true - }, - { - "description": "a valid date-time string with plus offset", - "data": "1937-01-01T12:00:27.87+00:20", - "valid": true - }, - { - "description": "a valid date-time string with minus offset", - "data": "1990-12-31T15:59:50.123-08:00", - "valid": true - }, - { - "description": "a valid date-time with a leap second, UTC", - "data": "1998-12-31T23:59:60Z", - "valid": true - }, - { - "description": "a valid date-time with a leap second, with minus offset", - "data": "1998-12-31T15:59:60.123-08:00", - "valid": true - }, - { - "description": "an invalid date-time past leap second, UTC", - "data": "1998-12-31T23:59:61Z", - "valid": false - }, - { - "description": "an invalid date-time with leap second on a wrong minute, UTC", - "data": "1998-12-31T23:58:60Z", - "valid": false - }, - { - "description": "an invalid date-time with leap second on a wrong hour, UTC", - "data": "1998-12-31T22:59:60Z", - "valid": false - }, - { - "description": "an invalid day in date-time string", - "data": "1990-02-31T15:59:59.123-08:00", - "valid": false - }, - { - "description": "an invalid offset in date-time string", - "data": "1990-12-31T15:59:59-24:00", - "valid": false - }, - { - "description": "an invalid closing Z after time-zone offset", - "data": "1963-06-19T08:30:06.28123+01:00Z", - "valid": false - }, - { - "description": "an invalid date-time string", - "data": "06/19/1963 08:30:06 PST", - "valid": false - }, - { - "description": "case-insensitive T and Z", - "data": "1963-06-19t08:30:06.283185z", - "valid": true - }, - { - "description": "only RFC3339 not all of ISO 8601 are valid", - "data": "2013-350T01:01:01", - "valid": false - }, - { - "description": "invalid non-padded month dates", - "data": "1963-6-19T08:30:06.283185Z", - "valid": false - }, - { - "description": "invalid non-padded day dates", - "data": "1963-06-1T08:30:06.283185Z", - "valid": false - }, - { - "description": "non-ascii digits should be rejected in the date portion", - "data": "1963-06-1৪T00:00:00Z", - "valid": false - }, - { - "description": "non-ascii digits should be rejected in the time portion", - "data": "1963-06-11T0৪:00:00Z", - "valid": false - } - ] - } -] diff --git a/json/tests/draft7/optional/format/ipv4.json b/json/tests/draft7/optional/format/ipv4.json deleted file mode 100644 index 6b166c7..0000000 --- a/json/tests/draft7/optional/format/ipv4.json +++ /dev/null @@ -1,84 +0,0 @@ -[ - { - "description": "validation of IP addresses", - "schema": { "format": "ipv4" }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true - }, - { - "description": "a valid IP address", - "data": "192.168.0.1", - "valid": true - }, - { - "description": "an IP address with too many components", - "data": "127.0.0.0.1", - "valid": false - }, - { - "description": "an IP address with out-of-range values", - "data": "256.256.256.256", - "valid": false - }, - { - "description": "an IP address without 4 components", - "data": "127.0", - "valid": false - }, - { - "description": "an IP address as an integer", - "data": "0x7f000001", - "valid": false - }, - { - "description": "an IP address as an integer (decimal)", - "data": "2130706433", - "valid": false - }, - { - "description": "leading zeroes should be rejected, as they are treated as octals", - "comment": "see https://sick.codes/universal-netmask-npm-package-used-by-270000-projects-vulnerable-to-octal-input-data-server-side-request-forgery-remote-file-inclusion-local-file-inclusion-and-more-cve-2021-28918/", - "data": "087.10.0.1", - "valid": false - }, - { - "description": "value without leading zero is valid", - "data": "87.10.0.1", - "valid": true - }, - { - "description": "non-ascii digits should be rejected", - "data": "1২7.0.0.1", - "valid": false - } - ] - } -] diff --git a/json/tests/draft7/optional/format/ipv6.json b/json/tests/draft7/optional/format/ipv6.json deleted file mode 100644 index 6379927..0000000 --- a/json/tests/draft7/optional/format/ipv6.json +++ /dev/null @@ -1,208 +0,0 @@ -[ - { - "description": "validation of IPv6 addresses", - "schema": { "format": "ipv6" }, - "tests": [ - { - "description": "all string formats ignore integers", - "data": 12, - "valid": true - }, - { - "description": "all string formats ignore floats", - "data": 13.7, - "valid": true - }, - { - "description": "all string formats ignore objects", - "data": {}, - "valid": true - }, - { - "description": "all string formats ignore arrays", - "data": [], - "valid": true - }, - { - "description": "all string formats ignore booleans", - "data": false, - "valid": true - }, - { - "description": "all string formats ignore nulls", - "data": null, - "valid": true - }, - { - "description": "a valid IPv6 address", - "data": "::1", - "valid": true - }, - { - "description": "an IPv6 address with out-of-range values", - "data": "12345::", - "valid": false - }, - { - "description": "trailing 4 hex symbols is valid", - "data": "::abef", - "valid": true - }, - { - "description": "trailing 5 hex symbols is invalid", - "data": "::abcef", - "valid": false - }, - { - "description": "an IPv6 address with too many components", - "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", - "valid": false - }, - { - "description": "an IPv6 address containing illegal characters", - "data": "::laptop", - "valid": false - }, - { - "description": "no digits is valid", - "data": "::", - "valid": true - }, - { - "description": "leading colons is valid", - "data": "::42:ff:1", - "valid": true - }, - { - "description": "trailing colons is valid", - "data": "d6::", - "valid": true - }, - { - "description": "missing leading octet is invalid", - "data": ":2:3:4:5:6:7:8", - "valid": false - }, - { - "description": "missing trailing octet is invalid", - "data": "1:2:3:4:5:6:7:", - "valid": false - }, - { - "description": "missing leading octet with omitted octets later", - "data": ":2:3:4::8", - "valid": false - }, - { - "description": "single set of double colons in the middle is valid", - "data": "1:d6::42", - "valid": true - }, - { - "description": "two sets of double colons is invalid", - "data": "1::d6::42", - "valid": false - }, - { - "description": "mixed format with the ipv4 section as decimal octets", - "data": "1::d6:192.168.0.1", - "valid": true - }, - { - "description": "mixed format with double colons between the sections", - "data": "1:2::192.168.0.1", - "valid": true - }, - { - "description": "mixed format with ipv4 section with octet out of range", - "data": "1::2:192.168.256.1", - "valid": false - }, - { - "description": "mixed format with ipv4 section with a hex octet", - "data": "1::2:192.168.ff.1", - "valid": false - }, - { - "description": "mixed format with leading double colons (ipv4-mapped ipv6 address)", - "data": "::ffff:192.168.0.1", - "valid": true - }, - { - "description": "triple colons is invalid", - "data": "1:2:3:4:5:::8", - "valid": false - }, - { - "description": "8 octets", - "data": "1:2:3:4:5:6:7:8", - "valid": true - }, - { - "description": "insufficient octets without double colons", - "data": "1:2:3:4:5:6:7", - "valid": false - }, - { - "description": "no colons is invalid", - "data": "1", - "valid": false - }, - { - "description": "ipv4 is not ipv6", - "data": "127.0.0.1", - "valid": false - }, - { - "description": "ipv4 segment must have 4 octets", - "data": "1:2:3:4:1.2.3", - "valid": false - }, - { - "description": "leading whitespace is invalid", - "data": " ::1", - "valid": false - }, - { - "description": "trailing whitespace is invalid", - "data": "::1 ", - "valid": false - }, - { - "description": "netmask is not a part of ipv6 address", - "data": "fe80::/64", - "valid": false - }, - { - "description": "zone id is not a part of ipv6 address", - "data": "fe80::a%eth1", - "valid": false - }, - { - "description": "a long valid ipv6", - "data": "1000:1000:1000:1000:1000:1000:255.255.255.255", - "valid": true - }, - { - "description": "a long invalid ipv6, below length limit, first", - "data": "100:100:100:100:100:100:255.255.255.255.255", - "valid": false - }, - { - "description": "a long invalid ipv6, below length limit, second", - "data": "100:100:100:100:100:100:100:255.255.255.255", - "valid": false - }, - { - "description": "non-ascii digits should be rejected", - "data": "1:2:3:4:5:6:7:৪", - "valid": false - }, - { - "description": "non-ascii digits should be rejected in the ipv4 portion also", - "data": "1:2::192.16৪.0.1", - "valid": false - } - ] - } -] diff --git a/json/tox.ini b/json/tox.ini deleted file mode 100644 index ec180a9..0000000 --- a/json/tox.ini +++ /dev/null @@ -1,9 +0,0 @@ -[tox] -minversion = 1.6 -envlist = sanity -skipsdist = True - -[testenv:sanity] -# used just for validating the structure of the test case files themselves -deps = jsonschema==4.6.1 -commands = {envpython} bin/jsonschema_suite check diff --git a/jsonschema/__init__.py b/jsonschema/__init__.py deleted file mode 100644 index 75f2946..0000000 --- a/jsonschema/__init__.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -An implementation of JSON Schema for Python - -The main functionality is provided by the validator classes for each of the -supported JSON Schema versions. - -Most commonly, `validate` is the quickest way to simply validate a given -instance under a schema, and will create a validator for you. -""" -import warnings - -from jsonschema._format import ( - FormatChecker, - draft3_format_checker, - draft4_format_checker, - draft6_format_checker, - draft7_format_checker, - draft201909_format_checker, - draft202012_format_checker, -) -from jsonschema._types import TypeChecker -from jsonschema.exceptions import ( - ErrorTree, - FormatError, - RefResolutionError, - SchemaError, - ValidationError, -) -from jsonschema.protocols import Validator -from jsonschema.validators import ( - Draft3Validator, - Draft4Validator, - Draft6Validator, - Draft7Validator, - Draft201909Validator, - Draft202012Validator, - RefResolver, - validate, -) - - -def __getattr__(name): - if name == "__version__": - warnings.warn( - "Accessing jsonschema.__version__ is deprecated and will be " - "removed in a future release. Use importlib.metadata directly " - "to query for jsonschema's version.", - DeprecationWarning, - stacklevel=2, - ) - - try: - from importlib import metadata - except ImportError: - import importlib_metadata as metadata - - return metadata.version("jsonschema") - raise AttributeError(f"module {__name__} has no attribute {name}") diff --git a/jsonschema/__main__.py b/jsonschema/__main__.py deleted file mode 100644 index fdc21e2..0000000 --- a/jsonschema/__main__.py +++ /dev/null @@ -1,3 +0,0 @@ -from jsonschema.cli import main - -main() diff --git a/jsonschema/_format.py b/jsonschema/_format.py deleted file mode 100644 index da4bb79..0000000 --- a/jsonschema/_format.py +++ /dev/null @@ -1,498 +0,0 @@ -from __future__ import annotations - -from contextlib import suppress -from uuid import UUID -import datetime -import ipaddress -import re -import typing - -from jsonschema.exceptions import FormatError - -_FormatCheckCallable = typing.Callable[[object], bool] -_F = typing.TypeVar("_F", bound=_FormatCheckCallable) -_RaisesType = typing.Union[ - typing.Type[Exception], typing.Tuple[typing.Type[Exception], ...], -] - - -class FormatChecker(object): - """ - A ``format`` property checker. - - JSON Schema does not mandate that the ``format`` property actually do any - validation. If validation is desired however, instances of this class can - be hooked into validators to enable format validation. - - `FormatChecker` objects always return ``True`` when asked about - formats that they do not know how to validate. - - To check a custom format using a function that takes an instance and - returns a ``bool``, use the `FormatChecker.checks` or - `FormatChecker.cls_checks` decorators. - - Arguments: - - formats (~collections.abc.Iterable): - - The known formats to validate. This argument can be used to - limit which formats will be used during validation. - """ - - checkers: dict[ - str, - tuple[_FormatCheckCallable, _RaisesType], - ] = {} - - def __init__(self, formats: typing.Iterable[str] | None = None): - if formats is None: - self.checkers = self.checkers.copy() - else: - self.checkers = dict((k, self.checkers[k]) for k in formats) - - def __repr__(self): - return "<FormatChecker checkers={}>".format(sorted(self.checkers)) - - def checks( - self, format: str, raises: _RaisesType = (), - ) -> typing.Callable[[_F], _F]: - """ - Register a decorated function as validating a new format. - - Arguments: - - format (str): - - The format that the decorated function will check. - - raises (Exception): - - The exception(s) raised by the decorated function when an - invalid instance is found. - - The exception object will be accessible as the - `jsonschema.exceptions.ValidationError.cause` attribute of the - resulting validation error. - """ - - def _checks(func: _F) -> _F: - self.checkers[format] = (func, raises) - return func - - return _checks - - @classmethod - def cls_checks( - cls, format: str, raises: _RaisesType = (), - ) -> typing.Callable[[_F], _F]: - def _checks(func: _F) -> _F: - cls.checkers[format] = (func, raises) - return func - - return _checks - - def check(self, instance: object, format: str) -> None: - """ - Check whether the instance conforms to the given format. - - Arguments: - - instance (*any primitive type*, i.e. str, number, bool): - - The instance to check - - format (str): - - The format that instance should conform to - - - Raises: - - FormatError: if the instance does not conform to ``format`` - """ - - if format not in self.checkers: - return - - func, raises = self.checkers[format] - result, cause = None, None - try: - result = func(instance) - except raises as e: - cause = e - if not result: - raise FormatError(f"{instance!r} is not a {format!r}", cause=cause) - - def conforms(self, instance: object, format: str) -> bool: - """ - Check whether the instance conforms to the given format. - - Arguments: - - instance (*any primitive type*, i.e. str, number, bool): - - The instance to check - - format (str): - - The format that instance should conform to - - Returns: - - bool: whether it conformed - """ - - try: - self.check(instance, format) - except FormatError: - return False - else: - return True - - -draft3_format_checker = FormatChecker() -draft4_format_checker = FormatChecker() -draft6_format_checker = FormatChecker() -draft7_format_checker = FormatChecker() -draft201909_format_checker = FormatChecker() -draft202012_format_checker = FormatChecker() - -_draft_checkers: dict[str, FormatChecker] = dict( - draft3=draft3_format_checker, - draft4=draft4_format_checker, - draft6=draft6_format_checker, - draft7=draft7_format_checker, - draft201909=draft201909_format_checker, - draft202012=draft202012_format_checker, -) - - -def _checks_drafts( - name=None, - draft3=None, - draft4=None, - draft6=None, - draft7=None, - draft201909=None, - draft202012=None, - raises=(), -) -> typing.Callable[[_F], _F]: - draft3 = draft3 or name - draft4 = draft4 or name - draft6 = draft6 or name - draft7 = draft7 or name - draft201909 = draft201909 or name - draft202012 = draft202012 or name - - def wrap(func: _F) -> _F: - if draft3: - func = _draft_checkers["draft3"].checks(draft3, raises)(func) - if draft4: - func = _draft_checkers["draft4"].checks(draft4, raises)(func) - if draft6: - func = _draft_checkers["draft6"].checks(draft6, raises)(func) - if draft7: - func = _draft_checkers["draft7"].checks(draft7, raises)(func) - if draft201909: - func = _draft_checkers["draft201909"].checks(draft201909, raises)( - func, - ) - if draft202012: - func = _draft_checkers["draft202012"].checks(draft202012, raises)( - func, - ) - - # Oy. This is bad global state, but relied upon for now, until - # deprecation. See #519 and test_format_checkers_come_with_defaults - FormatChecker.cls_checks( - draft202012 or draft201909 or draft7 or draft6 or draft4 or draft3, - raises, - )(func) - return func - - return wrap - - -@_checks_drafts(name="idn-email") -@_checks_drafts(name="email") -def is_email(instance: object) -> bool: - if not isinstance(instance, str): - return True - return "@" in instance - - -@_checks_drafts( - draft3="ip-address", - draft4="ipv4", - draft6="ipv4", - draft7="ipv4", - draft201909="ipv4", - draft202012="ipv4", - raises=ipaddress.AddressValueError, -) -def is_ipv4(instance: object) -> bool: - if not isinstance(instance, str): - return True - return bool(ipaddress.IPv4Address(instance)) - - -@_checks_drafts(name="ipv6", raises=ipaddress.AddressValueError) -def is_ipv6(instance: object) -> bool: - if not isinstance(instance, str): - return True - address = ipaddress.IPv6Address(instance) - return not getattr(address, "scope_id", "") - - -with suppress(ImportError): - from fqdn import FQDN - - @_checks_drafts( - draft3="host-name", - draft4="hostname", - draft6="hostname", - draft7="hostname", - draft201909="hostname", - draft202012="hostname", - ) - def is_host_name(instance: object) -> bool: - if not isinstance(instance, str): - return True - return FQDN(instance).is_valid - - -with suppress(ImportError): - # The built-in `idna` codec only implements RFC 3890, so we go elsewhere. - import idna - - @_checks_drafts( - draft7="idn-hostname", - draft201909="idn-hostname", - draft202012="idn-hostname", - raises=(idna.IDNAError, UnicodeError), - ) - def is_idn_host_name(instance: object) -> bool: - if not isinstance(instance, str): - return True - idna.encode(instance) - return True - - -try: - import rfc3987 -except ImportError: - with suppress(ImportError): - from rfc3986_validator import validate_rfc3986 - - @_checks_drafts(name="uri") - def is_uri(instance: object) -> bool: - if not isinstance(instance, str): - return True - return validate_rfc3986(instance, rule="URI") - - @_checks_drafts( - draft6="uri-reference", - draft7="uri-reference", - draft201909="uri-reference", - draft202012="uri-reference", - raises=ValueError, - ) - def is_uri_reference(instance: object) -> bool: - if not isinstance(instance, str): - return True - return validate_rfc3986(instance, rule="URI_reference") - -else: - - @_checks_drafts( - draft7="iri", - draft201909="iri", - draft202012="iri", - raises=ValueError, - ) - def is_iri(instance: object) -> bool: - if not isinstance(instance, str): - return True - return rfc3987.parse(instance, rule="IRI") - - @_checks_drafts( - draft7="iri-reference", - draft201909="iri-reference", - draft202012="iri-reference", - raises=ValueError, - ) - def is_iri_reference(instance: object) -> bool: - if not isinstance(instance, str): - return True - return rfc3987.parse(instance, rule="IRI_reference") - - @_checks_drafts(name="uri", raises=ValueError) - def is_uri(instance: object) -> bool: - if not isinstance(instance, str): - return True - return rfc3987.parse(instance, rule="URI") - - @_checks_drafts( - draft6="uri-reference", - draft7="uri-reference", - draft201909="uri-reference", - draft202012="uri-reference", - raises=ValueError, - ) - def is_uri_reference(instance: object) -> bool: - if not isinstance(instance, str): - return True - return rfc3987.parse(instance, rule="URI_reference") - - -with suppress(ImportError): - from rfc3339_validator import validate_rfc3339 - - @_checks_drafts(name="date-time") - def is_datetime(instance: object) -> bool: - if not isinstance(instance, str): - return True - return validate_rfc3339(instance.upper()) - - @_checks_drafts( - draft7="time", - draft201909="time", - draft202012="time", - ) - def is_time(instance: object) -> bool: - if not isinstance(instance, str): - return True - return is_datetime("1970-01-01T" + instance) - - -@_checks_drafts(name="regex", raises=re.error) -def is_regex(instance: object) -> bool: - if not isinstance(instance, str): - return True - return bool(re.compile(instance)) - - -@_checks_drafts( - draft3="date", - draft7="date", - draft201909="date", - draft202012="date", - raises=ValueError, -) -def is_date(instance: object) -> bool: - if not isinstance(instance, str): - return True - return bool(instance.isascii() and datetime.date.fromisoformat(instance)) - - -@_checks_drafts(draft3="time", raises=ValueError) -def is_draft3_time(instance: object) -> bool: - if not isinstance(instance, str): - return True - return bool(datetime.datetime.strptime(instance, "%H:%M:%S")) - - -with suppress(ImportError): - from webcolors import CSS21_NAMES_TO_HEX - import webcolors - - def is_css_color_code(instance: object) -> bool: - return webcolors.normalize_hex(instance) - - @_checks_drafts(draft3="color", raises=(ValueError, TypeError)) - def is_css21_color(instance: object) -> bool: - if ( - not isinstance(instance, str) - or instance.lower() in CSS21_NAMES_TO_HEX - ): - return True - return is_css_color_code(instance) - - -with suppress(ImportError): - import jsonpointer - - @_checks_drafts( - draft6="json-pointer", - draft7="json-pointer", - draft201909="json-pointer", - draft202012="json-pointer", - raises=jsonpointer.JsonPointerException, - ) - def is_json_pointer(instance: object) -> bool: - if not isinstance(instance, str): - return True - return bool(jsonpointer.JsonPointer(instance)) - - # TODO: I don't want to maintain this, so it - # needs to go either into jsonpointer (pending - # https://github.com/stefankoegl/python-json-pointer/issues/34) or - # into a new external library. - @_checks_drafts( - draft7="relative-json-pointer", - draft201909="relative-json-pointer", - draft202012="relative-json-pointer", - raises=jsonpointer.JsonPointerException, - ) - def is_relative_json_pointer(instance: object) -> bool: - # Definition taken from: - # https://tools.ietf.org/html/draft-handrews-relative-json-pointer-01#section-3 - if not isinstance(instance, str): - return True - non_negative_integer, rest = [], "" - for i, character in enumerate(instance): - if character.isdigit(): - # digits with a leading "0" are not allowed - if i > 0 and int(instance[i - 1]) == 0: - return False - - non_negative_integer.append(character) - continue - - if not non_negative_integer: - return False - - rest = instance[i:] - break - return (rest == "#") or bool(jsonpointer.JsonPointer(rest)) - - -with suppress(ImportError): - import uri_template - - @_checks_drafts( - draft6="uri-template", - draft7="uri-template", - draft201909="uri-template", - draft202012="uri-template", - ) - def is_uri_template(instance: object) -> bool: - if not isinstance(instance, str): - return True - return uri_template.validate(instance) - - -with suppress(ImportError): - import isoduration - - @_checks_drafts( - draft201909="duration", - draft202012="duration", - raises=isoduration.DurationParsingException, - ) - def is_duration(instance: object) -> bool: - if not isinstance(instance, str): - return True - return bool(isoduration.parse_duration(instance)) - - -@_checks_drafts( - draft201909="uuid", - draft202012="uuid", - raises=ValueError, -) -def is_uuid(instance: object) -> bool: - if not isinstance(instance, str): - return True - UUID(instance) - return all(instance[position] == "-" for position in (8, 13, 18, 23)) diff --git a/jsonschema/_legacy_validators.py b/jsonschema/_legacy_validators.py deleted file mode 100644 index 5be628f..0000000 --- a/jsonschema/_legacy_validators.py +++ /dev/null @@ -1,228 +0,0 @@ -from jsonschema import _utils -from jsonschema.exceptions import ValidationError - - -def ignore_ref_siblings(schema): - """ - Ignore siblings of ``$ref`` if it is present. - - Otherwise, return all validators. - - Suitable for use with `create`'s ``applicable_validators`` argument. - """ - ref = schema.get("$ref") - if ref is not None: - return [("$ref", ref)] - else: - return schema.items() - - -def dependencies_draft3(validator, dependencies, instance, schema): - if not validator.is_type(instance, "object"): - return - - for property, dependency in dependencies.items(): - if property not in instance: - continue - - if validator.is_type(dependency, "object"): - yield from validator.descend( - instance, dependency, schema_path=property, - ) - elif validator.is_type(dependency, "string"): - if dependency not in instance: - message = f"{dependency!r} is a dependency of {property!r}" - yield ValidationError(message) - else: - for each in dependency: - if each not in instance: - message = f"{each!r} is a dependency of {property!r}" - yield ValidationError(message) - - -def dependencies_draft4_draft6_draft7( - validator, - dependencies, - instance, - schema, -): - """ - Support for the ``dependencies`` validator from pre-draft 2019-09. - - In later drafts, the validator was split into separate - ``dependentRequired`` and ``dependentSchemas`` validators. - """ - if not validator.is_type(instance, "object"): - return - - for property, dependency in dependencies.items(): - if property not in instance: - continue - - if validator.is_type(dependency, "array"): - for each in dependency: - if each not in instance: - message = f"{each!r} is a dependency of {property!r}" - yield ValidationError(message) - else: - yield from validator.descend( - instance, dependency, schema_path=property, - ) - - -def disallow_draft3(validator, disallow, instance, schema): - for disallowed in _utils.ensure_list(disallow): - if validator.evolve(schema={"type": [disallowed]}).is_valid(instance): - message = f"{disallowed!r} is disallowed for {instance!r}" - yield ValidationError(message) - - -def extends_draft3(validator, extends, instance, schema): - if validator.is_type(extends, "object"): - yield from validator.descend(instance, extends) - return - for index, subschema in enumerate(extends): - yield from validator.descend(instance, subschema, schema_path=index) - - -def items_draft3_draft4(validator, items, instance, schema): - if not validator.is_type(instance, "array"): - return - - if validator.is_type(items, "object"): - for index, item in enumerate(instance): - yield from validator.descend(item, items, path=index) - else: - for (index, item), subschema in zip(enumerate(instance), items): - yield from validator.descend( - item, subschema, path=index, schema_path=index, - ) - - -def items_draft6_draft7_draft201909(validator, items, instance, schema): - if not validator.is_type(instance, "array"): - return - - if validator.is_type(items, "array"): - for (index, item), subschema in zip(enumerate(instance), items): - yield from validator.descend( - item, subschema, path=index, schema_path=index, - ) - else: - for index, item in enumerate(instance): - yield from validator.descend(item, items, path=index) - - -def minimum_draft3_draft4(validator, minimum, instance, schema): - if not validator.is_type(instance, "number"): - return - - if schema.get("exclusiveMinimum", False): - failed = instance <= minimum - cmp = "less than or equal to" - else: - failed = instance < minimum - cmp = "less than" - - if failed: - message = f"{instance!r} is {cmp} the minimum of {minimum!r}" - yield ValidationError(message) - - -def maximum_draft3_draft4(validator, maximum, instance, schema): - if not validator.is_type(instance, "number"): - return - - if schema.get("exclusiveMaximum", False): - failed = instance >= maximum - cmp = "greater than or equal to" - else: - failed = instance > maximum - cmp = "greater than" - - if failed: - message = f"{instance!r} is {cmp} the maximum of {maximum!r}" - yield ValidationError(message) - - -def properties_draft3(validator, properties, instance, schema): - if not validator.is_type(instance, "object"): - return - - for property, subschema in properties.items(): - if property in instance: - yield from validator.descend( - instance[property], - subschema, - path=property, - schema_path=property, - ) - elif subschema.get("required", False): - error = ValidationError(f"{property!r} is a required property") - error._set( - validator="required", - validator_value=subschema["required"], - instance=instance, - schema=schema, - ) - error.path.appendleft(property) - error.schema_path.extend([property, "required"]) - yield error - - -def type_draft3(validator, types, instance, schema): - types = _utils.ensure_list(types) - - all_errors = [] - for index, type in enumerate(types): - if validator.is_type(type, "object"): - errors = list(validator.descend(instance, type, schema_path=index)) - if not errors: - return - all_errors.extend(errors) - else: - if validator.is_type(instance, type): - return - else: - reprs = [] - for type in types: - try: - reprs.append(repr(type["name"])) - except Exception: - reprs.append(repr(type)) - yield ValidationError( - f"{instance!r} is not of type {', '.join(reprs)}", - context=all_errors, - ) - - -def contains_draft6_draft7(validator, contains, instance, schema): - if not validator.is_type(instance, "array"): - return - - if not any( - validator.evolve(schema=contains).is_valid(element) - for element in instance - ): - yield ValidationError( - f"None of {instance!r} are valid under the given schema", - ) - - -def recursiveRef(validator, recursiveRef, instance, schema): - lookup_url, target = validator.resolver.resolution_scope, validator.schema - - for each in reversed(validator.resolver._scopes_stack[1:]): - lookup_url, next_target = validator.resolver.resolve(each) - if next_target.get("$recursiveAnchor"): - target = next_target - else: - break - - fragment = recursiveRef.lstrip("#") - subschema = validator.resolver.resolve_fragment(target, fragment) - # FIXME: This is gutted (and not calling .descend) because it can trigger - # recursion errors, so there's a bug here. Re-enable the tests to - # see it. - subschema - return [] diff --git a/jsonschema/_types.py b/jsonschema/_types.py deleted file mode 100644 index 9d59eb3..0000000 --- a/jsonschema/_types.py +++ /dev/null @@ -1,217 +0,0 @@ -from __future__ import annotations - -import numbers -import typing - -from pyrsistent import pmap -import attr - -from jsonschema.exceptions import UndefinedTypeCheck - - -# unfortunately, the type of pmap is generic, and if used as the attr.ib -# converter, the generic type is presented to mypy, which then fails to match -# the concrete type of a type checker mapping -# this "do nothing" wrapper presents the correct information to mypy -def _typed_pmap_converter( - init_val: typing.Mapping[ - str, - typing.Callable[["TypeChecker", typing.Any], bool], - ], -) -> typing.Mapping[str, typing.Callable[["TypeChecker", typing.Any], bool]]: - return typing.cast( - typing.Mapping[ - str, - typing.Callable[["TypeChecker", typing.Any], bool], - ], - pmap(init_val), - ) - - -def is_array(checker, instance): - return isinstance(instance, list) - - -def is_bool(checker, instance): - return isinstance(instance, bool) - - -def is_integer(checker, instance): - # bool inherits from int, so ensure bools aren't reported as ints - if isinstance(instance, bool): - return False - return isinstance(instance, int) - - -def is_null(checker, instance): - return instance is None - - -def is_number(checker, instance): - # bool inherits from int, so ensure bools aren't reported as ints - if isinstance(instance, bool): - return False - return isinstance(instance, numbers.Number) - - -def is_object(checker, instance): - return isinstance(instance, dict) - - -def is_string(checker, instance): - return isinstance(instance, str) - - -def is_any(checker, instance): - return True - - -@attr.s(frozen=True) -class TypeChecker(object): - """ - A ``type`` property checker. - - A `TypeChecker` performs type checking for a `Validator`. Type - checks to perform are updated using `TypeChecker.redefine` or - `TypeChecker.redefine_many` and removed via `TypeChecker.remove`. - Each of these return a new `TypeChecker` object. - - Arguments: - - type_checkers (dict): - - The initial mapping of types to their checking functions. - """ - - _type_checkers: typing.Mapping[ - str, typing.Callable[["TypeChecker", typing.Any], bool], - ] = attr.ib( - default=pmap(), - converter=_typed_pmap_converter, - ) - - def is_type(self, instance, type): - """ - Check if the instance is of the appropriate type. - - Arguments: - - instance (object): - - The instance to check - - type (str): - - The name of the type that is expected. - - Returns: - - bool: Whether it conformed. - - - Raises: - - `jsonschema.exceptions.UndefinedTypeCheck`: - if type is unknown to this object. - """ - try: - fn = self._type_checkers[type] - except KeyError: - raise UndefinedTypeCheck(type) from None - - return fn(self, instance) - - def redefine(self, type, fn): - """ - Produce a new checker with the given type redefined. - - Arguments: - - type (str): - - The name of the type to check. - - fn (collections.abc.Callable): - - A function taking exactly two parameters - the type - checker calling the function and the instance to check. - The function should return true if instance is of this - type and false otherwise. - - Returns: - - A new `TypeChecker` instance. - """ - return self.redefine_many({type: fn}) - - def redefine_many(self, definitions=()): - """ - Produce a new checker with the given types redefined. - - Arguments: - - definitions (dict): - - A dictionary mapping types to their checking functions. - - Returns: - - A new `TypeChecker` instance. - """ - return attr.evolve( - self, type_checkers=self._type_checkers.update(definitions), - ) - - def remove(self, *types): - """ - Produce a new checker with the given types forgotten. - - Arguments: - - types (~collections.abc.Iterable): - - the names of the types to remove. - - Returns: - - A new `TypeChecker` instance - - Raises: - - `jsonschema.exceptions.UndefinedTypeCheck`: - - if any given type is unknown to this object - """ - - checkers = self._type_checkers - for each in types: - try: - checkers = checkers.remove(each) - except KeyError: - raise UndefinedTypeCheck(each) - return attr.evolve(self, type_checkers=checkers) - - -draft3_type_checker = TypeChecker( - { - "any": is_any, - "array": is_array, - "boolean": is_bool, - "integer": is_integer, - "object": is_object, - "null": is_null, - "number": is_number, - "string": is_string, - }, -) -draft4_type_checker = draft3_type_checker.remove("any") -draft6_type_checker = draft4_type_checker.redefine( - "integer", - lambda checker, instance: ( - is_integer(checker, instance) - or isinstance(instance, float) and instance.is_integer() - ), -) -draft7_type_checker = draft6_type_checker -draft201909_type_checker = draft7_type_checker -draft202012_type_checker = draft201909_type_checker diff --git a/jsonschema/_utils.py b/jsonschema/_utils.py deleted file mode 100644 index a2ad5a9..0000000 --- a/jsonschema/_utils.py +++ /dev/null @@ -1,348 +0,0 @@ -from collections.abc import Mapping, MutableMapping, Sequence -from urllib.parse import urlsplit -import itertools -import json -import re -import sys - -# The files() API was added in Python 3.9. -if sys.version_info >= (3, 9): # pragma: no cover - from importlib import resources -else: # pragma: no cover - import importlib_resources as resources # type: ignore - - -class URIDict(MutableMapping): - """ - Dictionary which uses normalized URIs as keys. - """ - - def normalize(self, uri): - return urlsplit(uri).geturl() - - def __init__(self, *args, **kwargs): - self.store = dict() - self.store.update(*args, **kwargs) - - def __getitem__(self, uri): - return self.store[self.normalize(uri)] - - def __setitem__(self, uri, value): - self.store[self.normalize(uri)] = value - - def __delitem__(self, uri): - del self.store[self.normalize(uri)] - - def __iter__(self): - return iter(self.store) - - def __len__(self): - return len(self.store) - - def __repr__(self): - return repr(self.store) - - -class Unset(object): - """ - An as-of-yet unset attribute or unprovided default parameter. - """ - - def __repr__(self): - return "<unset>" - - -def load_schema(name): - """ - Load a schema from ./schemas/``name``.json and return it. - """ - - path = resources.files(__package__).joinpath(f"schemas/{name}.json") - data = path.read_text(encoding="utf-8") - return json.loads(data) - - -def format_as_index(container, indices): - """ - Construct a single string containing indexing operations for the indices. - - For example for a container ``bar``, [1, 2, "foo"] -> bar[1][2]["foo"] - - Arguments: - - container (str): - - A word to use for the thing being indexed - - indices (sequence): - - The indices to format. - """ - - if not indices: - return container - return f"{container}[{']['.join(repr(index) for index in indices)}]" - - -def find_additional_properties(instance, schema): - """ - Return the set of additional properties for the given ``instance``. - - Weeds out properties that should have been validated by ``properties`` and - / or ``patternProperties``. - - Assumes ``instance`` is dict-like already. - """ - - properties = schema.get("properties", {}) - patterns = "|".join(schema.get("patternProperties", {})) - for property in instance: - if property not in properties: - if patterns and re.search(patterns, property): - continue - yield property - - -def extras_msg(extras): - """ - Create an error message for extra items or properties. - """ - - if len(extras) == 1: - verb = "was" - else: - verb = "were" - return ", ".join(repr(extra) for extra in sorted(extras)), verb - - -def ensure_list(thing): - """ - Wrap ``thing`` in a list if it's a single str. - - Otherwise, return it unchanged. - """ - - if isinstance(thing, str): - return [thing] - return thing - - -def _mapping_equal(one, two): - """ - Check if two mappings are equal using the semantics of `equal`. - """ - if len(one) != len(two): - return False - return all( - key in two and equal(value, two[key]) - for key, value in one.items() - ) - - -def _sequence_equal(one, two): - """ - Check if two sequences are equal using the semantics of `equal`. - """ - if len(one) != len(two): - return False - return all(equal(i, j) for i, j in zip(one, two)) - - -def equal(one, two): - """ - Check if two things are equal evading some Python type hierarchy semantics. - - Specifically in JSON Schema, evade `bool` inheriting from `int`, - recursing into sequences to do the same. - """ - if isinstance(one, str) or isinstance(two, str): - return one == two - if isinstance(one, Sequence) and isinstance(two, Sequence): - return _sequence_equal(one, two) - if isinstance(one, Mapping) and isinstance(two, Mapping): - return _mapping_equal(one, two) - return unbool(one) == unbool(two) - - -def unbool(element, true=object(), false=object()): - """ - A hack to make True and 1 and False and 0 unique for ``uniq``. - """ - - if element is True: - return true - elif element is False: - return false - return element - - -def uniq(container): - """ - Check if all of a container's elements are unique. - - Tries to rely on the container being recursively sortable, or otherwise - falls back on (slow) brute force. - """ - try: - sort = sorted(unbool(i) for i in container) - sliced = itertools.islice(sort, 1, None) - - for i, j in zip(sort, sliced): - if equal(i, j): - return False - - except (NotImplementedError, TypeError): - seen = [] - for e in container: - e = unbool(e) - - for i in seen: - if equal(i, e): - return False - - seen.append(e) - return True - - -def find_evaluated_item_indexes_by_schema(validator, instance, schema): - """ - Get all indexes of items that get evaluated under the current schema - - Covers all keywords related to unevaluatedItems: items, prefixItems, if, - then, else, contains, unevaluatedItems, allOf, oneOf, anyOf - """ - if validator.is_type(schema, "boolean"): - return [] - evaluated_indexes = [] - - if "items" in schema: - return list(range(0, len(instance))) - - if "$ref" in schema: - scope, resolved = validator.resolver.resolve(schema["$ref"]) - validator.resolver.push_scope(scope) - - try: - evaluated_indexes += find_evaluated_item_indexes_by_schema( - validator, instance, resolved) - finally: - validator.resolver.pop_scope() - - if "prefixItems" in schema: - evaluated_indexes += list(range(0, len(schema["prefixItems"]))) - - if "if" in schema: - if validator.evolve(schema=schema["if"]).is_valid(instance): - evaluated_indexes += find_evaluated_item_indexes_by_schema( - validator, instance, schema["if"], - ) - if "then" in schema: - evaluated_indexes += find_evaluated_item_indexes_by_schema( - validator, instance, schema["then"], - ) - else: - if "else" in schema: - evaluated_indexes += find_evaluated_item_indexes_by_schema( - validator, instance, schema["else"], - ) - - for keyword in ["contains", "unevaluatedItems"]: - if keyword in schema: - for k, v in enumerate(instance): - if validator.evolve(schema=schema[keyword]).is_valid(v): - evaluated_indexes.append(k) - - for keyword in ["allOf", "oneOf", "anyOf"]: - if keyword in schema: - for subschema in schema[keyword]: - errs = list(validator.descend(instance, subschema)) - if not errs: - evaluated_indexes += find_evaluated_item_indexes_by_schema( - validator, instance, subschema, - ) - - return evaluated_indexes - - -def find_evaluated_property_keys_by_schema(validator, instance, schema): - """ - Get all keys of items that get evaluated under the current schema - - Covers all keywords related to unevaluatedProperties: properties, - additionalProperties, unevaluatedProperties, patternProperties, - dependentSchemas, allOf, oneOf, anyOf, if, then, else - """ - if validator.is_type(schema, "boolean"): - return [] - evaluated_keys = [] - - if "$ref" in schema: - scope, resolved = validator.resolver.resolve(schema["$ref"]) - validator.resolver.push_scope(scope) - - try: - evaluated_keys += find_evaluated_property_keys_by_schema( - validator, instance, resolved, - ) - finally: - validator.resolver.pop_scope() - - for keyword in [ - "properties", "additionalProperties", "unevaluatedProperties", - ]: - if keyword in schema: - if validator.is_type(schema[keyword], "boolean"): - for property, value in instance.items(): - if validator.evolve(schema=schema[keyword]).is_valid( - {property: value}, - ): - evaluated_keys.append(property) - - if validator.is_type(schema[keyword], "object"): - for property, subschema in schema[keyword].items(): - if property in instance and validator.evolve( - schema=subschema, - ).is_valid(instance[property]): - evaluated_keys.append(property) - - if "patternProperties" in schema: - for property, value in instance.items(): - for pattern, _ in schema["patternProperties"].items(): - if re.search(pattern, property) and validator.evolve( - schema=schema["patternProperties"], - ).is_valid({property: value}): - evaluated_keys.append(property) - - if "dependentSchemas" in schema: - for property, subschema in schema["dependentSchemas"].items(): - if property not in instance: - continue - evaluated_keys += find_evaluated_property_keys_by_schema( - validator, instance, subschema, - ) - - for keyword in ["allOf", "oneOf", "anyOf"]: - if keyword in schema: - for subschema in schema[keyword]: - errs = list(validator.descend(instance, subschema)) - if not errs: - evaluated_keys += find_evaluated_property_keys_by_schema( - validator, instance, subschema, - ) - - if "if" in schema: - if validator.evolve(schema=schema["if"]).is_valid(instance): - evaluated_keys += find_evaluated_property_keys_by_schema( - validator, instance, schema["if"], - ) - if "then" in schema: - evaluated_keys += find_evaluated_property_keys_by_schema( - validator, instance, schema["then"], - ) - else: - if "else" in schema: - evaluated_keys += find_evaluated_property_keys_by_schema( - validator, instance, schema["else"], - ) - - return evaluated_keys diff --git a/jsonschema/_validators.py b/jsonschema/_validators.py deleted file mode 100644 index 874e879..0000000 --- a/jsonschema/_validators.py +++ /dev/null @@ -1,467 +0,0 @@ -from fractions import Fraction -from urllib.parse import urldefrag, urljoin -import re - -from jsonschema._utils import ( - ensure_list, - equal, - extras_msg, - find_additional_properties, - find_evaluated_item_indexes_by_schema, - find_evaluated_property_keys_by_schema, - unbool, - uniq, -) -from jsonschema.exceptions import FormatError, ValidationError - - -def patternProperties(validator, patternProperties, instance, schema): - if not validator.is_type(instance, "object"): - return - - for pattern, subschema in patternProperties.items(): - for k, v in instance.items(): - if re.search(pattern, k): - yield from validator.descend( - v, subschema, path=k, schema_path=pattern, - ) - - -def propertyNames(validator, propertyNames, instance, schema): - if not validator.is_type(instance, "object"): - return - - for property in instance: - yield from validator.descend(instance=property, schema=propertyNames) - - -def additionalProperties(validator, aP, instance, schema): - if not validator.is_type(instance, "object"): - return - - extras = set(find_additional_properties(instance, schema)) - - if validator.is_type(aP, "object"): - for extra in extras: - yield from validator.descend(instance[extra], aP, path=extra) - elif not aP and extras: - if "patternProperties" in schema: - if len(extras) == 1: - verb = "does" - else: - verb = "do" - - joined = ", ".join(repr(each) for each in sorted(extras)) - patterns = ", ".join( - repr(each) for each in sorted(schema["patternProperties"]) - ) - error = f"{joined} {verb} not match any of the regexes: {patterns}" - yield ValidationError(error) - else: - error = "Additional properties are not allowed (%s %s unexpected)" - yield ValidationError(error % extras_msg(extras)) - - -def items(validator, items, instance, schema): - if not validator.is_type(instance, "array"): - return - - prefix = len(schema.get("prefixItems", [])) - total = len(instance) - if items is False and total > prefix: - message = f"Expected at most {prefix} items, but found {total}" - yield ValidationError(message) - else: - for index in range(prefix, total): - yield from validator.descend( - instance=instance[index], - schema=items, - path=index, - ) - - -def additionalItems(validator, aI, instance, schema): - if ( - not validator.is_type(instance, "array") - or validator.is_type(schema.get("items", {}), "object") - ): - return - - len_items = len(schema.get("items", [])) - if validator.is_type(aI, "object"): - for index, item in enumerate(instance[len_items:], start=len_items): - yield from validator.descend(item, aI, path=index) - elif not aI and len(instance) > len(schema.get("items", [])): - error = "Additional items are not allowed (%s %s unexpected)" - yield ValidationError( - error % extras_msg(instance[len(schema.get("items", [])):]), - ) - - -def const(validator, const, instance, schema): - if not equal(instance, const): - yield ValidationError(f"{const!r} was expected") - - -def contains(validator, contains, instance, schema): - if not validator.is_type(instance, "array"): - return - - matches = 0 - min_contains = schema.get("minContains", 1) - max_contains = schema.get("maxContains", len(instance)) - - for each in instance: - if validator.evolve(schema=contains).is_valid(each): - matches += 1 - if matches > max_contains: - yield ValidationError( - "Too many items match the given schema " - f"(expected at most {max_contains})", - validator="maxContains", - validator_value=max_contains, - ) - return - - if matches < min_contains: - if not matches: - yield ValidationError( - f"{instance!r} does not contain items " - "matching the given schema", - ) - else: - yield ValidationError( - "Too few items match the given schema (expected at least " - f"{min_contains} but only {matches} matched)", - validator="minContains", - validator_value=min_contains, - ) - - -def exclusiveMinimum(validator, minimum, instance, schema): - if not validator.is_type(instance, "number"): - return - - if instance <= minimum: - yield ValidationError( - f"{instance!r} is less than or equal to " - f"the minimum of {minimum!r}", - ) - - -def exclusiveMaximum(validator, maximum, instance, schema): - if not validator.is_type(instance, "number"): - return - - if instance >= maximum: - yield ValidationError( - f"{instance!r} is greater than or equal " - f"to the maximum of {maximum!r}", - ) - - -def minimum(validator, minimum, instance, schema): - if not validator.is_type(instance, "number"): - return - - if instance < minimum: - message = f"{instance!r} is less than the minimum of {minimum!r}" - yield ValidationError(message) - - -def maximum(validator, maximum, instance, schema): - if not validator.is_type(instance, "number"): - return - - if instance > maximum: - message = f"{instance!r} is greater than the maximum of {maximum!r}" - yield ValidationError(message) - - -def multipleOf(validator, dB, instance, schema): - if not validator.is_type(instance, "number"): - return - - if isinstance(dB, float): - quotient = instance / dB - try: - failed = int(quotient) != quotient - except OverflowError: - # When `instance` is large and `dB` is less than one, - # quotient can overflow to infinity; and then casting to int - # raises an error. - # - # In this case we fall back to Fraction logic, which is - # exact and cannot overflow. The performance is also - # acceptable: we try the fast all-float option first, and - # we know that fraction(dB) can have at most a few hundred - # digits in each part. The worst-case slowdown is therefore - # for already-slow enormous integers or Decimals. - failed = (Fraction(instance) / Fraction(dB)).denominator != 1 - else: - failed = instance % dB - - if failed: - yield ValidationError(f"{instance!r} is not a multiple of {dB}") - - -def minItems(validator, mI, instance, schema): - if validator.is_type(instance, "array") and len(instance) < mI: - yield ValidationError(f"{instance!r} is too short") - - -def maxItems(validator, mI, instance, schema): - if validator.is_type(instance, "array") and len(instance) > mI: - yield ValidationError(f"{instance!r} is too long") - - -def uniqueItems(validator, uI, instance, schema): - if ( - uI - and validator.is_type(instance, "array") - and not uniq(instance) - ): - yield ValidationError(f"{instance!r} has non-unique elements") - - -def pattern(validator, patrn, instance, schema): - if ( - validator.is_type(instance, "string") - and not re.search(patrn, instance) - ): - yield ValidationError(f"{instance!r} does not match {patrn!r}") - - -def format(validator, format, instance, schema): - if validator.format_checker is not None: - try: - validator.format_checker.check(instance, format) - except FormatError as error: - yield ValidationError(error.message, cause=error.cause) - - -def minLength(validator, mL, instance, schema): - if validator.is_type(instance, "string") and len(instance) < mL: - yield ValidationError(f"{instance!r} is too short") - - -def maxLength(validator, mL, instance, schema): - if validator.is_type(instance, "string") and len(instance) > mL: - yield ValidationError(f"{instance!r} is too long") - - -def dependentRequired(validator, dependentRequired, instance, schema): - if not validator.is_type(instance, "object"): - return - - for property, dependency in dependentRequired.items(): - if property not in instance: - continue - - for each in dependency: - if each not in instance: - message = f"{each!r} is a dependency of {property!r}" - yield ValidationError(message) - - -def dependentSchemas(validator, dependentSchemas, instance, schema): - if not validator.is_type(instance, "object"): - return - - for property, dependency in dependentSchemas.items(): - if property not in instance: - continue - yield from validator.descend( - instance, dependency, schema_path=property, - ) - - -def enum(validator, enums, instance, schema): - if instance == 0 or instance == 1: - unbooled = unbool(instance) - if all(unbooled != unbool(each) for each in enums): - yield ValidationError(f"{instance!r} is not one of {enums!r}") - elif instance not in enums: - yield ValidationError(f"{instance!r} is not one of {enums!r}") - - -def ref(validator, ref, instance, schema): - resolve = getattr(validator.resolver, "resolve", None) - if resolve is None: - with validator.resolver.resolving(ref) as resolved: - yield from validator.descend(instance, resolved) - else: - scope, resolved = validator.resolver.resolve(ref) - validator.resolver.push_scope(scope) - - try: - yield from validator.descend(instance, resolved) - finally: - validator.resolver.pop_scope() - - -def dynamicRef(validator, dynamicRef, instance, schema): - _, fragment = urldefrag(dynamicRef) - - for url in validator.resolver._scopes_stack: - lookup_url = urljoin(url, dynamicRef) - with validator.resolver.resolving(lookup_url) as subschema: - if ("$dynamicAnchor" in subschema - and fragment == subschema["$dynamicAnchor"]): - yield from validator.descend(instance, subschema) - break - else: - with validator.resolver.resolving(dynamicRef) as subschema: - yield from validator.descend(instance, subschema) - - -def type(validator, types, instance, schema): - types = ensure_list(types) - - if not any(validator.is_type(instance, type) for type in types): - reprs = ", ".join(repr(type) for type in types) - yield ValidationError(f"{instance!r} is not of type {reprs}") - - -def properties(validator, properties, instance, schema): - if not validator.is_type(instance, "object"): - return - - for property, subschema in properties.items(): - if property in instance: - yield from validator.descend( - instance[property], - subschema, - path=property, - schema_path=property, - ) - - -def required(validator, required, instance, schema): - if not validator.is_type(instance, "object"): - return - for property in required: - if property not in instance: - yield ValidationError(f"{property!r} is a required property") - - -def minProperties(validator, mP, instance, schema): - if validator.is_type(instance, "object") and len(instance) < mP: - yield ValidationError(f"{instance!r} does not have enough properties") - - -def maxProperties(validator, mP, instance, schema): - if not validator.is_type(instance, "object"): - return - if validator.is_type(instance, "object") and len(instance) > mP: - yield ValidationError(f"{instance!r} has too many properties") - - -def allOf(validator, allOf, instance, schema): - for index, subschema in enumerate(allOf): - yield from validator.descend(instance, subschema, schema_path=index) - - -def anyOf(validator, anyOf, instance, schema): - all_errors = [] - for index, subschema in enumerate(anyOf): - errs = list(validator.descend(instance, subschema, schema_path=index)) - if not errs: - break - all_errors.extend(errs) - else: - yield ValidationError( - f"{instance!r} is not valid under any of the given schemas", - context=all_errors, - ) - - -def oneOf(validator, oneOf, instance, schema): - subschemas = enumerate(oneOf) - all_errors = [] - for index, subschema in subschemas: - errs = list(validator.descend(instance, subschema, schema_path=index)) - if not errs: - first_valid = subschema - break - all_errors.extend(errs) - else: - yield ValidationError( - f"{instance!r} is not valid under any of the given schemas", - context=all_errors, - ) - - more_valid = [ - each for _, each in subschemas - if validator.evolve(schema=each).is_valid(instance) - ] - if more_valid: - more_valid.append(first_valid) - reprs = ", ".join(repr(schema) for schema in more_valid) - yield ValidationError(f"{instance!r} is valid under each of {reprs}") - - -def not_(validator, not_schema, instance, schema): - if validator.evolve(schema=not_schema).is_valid(instance): - message = f"{instance!r} should not be valid under {not_schema!r}" - yield ValidationError(message) - - -def if_(validator, if_schema, instance, schema): - if validator.evolve(schema=if_schema).is_valid(instance): - if "then" in schema: - then = schema["then"] - yield from validator.descend(instance, then, schema_path="then") - elif "else" in schema: - else_ = schema["else"] - yield from validator.descend(instance, else_, schema_path="else") - - -def unevaluatedItems(validator, unevaluatedItems, instance, schema): - if not validator.is_type(instance, "array"): - return - evaluated_item_indexes = find_evaluated_item_indexes_by_schema( - validator, instance, schema, - ) - unevaluated_items = [ - item for index, item in enumerate(instance) - if index not in evaluated_item_indexes - ] - if unevaluated_items: - error = "Unevaluated items are not allowed (%s %s unexpected)" - yield ValidationError(error % extras_msg(unevaluated_items)) - - -def unevaluatedProperties(validator, unevaluatedProperties, instance, schema): - if not validator.is_type(instance, "object"): - return - evaluated_property_keys = find_evaluated_property_keys_by_schema( - validator, instance, schema, - ) - unevaluated_property_keys = [] - for property in instance: - if property not in evaluated_property_keys: - for _ in validator.descend( - instance[property], - unevaluatedProperties, - path=property, - schema_path=property, - ): - unevaluated_property_keys.append(property) - - if unevaluated_property_keys: - error = "Unevaluated properties are not allowed (%s %s unexpected)" - yield ValidationError(error % extras_msg(unevaluated_property_keys)) - - -def prefixItems(validator, prefixItems, instance, schema): - if not validator.is_type(instance, "array"): - return - - for (index, item), subschema in zip(enumerate(instance), prefixItems): - yield from validator.descend( - instance=item, - schema=subschema, - schema_path=index, - path=index, - ) diff --git a/jsonschema/benchmarks/__init__.py b/jsonschema/benchmarks/__init__.py deleted file mode 100644 index e3dcc68..0000000 --- a/jsonschema/benchmarks/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -""" -Benchmarks for validation. - -This package is *not* public API. -""" diff --git a/jsonschema/benchmarks/issue232.py b/jsonschema/benchmarks/issue232.py deleted file mode 100644 index bf357e9..0000000 --- a/jsonschema/benchmarks/issue232.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -A performance benchmark using the example from issue #232. - -See https://github.com/python-jsonschema/jsonschema/pull/232. -""" -from pathlib import Path - -from pyperf import Runner -from pyrsistent import m - -from jsonschema.tests._suite import Version -import jsonschema - -issue232 = Version( - path=Path(__file__).parent / "issue232", - remotes=m(), - name="issue232", -) - - -if __name__ == "__main__": - issue232.benchmark( - runner=Runner(), - Validator=jsonschema.Draft4Validator, - ) diff --git a/jsonschema/benchmarks/issue232/issue.json b/jsonschema/benchmarks/issue232/issue.json deleted file mode 100644 index 804c340..0000000 --- a/jsonschema/benchmarks/issue232/issue.json +++ /dev/null @@ -1,2653 +0,0 @@ -[ - { - "description": "Petstore", - "schema": { - "title": "A JSON Schema for Swagger 2.0 API.", - "id": "http://swagger.io/v2/schema.json#", - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "required": [ - "swagger", - "info", - "paths" - ], - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "swagger": { - "type": "string", - "enum": [ - "2.0" - ], - "description": "The Swagger version of this document." - }, - "info": { - "$ref": "#/definitions/info" - }, - "host": { - "type": "string", - "pattern": "^[^{}/ :\\\\]+(?::\\d+)?$", - "description": "The host (name or ip) of the API. Example: 'swagger.io'" - }, - "basePath": { - "type": "string", - "pattern": "^/", - "description": "The base path to the API. Example: '/api'." - }, - "schemes": { - "$ref": "#/definitions/schemesList" - }, - "consumes": { - "description": "A list of MIME types accepted by the API.", - "allOf": [ - { - "$ref": "#/definitions/mediaTypeList" - } - ] - }, - "produces": { - "description": "A list of MIME types the API can produce.", - "allOf": [ - { - "$ref": "#/definitions/mediaTypeList" - } - ] - }, - "paths": { - "$ref": "#/definitions/paths" - }, - "definitions": { - "$ref": "#/definitions/definitions" - }, - "parameters": { - "$ref": "#/definitions/parameterDefinitions" - }, - "responses": { - "$ref": "#/definitions/responseDefinitions" - }, - "security": { - "$ref": "#/definitions/security" - }, - "securityDefinitions": { - "$ref": "#/definitions/securityDefinitions" - }, - "tags": { - "type": "array", - "items": { - "$ref": "#/definitions/tag" - }, - "uniqueItems": true - }, - "externalDocs": { - "$ref": "#/definitions/externalDocs" - } - }, - "definitions": { - "info": { - "type": "object", - "description": "General information about the API.", - "required": [ - "version", - "title" - ], - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "title": { - "type": "string", - "description": "A unique and precise title of the API." - }, - "version": { - "type": "string", - "description": "A semantic version number of the API." - }, - "description": { - "type": "string", - "description": "A longer description of the API. Should be different from the title. GitHub Flavored Markdown is allowed." - }, - "termsOfService": { - "type": "string", - "description": "The terms of service for the API." - }, - "contact": { - "$ref": "#/definitions/contact" - }, - "license": { - "$ref": "#/definitions/license" - } - } - }, - "contact": { - "type": "object", - "description": "Contact information for the owners of the API.", - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "The identifying name of the contact person/organization." - }, - "url": { - "type": "string", - "description": "The URL pointing to the contact information.", - "format": "uri" - }, - "email": { - "type": "string", - "description": "The email address of the contact person/organization.", - "format": "email" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "license": { - "type": "object", - "required": [ - "name" - ], - "additionalProperties": false, - "properties": { - "name": { - "type": "string", - "description": "The name of the license type. It's encouraged to use an OSI compatible license." - }, - "url": { - "type": "string", - "description": "The URL pointing to the license.", - "format": "uri" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "paths": { - "type": "object", - "description": "Relative paths to the individual endpoints. They must be relative to the 'basePath'.", - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - }, - "^/": { - "$ref": "#/definitions/pathItem" - } - }, - "additionalProperties": false - }, - "definitions": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/schema" - }, - "description": "One or more JSON objects describing the schemas being consumed and produced by the API." - }, - "parameterDefinitions": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/parameter" - }, - "description": "One or more JSON representations for parameters" - }, - "responseDefinitions": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/response" - }, - "description": "One or more JSON representations for parameters" - }, - "externalDocs": { - "type": "object", - "additionalProperties": false, - "description": "information about external documentation", - "required": [ - "url" - ], - "properties": { - "description": { - "type": "string" - }, - "url": { - "type": "string", - "format": "uri" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "examples": { - "type": "object", - "additionalProperties": true - }, - "mimeType": { - "type": "string", - "description": "The MIME type of the HTTP message." - }, - "operation": { - "type": "object", - "required": [ - "responses" - ], - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "tags": { - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true - }, - "summary": { - "type": "string", - "description": "A brief summary of the operation." - }, - "description": { - "type": "string", - "description": "A longer description of the operation, GitHub Flavored Markdown is allowed." - }, - "externalDocs": { - "$ref": "#/definitions/externalDocs" - }, - "operationId": { - "type": "string", - "description": "A unique identifier of the operation." - }, - "produces": { - "description": "A list of MIME types the API can produce.", - "allOf": [ - { - "$ref": "#/definitions/mediaTypeList" - } - ] - }, - "consumes": { - "description": "A list of MIME types the API can consume.", - "allOf": [ - { - "$ref": "#/definitions/mediaTypeList" - } - ] - }, - "parameters": { - "$ref": "#/definitions/parametersList" - }, - "responses": { - "$ref": "#/definitions/responses" - }, - "schemes": { - "$ref": "#/definitions/schemesList" - }, - "deprecated": { - "type": "boolean", - "default": false - }, - "security": { - "$ref": "#/definitions/security" - } - } - }, - "pathItem": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "$ref": { - "type": "string" - }, - "get": { - "$ref": "#/definitions/operation" - }, - "put": { - "$ref": "#/definitions/operation" - }, - "post": { - "$ref": "#/definitions/operation" - }, - "delete": { - "$ref": "#/definitions/operation" - }, - "options": { - "$ref": "#/definitions/operation" - }, - "head": { - "$ref": "#/definitions/operation" - }, - "patch": { - "$ref": "#/definitions/operation" - }, - "parameters": { - "$ref": "#/definitions/parametersList" - } - } - }, - "responses": { - "type": "object", - "description": "Response objects names can either be any valid HTTP status code or 'default'.", - "minProperties": 1, - "additionalProperties": false, - "patternProperties": { - "^([0-9]{3})$|^(default)$": { - "$ref": "#/definitions/responseValue" - }, - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "not": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - } - }, - "responseValue": { - "oneOf": [ - { - "$ref": "#/definitions/response" - }, - { - "$ref": "#/definitions/jsonReference" - } - ] - }, - "response": { - "type": "object", - "required": [ - "description" - ], - "properties": { - "description": { - "type": "string" - }, - "schema": { - "oneOf": [ - { - "$ref": "#/definitions/schema" - }, - { - "$ref": "#/definitions/fileSchema" - } - ] - }, - "headers": { - "$ref": "#/definitions/headers" - }, - "examples": { - "$ref": "#/definitions/examples" - } - }, - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "headers": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/header" - } - }, - "header": { - "type": "object", - "additionalProperties": false, - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "string", - "number", - "integer", - "boolean", - "array" - ] - }, - "format": { - "type": "string" - }, - "items": { - "$ref": "#/definitions/primitivesItems" - }, - "collectionFormat": { - "$ref": "#/definitions/collectionFormat" - }, - "default": { - "$ref": "#/definitions/default" - }, - "maximum": { - "$ref": "#/definitions/maximum" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/exclusiveMaximum" - }, - "minimum": { - "$ref": "#/definitions/minimum" - }, - "exclusiveMinimum": { - "$ref": "#/definitions/exclusiveMinimum" - }, - "maxLength": { - "$ref": "#/definitions/maxLength" - }, - "minLength": { - "$ref": "#/definitions/minLength" - }, - "pattern": { - "$ref": "#/definitions/pattern" - }, - "maxItems": { - "$ref": "#/definitions/maxItems" - }, - "minItems": { - "$ref": "#/definitions/minItems" - }, - "uniqueItems": { - "$ref": "#/definitions/uniqueItems" - }, - "enum": { - "$ref": "#/definitions/enum" - }, - "multipleOf": { - "$ref": "#/definitions/multipleOf" - }, - "description": { - "type": "string" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "vendorExtension": { - "description": "Any property starting with x- is valid.", - "additionalProperties": true, - "additionalItems": true - }, - "bodyParameter": { - "type": "object", - "required": [ - "name", - "in", - "schema" - ], - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "description": { - "type": "string", - "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." - }, - "name": { - "type": "string", - "description": "The name of the parameter." - }, - "in": { - "type": "string", - "description": "Determines the location of the parameter.", - "enum": [ - "body" - ] - }, - "required": { - "type": "boolean", - "description": "Determines whether or not this parameter is required or optional.", - "default": false - }, - "schema": { - "$ref": "#/definitions/schema" - } - }, - "additionalProperties": false - }, - "headerParameterSubSchema": { - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "required": { - "type": "boolean", - "description": "Determines whether or not this parameter is required or optional.", - "default": false - }, - "in": { - "type": "string", - "description": "Determines the location of the parameter.", - "enum": [ - "header" - ] - }, - "description": { - "type": "string", - "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." - }, - "name": { - "type": "string", - "description": "The name of the parameter." - }, - "type": { - "type": "string", - "enum": [ - "string", - "number", - "boolean", - "integer", - "array" - ] - }, - "format": { - "type": "string" - }, - "items": { - "$ref": "#/definitions/primitivesItems" - }, - "collectionFormat": { - "$ref": "#/definitions/collectionFormat" - }, - "default": { - "$ref": "#/definitions/default" - }, - "maximum": { - "$ref": "#/definitions/maximum" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/exclusiveMaximum" - }, - "minimum": { - "$ref": "#/definitions/minimum" - }, - "exclusiveMinimum": { - "$ref": "#/definitions/exclusiveMinimum" - }, - "maxLength": { - "$ref": "#/definitions/maxLength" - }, - "minLength": { - "$ref": "#/definitions/minLength" - }, - "pattern": { - "$ref": "#/definitions/pattern" - }, - "maxItems": { - "$ref": "#/definitions/maxItems" - }, - "minItems": { - "$ref": "#/definitions/minItems" - }, - "uniqueItems": { - "$ref": "#/definitions/uniqueItems" - }, - "enum": { - "$ref": "#/definitions/enum" - }, - "multipleOf": { - "$ref": "#/definitions/multipleOf" - } - } - }, - "queryParameterSubSchema": { - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "required": { - "type": "boolean", - "description": "Determines whether or not this parameter is required or optional.", - "default": false - }, - "in": { - "type": "string", - "description": "Determines the location of the parameter.", - "enum": [ - "query" - ] - }, - "description": { - "type": "string", - "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." - }, - "name": { - "type": "string", - "description": "The name of the parameter." - }, - "allowEmptyValue": { - "type": "boolean", - "default": false, - "description": "allows sending a parameter by name only or with an empty value." - }, - "type": { - "type": "string", - "enum": [ - "string", - "number", - "boolean", - "integer", - "array" - ] - }, - "format": { - "type": "string" - }, - "items": { - "$ref": "#/definitions/primitivesItems" - }, - "collectionFormat": { - "$ref": "#/definitions/collectionFormatWithMulti" - }, - "default": { - "$ref": "#/definitions/default" - }, - "maximum": { - "$ref": "#/definitions/maximum" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/exclusiveMaximum" - }, - "minimum": { - "$ref": "#/definitions/minimum" - }, - "exclusiveMinimum": { - "$ref": "#/definitions/exclusiveMinimum" - }, - "maxLength": { - "$ref": "#/definitions/maxLength" - }, - "minLength": { - "$ref": "#/definitions/minLength" - }, - "pattern": { - "$ref": "#/definitions/pattern" - }, - "maxItems": { - "$ref": "#/definitions/maxItems" - }, - "minItems": { - "$ref": "#/definitions/minItems" - }, - "uniqueItems": { - "$ref": "#/definitions/uniqueItems" - }, - "enum": { - "$ref": "#/definitions/enum" - }, - "multipleOf": { - "$ref": "#/definitions/multipleOf" - } - } - }, - "formDataParameterSubSchema": { - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "required": { - "type": "boolean", - "description": "Determines whether or not this parameter is required or optional.", - "default": false - }, - "in": { - "type": "string", - "description": "Determines the location of the parameter.", - "enum": [ - "formData" - ] - }, - "description": { - "type": "string", - "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." - }, - "name": { - "type": "string", - "description": "The name of the parameter." - }, - "allowEmptyValue": { - "type": "boolean", - "default": false, - "description": "allows sending a parameter by name only or with an empty value." - }, - "type": { - "type": "string", - "enum": [ - "string", - "number", - "boolean", - "integer", - "array", - "file" - ] - }, - "format": { - "type": "string" - }, - "items": { - "$ref": "#/definitions/primitivesItems" - }, - "collectionFormat": { - "$ref": "#/definitions/collectionFormatWithMulti" - }, - "default": { - "$ref": "#/definitions/default" - }, - "maximum": { - "$ref": "#/definitions/maximum" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/exclusiveMaximum" - }, - "minimum": { - "$ref": "#/definitions/minimum" - }, - "exclusiveMinimum": { - "$ref": "#/definitions/exclusiveMinimum" - }, - "maxLength": { - "$ref": "#/definitions/maxLength" - }, - "minLength": { - "$ref": "#/definitions/minLength" - }, - "pattern": { - "$ref": "#/definitions/pattern" - }, - "maxItems": { - "$ref": "#/definitions/maxItems" - }, - "minItems": { - "$ref": "#/definitions/minItems" - }, - "uniqueItems": { - "$ref": "#/definitions/uniqueItems" - }, - "enum": { - "$ref": "#/definitions/enum" - }, - "multipleOf": { - "$ref": "#/definitions/multipleOf" - } - } - }, - "pathParameterSubSchema": { - "additionalProperties": false, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "required": [ - "required" - ], - "properties": { - "required": { - "type": "boolean", - "enum": [ - true - ], - "description": "Determines whether or not this parameter is required or optional." - }, - "in": { - "type": "string", - "description": "Determines the location of the parameter.", - "enum": [ - "path" - ] - }, - "description": { - "type": "string", - "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." - }, - "name": { - "type": "string", - "description": "The name of the parameter." - }, - "type": { - "type": "string", - "enum": [ - "string", - "number", - "boolean", - "integer", - "array" - ] - }, - "format": { - "type": "string" - }, - "items": { - "$ref": "#/definitions/primitivesItems" - }, - "collectionFormat": { - "$ref": "#/definitions/collectionFormat" - }, - "default": { - "$ref": "#/definitions/default" - }, - "maximum": { - "$ref": "#/definitions/maximum" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/exclusiveMaximum" - }, - "minimum": { - "$ref": "#/definitions/minimum" - }, - "exclusiveMinimum": { - "$ref": "#/definitions/exclusiveMinimum" - }, - "maxLength": { - "$ref": "#/definitions/maxLength" - }, - "minLength": { - "$ref": "#/definitions/minLength" - }, - "pattern": { - "$ref": "#/definitions/pattern" - }, - "maxItems": { - "$ref": "#/definitions/maxItems" - }, - "minItems": { - "$ref": "#/definitions/minItems" - }, - "uniqueItems": { - "$ref": "#/definitions/uniqueItems" - }, - "enum": { - "$ref": "#/definitions/enum" - }, - "multipleOf": { - "$ref": "#/definitions/multipleOf" - } - } - }, - "nonBodyParameter": { - "type": "object", - "required": [ - "name", - "in", - "type" - ], - "oneOf": [ - { - "$ref": "#/definitions/headerParameterSubSchema" - }, - { - "$ref": "#/definitions/formDataParameterSubSchema" - }, - { - "$ref": "#/definitions/queryParameterSubSchema" - }, - { - "$ref": "#/definitions/pathParameterSubSchema" - } - ] - }, - "parameter": { - "oneOf": [ - { - "$ref": "#/definitions/bodyParameter" - }, - { - "$ref": "#/definitions/nonBodyParameter" - } - ] - }, - "schema": { - "type": "object", - "description": "A deterministic version of a JSON Schema object.", - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "properties": { - "$ref": { - "type": "string" - }, - "format": { - "type": "string" - }, - "title": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/title" - }, - "description": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/description" - }, - "default": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/default" - }, - "multipleOf": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf" - }, - "maximum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/maximum" - }, - "exclusiveMaximum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum" - }, - "minimum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/minimum" - }, - "exclusiveMinimum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum" - }, - "maxLength": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" - }, - "minLength": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" - }, - "pattern": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/pattern" - }, - "maxItems": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" - }, - "minItems": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" - }, - "uniqueItems": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems" - }, - "maxProperties": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" - }, - "minProperties": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" - }, - "required": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray" - }, - "enum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/enum" - }, - "additionalProperties": { - "anyOf": [ - { - "$ref": "#/definitions/schema" - }, - { - "type": "boolean" - } - ], - "default": {} - }, - "type": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/type" - }, - "items": { - "anyOf": [ - { - "$ref": "#/definitions/schema" - }, - { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/definitions/schema" - } - } - ], - "default": {} - }, - "allOf": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/definitions/schema" - } - }, - "properties": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/schema" - }, - "default": {} - }, - "discriminator": { - "type": "string" - }, - "readOnly": { - "type": "boolean", - "default": false - }, - "xml": { - "$ref": "#/definitions/xml" - }, - "externalDocs": { - "$ref": "#/definitions/externalDocs" - }, - "example": {} - }, - "additionalProperties": false - }, - "fileSchema": { - "type": "object", - "description": "A deterministic version of a JSON Schema object.", - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - }, - "required": [ - "type" - ], - "properties": { - "format": { - "type": "string" - }, - "title": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/title" - }, - "description": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/description" - }, - "default": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/default" - }, - "required": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray" - }, - "type": { - "type": "string", - "enum": [ - "file" - ] - }, - "readOnly": { - "type": "boolean", - "default": false - }, - "externalDocs": { - "$ref": "#/definitions/externalDocs" - }, - "example": {} - }, - "additionalProperties": false - }, - "primitivesItems": { - "type": "object", - "additionalProperties": false, - "properties": { - "type": { - "type": "string", - "enum": [ - "string", - "number", - "integer", - "boolean", - "array" - ] - }, - "format": { - "type": "string" - }, - "items": { - "$ref": "#/definitions/primitivesItems" - }, - "collectionFormat": { - "$ref": "#/definitions/collectionFormat" - }, - "default": { - "$ref": "#/definitions/default" - }, - "maximum": { - "$ref": "#/definitions/maximum" - }, - "exclusiveMaximum": { - "$ref": "#/definitions/exclusiveMaximum" - }, - "minimum": { - "$ref": "#/definitions/minimum" - }, - "exclusiveMinimum": { - "$ref": "#/definitions/exclusiveMinimum" - }, - "maxLength": { - "$ref": "#/definitions/maxLength" - }, - "minLength": { - "$ref": "#/definitions/minLength" - }, - "pattern": { - "$ref": "#/definitions/pattern" - }, - "maxItems": { - "$ref": "#/definitions/maxItems" - }, - "minItems": { - "$ref": "#/definitions/minItems" - }, - "uniqueItems": { - "$ref": "#/definitions/uniqueItems" - }, - "enum": { - "$ref": "#/definitions/enum" - }, - "multipleOf": { - "$ref": "#/definitions/multipleOf" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "security": { - "type": "array", - "items": { - "$ref": "#/definitions/securityRequirement" - }, - "uniqueItems": true - }, - "securityRequirement": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true - } - }, - "xml": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "namespace": { - "type": "string" - }, - "prefix": { - "type": "string" - }, - "attribute": { - "type": "boolean", - "default": false - }, - "wrapped": { - "type": "boolean", - "default": false - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "tag": { - "type": "object", - "additionalProperties": false, - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "externalDocs": { - "$ref": "#/definitions/externalDocs" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "securityDefinitions": { - "type": "object", - "additionalProperties": { - "oneOf": [ - { - "$ref": "#/definitions/basicAuthenticationSecurity" - }, - { - "$ref": "#/definitions/apiKeySecurity" - }, - { - "$ref": "#/definitions/oauth2ImplicitSecurity" - }, - { - "$ref": "#/definitions/oauth2PasswordSecurity" - }, - { - "$ref": "#/definitions/oauth2ApplicationSecurity" - }, - { - "$ref": "#/definitions/oauth2AccessCodeSecurity" - } - ] - } - }, - "basicAuthenticationSecurity": { - "type": "object", - "additionalProperties": false, - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "basic" - ] - }, - "description": { - "type": "string" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "apiKeySecurity": { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "name", - "in" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "apiKey" - ] - }, - "name": { - "type": "string" - }, - "in": { - "type": "string", - "enum": [ - "header", - "query" - ] - }, - "description": { - "type": "string" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "oauth2ImplicitSecurity": { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "flow", - "authorizationUrl" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "oauth2" - ] - }, - "flow": { - "type": "string", - "enum": [ - "implicit" - ] - }, - "scopes": { - "$ref": "#/definitions/oauth2Scopes" - }, - "authorizationUrl": { - "type": "string", - "format": "uri" - }, - "description": { - "type": "string" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "oauth2PasswordSecurity": { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "flow", - "tokenUrl" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "oauth2" - ] - }, - "flow": { - "type": "string", - "enum": [ - "password" - ] - }, - "scopes": { - "$ref": "#/definitions/oauth2Scopes" - }, - "tokenUrl": { - "type": "string", - "format": "uri" - }, - "description": { - "type": "string" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "oauth2ApplicationSecurity": { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "flow", - "tokenUrl" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "oauth2" - ] - }, - "flow": { - "type": "string", - "enum": [ - "application" - ] - }, - "scopes": { - "$ref": "#/definitions/oauth2Scopes" - }, - "tokenUrl": { - "type": "string", - "format": "uri" - }, - "description": { - "type": "string" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "oauth2AccessCodeSecurity": { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "flow", - "authorizationUrl", - "tokenUrl" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "oauth2" - ] - }, - "flow": { - "type": "string", - "enum": [ - "accessCode" - ] - }, - "scopes": { - "$ref": "#/definitions/oauth2Scopes" - }, - "authorizationUrl": { - "type": "string", - "format": "uri" - }, - "tokenUrl": { - "type": "string", - "format": "uri" - }, - "description": { - "type": "string" - } - }, - "patternProperties": { - "^x-": { - "$ref": "#/definitions/vendorExtension" - } - } - }, - "oauth2Scopes": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "mediaTypeList": { - "type": "array", - "items": { - "$ref": "#/definitions/mimeType" - }, - "uniqueItems": true - }, - "parametersList": { - "type": "array", - "description": "The parameters needed to send a valid API call.", - "additionalItems": false, - "items": { - "oneOf": [ - { - "$ref": "#/definitions/parameter" - }, - { - "$ref": "#/definitions/jsonReference" - } - ] - }, - "uniqueItems": true - }, - "schemesList": { - "type": "array", - "description": "The transfer protocol of the API.", - "items": { - "type": "string", - "enum": [ - "http", - "https", - "ws", - "wss" - ] - }, - "uniqueItems": true - }, - "collectionFormat": { - "type": "string", - "enum": [ - "csv", - "ssv", - "tsv", - "pipes" - ], - "default": "csv" - }, - "collectionFormatWithMulti": { - "type": "string", - "enum": [ - "csv", - "ssv", - "tsv", - "pipes", - "multi" - ], - "default": "csv" - }, - "title": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/title" - }, - "description": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/description" - }, - "default": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/default" - }, - "multipleOf": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf" - }, - "maximum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/maximum" - }, - "exclusiveMaximum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum" - }, - "minimum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/minimum" - }, - "exclusiveMinimum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum" - }, - "maxLength": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" - }, - "minLength": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" - }, - "pattern": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/pattern" - }, - "maxItems": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" - }, - "minItems": { - "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" - }, - "uniqueItems": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems" - }, - "enum": { - "$ref": "http://json-schema.org/draft-04/schema#/properties/enum" - }, - "jsonReference": { - "type": "object", - "required": [ - "$ref" - ], - "additionalProperties": false, - "properties": { - "$ref": { - "type": "string" - } - } - } - } - }, - "tests": [ - { - "description": "Example petsore", - "data": { - "swagger": "2.0", - "info": { - "description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.", - "version": "1.0.0", - "title": "Swagger Petstore", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "email": "apiteam@swagger.io" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - } - }, - "host": "petstore.swagger.io", - "basePath": "/v2", - "tags": [ - { - "name": "pet", - "description": "Everything about your Pets", - "externalDocs": { - "description": "Find out more", - "url": "http://swagger.io" - } - }, - { - "name": "store", - "description": "Access to Petstore orders" - }, - { - "name": "user", - "description": "Operations about user", - "externalDocs": { - "description": "Find out more about our store", - "url": "http://swagger.io" - } - } - ], - "schemes": [ - "http" - ], - "paths": { - "/pet": { - "post": { - "tags": [ - "pet" - ], - "summary": "Add a new pet to the store", - "description": "", - "operationId": "addPet", - "consumes": [ - "application/json", - "application/xml" - ], - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "in": "body", - "name": "body", - "description": "Pet object that needs to be added to the store", - "required": true, - "schema": { - "$ref": "#/definitions/Pet" - } - } - ], - "responses": { - "405": { - "description": "Invalid input" - } - }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ] - }, - "put": { - "tags": [ - "pet" - ], - "summary": "Update an existing pet", - "description": "", - "operationId": "updatePet", - "consumes": [ - "application/json", - "application/xml" - ], - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "in": "body", - "name": "body", - "description": "Pet object that needs to be added to the store", - "required": true, - "schema": { - "$ref": "#/definitions/Pet" - } - } - ], - "responses": { - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Pet not found" - }, - "405": { - "description": "Validation exception" - } - }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ] - } - }, - "/pet/findByStatus": { - "get": { - "tags": [ - "pet" - ], - "summary": "Finds Pets by status", - "description": "Multiple status values can be provided with comma separated strings", - "operationId": "findPetsByStatus", - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "name": "status", - "in": "query", - "description": "Status values that need to be considered for filter", - "required": true, - "type": "array", - "items": { - "type": "string", - "enum": [ - "available", - "pending", - "sold" - ], - "default": "available" - }, - "collectionFormat": "multi" - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/Pet" - } - } - }, - "400": { - "description": "Invalid status value" - } - }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ] - } - }, - "/pet/findByTags": { - "get": { - "tags": [ - "pet" - ], - "summary": "Finds Pets by tags", - "description": "Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", - "operationId": "findPetsByTags", - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "name": "tags", - "in": "query", - "description": "Tags to filter by", - "required": true, - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "multi" - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/Pet" - } - } - }, - "400": { - "description": "Invalid tag value" - } - }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ], - "deprecated": true - } - }, - "/pet/{petId}": { - "get": { - "tags": [ - "pet" - ], - "summary": "Find pet by ID", - "description": "Returns a single pet", - "operationId": "getPetById", - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "name": "petId", - "in": "path", - "description": "ID of pet to return", - "required": true, - "type": "integer", - "format": "int64" - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Pet" - } - }, - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Pet not found" - } - }, - "security": [ - { - "api_key": [] - } - ] - }, - "post": { - "tags": [ - "pet" - ], - "summary": "Updates a pet in the store with form data", - "description": "", - "operationId": "updatePetWithForm", - "consumes": [ - "application/x-www-form-urlencoded" - ], - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "name": "petId", - "in": "path", - "description": "ID of pet that needs to be updated", - "required": true, - "type": "integer", - "format": "int64" - }, - { - "name": "name", - "in": "formData", - "description": "Updated name of the pet", - "required": false, - "type": "string" - }, - { - "name": "status", - "in": "formData", - "description": "Updated status of the pet", - "required": false, - "type": "string" - } - ], - "responses": { - "405": { - "description": "Invalid input" - } - }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ] - }, - "delete": { - "tags": [ - "pet" - ], - "summary": "Deletes a pet", - "description": "", - "operationId": "deletePet", - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "name": "api_key", - "in": "header", - "required": false, - "type": "string" - }, - { - "name": "petId", - "in": "path", - "description": "Pet id to delete", - "required": true, - "type": "integer", - "format": "int64" - } - ], - "responses": { - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Pet not found" - } - }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ] - } - }, - "/pet/{petId}/uploadImage": { - "post": { - "tags": [ - "pet" - ], - "summary": "uploads an image", - "description": "", - "operationId": "uploadFile", - "consumes": [ - "multipart/form-data" - ], - "produces": [ - "application/json" - ], - "parameters": [ - { - "name": "petId", - "in": "path", - "description": "ID of pet to update", - "required": true, - "type": "integer", - "format": "int64" - }, - { - "name": "additionalMetadata", - "in": "formData", - "description": "Additional data to pass to server", - "required": false, - "type": "string" - }, - { - "name": "file", - "in": "formData", - "description": "file to upload", - "required": false, - "type": "file" - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/ApiResponse" - } - } - }, - "security": [ - { - "petstore_auth": [ - "write:pets", - "read:pets" - ] - } - ] - } - }, - "/store/inventory": { - "get": { - "tags": [ - "store" - ], - "summary": "Returns pet inventories by status", - "description": "Returns a map of status codes to quantities", - "operationId": "getInventory", - "produces": [ - "application/json" - ], - "parameters": [], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "object", - "additionalProperties": { - "type": "integer", - "format": "int32" - } - } - } - }, - "security": [ - { - "api_key": [] - } - ] - } - }, - "/store/order": { - "post": { - "tags": [ - "store" - ], - "summary": "Place an order for a pet", - "description": "", - "operationId": "placeOrder", - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "in": "body", - "name": "body", - "description": "order placed for purchasing the pet", - "required": true, - "schema": { - "$ref": "#/definitions/Order" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Order" - } - }, - "400": { - "description": "Invalid Order" - } - } - } - }, - "/store/order/{orderId}": { - "get": { - "tags": [ - "store" - ], - "summary": "Find purchase order by ID", - "description": "For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions", - "operationId": "getOrderById", - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "name": "orderId", - "in": "path", - "description": "ID of pet that needs to be fetched", - "required": true, - "type": "integer", - "maximum": 10.0, - "minimum": 1.0, - "format": "int64" - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Order" - } - }, - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Order not found" - } - } - }, - "delete": { - "tags": [ - "store" - ], - "summary": "Delete purchase order by ID", - "description": "For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors", - "operationId": "deleteOrder", - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "name": "orderId", - "in": "path", - "description": "ID of the order that needs to be deleted", - "required": true, - "type": "integer", - "minimum": 1.0, - "format": "int64" - } - ], - "responses": { - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Order not found" - } - } - } - }, - "/user": { - "post": { - "tags": [ - "user" - ], - "summary": "Create user", - "description": "This can only be done by the logged in user.", - "operationId": "createUser", - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "in": "body", - "name": "body", - "description": "Created user object", - "required": true, - "schema": { - "$ref": "#/definitions/User" - } - } - ], - "responses": { - "default": { - "description": "successful operation" - } - } - } - }, - "/user/createWithArray": { - "post": { - "tags": [ - "user" - ], - "summary": "Creates list of users with given input array", - "description": "", - "operationId": "createUsersWithArrayInput", - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "in": "body", - "name": "body", - "description": "List of user object", - "required": true, - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/User" - } - } - } - ], - "responses": { - "default": { - "description": "successful operation" - } - } - } - }, - "/user/createWithList": { - "post": { - "tags": [ - "user" - ], - "summary": "Creates list of users with given input array", - "description": "", - "operationId": "createUsersWithListInput", - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "in": "body", - "name": "body", - "description": "List of user object", - "required": true, - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/User" - } - } - } - ], - "responses": { - "default": { - "description": "successful operation" - } - } - } - }, - "/user/login": { - "get": { - "tags": [ - "user" - ], - "summary": "Logs user into the system", - "description": "", - "operationId": "loginUser", - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "name": "username", - "in": "query", - "description": "The user name for login", - "required": true, - "type": "string" - }, - { - "name": "password", - "in": "query", - "description": "The password for login in clear text", - "required": true, - "type": "string" - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "string" - }, - "headers": { - "X-Rate-Limit": { - "type": "integer", - "format": "int32", - "description": "calls per hour allowed by the user" - }, - "X-Expires-After": { - "type": "string", - "format": "date-time", - "description": "date in UTC when token expires" - } - } - }, - "400": { - "description": "Invalid username/password supplied" - } - } - } - }, - "/user/logout": { - "get": { - "tags": [ - "user" - ], - "summary": "Logs out current logged in user session", - "description": "", - "operationId": "logoutUser", - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [], - "responses": { - "default": { - "description": "successful operation" - } - } - } - }, - "/user/{username}": { - "get": { - "tags": [ - "user" - ], - "summary": "Get user by user name", - "description": "", - "operationId": "getUserByName", - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "name": "username", - "in": "path", - "description": "The name that needs to be fetched. Use user1 for testing. ", - "required": true, - "type": "string" - } - ], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/User" - } - }, - "400": { - "description": "Invalid username supplied" - }, - "404": { - "description": "User not found" - } - } - }, - "put": { - "tags": [ - "user" - ], - "summary": "Updated user", - "description": "This can only be done by the logged in user.", - "operationId": "updateUser", - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "name": "username", - "in": "path", - "description": "name that need to be updated", - "required": true, - "type": "string" - }, - { - "in": "body", - "name": "body", - "description": "Updated user object", - "required": true, - "schema": { - "$ref": "#/definitions/User" - } - } - ], - "responses": { - "400": { - "description": "Invalid user supplied" - }, - "404": { - "description": "User not found" - } - } - }, - "delete": { - "tags": [ - "user" - ], - "summary": "Delete user", - "description": "This can only be done by the logged in user.", - "operationId": "deleteUser", - "produces": [ - "application/xml", - "application/json" - ], - "parameters": [ - { - "name": "username", - "in": "path", - "description": "The name that needs to be deleted", - "required": true, - "type": "string" - } - ], - "responses": { - "400": { - "description": "Invalid username supplied" - }, - "404": { - "description": "User not found" - } - } - } - } - }, - "securityDefinitions": { - "petstore_auth": { - "type": "oauth2", - "authorizationUrl": "http://petstore.swagger.io/oauth/dialog", - "flow": "implicit", - "scopes": { - "write:pets": "modify pets in your account", - "read:pets": "read your pets" - } - }, - "api_key": { - "type": "apiKey", - "name": "api_key", - "in": "header" - } - }, - "definitions": { - "Order": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "petId": { - "type": "integer", - "format": "int64" - }, - "quantity": { - "type": "integer", - "format": "int32" - }, - "shipDate": { - "type": "string", - "format": "date-time" - }, - "status": { - "type": "string", - "description": "Order Status", - "enum": [ - "placed", - "approved", - "delivered" - ] - }, - "complete": { - "type": "boolean", - "default": false - } - }, - "xml": { - "name": "Order" - } - }, - "Category": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } - }, - "xml": { - "name": "Category" - } - }, - "User": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "username": { - "type": "string" - }, - "firstName": { - "type": "string" - }, - "lastName": { - "type": "string" - }, - "email": { - "type": "string" - }, - "password": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "userStatus": { - "type": "integer", - "format": "int32", - "description": "User Status" - } - }, - "xml": { - "name": "User" - } - }, - "Tag": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } - }, - "xml": { - "name": "Tag" - } - }, - "Pet": { - "type": "object", - "required": [ - "name", - "photoUrls" - ], - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "category": { - "$ref": "#/definitions/Category" - }, - "name": { - "type": "string", - "example": "doggie" - }, - "photoUrls": { - "type": "array", - "xml": { - "name": "photoUrl", - "wrapped": true - }, - "items": { - "type": "string" - } - }, - "tags": { - "type": "array", - "xml": { - "name": "tag", - "wrapped": true - }, - "items": { - "$ref": "#/definitions/Tag" - } - }, - "status": { - "type": "string", - "description": "pet status in the store", - "enum": [ - "available", - "pending", - "sold" - ] - } - }, - "xml": { - "name": "Pet" - } - }, - "ApiResponse": { - "type": "object", - "properties": { - "code": { - "type": "integer", - "format": "int32" - }, - "type": { - "type": "string" - }, - "message": { - "type": "string" - } - } - } - }, - "externalDocs": { - "description": "Find out more about Swagger", - "url": "http://swagger.io" - } - }, - "valid": true - } - ] - } -] diff --git a/jsonschema/benchmarks/json_schema_test_suite.py b/jsonschema/benchmarks/json_schema_test_suite.py deleted file mode 100644 index 905fb6a..0000000 --- a/jsonschema/benchmarks/json_schema_test_suite.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -A performance benchmark using the official test suite. - -This benchmarks jsonschema using every valid example in the -JSON-Schema-Test-Suite. It will take some time to complete. -""" -from pyperf import Runner - -from jsonschema.tests._suite import Suite - -if __name__ == "__main__": - Suite().benchmark(runner=Runner()) diff --git a/jsonschema/cli.py b/jsonschema/cli.py deleted file mode 100644 index f19b680..0000000 --- a/jsonschema/cli.py +++ /dev/null @@ -1,288 +0,0 @@ -""" -The ``jsonschema`` command line. -""" - -from json import JSONDecodeError -from textwrap import dedent -import argparse -import json -import sys -import traceback - -try: - from importlib import metadata -except ImportError: - import importlib_metadata as metadata # type: ignore - -try: - from pkgutil import resolve_name -except ImportError: - from pkgutil_resolve_name import resolve_name # type: ignore - -import attr - -from jsonschema.exceptions import SchemaError -from jsonschema.validators import RefResolver, validator_for - - -class _CannotLoadFile(Exception): - pass - - -@attr.s -class _Outputter(object): - - _formatter = attr.ib() - _stdout = attr.ib() - _stderr = attr.ib() - - @classmethod - def from_arguments(cls, arguments, stdout, stderr): - if arguments["output"] == "plain": - formatter = _PlainFormatter(arguments["error_format"]) - elif arguments["output"] == "pretty": - formatter = _PrettyFormatter() - return cls(formatter=formatter, stdout=stdout, stderr=stderr) - - def load(self, path): - try: - file = open(path) - except FileNotFoundError: - self.filenotfound_error(path=path, exc_info=sys.exc_info()) - raise _CannotLoadFile() - - with file: - try: - return json.load(file) - except JSONDecodeError: - self.parsing_error(path=path, exc_info=sys.exc_info()) - raise _CannotLoadFile() - - def filenotfound_error(self, **kwargs): - self._stderr.write(self._formatter.filenotfound_error(**kwargs)) - - def parsing_error(self, **kwargs): - self._stderr.write(self._formatter.parsing_error(**kwargs)) - - def validation_error(self, **kwargs): - self._stderr.write(self._formatter.validation_error(**kwargs)) - - def validation_success(self, **kwargs): - self._stdout.write(self._formatter.validation_success(**kwargs)) - - -@attr.s -class _PrettyFormatter(object): - - _ERROR_MSG = dedent( - """\ - ===[{type}]===({path})=== - - {body} - ----------------------------- - """, - ) - _SUCCESS_MSG = "===[SUCCESS]===({path})===\n" - - def filenotfound_error(self, path, exc_info): - return self._ERROR_MSG.format( - path=path, - type="FileNotFoundError", - body="{!r} does not exist.".format(path), - ) - - def parsing_error(self, path, exc_info): - exc_type, exc_value, exc_traceback = exc_info - exc_lines = "".join( - traceback.format_exception(exc_type, exc_value, exc_traceback), - ) - return self._ERROR_MSG.format( - path=path, - type=exc_type.__name__, - body=exc_lines, - ) - - def validation_error(self, instance_path, error): - return self._ERROR_MSG.format( - path=instance_path, - type=error.__class__.__name__, - body=error, - ) - - def validation_success(self, instance_path): - return self._SUCCESS_MSG.format(path=instance_path) - - -@attr.s -class _PlainFormatter(object): - - _error_format = attr.ib() - - def filenotfound_error(self, path, exc_info): - return "{!r} does not exist.\n".format(path) - - def parsing_error(self, path, exc_info): - return "Failed to parse {}: {}\n".format( - "<stdin>" if path == "<stdin>" else repr(path), - exc_info[1], - ) - - def validation_error(self, instance_path, error): - return self._error_format.format(file_name=instance_path, error=error) - - def validation_success(self, instance_path): - return "" - - -def _resolve_name_with_default(name): - if "." not in name: - name = "jsonschema." + name - return resolve_name(name) - - -parser = argparse.ArgumentParser( - description="JSON Schema Validation CLI", -) -parser.add_argument( - "-i", "--instance", - action="append", - dest="instances", - help=""" - a path to a JSON instance (i.e. filename.json) to validate (may - be specified multiple times). If no instances are provided via this - option, one will be expected on standard input. - """, -) -parser.add_argument( - "-F", "--error-format", - help=""" - the format to use for each validation error message, specified - in a form suitable for str.format. This string will be passed - one formatted object named 'error' for each ValidationError. - Only provide this option when using --output=plain, which is the - default. If this argument is unprovided and --output=plain is - used, a simple default representation will be used. - """, -) -parser.add_argument( - "-o", "--output", - choices=["plain", "pretty"], - default="plain", - help=""" - an output format to use. 'plain' (default) will produce minimal - text with one line for each error, while 'pretty' will produce - more detailed human-readable output on multiple lines. - """, -) -parser.add_argument( - "-V", "--validator", - type=_resolve_name_with_default, - help=""" - the fully qualified object name of a validator to use, or, for - validators that are registered with jsonschema, simply the name - of the class. - """, -) -parser.add_argument( - "--base-uri", - help=""" - a base URI to assign to the provided schema, even if it does not - declare one (via e.g. $id). This option can be used if you wish to - resolve relative references to a particular URI (or local path) - """, -) -parser.add_argument( - "--version", - action="version", - version=metadata.version("jsonschema"), -) -parser.add_argument( - "schema", - help="the path to a JSON Schema to validate with (i.e. schema.json)", -) - - -def parse_args(args): - arguments = vars(parser.parse_args(args=args or ["--help"])) - if arguments["output"] != "plain" and arguments["error_format"]: - raise parser.error( - "--error-format can only be used with --output plain", - ) - if arguments["output"] == "plain" and arguments["error_format"] is None: - arguments["error_format"] = "{error.instance}: {error.message}\n" - return arguments - - -def _validate_instance(instance_path, instance, validator, outputter): - invalid = False - for error in validator.iter_errors(instance): - invalid = True - outputter.validation_error(instance_path=instance_path, error=error) - - if not invalid: - outputter.validation_success(instance_path=instance_path) - return invalid - - -def main(args=sys.argv[1:]): - sys.exit(run(arguments=parse_args(args=args))) - - -def run(arguments, stdout=sys.stdout, stderr=sys.stderr, stdin=sys.stdin): - outputter = _Outputter.from_arguments( - arguments=arguments, - stdout=stdout, - stderr=stderr, - ) - - try: - schema = outputter.load(arguments["schema"]) - except _CannotLoadFile: - return 1 - - if arguments["validator"] is None: - arguments["validator"] = validator_for(schema) - - try: - arguments["validator"].check_schema(schema) - except SchemaError as error: - outputter.validation_error( - instance_path=arguments["schema"], - error=error, - ) - return 1 - - if arguments["instances"]: - load, instances = outputter.load, arguments["instances"] - else: - def load(_): - try: - return json.load(stdin) - except JSONDecodeError: - outputter.parsing_error( - path="<stdin>", exc_info=sys.exc_info(), - ) - raise _CannotLoadFile() - instances = ["<stdin>"] - - resolver = RefResolver( - base_uri=arguments["base_uri"], - referrer=schema, - ) if arguments["base_uri"] is not None else None - - validator = arguments["validator"](schema, resolver=resolver) - exit_code = 0 - for each in instances: - try: - instance = load(each) - except _CannotLoadFile: - exit_code = 1 - else: - exit_code |= _validate_instance( - instance_path=each, - instance=instance, - validator=validator, - outputter=outputter, - ) - - return exit_code diff --git a/jsonschema/exceptions.py b/jsonschema/exceptions.py deleted file mode 100644 index 43cb635..0000000 --- a/jsonschema/exceptions.py +++ /dev/null @@ -1,393 +0,0 @@ -""" -Validation errors, and some surrounding helpers. -""" -from __future__ import annotations - -from collections import defaultdict, deque -from pprint import pformat -from textwrap import dedent, indent -import heapq -import itertools - -import attr - -from jsonschema import _utils - -WEAK_MATCHES: frozenset[str] = frozenset(["anyOf", "oneOf"]) -STRONG_MATCHES: frozenset[str] = frozenset() - -_unset = _utils.Unset() - - -class _Error(Exception): - def __init__( - self, - message, - validator=_unset, - path=(), - cause=None, - context=(), - validator_value=_unset, - instance=_unset, - schema=_unset, - schema_path=(), - parent=None, - type_checker=_unset, - ): - super(_Error, self).__init__( - message, - validator, - path, - cause, - context, - validator_value, - instance, - schema, - schema_path, - parent, - ) - self.message = message - self.path = self.relative_path = deque(path) - self.schema_path = self.relative_schema_path = deque(schema_path) - self.context = list(context) - self.cause = self.__cause__ = cause - self.validator = validator - self.validator_value = validator_value - self.instance = instance - self.schema = schema - self.parent = parent - self._type_checker = type_checker - - for error in context: - error.parent = self - - def __repr__(self): - return f"<{self.__class__.__name__}: {self.message!r}>" - - def __str__(self): - essential_for_verbose = ( - self.validator, self.validator_value, self.instance, self.schema, - ) - if any(m is _unset for m in essential_for_verbose): - return self.message - - schema_path = _utils.format_as_index( - container=self._word_for_schema_in_error_message, - indices=list(self.relative_schema_path)[:-1], - ) - instance_path = _utils.format_as_index( - container=self._word_for_instance_in_error_message, - indices=self.relative_path, - ) - prefix = 16 * " " - - return dedent( - f"""\ - {self.message} - - Failed validating {self.validator!r} in {schema_path}: - {indent(pformat(self.schema, width=72), prefix).lstrip()} - - On {instance_path}: - {indent(pformat(self.instance, width=72), prefix).lstrip()} - """.rstrip(), - ) - - @classmethod - def create_from(cls, other): - return cls(**other._contents()) - - @property - def absolute_path(self): - parent = self.parent - if parent is None: - return self.relative_path - - path = deque(self.relative_path) - path.extendleft(reversed(parent.absolute_path)) - return path - - @property - def absolute_schema_path(self): - parent = self.parent - if parent is None: - return self.relative_schema_path - - path = deque(self.relative_schema_path) - path.extendleft(reversed(parent.absolute_schema_path)) - return path - - @property - def json_path(self): - path = "$" - for elem in self.absolute_path: - if isinstance(elem, int): - path += "[" + str(elem) + "]" - else: - path += "." + elem - return path - - def _set(self, type_checker=None, **kwargs): - if type_checker is not None and self._type_checker is _unset: - self._type_checker = type_checker - - for k, v in kwargs.items(): - if getattr(self, k) is _unset: - setattr(self, k, v) - - def _contents(self): - attrs = ( - "message", "cause", "context", "validator", "validator_value", - "path", "schema_path", "instance", "schema", "parent", - ) - return dict((attr, getattr(self, attr)) for attr in attrs) - - def _matches_type(self): - try: - expected = self.schema["type"] - except (KeyError, TypeError): - return False - - if isinstance(expected, str): - return self._type_checker.is_type(self.instance, expected) - - return any( - self._type_checker.is_type(self.instance, expected_type) - for expected_type in expected - ) - - -class ValidationError(_Error): - """ - An instance was invalid under a provided schema. - """ - - _word_for_schema_in_error_message = "schema" - _word_for_instance_in_error_message = "instance" - - -class SchemaError(_Error): - """ - A schema was invalid under its corresponding metaschema. - """ - - _word_for_schema_in_error_message = "metaschema" - _word_for_instance_in_error_message = "schema" - - -@attr.s(hash=True) -class RefResolutionError(Exception): - """ - A ref could not be resolved. - """ - - _cause = attr.ib() - - def __str__(self): - return str(self._cause) - - -class UndefinedTypeCheck(Exception): - """ - A type checker was asked to check a type it did not have registered. - """ - - def __init__(self, type): - self.type = type - - def __str__(self): - return f"Type {self.type!r} is unknown to this type checker" - - -class UnknownType(Exception): - """ - A validator was asked to validate an instance against an unknown type. - """ - - def __init__(self, type, instance, schema): - self.type = type - self.instance = instance - self.schema = schema - - def __str__(self): - prefix = 16 * " " - - return dedent( - f"""\ - Unknown type {self.type!r} for validator with schema: - {indent(pformat(self.schema, width=72), prefix).lstrip()} - - While checking instance: - {indent(pformat(self.instance, width=72), prefix).lstrip()} - """.rstrip(), - ) - - -class FormatError(Exception): - """ - Validating a format failed. - """ - - def __init__(self, message, cause=None): - super(FormatError, self).__init__(message, cause) - self.message = message - self.cause = self.__cause__ = cause - - def __str__(self): - return self.message - - -class ErrorTree(object): - """ - ErrorTrees make it easier to check which validations failed. - """ - - _instance = _unset - - def __init__(self, errors=()): - self.errors = {} - self._contents = defaultdict(self.__class__) - - for error in errors: - container = self - for element in error.path: - container = container[element] - container.errors[error.validator] = error - - container._instance = error.instance - - def __contains__(self, index): - """ - Check whether ``instance[index]`` has any errors. - """ - - return index in self._contents - - def __getitem__(self, index): - """ - Retrieve the child tree one level down at the given ``index``. - - If the index is not in the instance that this tree corresponds - to and is not known by this tree, whatever error would be raised - by ``instance.__getitem__`` will be propagated (usually this is - some subclass of `LookupError`. - """ - - if self._instance is not _unset and index not in self: - self._instance[index] - return self._contents[index] - - def __setitem__(self, index, value): - """ - Add an error to the tree at the given ``index``. - """ - self._contents[index] = value - - def __iter__(self): - """ - Iterate (non-recursively) over the indices in the instance with errors. - """ - - return iter(self._contents) - - def __len__(self): - """ - Return the `total_errors`. - """ - return self.total_errors - - def __repr__(self): - return f"<{self.__class__.__name__} ({len(self)} total errors)>" - - @property - def total_errors(self): - """ - The total number of errors in the entire tree, including children. - """ - - child_errors = sum(len(tree) for _, tree in self._contents.items()) - return len(self.errors) + child_errors - - -def by_relevance(weak=WEAK_MATCHES, strong=STRONG_MATCHES): - """ - Create a key function that can be used to sort errors by relevance. - - Arguments: - weak (set): - a collection of validator names to consider to be "weak". - If there are two errors at the same level of the instance - and one is in the set of weak validator names, the other - error will take priority. By default, :validator:`anyOf` and - :validator:`oneOf` are considered weak validators and will - be superseded by other same-level validation errors. - - strong (set): - a collection of validator names to consider to be "strong" - """ - def relevance(error): - validator = error.validator - return ( - -len(error.path), - validator not in weak, - validator in strong, - not error._matches_type(), - ) - return relevance - - -relevance = by_relevance() - - -def best_match(errors, key=relevance): - """ - Try to find an error that appears to be the best match among given errors. - - In general, errors that are higher up in the instance (i.e. for which - `ValidationError.path` is shorter) are considered better matches, - since they indicate "more" is wrong with the instance. - - If the resulting match is either :validator:`oneOf` or :validator:`anyOf`, - the *opposite* assumption is made -- i.e. the deepest error is picked, - since these validators only need to match once, and any other errors may - not be relevant. - - Arguments: - errors (collections.abc.Iterable): - - the errors to select from. Do not provide a mixture of - errors from different validation attempts (i.e. from - different instances or schemas), since it won't produce - sensical output. - - key (collections.abc.Callable): - - the key to use when sorting errors. See `relevance` and - transitively `by_relevance` for more details (the default is - to sort with the defaults of that function). Changing the - default is only useful if you want to change the function - that rates errors but still want the error context descent - done by this function. - - Returns: - the best matching error, or ``None`` if the iterable was empty - - .. note:: - - This function is a heuristic. Its return value may change for a given - set of inputs from version to version if better heuristics are added. - """ - errors = iter(errors) - best = next(errors, None) - if best is None: - return - best = max(itertools.chain([best], errors), key=key) - - while best.context: - # Calculate the minimum via nsmallest, because we don't recurse if - # all nested errors have the same relevance (i.e. if min == max == all) - smallest = heapq.nsmallest(2, best.context, key=key) - if len(smallest) == 2 and key(smallest[0]) == key(smallest[1]): - return best - best = smallest[0] - return best diff --git a/jsonschema/protocols.py b/jsonschema/protocols.py deleted file mode 100644 index 96e3885..0000000 --- a/jsonschema/protocols.py +++ /dev/null @@ -1,171 +0,0 @@ -""" -typing.Protocol classes for jsonschema interfaces. -""" - -# for reference material on Protocols, see -# https://www.python.org/dev/peps/pep-0544/ - -from __future__ import annotations - -from typing import TYPE_CHECKING, Any, ClassVar, Iterator -import sys - -# doing these imports with `try ... except ImportError` doesn't pass mypy -# checking because mypy sees `typing._SpecialForm` and -# `typing_extensions._SpecialForm` as incompatible -# -# see: -# https://mypy.readthedocs.io/en/stable/runtime_troubles.html#using-new-additions-to-the-typing-module -# https://github.com/python/mypy/issues/4427 -if sys.version_info >= (3, 8): - from typing import Protocol, runtime_checkable -else: - from typing_extensions import Protocol, runtime_checkable - -# in order for Sphinx to resolve references accurately from type annotations, -# it needs to see names like `jsonschema.TypeChecker` -# therefore, only import at type-checking time (to avoid circular references), -# but use `jsonschema` for any types which will otherwise not be resolvable -if TYPE_CHECKING: - import jsonschema - -from jsonschema.exceptions import ValidationError -from jsonschema.validators import RefResolver - -# For code authors working on the validator protocol, these are the three -# use-cases which should be kept in mind: -# -# 1. As a protocol class, it can be used in type annotations to describe the -# available methods and attributes of a validator -# 2. It is the source of autodoc for the validator documentation -# 3. It is runtime_checkable, meaning that it can be used in isinstance() -# checks. -# -# Since protocols are not base classes, isinstance() checking is limited in -# its capabilities. See docs on runtime_checkable for detail - - -@runtime_checkable -class Validator(Protocol): - """ - The protocol to which all validator classes should adhere. - - :argument schema: the schema that the validator object - will validate with. It is assumed to be valid, and providing - an invalid schema can lead to undefined behavior. See - `Validator.check_schema` to validate a schema first. - :argument resolver: an instance of `jsonschema.RefResolver` that will be - used to resolve :validator:`$ref` properties (JSON references). If - unprovided, one will be created. - :argument format_checker: an instance of `jsonschema.FormatChecker` - whose `jsonschema.FormatChecker.conforms` method will be called to - check and see if instances conform to each :validator:`format` - property present in the schema. If unprovided, no validation - will be done for :validator:`format`. Certain formats require - additional packages to be installed (ipv5, uri, color, date-time). - The required packages can be found at the bottom of this page. - """ - - #: An object representing the validator's meta schema (the schema that - #: describes valid schemas in the given version). - META_SCHEMA: ClassVar[dict] - - #: A mapping of validator names (`str`\s) to functions - #: that validate the validator property with that name. For more - #: information see `creating-validators`. - VALIDATORS: ClassVar[dict] - - #: A `jsonschema.TypeChecker` that will be used when validating - #: :validator:`type` properties in JSON schemas. - TYPE_CHECKER: ClassVar[jsonschema.TypeChecker] - - #: A `jsonschema.FormatChecker` that will be used when validating - #: :validator:`format` properties in JSON schemas. - FORMAT_CHECKER: ClassVar[jsonschema.FormatChecker] - - #: The schema that was passed in when initializing the object. - schema: dict | bool - - def __init__( - self, - schema: dict | bool, - resolver: RefResolver | None = None, - format_checker: jsonschema.FormatChecker | None = None, - ) -> None: - ... - - @classmethod - def check_schema(cls, schema: dict) -> None: - """ - Validate the given schema against the validator's `META_SCHEMA`. - - :raises: `jsonschema.exceptions.SchemaError` if the schema - is invalid - """ - - def is_type(self, instance: Any, type: str) -> bool: - """ - Check if the instance is of the given (JSON Schema) type. - - :type type: str - :rtype: bool - :raises: `jsonschema.exceptions.UnknownType` if ``type`` - is not a known type. - """ - - def is_valid(self, instance: dict) -> bool: - """ - Check if the instance is valid under the current `schema`. - - :rtype: bool - - >>> schema = {"maxItems" : 2} - >>> Draft3Validator(schema).is_valid([2, 3, 4]) - False - """ - - def iter_errors(self, instance: dict) -> Iterator[ValidationError]: - r""" - Lazily yield each of the validation errors in the given instance. - - :rtype: an `collections.abc.Iterable` of - `jsonschema.exceptions.ValidationError`\s - - >>> schema = { - ... "type" : "array", - ... "items" : {"enum" : [1, 2, 3]}, - ... "maxItems" : 2, - ... } - >>> v = Draft3Validator(schema) - >>> for error in sorted(v.iter_errors([2, 3, 4]), key=str): - ... print(error.message) - 4 is not one of [1, 2, 3] - [2, 3, 4] is too long - """ - - def validate(self, instance: dict) -> None: - """ - Check if the instance is valid under the current `schema`. - - :raises: `jsonschema.exceptions.ValidationError` if the - instance is invalid - - >>> schema = {"maxItems" : 2} - >>> Draft3Validator(schema).validate([2, 3, 4]) - Traceback (most recent call last): - ... - ValidationError: [2, 3, 4] is too long - """ - - def evolve(self, **kwargs) -> "Validator": - """ - Create a new validator like this one, but with given changes. - - Preserves all other attributes, so can be used to e.g. create a - validator with a different schema but with the same :validator:`$ref` - resolution behavior. - - >>> validator = Draft202012Validator({}) - >>> validator.evolve(schema={"type": "number"}) - Draft202012Validator(schema={'type': 'number'}, format_checker=None) - """ diff --git a/jsonschema/schemas/draft2019-09.json b/jsonschema/schemas/draft2019-09.json deleted file mode 100644 index 2248a0c..0000000 --- a/jsonschema/schemas/draft2019-09.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://json-schema.org/draft/2019-09/schema", - "$vocabulary": { - "https://json-schema.org/draft/2019-09/vocab/core": true, - "https://json-schema.org/draft/2019-09/vocab/applicator": true, - "https://json-schema.org/draft/2019-09/vocab/validation": true, - "https://json-schema.org/draft/2019-09/vocab/meta-data": true, - "https://json-schema.org/draft/2019-09/vocab/format": false, - "https://json-schema.org/draft/2019-09/vocab/content": true - }, - "$recursiveAnchor": true, - - "title": "Core and Validation specifications meta-schema", - "allOf": [ - {"$ref": "meta/core"}, - {"$ref": "meta/applicator"}, - {"$ref": "meta/validation"}, - {"$ref": "meta/meta-data"}, - {"$ref": "meta/format"}, - {"$ref": "meta/content"} - ], - "type": ["object", "boolean"], - "properties": { - "definitions": { - "$comment": "While no longer an official keyword as it is replaced by $defs, this keyword is retained in the meta-schema to prevent incompatible extensions as it remains in common use.", - "type": "object", - "additionalProperties": { "$recursiveRef": "#" }, - "default": {} - }, - "dependencies": { - "$comment": "\"dependencies\" is no longer a keyword, but schema authors should avoid redefining it to facilitate a smooth transition to \"dependentSchemas\" and \"dependentRequired\"", - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$recursiveRef": "#" }, - { "$ref": "meta/validation#/$defs/stringArray" } - ] - } - } - } -} diff --git a/jsonschema/schemas/draft2020-12.json b/jsonschema/schemas/draft2020-12.json deleted file mode 100644 index d5e2d31..0000000 --- a/jsonschema/schemas/draft2020-12.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://json-schema.org/draft/2020-12/schema", - "$vocabulary": { - "https://json-schema.org/draft/2020-12/vocab/core": true, - "https://json-schema.org/draft/2020-12/vocab/applicator": true, - "https://json-schema.org/draft/2020-12/vocab/unevaluated": true, - "https://json-schema.org/draft/2020-12/vocab/validation": true, - "https://json-schema.org/draft/2020-12/vocab/meta-data": true, - "https://json-schema.org/draft/2020-12/vocab/format-annotation": true, - "https://json-schema.org/draft/2020-12/vocab/content": true - }, - "$dynamicAnchor": "meta", - - "title": "Core and Validation specifications meta-schema", - "allOf": [ - {"$ref": "meta/core"}, - {"$ref": "meta/applicator"}, - {"$ref": "meta/unevaluated"}, - {"$ref": "meta/validation"}, - {"$ref": "meta/meta-data"}, - {"$ref": "meta/format-annotation"}, - {"$ref": "meta/content"} - ], - "type": ["object", "boolean"], - "$comment": "This meta-schema also defines keywords that have appeared in previous drafts in order to prevent incompatible extensions as they remain in common use.", - "properties": { - "definitions": { - "$comment": "\"definitions\" has been replaced by \"$defs\".", - "type": "object", - "additionalProperties": { "$dynamicRef": "#meta" }, - "deprecated": true, - "default": {} - }, - "dependencies": { - "$comment": "\"dependencies\" has been split and replaced by \"dependentSchemas\" and \"dependentRequired\" in order to serve their differing semantics.", - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$dynamicRef": "#meta" }, - { "$ref": "meta/validation#/$defs/stringArray" } - ] - }, - "deprecated": true, - "default": {} - }, - "$recursiveAnchor": { - "$comment": "\"$recursiveAnchor\" has been replaced by \"$dynamicAnchor\".", - "$ref": "meta/core#/$defs/anchorString", - "deprecated": true - }, - "$recursiveRef": { - "$comment": "\"$recursiveRef\" has been replaced by \"$dynamicRef\".", - "$ref": "meta/core#/$defs/uriReferenceString", - "deprecated": true - } - } -} diff --git a/jsonschema/schemas/draft3.json b/jsonschema/schemas/draft3.json deleted file mode 100644 index 23d59b6..0000000 --- a/jsonschema/schemas/draft3.json +++ /dev/null @@ -1,177 +0,0 @@ -{ - "$schema" : "http://json-schema.org/draft-03/schema#", - "id" : "http://json-schema.org/draft-03/schema#", - "type" : "object", - - "properties" : { - "type" : { - "type" : ["string", "array"], - "items" : { - "type" : ["string", {"$ref" : "#"}] - }, - "uniqueItems" : true, - "default" : "any" - }, - - "properties" : { - "type" : "object", - "additionalProperties" : {"$ref" : "#", "type" : "object"}, - "default" : {} - }, - - "patternProperties" : { - "type" : "object", - "additionalProperties" : {"$ref" : "#"}, - "default" : {} - }, - - "additionalProperties" : { - "type" : [{"$ref" : "#"}, "boolean"], - "default" : {} - }, - - "items" : { - "type" : [{"$ref" : "#"}, "array"], - "items" : {"$ref" : "#"}, - "default" : {} - }, - - "additionalItems" : { - "type" : [{"$ref" : "#"}, "boolean"], - "default" : {} - }, - - "required" : { - "type" : "boolean", - "default" : false - }, - - "dependencies" : { - "type" : ["string", "array", "object"], - "additionalProperties" : { - "type" : ["string", "array", {"$ref" : "#"}], - "items" : { - "type" : "string" - } - }, - "default" : {} - }, - - "minimum" : { - "type" : "number" - }, - - "maximum" : { - "type" : "number" - }, - - "exclusiveMinimum" : { - "type" : "boolean", - "default" : false - }, - - "exclusiveMaximum" : { - "type" : "boolean", - "default" : false - }, - - "maxDecimal": { - "minimum": 0, - "type": "number" - }, - - "minItems" : { - "type" : "integer", - "minimum" : 0, - "default" : 0 - }, - - "maxItems" : { - "type" : "integer", - "minimum" : 0 - }, - - "uniqueItems" : { - "type" : "boolean", - "default" : false - }, - - "pattern" : { - "type" : "string", - "format" : "regex" - }, - - "minLength" : { - "type" : "integer", - "minimum" : 0, - "default" : 0 - }, - - "maxLength" : { - "type" : "integer" - }, - - "enum" : { - "type" : "array" - }, - - "default" : { - "type" : "any" - }, - - "title" : { - "type" : "string" - }, - - "description" : { - "type" : "string" - }, - - "format" : { - "type" : "string" - }, - - "divisibleBy" : { - "type" : "number", - "minimum" : 0, - "exclusiveMinimum" : true, - "default" : 1 - }, - - "disallow" : { - "type" : ["string", "array"], - "items" : { - "type" : ["string", {"$ref" : "#"}] - }, - "uniqueItems" : true - }, - - "extends" : { - "type" : [{"$ref" : "#"}, "array"], - "items" : {"$ref" : "#"}, - "default" : {} - }, - - "id" : { - "type" : "string", - "format" : "uri" - }, - - "$ref" : { - "type" : "string", - "format" : "uri" - }, - - "$schema" : { - "type" : "string", - "format" : "uri" - } - }, - - "dependencies" : { - "exclusiveMinimum" : "minimum", - "exclusiveMaximum" : "maximum" - }, - - "default" : {} -} diff --git a/jsonschema/schemas/draft4.json b/jsonschema/schemas/draft4.json deleted file mode 100644 index ba0c117..0000000 --- a/jsonschema/schemas/draft4.json +++ /dev/null @@ -1,149 +0,0 @@ -{ - "id": "http://json-schema.org/draft-04/schema#", - "$schema": "http://json-schema.org/draft-04/schema#", - "description": "Core schema meta-schema", - "definitions": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#" } - }, - "positiveInteger": { - "type": "integer", - "minimum": 0 - }, - "positiveIntegerDefault0": { - "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ] - }, - "simpleTypes": { - "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ] - }, - "stringArray": { - "type": "array", - "items": { "type": "string" }, - "minItems": 1, - "uniqueItems": true - } - }, - "type": "object", - "properties": { - "id": { - "format": "uri", - "type": "string" - }, - "$schema": { - "type": "string", - "format": "uri" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": {}, - "multipleOf": { - "type": "number", - "minimum": 0, - "exclusiveMinimum": true - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "boolean", - "default": false - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "boolean", - "default": false - }, - "maxLength": { "$ref": "#/definitions/positiveInteger" }, - "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" }, - "pattern": { - "type": "string", - "format": "regex" - }, - "additionalItems": { - "anyOf": [ - { "type": "boolean" }, - { "$ref": "#" } - ], - "default": {} - }, - "items": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/schemaArray" } - ], - "default": {} - }, - "maxItems": { "$ref": "#/definitions/positiveInteger" }, - "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "maxProperties": { "$ref": "#/definitions/positiveInteger" }, - "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" }, - "required": { "$ref": "#/definitions/stringArray" }, - "additionalProperties": { - "anyOf": [ - { "type": "boolean" }, - { "$ref": "#" } - ], - "default": {} - }, - "definitions": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "properties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "patternProperties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "dependencies": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/stringArray" } - ] - } - }, - "enum": { - "type": "array" - }, - "type": { - "anyOf": [ - { "$ref": "#/definitions/simpleTypes" }, - { - "type": "array", - "items": { "$ref": "#/definitions/simpleTypes" }, - "minItems": 1, - "uniqueItems": true - } - ] - }, - "format": { "type": "string" }, - "allOf": { "$ref": "#/definitions/schemaArray" }, - "anyOf": { "$ref": "#/definitions/schemaArray" }, - "oneOf": { "$ref": "#/definitions/schemaArray" }, - "not": { "$ref": "#" } - }, - "dependencies": { - "exclusiveMaximum": [ "maximum" ], - "exclusiveMinimum": [ "minimum" ] - }, - "default": {} -} diff --git a/jsonschema/schemas/draft6.json b/jsonschema/schemas/draft6.json deleted file mode 100644 index a0d2bf7..0000000 --- a/jsonschema/schemas/draft6.json +++ /dev/null @@ -1,153 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-06/schema#", - "$id": "http://json-schema.org/draft-06/schema#", - "title": "Core schema meta-schema", - "definitions": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#" } - }, - "nonNegativeInteger": { - "type": "integer", - "minimum": 0 - }, - "nonNegativeIntegerDefault0": { - "allOf": [ - { "$ref": "#/definitions/nonNegativeInteger" }, - { "default": 0 } - ] - }, - "simpleTypes": { - "enum": [ - "array", - "boolean", - "integer", - "null", - "number", - "object", - "string" - ] - }, - "stringArray": { - "type": "array", - "items": { "type": "string" }, - "uniqueItems": true, - "default": [] - } - }, - "type": ["object", "boolean"], - "properties": { - "$id": { - "type": "string", - "format": "uri-reference" - }, - "$schema": { - "type": "string", - "format": "uri" - }, - "$ref": { - "type": "string", - "format": "uri-reference" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": {}, - "examples": { - "type": "array", - "items": {} - }, - "multipleOf": { - "type": "number", - "exclusiveMinimum": 0 - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "number" - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "number" - }, - "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, - "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "pattern": { - "type": "string", - "format": "regex" - }, - "additionalItems": { "$ref": "#" }, - "items": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/schemaArray" } - ], - "default": {} - }, - "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, - "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "contains": { "$ref": "#" }, - "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, - "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "required": { "$ref": "#/definitions/stringArray" }, - "additionalProperties": { "$ref": "#" }, - "definitions": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "properties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "patternProperties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "propertyNames": { "format": "regex" }, - "default": {} - }, - "dependencies": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/stringArray" } - ] - } - }, - "propertyNames": { "$ref": "#" }, - "const": {}, - "enum": { - "type": "array" - }, - "type": { - "anyOf": [ - { "$ref": "#/definitions/simpleTypes" }, - { - "type": "array", - "items": { "$ref": "#/definitions/simpleTypes" }, - "minItems": 1, - "uniqueItems": true - } - ] - }, - "format": { "type": "string" }, - "allOf": { "$ref": "#/definitions/schemaArray" }, - "anyOf": { "$ref": "#/definitions/schemaArray" }, - "oneOf": { "$ref": "#/definitions/schemaArray" }, - "not": { "$ref": "#" } - }, - "default": {} -} diff --git a/jsonschema/schemas/draft7.json b/jsonschema/schemas/draft7.json deleted file mode 100644 index 746cde9..0000000 --- a/jsonschema/schemas/draft7.json +++ /dev/null @@ -1,166 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "http://json-schema.org/draft-07/schema#", - "title": "Core schema meta-schema", - "definitions": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#" } - }, - "nonNegativeInteger": { - "type": "integer", - "minimum": 0 - }, - "nonNegativeIntegerDefault0": { - "allOf": [ - { "$ref": "#/definitions/nonNegativeInteger" }, - { "default": 0 } - ] - }, - "simpleTypes": { - "enum": [ - "array", - "boolean", - "integer", - "null", - "number", - "object", - "string" - ] - }, - "stringArray": { - "type": "array", - "items": { "type": "string" }, - "uniqueItems": true, - "default": [] - } - }, - "type": ["object", "boolean"], - "properties": { - "$id": { - "type": "string", - "format": "uri-reference" - }, - "$schema": { - "type": "string", - "format": "uri" - }, - "$ref": { - "type": "string", - "format": "uri-reference" - }, - "$comment": { - "type": "string" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": true, - "readOnly": { - "type": "boolean", - "default": false - }, - "examples": { - "type": "array", - "items": true - }, - "multipleOf": { - "type": "number", - "exclusiveMinimum": 0 - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "number" - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "number" - }, - "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, - "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "pattern": { - "type": "string", - "format": "regex" - }, - "additionalItems": { "$ref": "#" }, - "items": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/schemaArray" } - ], - "default": true - }, - "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, - "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "contains": { "$ref": "#" }, - "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, - "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "required": { "$ref": "#/definitions/stringArray" }, - "additionalProperties": { "$ref": "#" }, - "definitions": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "properties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "patternProperties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "propertyNames": { "format": "regex" }, - "default": {} - }, - "dependencies": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/stringArray" } - ] - } - }, - "propertyNames": { "$ref": "#" }, - "const": true, - "enum": { - "type": "array", - "items": true - }, - "type": { - "anyOf": [ - { "$ref": "#/definitions/simpleTypes" }, - { - "type": "array", - "items": { "$ref": "#/definitions/simpleTypes" }, - "minItems": 1, - "uniqueItems": true - } - ] - }, - "format": { "type": "string" }, - "contentMediaType": { "type": "string" }, - "contentEncoding": { "type": "string" }, - "if": {"$ref": "#"}, - "then": {"$ref": "#"}, - "else": {"$ref": "#"}, - "allOf": { "$ref": "#/definitions/schemaArray" }, - "anyOf": { "$ref": "#/definitions/schemaArray" }, - "oneOf": { "$ref": "#/definitions/schemaArray" }, - "not": { "$ref": "#" } - }, - "default": true -} diff --git a/jsonschema/schemas/vocabularies.json b/jsonschema/schemas/vocabularies.json deleted file mode 100644 index bca1705..0000000 --- a/jsonschema/schemas/vocabularies.json +++ /dev/null @@ -1 +0,0 @@ -{"https://json-schema.org/draft/2020-12/meta/content": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://json-schema.org/draft/2020-12/meta/content", "$vocabulary": {"https://json-schema.org/draft/2020-12/vocab/content": true}, "$dynamicAnchor": "meta", "title": "Content vocabulary meta-schema", "type": ["object", "boolean"], "properties": {"contentEncoding": {"type": "string"}, "contentMediaType": {"type": "string"}, "contentSchema": {"$dynamicRef": "#meta"}}}, "https://json-schema.org/draft/2020-12/meta/unevaluated": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://json-schema.org/draft/2020-12/meta/unevaluated", "$vocabulary": {"https://json-schema.org/draft/2020-12/vocab/unevaluated": true}, "$dynamicAnchor": "meta", "title": "Unevaluated applicator vocabulary meta-schema", "type": ["object", "boolean"], "properties": {"unevaluatedItems": {"$dynamicRef": "#meta"}, "unevaluatedProperties": {"$dynamicRef": "#meta"}}}, "https://json-schema.org/draft/2020-12/meta/format-annotation": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://json-schema.org/draft/2020-12/meta/format-annotation", "$vocabulary": {"https://json-schema.org/draft/2020-12/vocab/format-annotation": true}, "$dynamicAnchor": "meta", "title": "Format vocabulary meta-schema for annotation results", "type": ["object", "boolean"], "properties": {"format": {"type": "string"}}}, "https://json-schema.org/draft/2020-12/meta/applicator": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://json-schema.org/draft/2020-12/meta/applicator", "$vocabulary": {"https://json-schema.org/draft/2020-12/vocab/applicator": true}, "$dynamicAnchor": "meta", "title": "Applicator vocabulary meta-schema", "type": ["object", "boolean"], "properties": {"prefixItems": {"$ref": "#/$defs/schemaArray"}, "items": {"$dynamicRef": "#meta"}, "contains": {"$dynamicRef": "#meta"}, "additionalProperties": {"$dynamicRef": "#meta"}, "properties": {"type": "object", "additionalProperties": {"$dynamicRef": "#meta"}, "default": {}}, "patternProperties": {"type": "object", "additionalProperties": {"$dynamicRef": "#meta"}, "propertyNames": {"format": "regex"}, "default": {}}, "dependentSchemas": {"type": "object", "additionalProperties": {"$dynamicRef": "#meta"}, "default": {}}, "propertyNames": {"$dynamicRef": "#meta"}, "if": {"$dynamicRef": "#meta"}, "then": {"$dynamicRef": "#meta"}, "else": {"$dynamicRef": "#meta"}, "allOf": {"$ref": "#/$defs/schemaArray"}, "anyOf": {"$ref": "#/$defs/schemaArray"}, "oneOf": {"$ref": "#/$defs/schemaArray"}, "not": {"$dynamicRef": "#meta"}}, "$defs": {"schemaArray": {"type": "array", "minItems": 1, "items": {"$dynamicRef": "#meta"}}}}, "https://json-schema.org/draft/2020-12/meta/meta-data": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://json-schema.org/draft/2020-12/meta/meta-data", "$vocabulary": {"https://json-schema.org/draft/2020-12/vocab/meta-data": true}, "$dynamicAnchor": "meta", "title": "Meta-data vocabulary meta-schema", "type": ["object", "boolean"], "properties": {"title": {"type": "string"}, "description": {"type": "string"}, "default": true, "deprecated": {"type": "boolean", "default": false}, "readOnly": {"type": "boolean", "default": false}, "writeOnly": {"type": "boolean", "default": false}, "examples": {"type": "array", "items": true}}}, "https://json-schema.org/draft/2020-12/meta/core": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://json-schema.org/draft/2020-12/meta/core", "$vocabulary": {"https://json-schema.org/draft/2020-12/vocab/core": true}, "$dynamicAnchor": "meta", "title": "Core vocabulary meta-schema", "type": ["object", "boolean"], "properties": {"$id": {"$ref": "#/$defs/uriReferenceString", "$comment": "Non-empty fragments not allowed.", "pattern": "^[^#]*#?$"}, "$schema": {"$ref": "#/$defs/uriString"}, "$ref": {"$ref": "#/$defs/uriReferenceString"}, "$anchor": {"$ref": "#/$defs/anchorString"}, "$dynamicRef": {"$ref": "#/$defs/uriReferenceString"}, "$dynamicAnchor": {"$ref": "#/$defs/anchorString"}, "$vocabulary": {"type": "object", "propertyNames": {"$ref": "#/$defs/uriString"}, "additionalProperties": {"type": "boolean"}}, "$comment": {"type": "string"}, "$defs": {"type": "object", "additionalProperties": {"$dynamicRef": "#meta"}}}, "$defs": {"anchorString": {"type": "string", "pattern": "^[A-Za-z_][-A-Za-z0-9._]*$"}, "uriString": {"type": "string", "format": "uri"}, "uriReferenceString": {"type": "string", "format": "uri-reference"}}}, "https://json-schema.org/draft/2020-12/meta/validation": {"$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://json-schema.org/draft/2020-12/meta/validation", "$vocabulary": {"https://json-schema.org/draft/2020-12/vocab/validation": true}, "$dynamicAnchor": "meta", "title": "Validation vocabulary meta-schema", "type": ["object", "boolean"], "properties": {"type": {"anyOf": [{"$ref": "#/$defs/simpleTypes"}, {"type": "array", "items": {"$ref": "#/$defs/simpleTypes"}, "minItems": 1, "uniqueItems": true}]}, "const": true, "enum": {"type": "array", "items": true}, "multipleOf": {"type": "number", "exclusiveMinimum": 0}, "maximum": {"type": "number"}, "exclusiveMaximum": {"type": "number"}, "minimum": {"type": "number"}, "exclusiveMinimum": {"type": "number"}, "maxLength": {"$ref": "#/$defs/nonNegativeInteger"}, "minLength": {"$ref": "#/$defs/nonNegativeIntegerDefault0"}, "pattern": {"type": "string", "format": "regex"}, "maxItems": {"$ref": "#/$defs/nonNegativeInteger"}, "minItems": {"$ref": "#/$defs/nonNegativeIntegerDefault0"}, "uniqueItems": {"type": "boolean", "default": false}, "maxContains": {"$ref": "#/$defs/nonNegativeInteger"}, "minContains": {"$ref": "#/$defs/nonNegativeInteger", "default": 1}, "maxProperties": {"$ref": "#/$defs/nonNegativeInteger"}, "minProperties": {"$ref": "#/$defs/nonNegativeIntegerDefault0"}, "required": {"$ref": "#/$defs/stringArray"}, "dependentRequired": {"type": "object", "additionalProperties": {"$ref": "#/$defs/stringArray"}}}, "$defs": {"nonNegativeInteger": {"type": "integer", "minimum": 0}, "nonNegativeIntegerDefault0": {"$ref": "#/$defs/nonNegativeInteger", "default": 0}, "simpleTypes": {"enum": ["array", "boolean", "integer", "null", "number", "object", "string"]}, "stringArray": {"type": "array", "items": {"type": "string"}, "uniqueItems": true, "default": []}}}, "https://json-schema.org/draft/2019-09/meta/content": {"$schema": "https://json-schema.org/draft/2019-09/schema", "$id": "https://json-schema.org/draft/2019-09/meta/content", "$vocabulary": {"https://json-schema.org/draft/2019-09/vocab/content": true}, "$recursiveAnchor": true, "title": "Content vocabulary meta-schema", "type": ["object", "boolean"], "properties": {"contentMediaType": {"type": "string"}, "contentEncoding": {"type": "string"}, "contentSchema": {"$recursiveRef": "#"}}}, "https://json-schema.org/draft/2019-09/meta/applicator": {"$schema": "https://json-schema.org/draft/2019-09/schema", "$id": "https://json-schema.org/draft/2019-09/meta/applicator", "$vocabulary": {"https://json-schema.org/draft/2019-09/vocab/applicator": true}, "$recursiveAnchor": true, "title": "Applicator vocabulary meta-schema", "type": ["object", "boolean"], "properties": {"additionalItems": {"$recursiveRef": "#"}, "unevaluatedItems": {"$recursiveRef": "#"}, "items": {"anyOf": [{"$recursiveRef": "#"}, {"$ref": "#/$defs/schemaArray"}]}, "contains": {"$recursiveRef": "#"}, "additionalProperties": {"$recursiveRef": "#"}, "unevaluatedProperties": {"$recursiveRef": "#"}, "properties": {"type": "object", "additionalProperties": {"$recursiveRef": "#"}, "default": {}}, "patternProperties": {"type": "object", "additionalProperties": {"$recursiveRef": "#"}, "propertyNames": {"format": "regex"}, "default": {}}, "dependentSchemas": {"type": "object", "additionalProperties": {"$recursiveRef": "#"}}, "propertyNames": {"$recursiveRef": "#"}, "if": {"$recursiveRef": "#"}, "then": {"$recursiveRef": "#"}, "else": {"$recursiveRef": "#"}, "allOf": {"$ref": "#/$defs/schemaArray"}, "anyOf": {"$ref": "#/$defs/schemaArray"}, "oneOf": {"$ref": "#/$defs/schemaArray"}, "not": {"$recursiveRef": "#"}}, "$defs": {"schemaArray": {"type": "array", "minItems": 1, "items": {"$recursiveRef": "#"}}}}, "https://json-schema.org/draft/2019-09/meta/meta-data": {"$schema": "https://json-schema.org/draft/2019-09/schema", "$id": "https://json-schema.org/draft/2019-09/meta/meta-data", "$vocabulary": {"https://json-schema.org/draft/2019-09/vocab/meta-data": true}, "$recursiveAnchor": true, "title": "Meta-data vocabulary meta-schema", "type": ["object", "boolean"], "properties": {"title": {"type": "string"}, "description": {"type": "string"}, "default": true, "deprecated": {"type": "boolean", "default": false}, "readOnly": {"type": "boolean", "default": false}, "writeOnly": {"type": "boolean", "default": false}, "examples": {"type": "array", "items": true}}}, "https://json-schema.org/draft/2019-09/meta/core": {"$schema": "https://json-schema.org/draft/2019-09/schema", "$id": "https://json-schema.org/draft/2019-09/meta/core", "$vocabulary": {"https://json-schema.org/draft/2019-09/vocab/core": true}, "$recursiveAnchor": true, "title": "Core vocabulary meta-schema", "type": ["object", "boolean"], "properties": {"$id": {"type": "string", "format": "uri-reference", "$comment": "Non-empty fragments not allowed.", "pattern": "^[^#]*#?$"}, "$schema": {"type": "string", "format": "uri"}, "$anchor": {"type": "string", "pattern": "^[A-Za-z][-A-Za-z0-9.:_]*$"}, "$ref": {"type": "string", "format": "uri-reference"}, "$recursiveRef": {"type": "string", "format": "uri-reference"}, "$recursiveAnchor": {"type": "boolean", "default": false}, "$vocabulary": {"type": "object", "propertyNames": {"type": "string", "format": "uri"}, "additionalProperties": {"type": "boolean"}}, "$comment": {"type": "string"}, "$defs": {"type": "object", "additionalProperties": {"$recursiveRef": "#"}, "default": {}}}}, "https://json-schema.org/draft/2019-09/meta/validation": {"$schema": "https://json-schema.org/draft/2019-09/schema", "$id": "https://json-schema.org/draft/2019-09/meta/validation", "$vocabulary": {"https://json-schema.org/draft/2019-09/vocab/validation": true}, "$recursiveAnchor": true, "title": "Validation vocabulary meta-schema", "type": ["object", "boolean"], "properties": {"multipleOf": {"type": "number", "exclusiveMinimum": 0}, "maximum": {"type": "number"}, "exclusiveMaximum": {"type": "number"}, "minimum": {"type": "number"}, "exclusiveMinimum": {"type": "number"}, "maxLength": {"$ref": "#/$defs/nonNegativeInteger"}, "minLength": {"$ref": "#/$defs/nonNegativeIntegerDefault0"}, "pattern": {"type": "string", "format": "regex"}, "maxItems": {"$ref": "#/$defs/nonNegativeInteger"}, "minItems": {"$ref": "#/$defs/nonNegativeIntegerDefault0"}, "uniqueItems": {"type": "boolean", "default": false}, "maxContains": {"$ref": "#/$defs/nonNegativeInteger"}, "minContains": {"$ref": "#/$defs/nonNegativeInteger", "default": 1}, "maxProperties": {"$ref": "#/$defs/nonNegativeInteger"}, "minProperties": {"$ref": "#/$defs/nonNegativeIntegerDefault0"}, "required": {"$ref": "#/$defs/stringArray"}, "dependentRequired": {"type": "object", "additionalProperties": {"$ref": "#/$defs/stringArray"}}, "const": true, "enum": {"type": "array", "items": true}, "type": {"anyOf": [{"$ref": "#/$defs/simpleTypes"}, {"type": "array", "items": {"$ref": "#/$defs/simpleTypes"}, "minItems": 1, "uniqueItems": true}]}}, "$defs": {"nonNegativeInteger": {"type": "integer", "minimum": 0}, "nonNegativeIntegerDefault0": {"$ref": "#/$defs/nonNegativeInteger", "default": 0}, "simpleTypes": {"enum": ["array", "boolean", "integer", "null", "number", "object", "string"]}, "stringArray": {"type": "array", "items": {"type": "string"}, "uniqueItems": true, "default": []}}}, "https://json-schema.org/draft/2019-09/meta/hyper-schema": {"$schema": "https://json-schema.org/draft/2019-09/hyper-schema", "$id": "https://json-schema.org/draft/2019-09/meta/hyper-schema", "$vocabulary": {"https://json-schema.org/draft/2019-09/vocab/hyper-schema": true}, "$recursiveAnchor": true, "title": "JSON Hyper-Schema Vocabulary Schema", "type": ["object", "boolean"], "properties": {"base": {"type": "string", "format": "uri-template"}, "links": {"type": "array", "items": {"$ref": "https://json-schema.org/draft/2019-09/links"}}}, "links": [{"rel": "self", "href": "{+%24id}"}]}, "https://json-schema.org/draft/2019-09/meta/format": {"$schema": "https://json-schema.org/draft/2019-09/schema", "$id": "https://json-schema.org/draft/2019-09/meta/format", "$vocabulary": {"https://json-schema.org/draft/2019-09/vocab/format": true}, "$recursiveAnchor": true, "title": "Format vocabulary meta-schema", "type": ["object", "boolean"], "properties": {"format": {"type": "string"}}}} diff --git a/jsonschema/tests/__init__.py b/jsonschema/tests/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/jsonschema/tests/__init__.py +++ /dev/null diff --git a/jsonschema/tests/_helpers.py b/jsonschema/tests/_helpers.py deleted file mode 100644 index 70f291f..0000000 --- a/jsonschema/tests/_helpers.py +++ /dev/null @@ -1,5 +0,0 @@ -def bug(issue=None): - message = "A known bug." - if issue is not None: - message += " See issue #{issue}.".format(issue=issue) - return message diff --git a/jsonschema/tests/_suite.py b/jsonschema/tests/_suite.py deleted file mode 100644 index 61a8fc8..0000000 --- a/jsonschema/tests/_suite.py +++ /dev/null @@ -1,231 +0,0 @@ -""" -Python representations of the JSON Schema Test Suite tests. -""" - -from functools import partial -from pathlib import Path -import json -import os -import re -import subprocess -import sys -import unittest - -import attr - -from jsonschema.validators import _VALIDATORS -import jsonschema - - -def _find_suite(): - root = os.environ.get("JSON_SCHEMA_TEST_SUITE") - if root is not None: - return Path(root) - - root = Path(jsonschema.__file__).parent.parent / "json" - if not root.is_dir(): # pragma: no cover - raise ValueError( - ( - "Can't find the JSON-Schema-Test-Suite directory. " - "Set the 'JSON_SCHEMA_TEST_SUITE' environment " - "variable or run the tests from alongside a checkout " - "of the suite." - ), - ) - return root - - -@attr.s(hash=True) -class Suite(object): - - _root = attr.ib(default=attr.Factory(_find_suite)) - - def _remotes(self): - jsonschema_suite = self._root.joinpath("bin", "jsonschema_suite") - remotes = subprocess.check_output( - [sys.executable, str(jsonschema_suite), "remotes"], - ) - return { - "http://localhost:1234/" + name.replace("\\", "/"): schema - for name, schema in json.loads(remotes.decode("utf-8")).items() - } - - def benchmark(self, runner): # pragma: no cover - for name, Validator in _VALIDATORS.items(): - self.version(name=name).benchmark( - runner=runner, - Validator=Validator, - ) - - def version(self, name): - return Version( - name=name, - path=self._root.joinpath("tests", name), - remotes=self._remotes(), - ) - - -@attr.s(hash=True) -class Version(object): - - _path = attr.ib() - _remotes = attr.ib() - - name = attr.ib() - - def benchmark(self, runner, **kwargs): # pragma: no cover - for suite in self.tests(): - for test in suite: - runner.bench_func( - test.fully_qualified_name, - partial(test.validate_ignoring_errors, **kwargs), - ) - - def tests(self): - return ( - test - for child in self._path.glob("*.json") - for test in self._tests_in( - subject=child.name[:-5], - path=child, - ) - ) - - def format_tests(self): - path = self._path.joinpath("optional", "format") - return ( - test - for child in path.glob("*.json") - for test in self._tests_in( - subject=child.name[:-5], - path=child, - ) - ) - - def optional_tests_of(self, name): - return self._tests_in( - subject=name, - path=self._path.joinpath("optional", name + ".json"), - ) - - def to_unittest_testcase(self, *suites, **kwargs): - name = kwargs.pop("name", "Test" + self.name.title().replace("-", "")) - methods = { - test.method_name: test.to_unittest_method(**kwargs) - for suite in suites - for tests in suite - for test in tests - } - cls = type(name, (unittest.TestCase,), methods) - - try: - cls.__module__ = _someone_save_us_the_module_of_the_caller() - except Exception: # pragma: no cover - # We're doing crazy things, so if they go wrong, like a function - # behaving differently on some other interpreter, just make them - # not happen. - pass - - return cls - - def _tests_in(self, subject, path): - for each in json.loads(path.read_text(encoding="utf-8")): - yield ( - _Test( - version=self, - subject=subject, - case_description=each["description"], - schema=each["schema"], - remotes=self._remotes, - **test, - ) for test in each["tests"] - ) - - -@attr.s(hash=True, repr=False) -class _Test(object): - - version = attr.ib() - - subject = attr.ib() - case_description = attr.ib() - description = attr.ib() - - data = attr.ib() - schema = attr.ib(repr=False) - - valid = attr.ib() - - _remotes = attr.ib() - - comment = attr.ib(default=None) - - def __repr__(self): # pragma: no cover - return "<Test {}>".format(self.fully_qualified_name) - - @property - def fully_qualified_name(self): # pragma: no cover - return " > ".join( - [ - self.version.name, - self.subject, - self.case_description, - self.description, - ], - ) - - @property - def method_name(self): - delimiters = r"[\W\- ]+" - return "test_{}_{}_{}".format( - re.sub(delimiters, "_", self.subject), - re.sub(delimiters, "_", self.case_description), - re.sub(delimiters, "_", self.description), - ) - - def to_unittest_method(self, skip=lambda test: None, **kwargs): - if self.valid: - def fn(this): - self.validate(**kwargs) - else: - def fn(this): - with this.assertRaises(jsonschema.ValidationError): - self.validate(**kwargs) - - fn.__name__ = self.method_name - reason = skip(self) - return unittest.skipIf(reason is not None, reason)(fn) - - def validate(self, Validator, **kwargs): - Validator.check_schema(self.schema) - resolver = jsonschema.RefResolver.from_schema( - schema=self.schema, - store=self._remotes, - id_of=Validator.ID_OF, - ) - validator = Validator(schema=self.schema, resolver=resolver, **kwargs) - if os.environ.get("JSON_SCHEMA_DEBUG", "0") != "0": - breakpoint() - validator.validate(instance=self.data) - - def validate_ignoring_errors(self, Validator): # pragma: no cover - try: - self.validate(Validator=Validator) - except jsonschema.ValidationError: - pass - - -def _someone_save_us_the_module_of_the_caller(): - """ - The FQON of the module 2nd stack frames up from here. - - This is intended to allow us to dynamically return test case classes that - are indistinguishable from being defined in the module that wants them. - - Otherwise, trial will mis-print the FQON, and copy pasting it won't re-run - the class that really is running. - - Save us all, this is all so so so so so terrible. - """ - - return sys._getframe(2).f_globals["__name__"] diff --git a/jsonschema/tests/fuzz_validate.py b/jsonschema/tests/fuzz_validate.py deleted file mode 100644 index c12e88b..0000000 --- a/jsonschema/tests/fuzz_validate.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -Fuzzing setup for OSS-Fuzz. - -See https://github.com/google/oss-fuzz/tree/master/projects/jsonschema for the -other half of the setup here. -""" -import sys - -from hypothesis import given, strategies - -import jsonschema - -PRIM = strategies.one_of( - strategies.booleans(), - strategies.integers(), - strategies.floats(allow_nan=False, allow_infinity=False), - strategies.text(), -) -DICT = strategies.recursive( - base=strategies.one_of( - strategies.booleans(), - strategies.dictionaries(strategies.text(), PRIM), - ), - extend=lambda inner: strategies.dictionaries(strategies.text(), inner), -) - - -@given(obj1=DICT, obj2=DICT) -def test_schemas(obj1, obj2): - try: - jsonschema.validate(instance=obj1, schema=obj2) - except jsonschema.exceptions.ValidationError: - pass - except jsonschema.exceptions.SchemaError: - pass - - -def main(): - atheris.instrument_all() - atheris.Setup( - sys.argv, - test_schemas.hypothesis.fuzz_one_input, - enable_python_coverage=True, - ) - atheris.Fuzz() - - -if __name__ == "__main__": - import atheris - main() diff --git a/jsonschema/tests/test_cli.py b/jsonschema/tests/test_cli.py deleted file mode 100644 index 6d42af6..0000000 --- a/jsonschema/tests/test_cli.py +++ /dev/null @@ -1,911 +0,0 @@ -from contextlib import redirect_stderr, redirect_stdout -from io import StringIO -from json import JSONDecodeError -from pathlib import Path -from textwrap import dedent -from unittest import TestCase -import json -import os -import subprocess -import sys -import tempfile - -try: # pragma: no cover - from importlib import metadata -except ImportError: # pragma: no cover - import importlib_metadata as metadata # type: ignore - -from pyrsistent import m - -from jsonschema import Draft4Validator, Draft202012Validator, cli -from jsonschema.exceptions import ( - RefResolutionError, - SchemaError, - ValidationError, -) -from jsonschema.validators import _LATEST_VERSION, validate - - -def fake_validator(*errors): - errors = list(reversed(errors)) - - class FakeValidator(object): - def __init__(self, *args, **kwargs): - pass - - def iter_errors(self, instance): - if errors: - return errors.pop() - return [] # pragma: no cover - - @classmethod - def check_schema(self, schema): - pass - - return FakeValidator - - -def fake_open(all_contents): - def open(path): - contents = all_contents.get(path) - if contents is None: - raise FileNotFoundError(path) - return StringIO(contents) - return open - - -def _message_for(non_json): - try: - json.loads(non_json) - except JSONDecodeError as error: - return str(error) - else: # pragma: no cover - raise RuntimeError("Tried and failed to capture a JSON dump error.") - - -class TestCLI(TestCase): - def run_cli( - self, argv, files=m(), stdin=StringIO(), exit_code=0, **override, - ): - arguments = cli.parse_args(argv) - arguments.update(override) - - self.assertFalse(hasattr(cli, "open")) - cli.open = fake_open(files) - try: - stdout, stderr = StringIO(), StringIO() - actual_exit_code = cli.run( - arguments, - stdin=stdin, - stdout=stdout, - stderr=stderr, - ) - finally: - del cli.open - - self.assertEqual( - actual_exit_code, exit_code, msg=dedent( - """ - Expected an exit code of {} != {}. - - stdout: {} - - stderr: {} - """.format( - exit_code, - actual_exit_code, - stdout.getvalue(), - stderr.getvalue(), - ), - ), - ) - return stdout.getvalue(), stderr.getvalue() - - def assertOutputs(self, stdout="", stderr="", **kwargs): - self.assertEqual( - self.run_cli(**kwargs), - (dedent(stdout), dedent(stderr)), - ) - - def test_invalid_instance(self): - error = ValidationError("I am an error!", instance=12) - self.assertOutputs( - files=dict( - some_schema='{"does not": "matter since it is stubbed"}', - some_instance=json.dumps(error.instance), - ), - validator=fake_validator([error]), - - argv=["-i", "some_instance", "some_schema"], - - exit_code=1, - stderr="12: I am an error!\n", - ) - - def test_invalid_instance_pretty_output(self): - error = ValidationError("I am an error!", instance=12) - self.assertOutputs( - files=dict( - some_schema='{"does not": "matter since it is stubbed"}', - some_instance=json.dumps(error.instance), - ), - validator=fake_validator([error]), - - argv=["-i", "some_instance", "--output", "pretty", "some_schema"], - - exit_code=1, - stderr="""\ - ===[ValidationError]===(some_instance)=== - - I am an error! - ----------------------------- - """, - ) - - def test_invalid_instance_explicit_plain_output(self): - error = ValidationError("I am an error!", instance=12) - self.assertOutputs( - files=dict( - some_schema='{"does not": "matter since it is stubbed"}', - some_instance=json.dumps(error.instance), - ), - validator=fake_validator([error]), - - argv=["--output", "plain", "-i", "some_instance", "some_schema"], - - exit_code=1, - stderr="12: I am an error!\n", - ) - - def test_invalid_instance_multiple_errors(self): - instance = 12 - first = ValidationError("First error", instance=instance) - second = ValidationError("Second error", instance=instance) - - self.assertOutputs( - files=dict( - some_schema='{"does not": "matter since it is stubbed"}', - some_instance=json.dumps(instance), - ), - validator=fake_validator([first, second]), - - argv=["-i", "some_instance", "some_schema"], - - exit_code=1, - stderr="""\ - 12: First error - 12: Second error - """, - ) - - def test_invalid_instance_multiple_errors_pretty_output(self): - instance = 12 - first = ValidationError("First error", instance=instance) - second = ValidationError("Second error", instance=instance) - - self.assertOutputs( - files=dict( - some_schema='{"does not": "matter since it is stubbed"}', - some_instance=json.dumps(instance), - ), - validator=fake_validator([first, second]), - - argv=["-i", "some_instance", "--output", "pretty", "some_schema"], - - exit_code=1, - stderr="""\ - ===[ValidationError]===(some_instance)=== - - First error - ----------------------------- - ===[ValidationError]===(some_instance)=== - - Second error - ----------------------------- - """, - ) - - def test_multiple_invalid_instances(self): - first_instance = 12 - first_errors = [ - ValidationError("An error", instance=first_instance), - ValidationError("Another error", instance=first_instance), - ] - second_instance = "foo" - second_errors = [ValidationError("BOOM", instance=second_instance)] - - self.assertOutputs( - files=dict( - some_schema='{"does not": "matter since it is stubbed"}', - some_first_instance=json.dumps(first_instance), - some_second_instance=json.dumps(second_instance), - ), - validator=fake_validator(first_errors, second_errors), - - argv=[ - "-i", "some_first_instance", - "-i", "some_second_instance", - "some_schema", - ], - - exit_code=1, - stderr="""\ - 12: An error - 12: Another error - foo: BOOM - """, - ) - - def test_multiple_invalid_instances_pretty_output(self): - first_instance = 12 - first_errors = [ - ValidationError("An error", instance=first_instance), - ValidationError("Another error", instance=first_instance), - ] - second_instance = "foo" - second_errors = [ValidationError("BOOM", instance=second_instance)] - - self.assertOutputs( - files=dict( - some_schema='{"does not": "matter since it is stubbed"}', - some_first_instance=json.dumps(first_instance), - some_second_instance=json.dumps(second_instance), - ), - validator=fake_validator(first_errors, second_errors), - - argv=[ - "--output", "pretty", - "-i", "some_first_instance", - "-i", "some_second_instance", - "some_schema", - ], - - exit_code=1, - stderr="""\ - ===[ValidationError]===(some_first_instance)=== - - An error - ----------------------------- - ===[ValidationError]===(some_first_instance)=== - - Another error - ----------------------------- - ===[ValidationError]===(some_second_instance)=== - - BOOM - ----------------------------- - """, - ) - - def test_custom_error_format(self): - first_instance = 12 - first_errors = [ - ValidationError("An error", instance=first_instance), - ValidationError("Another error", instance=first_instance), - ] - second_instance = "foo" - second_errors = [ValidationError("BOOM", instance=second_instance)] - - self.assertOutputs( - files=dict( - some_schema='{"does not": "matter since it is stubbed"}', - some_first_instance=json.dumps(first_instance), - some_second_instance=json.dumps(second_instance), - ), - validator=fake_validator(first_errors, second_errors), - - argv=[ - "--error-format", ":{error.message}._-_.{error.instance}:", - "-i", "some_first_instance", - "-i", "some_second_instance", - "some_schema", - ], - - exit_code=1, - stderr=":An error._-_.12::Another error._-_.12::BOOM._-_.foo:", - ) - - def test_invalid_schema(self): - self.assertOutputs( - files=dict(some_schema='{"type": 12}'), - argv=["some_schema"], - - exit_code=1, - stderr="""\ - 12: 12 is not valid under any of the given schemas - """, - ) - - def test_invalid_schema_pretty_output(self): - schema = {"type": 12} - - with self.assertRaises(SchemaError) as e: - validate(schema=schema, instance="") - error = str(e.exception) - - self.assertOutputs( - files=dict(some_schema=json.dumps(schema)), - argv=["--output", "pretty", "some_schema"], - - exit_code=1, - stderr=( - "===[SchemaError]===(some_schema)===\n\n" - + str(error) - + "\n-----------------------------\n" - ), - ) - - def test_invalid_schema_multiple_errors(self): - self.assertOutputs( - files=dict(some_schema='{"type": 12, "items": 57}'), - argv=["some_schema"], - - exit_code=1, - stderr="""\ - 57: 57 is not of type 'object', 'boolean' - """, - ) - - def test_invalid_schema_multiple_errors_pretty_output(self): - schema = {"type": 12, "items": 57} - - with self.assertRaises(SchemaError) as e: - validate(schema=schema, instance="") - error = str(e.exception) - - self.assertOutputs( - files=dict(some_schema=json.dumps(schema)), - argv=["--output", "pretty", "some_schema"], - - exit_code=1, - stderr=( - "===[SchemaError]===(some_schema)===\n\n" - + str(error) - + "\n-----------------------------\n" - ), - ) - - def test_invalid_schema_with_invalid_instance(self): - """ - "Validating" an instance that's invalid under an invalid schema - just shows the schema error. - """ - self.assertOutputs( - files=dict( - some_schema='{"type": 12, "minimum": 30}', - some_instance="13", - ), - argv=["-i", "some_instance", "some_schema"], - - exit_code=1, - stderr="""\ - 12: 12 is not valid under any of the given schemas - """, - ) - - def test_invalid_schema_with_invalid_instance_pretty_output(self): - instance, schema = 13, {"type": 12, "minimum": 30} - - with self.assertRaises(SchemaError) as e: - validate(schema=schema, instance=instance) - error = str(e.exception) - - self.assertOutputs( - files=dict( - some_schema=json.dumps(schema), - some_instance=json.dumps(instance), - ), - argv=["--output", "pretty", "-i", "some_instance", "some_schema"], - - exit_code=1, - stderr=( - "===[SchemaError]===(some_schema)===\n\n" - + str(error) - + "\n-----------------------------\n" - ), - ) - - def test_invalid_instance_continues_with_the_rest(self): - self.assertOutputs( - files=dict( - some_schema='{"minimum": 30}', - first_instance="not valid JSON!", - second_instance="12", - ), - argv=[ - "-i", "first_instance", - "-i", "second_instance", - "some_schema", - ], - - exit_code=1, - stderr="""\ - Failed to parse 'first_instance': {} - 12: 12 is less than the minimum of 30 - """.format(_message_for("not valid JSON!")), - ) - - def test_custom_error_format_applies_to_schema_errors(self): - instance, schema = 13, {"type": 12, "minimum": 30} - - with self.assertRaises(SchemaError): - validate(schema=schema, instance=instance) - - self.assertOutputs( - files=dict(some_schema=json.dumps(schema)), - - argv=[ - "--error-format", ":{error.message}._-_.{error.instance}:", - "some_schema", - ], - - exit_code=1, - stderr=":12 is not valid under any of the given schemas._-_.12:", - ) - - def test_instance_is_invalid_JSON(self): - instance = "not valid JSON!" - - self.assertOutputs( - files=dict(some_schema="{}", some_instance=instance), - argv=["-i", "some_instance", "some_schema"], - - exit_code=1, - stderr="""\ - Failed to parse 'some_instance': {} - """.format(_message_for(instance)), - ) - - def test_instance_is_invalid_JSON_pretty_output(self): - stdout, stderr = self.run_cli( - files=dict( - some_schema="{}", - some_instance="not valid JSON!", - ), - - argv=["--output", "pretty", "-i", "some_instance", "some_schema"], - - exit_code=1, - ) - self.assertFalse(stdout) - self.assertIn( - "(some_instance)===\n\nTraceback (most recent call last):\n", - stderr, - ) - self.assertNotIn("some_schema", stderr) - - def test_instance_is_invalid_JSON_on_stdin(self): - instance = "not valid JSON!" - - self.assertOutputs( - files=dict(some_schema="{}"), - stdin=StringIO(instance), - - argv=["some_schema"], - - exit_code=1, - stderr="""\ - Failed to parse <stdin>: {} - """.format(_message_for(instance)), - ) - - def test_instance_is_invalid_JSON_on_stdin_pretty_output(self): - stdout, stderr = self.run_cli( - files=dict(some_schema="{}"), - stdin=StringIO("not valid JSON!"), - - argv=["--output", "pretty", "some_schema"], - - exit_code=1, - ) - self.assertFalse(stdout) - self.assertIn( - "(<stdin>)===\n\nTraceback (most recent call last):\n", - stderr, - ) - self.assertNotIn("some_schema", stderr) - - def test_schema_is_invalid_JSON(self): - schema = "not valid JSON!" - - self.assertOutputs( - files=dict(some_schema=schema), - - argv=["some_schema"], - - exit_code=1, - stderr="""\ - Failed to parse 'some_schema': {} - """.format(_message_for(schema)), - ) - - def test_schema_is_invalid_JSON_pretty_output(self): - stdout, stderr = self.run_cli( - files=dict(some_schema="not valid JSON!"), - - argv=["--output", "pretty", "some_schema"], - - exit_code=1, - ) - self.assertFalse(stdout) - self.assertIn( - "(some_schema)===\n\nTraceback (most recent call last):\n", - stderr, - ) - - def test_schema_and_instance_are_both_invalid_JSON(self): - """ - Only the schema error is reported, as we abort immediately. - """ - schema, instance = "not valid JSON!", "also not valid JSON!" - self.assertOutputs( - files=dict(some_schema=schema, some_instance=instance), - - argv=["some_schema"], - - exit_code=1, - stderr="""\ - Failed to parse 'some_schema': {} - """.format(_message_for(schema)), - ) - - def test_schema_and_instance_are_both_invalid_JSON_pretty_output(self): - """ - Only the schema error is reported, as we abort immediately. - """ - stdout, stderr = self.run_cli( - files=dict( - some_schema="not valid JSON!", - some_instance="also not valid JSON!", - ), - - argv=["--output", "pretty", "-i", "some_instance", "some_schema"], - - exit_code=1, - ) - self.assertFalse(stdout) - self.assertIn( - "(some_schema)===\n\nTraceback (most recent call last):\n", - stderr, - ) - self.assertNotIn("some_instance", stderr) - - def test_instance_does_not_exist(self): - self.assertOutputs( - files=dict(some_schema="{}"), - argv=["-i", "nonexisting_instance", "some_schema"], - - exit_code=1, - stderr="""\ - 'nonexisting_instance' does not exist. - """, - ) - - def test_instance_does_not_exist_pretty_output(self): - self.assertOutputs( - files=dict(some_schema="{}"), - argv=[ - "--output", "pretty", - "-i", "nonexisting_instance", - "some_schema", - ], - - exit_code=1, - stderr="""\ - ===[FileNotFoundError]===(nonexisting_instance)=== - - 'nonexisting_instance' does not exist. - ----------------------------- - """, - ) - - def test_schema_does_not_exist(self): - self.assertOutputs( - argv=["nonexisting_schema"], - - exit_code=1, - stderr="'nonexisting_schema' does not exist.\n", - ) - - def test_schema_does_not_exist_pretty_output(self): - self.assertOutputs( - argv=["--output", "pretty", "nonexisting_schema"], - - exit_code=1, - stderr="""\ - ===[FileNotFoundError]===(nonexisting_schema)=== - - 'nonexisting_schema' does not exist. - ----------------------------- - """, - ) - - def test_neither_instance_nor_schema_exist(self): - self.assertOutputs( - argv=["-i", "nonexisting_instance", "nonexisting_schema"], - - exit_code=1, - stderr="'nonexisting_schema' does not exist.\n", - ) - - def test_neither_instance_nor_schema_exist_pretty_output(self): - self.assertOutputs( - argv=[ - "--output", "pretty", - "-i", "nonexisting_instance", - "nonexisting_schema", - ], - - exit_code=1, - stderr="""\ - ===[FileNotFoundError]===(nonexisting_schema)=== - - 'nonexisting_schema' does not exist. - ----------------------------- - """, - ) - - def test_successful_validation(self): - self.assertOutputs( - files=dict(some_schema="{}", some_instance="{}"), - argv=["-i", "some_instance", "some_schema"], - stdout="", - stderr="", - ) - - def test_successful_validation_pretty_output(self): - self.assertOutputs( - files=dict(some_schema="{}", some_instance="{}"), - argv=["--output", "pretty", "-i", "some_instance", "some_schema"], - stdout="===[SUCCESS]===(some_instance)===\n", - stderr="", - ) - - def test_successful_validation_of_stdin(self): - self.assertOutputs( - files=dict(some_schema="{}"), - stdin=StringIO("{}"), - argv=["some_schema"], - stdout="", - stderr="", - ) - - def test_successful_validation_of_stdin_pretty_output(self): - self.assertOutputs( - files=dict(some_schema="{}"), - stdin=StringIO("{}"), - argv=["--output", "pretty", "some_schema"], - stdout="===[SUCCESS]===(<stdin>)===\n", - stderr="", - ) - - def test_successful_validation_of_just_the_schema(self): - self.assertOutputs( - files=dict(some_schema="{}", some_instance="{}"), - argv=["-i", "some_instance", "some_schema"], - stdout="", - stderr="", - ) - - def test_successful_validation_of_just_the_schema_pretty_output(self): - self.assertOutputs( - files=dict(some_schema="{}", some_instance="{}"), - argv=["--output", "pretty", "-i", "some_instance", "some_schema"], - stdout="===[SUCCESS]===(some_instance)===\n", - stderr="", - ) - - def test_successful_validation_via_explicit_base_uri(self): - ref_schema_file = tempfile.NamedTemporaryFile(delete=False) - self.addCleanup(os.remove, ref_schema_file.name) - - ref_path = Path(ref_schema_file.name) - ref_path.write_text('{"definitions": {"num": {"type": "integer"}}}') - - schema = f'{{"$ref": "{ref_path.name}#definitions/num"}}' - - self.assertOutputs( - files=dict(some_schema=schema, some_instance="1"), - argv=[ - "-i", "some_instance", - "--base-uri", ref_path.parent.as_uri() + "/", - "some_schema", - ], - stdout="", - stderr="", - ) - - def test_unsuccessful_validation_via_explicit_base_uri(self): - ref_schema_file = tempfile.NamedTemporaryFile(delete=False) - self.addCleanup(os.remove, ref_schema_file.name) - - ref_path = Path(ref_schema_file.name) - ref_path.write_text('{"definitions": {"num": {"type": "integer"}}}') - - schema = f'{{"$ref": "{ref_path.name}#definitions/num"}}' - - self.assertOutputs( - files=dict(some_schema=schema, some_instance='"1"'), - argv=[ - "-i", "some_instance", - "--base-uri", ref_path.parent.as_uri() + "/", - "some_schema", - ], - exit_code=1, - stdout="", - stderr="1: '1' is not of type 'integer'\n", - ) - - def test_nonexistent_file_with_explicit_base_uri(self): - schema = '{"$ref": "someNonexistentFile.json#definitions/num"}' - instance = "1" - - with self.assertRaises(RefResolutionError) as e: - self.assertOutputs( - files=dict( - some_schema=schema, - some_instance=instance, - ), - argv=[ - "-i", "some_instance", - "--base-uri", Path.cwd().as_uri(), - "some_schema", - ], - ) - error = str(e.exception) - self.assertIn(f"{os.sep}someNonexistentFile.json'", error) - - def test_invalid_exlicit_base_uri(self): - schema = '{"$ref": "foo.json#definitions/num"}' - instance = "1" - - with self.assertRaises(RefResolutionError) as e: - self.assertOutputs( - files=dict( - some_schema=schema, - some_instance=instance, - ), - argv=[ - "-i", "some_instance", - "--base-uri", "not@UR1", - "some_schema", - ], - ) - error = str(e.exception) - self.assertEqual( - error, "unknown url type: 'foo.json'", - ) - - def test_it_validates_using_the_latest_validator_when_unspecified(self): - # There isn't a better way now I can think of to ensure that the - # latest version was used, given that the call to validator_for - # is hidden inside the CLI, so guard that that's the case, and - # this test will have to be updated when versions change until - # we can think of a better way to ensure this behavior. - self.assertIs(Draft202012Validator, _LATEST_VERSION) - - self.assertOutputs( - files=dict(some_schema='{"const": "check"}', some_instance='"a"'), - argv=["-i", "some_instance", "some_schema"], - exit_code=1, - stdout="", - stderr="a: 'check' was expected\n", - ) - - def test_it_validates_using_draft7_when_specified(self): - """ - Specifically, `const` validation applies for Draft 7. - """ - schema = """ - { - "$schema": "http://json-schema.org/draft-07/schema#", - "const": "check" - } - """ - instance = '"foo"' - self.assertOutputs( - files=dict(some_schema=schema, some_instance=instance), - argv=["-i", "some_instance", "some_schema"], - exit_code=1, - stdout="", - stderr="foo: 'check' was expected\n", - ) - - def test_it_validates_using_draft4_when_specified(self): - """ - Specifically, `const` validation *does not* apply for Draft 4. - """ - schema = """ - { - "$schema": "http://json-schema.org/draft-04/schema#", - "const": "check" - } - """ - instance = '"foo"' - self.assertOutputs( - files=dict(some_schema=schema, some_instance=instance), - argv=["-i", "some_instance", "some_schema"], - stdout="", - stderr="", - ) - - -class TestParser(TestCase): - - FakeValidator = fake_validator() - - def test_find_validator_by_fully_qualified_object_name(self): - arguments = cli.parse_args( - [ - "--validator", - "jsonschema.tests.test_cli.TestParser.FakeValidator", - "--instance", "mem://some/instance", - "mem://some/schema", - ], - ) - self.assertIs(arguments["validator"], self.FakeValidator) - - def test_find_validator_in_jsonschema(self): - arguments = cli.parse_args( - [ - "--validator", "Draft4Validator", - "--instance", "mem://some/instance", - "mem://some/schema", - ], - ) - self.assertIs(arguments["validator"], Draft4Validator) - - def cli_output_for(self, *argv): - stdout, stderr = StringIO(), StringIO() - with redirect_stdout(stdout), redirect_stderr(stderr): - with self.assertRaises(SystemExit): - cli.parse_args(argv) - return stdout.getvalue(), stderr.getvalue() - - def test_unknown_output(self): - stdout, stderr = self.cli_output_for( - "--output", "foo", - "mem://some/schema", - ) - self.assertIn("invalid choice: 'foo'", stderr) - self.assertFalse(stdout) - - def test_useless_error_format(self): - stdout, stderr = self.cli_output_for( - "--output", "pretty", - "--error-format", "foo", - "mem://some/schema", - ) - self.assertIn( - "--error-format can only be used with --output plain", - stderr, - ) - self.assertFalse(stdout) - - -class TestCLIIntegration(TestCase): - def test_license(self): - output = subprocess.check_output( - [sys.executable, "-m", "pip", "show", "jsonschema"], - stderr=subprocess.STDOUT, - ) - self.assertIn(b"License: MIT", output) - - def test_version(self): - version = subprocess.check_output( - [sys.executable, "-m", "jsonschema", "--version"], - stderr=subprocess.STDOUT, - ) - version = version.decode("utf-8").strip() - self.assertEqual(version, metadata.version("jsonschema")) - - def test_no_arguments_shows_usage_notes(self): - output = subprocess.check_output( - [sys.executable, "-m", "jsonschema"], - stderr=subprocess.STDOUT, - ) - output_for_help = subprocess.check_output( - [sys.executable, "-m", "jsonschema", "--help"], - stderr=subprocess.STDOUT, - ) - self.assertEqual(output, output_for_help) diff --git a/jsonschema/tests/test_deprecations.py b/jsonschema/tests/test_deprecations.py deleted file mode 100644 index 58fd050..0000000 --- a/jsonschema/tests/test_deprecations.py +++ /dev/null @@ -1,123 +0,0 @@ -from unittest import TestCase - -from jsonschema import validators - - -class TestDeprecations(TestCase): - def test_version(self): - """ - As of v4.0.0, __version__ is deprecated in favor of importlib.metadata. - """ - - with self.assertWarns(DeprecationWarning) as w: - from jsonschema import __version__ # noqa - - self.assertEqual(w.filename, __file__) - self.assertTrue( - str(w.warning).startswith( - "Accessing jsonschema.__version__ is deprecated", - ), - ) - - def test_validators_ErrorTree(self): - """ - As of v4.0.0, importing ErrorTree from jsonschema.validators is - deprecated in favor of doing so from jsonschema.exceptions. - """ - - with self.assertWarns(DeprecationWarning) as w: - from jsonschema.validators import ErrorTree # noqa - - self.assertEqual(w.filename, __file__) - self.assertTrue( - str(w.warning).startswith( - "Importing ErrorTree from jsonschema.validators is deprecated", - ), - ) - - def test_validators_validators(self): - """ - As of v4.0.0, accessing jsonschema.validators.validators is - deprecated. - """ - - with self.assertWarns(DeprecationWarning) as w: - value = validators.validators - self.assertEqual(value, validators._VALIDATORS) - - self.assertEqual(w.filename, __file__) - self.assertTrue( - str(w.warning).startswith( - "Accessing jsonschema.validators.validators is deprecated", - ), - ) - - def test_validators_meta_schemas(self): - """ - As of v4.0.0, accessing jsonschema.validators.meta_schemas is - deprecated. - """ - - with self.assertWarns(DeprecationWarning) as w: - value = validators.meta_schemas - self.assertEqual(value, validators._META_SCHEMAS) - - self.assertEqual(w.filename, __file__) - self.assertTrue( - str(w.warning).startswith( - "Accessing jsonschema.validators.meta_schemas is deprecated", - ), - ) - - def test_RefResolver_in_scope(self): - """ - As of v4.0.0, RefResolver.in_scope is deprecated. - """ - - resolver = validators.RefResolver.from_schema({}) - with self.assertWarns(DeprecationWarning) as w: - with resolver.in_scope("foo"): - pass - - self.assertEqual(w.filename, __file__) - self.assertTrue( - str(w.warning).startswith( - "jsonschema.RefResolver.in_scope is deprecated ", - ), - ) - - def test_Validator_is_valid_two_arguments(self): - """ - As of v4.0.0, calling is_valid with two arguments (to provide a - different schema) is deprecated. - """ - - validator = validators.Draft7Validator({}) - with self.assertWarns(DeprecationWarning) as w: - result = validator.is_valid("foo", {"type": "number"}) - - self.assertFalse(result) - self.assertEqual(w.filename, __file__) - self.assertTrue( - str(w.warning).startswith( - "Passing a schema to Validator.is_valid is deprecated ", - ), - ) - - def test_Validator_iter_errors_two_arguments(self): - """ - As of v4.0.0, calling iter_errors with two arguments (to provide a - different schema) is deprecated. - """ - - validator = validators.Draft7Validator({}) - with self.assertWarns(DeprecationWarning) as w: - error, = validator.iter_errors("foo", {"type": "number"}) - - self.assertEqual(error.validator, "type") - self.assertEqual(w.filename, __file__) - self.assertTrue( - str(w.warning).startswith( - "Passing a schema to Validator.iter_errors is deprecated ", - ), - ) diff --git a/jsonschema/tests/test_exceptions.py b/jsonschema/tests/test_exceptions.py deleted file mode 100644 index c565daa..0000000 --- a/jsonschema/tests/test_exceptions.py +++ /dev/null @@ -1,588 +0,0 @@ -from unittest import TestCase -import textwrap - -from jsonschema import exceptions -from jsonschema.validators import _LATEST_VERSION - - -class TestBestMatch(TestCase): - def best_match_of(self, instance, schema): - errors = list(_LATEST_VERSION(schema).iter_errors(instance)) - best = exceptions.best_match(iter(errors)) - reversed_best = exceptions.best_match(reversed(errors)) - self.assertEqual( - best._contents(), - reversed_best._contents(), - f"No consistent best match!\nGot: {best}\n\nThen: {reversed_best}", - ) - return best - - def test_shallower_errors_are_better_matches(self): - schema = { - "properties": { - "foo": { - "minProperties": 2, - "properties": {"bar": {"type": "object"}}, - }, - }, - } - best = self.best_match_of(instance={"foo": {"bar": []}}, schema=schema) - self.assertEqual(best.validator, "minProperties") - - def test_oneOf_and_anyOf_are_weak_matches(self): - """ - A property you *must* match is probably better than one you have to - match a part of. - """ - - schema = { - "minProperties": 2, - "anyOf": [{"type": "string"}, {"type": "number"}], - "oneOf": [{"type": "string"}, {"type": "number"}], - } - best = self.best_match_of(instance={}, schema=schema) - self.assertEqual(best.validator, "minProperties") - - def test_if_the_most_relevant_error_is_anyOf_it_is_traversed(self): - """ - If the most relevant error is an anyOf, then we traverse its context - and select the otherwise *least* relevant error, since in this case - that means the most specific, deep, error inside the instance. - - I.e. since only one of the schemas must match, we look for the most - relevant one. - """ - - schema = { - "properties": { - "foo": { - "anyOf": [ - {"type": "string"}, - {"properties": {"bar": {"type": "array"}}}, - ], - }, - }, - } - best = self.best_match_of(instance={"foo": {"bar": 12}}, schema=schema) - self.assertEqual(best.validator_value, "array") - - def test_no_anyOf_traversal_for_equally_relevant_errors(self): - """ - We don't traverse into an anyOf (as above) if all of its context errors - seem to be equally "wrong" against the instance. - """ - - schema = { - "anyOf": [ - {"type": "string"}, - {"type": "integer"}, - {"type": "object"}, - ], - } - best = self.best_match_of(instance=[], schema=schema) - self.assertEqual(best.validator, "anyOf") - - def test_anyOf_traversal_for_single_equally_relevant_error(self): - """ - We *do* traverse anyOf with a single nested error, even though it is - vacuously equally relevant to itself. - """ - - schema = { - "anyOf": [ - {"type": "string"}, - ], - } - best = self.best_match_of(instance=[], schema=schema) - self.assertEqual(best.validator, "type") - - def test_if_the_most_relevant_error_is_oneOf_it_is_traversed(self): - """ - If the most relevant error is an oneOf, then we traverse its context - and select the otherwise *least* relevant error, since in this case - that means the most specific, deep, error inside the instance. - - I.e. since only one of the schemas must match, we look for the most - relevant one. - """ - - schema = { - "properties": { - "foo": { - "oneOf": [ - {"type": "string"}, - {"properties": {"bar": {"type": "array"}}}, - ], - }, - }, - } - best = self.best_match_of(instance={"foo": {"bar": 12}}, schema=schema) - self.assertEqual(best.validator_value, "array") - - def test_no_oneOf_traversal_for_equally_relevant_errors(self): - """ - We don't traverse into an oneOf (as above) if all of its context errors - seem to be equally "wrong" against the instance. - """ - - schema = { - "oneOf": [ - {"type": "string"}, - {"type": "integer"}, - {"type": "object"}, - ], - } - best = self.best_match_of(instance=[], schema=schema) - self.assertEqual(best.validator, "oneOf") - - def test_oneOf_traversal_for_single_equally_relevant_error(self): - """ - We *do* traverse oneOf with a single nested error, even though it is - vacuously equally relevant to itself. - """ - - schema = { - "oneOf": [ - {"type": "string"}, - ], - } - best = self.best_match_of(instance=[], schema=schema) - self.assertEqual(best.validator, "type") - - def test_if_the_most_relevant_error_is_allOf_it_is_traversed(self): - """ - Now, if the error is allOf, we traverse but select the *most* relevant - error from the context, because all schemas here must match anyways. - """ - - schema = { - "properties": { - "foo": { - "allOf": [ - {"type": "string"}, - {"properties": {"bar": {"type": "array"}}}, - ], - }, - }, - } - best = self.best_match_of(instance={"foo": {"bar": 12}}, schema=schema) - self.assertEqual(best.validator_value, "string") - - def test_nested_context_for_oneOf(self): - """ - We traverse into nested contexts (a oneOf containing an error in a - nested oneOf here). - """ - - schema = { - "properties": { - "foo": { - "oneOf": [ - {"type": "string"}, - { - "oneOf": [ - {"type": "string"}, - { - "properties": { - "bar": {"type": "array"}, - }, - }, - ], - }, - ], - }, - }, - } - best = self.best_match_of(instance={"foo": {"bar": 12}}, schema=schema) - self.assertEqual(best.validator_value, "array") - - def test_it_prioritizes_matching_types(self): - schema = { - "properties": { - "foo": { - "anyOf": [ - {"type": "array", "minItems": 2}, - {"type": "string", "minLength": 10}, - ], - }, - }, - } - best = self.best_match_of(instance={"foo": "bar"}, schema=schema) - self.assertEqual(best.validator, "minLength") - - reordered = { - "properties": { - "foo": { - "anyOf": [ - {"type": "string", "minLength": 10}, - {"type": "array", "minItems": 2}, - ], - }, - }, - } - best = self.best_match_of(instance={"foo": "bar"}, schema=reordered) - self.assertEqual(best.validator, "minLength") - - def test_it_prioritizes_matching_union_types(self): - schema = { - "properties": { - "foo": { - "anyOf": [ - {"type": ["array", "object"], "minItems": 2}, - {"type": ["integer", "string"], "minLength": 10}, - ], - }, - }, - } - best = self.best_match_of(instance={"foo": "bar"}, schema=schema) - self.assertEqual(best.validator, "minLength") - - reordered = { - "properties": { - "foo": { - "anyOf": [ - {"type": "string", "minLength": 10}, - {"type": "array", "minItems": 2}, - ], - }, - }, - } - best = self.best_match_of(instance={"foo": "bar"}, schema=reordered) - self.assertEqual(best.validator, "minLength") - - def test_boolean_schemas(self): - schema = {"properties": {"foo": False}} - best = self.best_match_of(instance={"foo": "bar"}, schema=schema) - self.assertIsNone(best.validator) - - def test_one_error(self): - validator = _LATEST_VERSION({"minProperties": 2}) - error, = validator.iter_errors({}) - self.assertEqual( - exceptions.best_match(validator.iter_errors({})).validator, - "minProperties", - ) - - def test_no_errors(self): - validator = _LATEST_VERSION({}) - self.assertIsNone(exceptions.best_match(validator.iter_errors({}))) - - -class TestByRelevance(TestCase): - def test_short_paths_are_better_matches(self): - shallow = exceptions.ValidationError("Oh no!", path=["baz"]) - deep = exceptions.ValidationError("Oh yes!", path=["foo", "bar"]) - match = max([shallow, deep], key=exceptions.relevance) - self.assertIs(match, shallow) - - match = max([deep, shallow], key=exceptions.relevance) - self.assertIs(match, shallow) - - def test_global_errors_are_even_better_matches(self): - shallow = exceptions.ValidationError("Oh no!", path=[]) - deep = exceptions.ValidationError("Oh yes!", path=["foo"]) - - errors = sorted([shallow, deep], key=exceptions.relevance) - self.assertEqual( - [list(error.path) for error in errors], - [["foo"], []], - ) - - errors = sorted([deep, shallow], key=exceptions.relevance) - self.assertEqual( - [list(error.path) for error in errors], - [["foo"], []], - ) - - def test_weak_validators_are_lower_priority(self): - weak = exceptions.ValidationError("Oh no!", path=[], validator="a") - normal = exceptions.ValidationError("Oh yes!", path=[], validator="b") - - best_match = exceptions.by_relevance(weak="a") - - match = max([weak, normal], key=best_match) - self.assertIs(match, normal) - - match = max([normal, weak], key=best_match) - self.assertIs(match, normal) - - def test_strong_validators_are_higher_priority(self): - weak = exceptions.ValidationError("Oh no!", path=[], validator="a") - normal = exceptions.ValidationError("Oh yes!", path=[], validator="b") - strong = exceptions.ValidationError("Oh fine!", path=[], validator="c") - - best_match = exceptions.by_relevance(weak="a", strong="c") - - match = max([weak, normal, strong], key=best_match) - self.assertIs(match, strong) - - match = max([strong, normal, weak], key=best_match) - self.assertIs(match, strong) - - -class TestErrorTree(TestCase): - def test_it_knows_how_many_total_errors_it_contains(self): - # FIXME: #442 - errors = [ - exceptions.ValidationError("Something", validator=i) - for i in range(8) - ] - tree = exceptions.ErrorTree(errors) - self.assertEqual(tree.total_errors, 8) - - def test_it_contains_an_item_if_the_item_had_an_error(self): - errors = [exceptions.ValidationError("a message", path=["bar"])] - tree = exceptions.ErrorTree(errors) - self.assertIn("bar", tree) - - def test_it_does_not_contain_an_item_if_the_item_had_no_error(self): - errors = [exceptions.ValidationError("a message", path=["bar"])] - tree = exceptions.ErrorTree(errors) - self.assertNotIn("foo", tree) - - def test_validators_that_failed_appear_in_errors_dict(self): - error = exceptions.ValidationError("a message", validator="foo") - tree = exceptions.ErrorTree([error]) - self.assertEqual(tree.errors, {"foo": error}) - - def test_it_creates_a_child_tree_for_each_nested_path(self): - errors = [ - exceptions.ValidationError("a bar message", path=["bar"]), - exceptions.ValidationError("a bar -> 0 message", path=["bar", 0]), - ] - tree = exceptions.ErrorTree(errors) - self.assertIn(0, tree["bar"]) - self.assertNotIn(1, tree["bar"]) - - def test_children_have_their_errors_dicts_built(self): - e1, e2 = ( - exceptions.ValidationError("1", validator="foo", path=["bar", 0]), - exceptions.ValidationError("2", validator="quux", path=["bar", 0]), - ) - tree = exceptions.ErrorTree([e1, e2]) - self.assertEqual(tree["bar"][0].errors, {"foo": e1, "quux": e2}) - - def test_multiple_errors_with_instance(self): - e1, e2 = ( - exceptions.ValidationError( - "1", - validator="foo", - path=["bar", "bar2"], - instance="i1"), - exceptions.ValidationError( - "2", - validator="quux", - path=["foobar", 2], - instance="i2"), - ) - exceptions.ErrorTree([e1, e2]) - - def test_it_does_not_contain_subtrees_that_are_not_in_the_instance(self): - error = exceptions.ValidationError("123", validator="foo", instance=[]) - tree = exceptions.ErrorTree([error]) - - with self.assertRaises(IndexError): - tree[0] - - def test_if_its_in_the_tree_anyhow_it_does_not_raise_an_error(self): - """ - If a validator is dumb (like :validator:`required` in draft 3) and - refers to a path that isn't in the instance, the tree still properly - returns a subtree for that path. - """ - - error = exceptions.ValidationError( - "a message", validator="foo", instance={}, path=["foo"], - ) - tree = exceptions.ErrorTree([error]) - self.assertIsInstance(tree["foo"], exceptions.ErrorTree) - - def test_repr(self): - e1, e2 = ( - exceptions.ValidationError( - "1", - validator="foo", - path=["bar", "bar2"], - instance="i1"), - exceptions.ValidationError( - "2", - validator="quux", - path=["foobar", 2], - instance="i2"), - ) - tree = exceptions.ErrorTree([e1, e2]) - self.assertEqual(repr(tree), "<ErrorTree (2 total errors)>") - - -class TestErrorInitReprStr(TestCase): - def make_error(self, **kwargs): - defaults = dict( - message="hello", - validator="type", - validator_value="string", - instance=5, - schema={"type": "string"}, - ) - defaults.update(kwargs) - return exceptions.ValidationError(**defaults) - - def assertShows(self, expected, **kwargs): - expected = textwrap.dedent(expected).rstrip("\n") - - error = self.make_error(**kwargs) - message_line, _, rest = str(error).partition("\n") - self.assertEqual(message_line, error.message) - self.assertEqual(rest, expected) - - def test_it_calls_super_and_sets_args(self): - error = self.make_error() - self.assertGreater(len(error.args), 1) - - def test_repr(self): - self.assertEqual( - repr(exceptions.ValidationError(message="Hello!")), - "<ValidationError: 'Hello!'>", - ) - - def test_unset_error(self): - error = exceptions.ValidationError("message") - self.assertEqual(str(error), "message") - - kwargs = { - "validator": "type", - "validator_value": "string", - "instance": 5, - "schema": {"type": "string"}, - } - # Just the message should show if any of the attributes are unset - for attr in kwargs: - k = dict(kwargs) - del k[attr] - error = exceptions.ValidationError("message", **k) - self.assertEqual(str(error), "message") - - def test_empty_paths(self): - self.assertShows( - """ - Failed validating 'type' in schema: - {'type': 'string'} - - On instance: - 5 - """, - path=[], - schema_path=[], - ) - - def test_one_item_paths(self): - self.assertShows( - """ - Failed validating 'type' in schema: - {'type': 'string'} - - On instance[0]: - 5 - """, - path=[0], - schema_path=["items"], - ) - - def test_multiple_item_paths(self): - self.assertShows( - """ - Failed validating 'type' in schema['items'][0]: - {'type': 'string'} - - On instance[0]['a']: - 5 - """, - path=[0, "a"], - schema_path=["items", 0, 1], - ) - - def test_uses_pprint(self): - self.assertShows( - """ - Failed validating 'maxLength' in schema: - {0: 0, - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - 10: 10, - 11: 11, - 12: 12, - 13: 13, - 14: 14, - 15: 15, - 16: 16, - 17: 17, - 18: 18, - 19: 19} - - On instance: - [0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24] - """, - instance=list(range(25)), - schema=dict(zip(range(20), range(20))), - validator="maxLength", - ) - - def test_str_works_with_instances_having_overriden_eq_operator(self): - """ - Check for #164 which rendered exceptions unusable when a - `ValidationError` involved instances with an `__eq__` method - that returned truthy values. - """ - - class DontEQMeBro(object): - def __eq__(this, other): # pragma: no cover - self.fail("Don't!") - - def __ne__(this, other): # pragma: no cover - self.fail("Don't!") - - instance = DontEQMeBro() - error = exceptions.ValidationError( - "a message", - validator="foo", - instance=instance, - validator_value="some", - schema="schema", - ) - self.assertIn(repr(instance), str(error)) - - -class TestHashable(TestCase): - def test_hashable(self): - set([exceptions.ValidationError("")]) - set([exceptions.SchemaError("")]) diff --git a/jsonschema/tests/test_format.py b/jsonschema/tests/test_format.py deleted file mode 100644 index 1846cb2..0000000 --- a/jsonschema/tests/test_format.py +++ /dev/null @@ -1,107 +0,0 @@ -""" -Tests for the parts of jsonschema related to the :validator:`format` property. -""" - -from unittest import TestCase - -from jsonschema import FormatChecker, FormatError, ValidationError -from jsonschema.validators import Draft4Validator - -BOOM = ValueError("Boom!") -BANG = ZeroDivisionError("Bang!") - - -def boom(thing): - if thing == "bang": - raise BANG - raise BOOM - - -class TestFormatChecker(TestCase): - def test_it_can_validate_no_formats(self): - checker = FormatChecker(formats=()) - self.assertFalse(checker.checkers) - - def test_it_raises_a_key_error_for_unknown_formats(self): - with self.assertRaises(KeyError): - FormatChecker(formats=["o noes"]) - - def test_it_can_register_cls_checkers(self): - original = dict(FormatChecker.checkers) - self.addCleanup(FormatChecker.checkers.pop, "boom") - FormatChecker.cls_checks("boom")(boom) - self.assertEqual( - FormatChecker.checkers, - dict(original, boom=(boom, ())), - ) - - def test_it_can_register_checkers(self): - checker = FormatChecker() - checker.checks("boom")(boom) - self.assertEqual( - checker.checkers, - dict(FormatChecker.checkers, boom=(boom, ())), - ) - - def test_it_catches_registered_errors(self): - checker = FormatChecker() - checker.checks("boom", raises=type(BOOM))(boom) - - with self.assertRaises(FormatError) as cm: - checker.check(instance=12, format="boom") - - self.assertIs(cm.exception.cause, BOOM) - self.assertIs(cm.exception.__cause__, BOOM) - - # Unregistered errors should not be caught - with self.assertRaises(type(BANG)): - checker.check(instance="bang", format="boom") - - def test_format_error_causes_become_validation_error_causes(self): - checker = FormatChecker() - checker.checks("boom", raises=ValueError)(boom) - validator = Draft4Validator({"format": "boom"}, format_checker=checker) - - with self.assertRaises(ValidationError) as cm: - validator.validate("BOOM") - - self.assertIs(cm.exception.cause, BOOM) - self.assertIs(cm.exception.__cause__, BOOM) - - def test_format_checkers_come_with_defaults(self): - # This is bad :/ but relied upon. - # The docs for quite awhile recommended people do things like - # validate(..., format_checker=FormatChecker()) - # We should change that, but we can't without deprecation... - checker = FormatChecker() - with self.assertRaises(FormatError): - checker.check(instance="not-an-ipv4", format="ipv4") - - def test_repr(self): - checker = FormatChecker(formats=()) - checker.checks("foo")(lambda thing: True) # pragma: no cover - checker.checks("bar")(lambda thing: True) # pragma: no cover - checker.checks("baz")(lambda thing: True) # pragma: no cover - self.assertEqual( - repr(checker), - "<FormatChecker checkers=['bar', 'baz', 'foo']>", - ) - - def test_duration_format(self): - try: - from jsonschema._format import is_duration # noqa: F401 - except ImportError: # pragma: no cover - pass - else: - checker = FormatChecker() - self.assertTrue(checker.conforms(1, "duration")) - self.assertTrue(checker.conforms("P4Y", "duration")) - self.assertFalse(checker.conforms("test", "duration")) - - def test_uuid_format(self): - checker = FormatChecker() - self.assertTrue(checker.conforms(1, "uuid")) - self.assertTrue( - checker.conforms("6e6659ec-4503-4428-9f03-2e2ea4d6c278", "uuid"), - ) - self.assertFalse(checker.conforms("test", "uuid")) diff --git a/jsonschema/tests/test_jsonschema_test_suite.py b/jsonschema/tests/test_jsonschema_test_suite.py deleted file mode 100644 index 96a6c80..0000000 --- a/jsonschema/tests/test_jsonschema_test_suite.py +++ /dev/null @@ -1,446 +0,0 @@ -""" -Test runner for the JSON Schema official test suite - -Tests comprehensive correctness of each draft's validator. - -See https://github.com/json-schema-org/JSON-Schema-Test-Suite for details. -""" - -import sys - -from jsonschema.tests._helpers import bug -from jsonschema.tests._suite import Suite -import jsonschema - -SUITE = Suite() -DRAFT3 = SUITE.version(name="draft3") -DRAFT4 = SUITE.version(name="draft4") -DRAFT6 = SUITE.version(name="draft6") -DRAFT7 = SUITE.version(name="draft7") -DRAFT201909 = SUITE.version(name="draft2019-09") -DRAFT202012 = SUITE.version(name="draft2020-12") - - -def skip(message, **kwargs): - def skipper(test): - if all(value == getattr(test, attr) for attr, value in kwargs.items()): - return message - return skipper - - -def missing_format(checker): - def missing_format(test): # pragma: no cover - schema = test.schema - if ( - schema is True - or schema is False - or "format" not in schema - or schema["format"] in checker.checkers - or test.valid - ): - return - - return "Format checker {0!r} not found.".format(schema["format"]) - return missing_format - - -def complex_email_validation(test): - if test.subject != "email": - return - - message = "Complex email validation is (intentionally) unsupported." - return skip( - message=message, - description="an invalid domain", - )(test) or skip( - message=message, - description="an invalid IPv4-address-literal", - )(test) or skip( - message=message, - description="dot after local part is not valid", - )(test) or skip( - message=message, - description="dot before local part is not valid", - )(test) or skip( - message=message, - description="two subsequent dots inside local part are not valid", - )(test) - - -is_narrow_build = sys.maxunicode == 2 ** 16 - 1 -if is_narrow_build: # pragma: no cover - message = "Not running surrogate Unicode case, this Python is narrow." - - def narrow_unicode_build(test): # pragma: no cover - return skip( - message=message, - description=( - "one supplementary Unicode code point is not long enough" - ), - )(test) or skip( - message=message, - description="two supplementary Unicode code points is long enough", - )(test) -else: - def narrow_unicode_build(test): # pragma: no cover - return - - -if sys.version_info < (3, 9): # pragma: no cover - message = "Rejecting leading zeros is 3.9+" - allowed_leading_zeros = skip( - message=message, - subject="ipv4", - description=( - "leading zeroes should be rejected, as they are treated as octals" - ), - ) -else: - def allowed_leading_zeros(test): # pragma: no cover - return - - -def leap_second(test): - message = "Leap seconds are unsupported." - return skip( - message=message, - subject="time", - description="a valid time string with leap second", - )(test) or skip( - message=message, - subject="time", - description="a valid time string with leap second, Zulu", - )(test) or skip( - message=message, - subject="time", - description="a valid time string with leap second with offset", - )(test) or skip( - message=message, - subject="time", - description="valid leap second, positive time-offset", - )(test) or skip( - message=message, - subject="time", - description="valid leap second, negative time-offset", - )(test) or skip( - message=message, - subject="time", - description="valid leap second, large positive time-offset", - )(test) or skip( - message=message, - subject="time", - description="valid leap second, large negative time-offset", - )(test) or skip( - message=message, - subject="time", - description="valid leap second, zero time-offset", - )(test) or skip( - message=message, - subject="date-time", - description="a valid date-time with a leap second, UTC", - )(test) or skip( - message=message, - subject="date-time", - description="a valid date-time with a leap second, with minus offset", - )(test) - - -TestDraft3 = DRAFT3.to_unittest_testcase( - DRAFT3.tests(), - DRAFT3.format_tests(), - DRAFT3.optional_tests_of(name="bignum"), - DRAFT3.optional_tests_of(name="non-bmp-regex"), - DRAFT3.optional_tests_of(name="zeroTerminatedFloats"), - Validator=jsonschema.Draft3Validator, - format_checker=jsonschema.draft3_format_checker, - skip=lambda test: ( - narrow_unicode_build(test) - or missing_format(jsonschema.draft3_format_checker)(test) - or complex_email_validation(test) - or skip( - message=bug(371), - subject="ref", - case_description=( - "$ref prevents a sibling id from changing the base uri" - ), - )(test) - ), -) - - -TestDraft4 = DRAFT4.to_unittest_testcase( - DRAFT4.tests(), - DRAFT4.format_tests(), - DRAFT4.optional_tests_of(name="bignum"), - DRAFT4.optional_tests_of(name="float-overflow"), - DRAFT4.optional_tests_of(name="non-bmp-regex"), - DRAFT4.optional_tests_of(name="zeroTerminatedFloats"), - Validator=jsonschema.Draft4Validator, - format_checker=jsonschema.draft4_format_checker, - skip=lambda test: ( - narrow_unicode_build(test) - or allowed_leading_zeros(test) - or leap_second(test) - or missing_format(jsonschema.draft4_format_checker)(test) - or complex_email_validation(test) - or skip( - message=bug(), - subject="ref", - case_description="Recursive references between schemas", - )(test) - or skip( - message=bug(371), - subject="ref", - case_description=( - "Location-independent identifier with " - "base URI change in subschema" - ), - )(test) - or skip( - message=bug(371), - subject="ref", - case_description=( - "$ref prevents a sibling id from changing the base uri" - ), - )(test) - or skip( - message=bug(371), - subject="id", - description="match $ref to id", - )(test) - or skip( - message=bug(371), - subject="id", - description="no match on enum or $ref to id", - )(test) - or skip( - message=bug(), - subject="refRemote", - case_description="base URI change - change folder in subschema", - )(test) - or skip( - message=bug(), - subject="ref", - case_description=( - "id must be resolved against nearest parent, " - "not just immediate parent" - ), - )(test) - ), -) - - -TestDraft6 = DRAFT6.to_unittest_testcase( - DRAFT6.tests(), - DRAFT6.format_tests(), - DRAFT6.optional_tests_of(name="bignum"), - DRAFT6.optional_tests_of(name="float-overflow"), - DRAFT6.optional_tests_of(name="non-bmp-regex"), - Validator=jsonschema.Draft6Validator, - format_checker=jsonschema.draft6_format_checker, - skip=lambda test: ( - narrow_unicode_build(test) - or allowed_leading_zeros(test) - or leap_second(test) - or missing_format(jsonschema.draft6_format_checker)(test) - or complex_email_validation(test) - or skip( - message="id is incorrectly finding non-ids", - subject="id", - description="const at const_not_anchor does not match", - )(test) - or skip( - message="id is incorrectly finding non-ids", - subject="id", - description="const at const_not_id does not match", - )(test) - or skip( - message=bug(), - subject="refRemote", - case_description="base URI change - change folder in subschema", - )(test) - or skip( - message=bug(371), - subject="ref", - case_description=( - "$ref prevents a sibling $id from changing the base uri" - ), - )(test) - ), -) - - -TestDraft7 = DRAFT7.to_unittest_testcase( - DRAFT7.tests(), - DRAFT7.format_tests(), - DRAFT7.optional_tests_of(name="bignum"), - DRAFT7.optional_tests_of(name="content"), - DRAFT7.optional_tests_of(name="float-overflow"), - DRAFT7.optional_tests_of(name="non-bmp-regex"), - Validator=jsonschema.Draft7Validator, - format_checker=jsonschema.draft7_format_checker, - skip=lambda test: ( - narrow_unicode_build(test) - or allowed_leading_zeros(test) - or leap_second(test) - or missing_format(jsonschema.draft7_format_checker)(test) - or complex_email_validation(test) - or skip( - message=bug(), - subject="refRemote", - case_description="base URI change - change folder in subschema", - )(test) - or skip( - message=bug(371), - subject="ref", - case_description=( - "$ref prevents a sibling $id from changing the base uri" - ), - )(test) - or skip( - message=bug(), - subject="ref", - case_description=( - "$id must be resolved against nearest parent, " - "not just immediate parent" - ), - )(test) - or skip( - message=bug(593), - subject="content", - valid=False, - case_description=( - "validation of string-encoded content based on media type" - ), - )(test) - or skip( - message=bug(593), - subject="content", - valid=False, - case_description="validation of binary string-encoding", - )(test) - or skip( - message=bug(593), - subject="content", - valid=False, - case_description=( - "validation of binary-encoded media type documents" - ), - )(test) - ), -) - - -TestDraft201909 = DRAFT201909.to_unittest_testcase( - DRAFT201909.tests(), - DRAFT201909.optional_tests_of(name="bignum"), - DRAFT201909.optional_tests_of(name="float-overflow"), - DRAFT201909.optional_tests_of(name="non-bmp-regex"), - DRAFT201909.optional_tests_of(name="refOfUnknownKeyword"), - Validator=jsonschema.Draft201909Validator, - skip=lambda test: ( - skip( - message="unevaluatedItems is different in 2019-09 (needs work).", - subject="unevaluatedItems", - )(test) - or skip( - message="dynamicRef support isn't working yet.", - subject="recursiveRef", - )(test) - or skip( - message="These tests depends on dynamicRef working.", - subject="id", - case_description=( - "Invalid use of fragments in location-independent $id" - ), - )(test) - or skip( - message="These tests depends on dynamicRef working.", - subject="defs", - description="invalid definition schema", - )(test) - or skip( - message="These tests depends on dynamicRef working.", - subject="anchor", - case_description="same $anchor with different base uri", - )(test) - or skip( - message="Vocabulary support is not yet present.", - subject="vocabulary", - )(test) - or skip( - message=bug(), - subject="ref", - case_description=( - "$id must be resolved against nearest parent, " - "not just immediate parent" - ), - )(test) - ), -) - - -TestDraft201909Format = DRAFT201909.to_unittest_testcase( - DRAFT201909.format_tests(), - Validator=jsonschema.Draft201909Validator, - format_checker=jsonschema.draft201909_format_checker, - skip=lambda test: ( - complex_email_validation(test) - or allowed_leading_zeros(test) - or leap_second(test) - or missing_format(jsonschema.draft201909_format_checker)(test) - or complex_email_validation(test) - ), -) - - -TestDraft202012 = DRAFT202012.to_unittest_testcase( - DRAFT202012.tests(), - DRAFT202012.optional_tests_of(name="bignum"), - DRAFT202012.optional_tests_of(name="float-overflow"), - DRAFT202012.optional_tests_of(name="non-bmp-regex"), - DRAFT202012.optional_tests_of(name="refOfUnknownKeyword"), - Validator=jsonschema.Draft202012Validator, - skip=lambda test: ( - narrow_unicode_build(test) - or skip( - message="dynamicRef support isn't working yet.", - subject="dynamicRef", - )(test) - or skip( - message="These tests depends on dynamicRef working.", - subject="defs", - )(test) - or skip( - message="These tests depends on dynamicRef working.", - subject="anchor", - case_description="same $anchor with different base uri", - )(test) - or skip( - message="Vocabulary support is not yet present.", - subject="vocabulary", - )(test) - or skip( - message=bug(), - subject="ref", - case_description=( - "$id must be resolved against nearest parent, " - "not just immediate parent" - ), - )(test) - ), -) - - -TestDraft202012Format = DRAFT202012.to_unittest_testcase( - DRAFT202012.format_tests(), - Validator=jsonschema.Draft202012Validator, - format_checker=jsonschema.draft202012_format_checker, - skip=lambda test: ( - complex_email_validation(test) - or allowed_leading_zeros(test) - or leap_second(test) - or missing_format(jsonschema.draft202012_format_checker)(test) - or complex_email_validation(test) - ), -) diff --git a/jsonschema/tests/test_types.py b/jsonschema/tests/test_types.py deleted file mode 100644 index 3fd1a70..0000000 --- a/jsonschema/tests/test_types.py +++ /dev/null @@ -1,217 +0,0 @@ -""" -Tests for the `TypeChecker`-based type interface. - -The actual correctness of the type checking is handled in -`test_jsonschema_test_suite`; these tests check that TypeChecker -functions correctly at a more granular level. -""" -from collections import namedtuple -from unittest import TestCase - -from jsonschema import ValidationError, _validators -from jsonschema._types import TypeChecker -from jsonschema.exceptions import UndefinedTypeCheck, UnknownType -from jsonschema.validators import Draft202012Validator, extend - - -def equals_2(checker, instance): - return instance == 2 - - -def is_namedtuple(instance): - return isinstance(instance, tuple) and getattr(instance, "_fields", None) - - -def is_object_or_named_tuple(checker, instance): - if Draft202012Validator.TYPE_CHECKER.is_type(instance, "object"): - return True - return is_namedtuple(instance) - - -class TestTypeChecker(TestCase): - def test_is_type(self): - checker = TypeChecker({"two": equals_2}) - self.assertEqual( - ( - checker.is_type(instance=2, type="two"), - checker.is_type(instance="bar", type="two"), - ), - (True, False), - ) - - def test_is_unknown_type(self): - with self.assertRaises(UndefinedTypeCheck) as e: - TypeChecker().is_type(4, "foobar") - self.assertIn( - "'foobar' is unknown to this type checker", - str(e.exception), - ) - self.assertTrue( - e.exception.__suppress_context__, - msg="Expected the internal KeyError to be hidden.", - ) - - def test_checks_can_be_added_at_init(self): - checker = TypeChecker({"two": equals_2}) - self.assertEqual(checker, TypeChecker().redefine("two", equals_2)) - - def test_redefine_existing_type(self): - self.assertEqual( - TypeChecker().redefine("two", object()).redefine("two", equals_2), - TypeChecker().redefine("two", equals_2), - ) - - def test_remove(self): - self.assertEqual( - TypeChecker({"two": equals_2}).remove("two"), - TypeChecker(), - ) - - def test_remove_unknown_type(self): - with self.assertRaises(UndefinedTypeCheck) as context: - TypeChecker().remove("foobar") - self.assertIn("foobar", str(context.exception)) - - def test_redefine_many(self): - self.assertEqual( - TypeChecker().redefine_many({"foo": int, "bar": str}), - TypeChecker().redefine("foo", int).redefine("bar", str), - ) - - def test_remove_multiple(self): - self.assertEqual( - TypeChecker({"foo": int, "bar": str}).remove("foo", "bar"), - TypeChecker(), - ) - - def test_type_check_can_raise_key_error(self): - """ - Make sure no one writes: - - try: - self._type_checkers[type](...) - except KeyError: - - ignoring the fact that the function itself can raise that. - """ - - error = KeyError("Stuff") - - def raises_keyerror(checker, instance): - raise error - - with self.assertRaises(KeyError) as context: - TypeChecker({"foo": raises_keyerror}).is_type(4, "foo") - - self.assertIs(context.exception, error) - - -class TestCustomTypes(TestCase): - def test_simple_type_can_be_extended(self): - def int_or_str_int(checker, instance): - if not isinstance(instance, (int, str)): - return False - try: - int(instance) - except ValueError: - return False - return True - - CustomValidator = extend( - Draft202012Validator, - type_checker=Draft202012Validator.TYPE_CHECKER.redefine( - "integer", int_or_str_int, - ), - ) - validator = CustomValidator({"type": "integer"}) - - validator.validate(4) - validator.validate("4") - - with self.assertRaises(ValidationError): - validator.validate(4.4) - - with self.assertRaises(ValidationError): - validator.validate("foo") - - def test_object_can_be_extended(self): - schema = {"type": "object"} - - Point = namedtuple("Point", ["x", "y"]) - - type_checker = Draft202012Validator.TYPE_CHECKER.redefine( - "object", is_object_or_named_tuple, - ) - - CustomValidator = extend( - Draft202012Validator, - type_checker=type_checker, - ) - validator = CustomValidator(schema) - - validator.validate(Point(x=4, y=5)) - - def test_object_extensions_require_custom_validators(self): - schema = {"type": "object", "required": ["x"]} - - type_checker = Draft202012Validator.TYPE_CHECKER.redefine( - "object", is_object_or_named_tuple, - ) - - CustomValidator = extend( - Draft202012Validator, - type_checker=type_checker, - ) - validator = CustomValidator(schema) - - Point = namedtuple("Point", ["x", "y"]) - # Cannot handle required - with self.assertRaises(ValidationError): - validator.validate(Point(x=4, y=5)) - - def test_object_extensions_can_handle_custom_validators(self): - schema = { - "type": "object", - "required": ["x"], - "properties": {"x": {"type": "integer"}}, - } - - type_checker = Draft202012Validator.TYPE_CHECKER.redefine( - "object", is_object_or_named_tuple, - ) - - def coerce_named_tuple(fn): - def coerced(validator, value, instance, schema): - if is_namedtuple(instance): - instance = instance._asdict() - return fn(validator, value, instance, schema) - return coerced - - required = coerce_named_tuple(_validators.required) - properties = coerce_named_tuple(_validators.properties) - - CustomValidator = extend( - Draft202012Validator, - type_checker=type_checker, - validators={"required": required, "properties": properties}, - ) - - validator = CustomValidator(schema) - - Point = namedtuple("Point", ["x", "y"]) - # Can now process required and properties - validator.validate(Point(x=4, y=5)) - - with self.assertRaises(ValidationError): - validator.validate(Point(x="not an integer", y=5)) - - # As well as still handle objects. - validator.validate({"x": 4, "y": 5}) - - with self.assertRaises(ValidationError): - validator.validate({"x": "not an integer", "y": 5}) - - def test_unknown_type(self): - with self.assertRaises(UnknownType) as e: - Draft202012Validator({}).is_type(12, "some unknown type") - self.assertIn("'some unknown type'", str(e.exception)) diff --git a/jsonschema/tests/test_utils.py b/jsonschema/tests/test_utils.py deleted file mode 100644 index 4e542b9..0000000 --- a/jsonschema/tests/test_utils.py +++ /dev/null @@ -1,124 +0,0 @@ -from unittest import TestCase - -from jsonschema._utils import equal - - -class TestEqual(TestCase): - def test_none(self): - self.assertTrue(equal(None, None)) - - -class TestDictEqual(TestCase): - def test_equal_dictionaries(self): - dict_1 = {"a": "b", "c": "d"} - dict_2 = {"c": "d", "a": "b"} - self.assertTrue(equal(dict_1, dict_2)) - - def test_missing_key(self): - dict_1 = {"a": "b", "c": "d"} - dict_2 = {"c": "d", "x": "b"} - self.assertFalse(equal(dict_1, dict_2)) - - def test_additional_key(self): - dict_1 = {"a": "b", "c": "d"} - dict_2 = {"c": "d", "a": "b", "x": "x"} - self.assertFalse(equal(dict_1, dict_2)) - - def test_missing_value(self): - dict_1 = {"a": "b", "c": "d"} - dict_2 = {"c": "d", "a": "x"} - self.assertFalse(equal(dict_1, dict_2)) - - def test_empty_dictionaries(self): - dict_1 = {} - dict_2 = {} - self.assertTrue(equal(dict_1, dict_2)) - - def test_one_none(self): - dict_1 = None - dict_2 = {"a": "b", "c": "d"} - self.assertFalse(equal(dict_1, dict_2)) - - def test_same_item(self): - dict_1 = {"a": "b", "c": "d"} - self.assertTrue(equal(dict_1, dict_1)) - - def test_nested_equal(self): - dict_1 = {"a": {"a": "b", "c": "d"}, "c": "d"} - dict_2 = {"c": "d", "a": {"a": "b", "c": "d"}} - self.assertTrue(equal(dict_1, dict_2)) - - def test_nested_dict_unequal(self): - dict_1 = {"a": {"a": "b", "c": "d"}, "c": "d"} - dict_2 = {"c": "d", "a": {"a": "b", "c": "x"}} - self.assertFalse(equal(dict_1, dict_2)) - - def test_mixed_nested_equal(self): - dict_1 = {"a": ["a", "b", "c", "d"], "c": "d"} - dict_2 = {"c": "d", "a": ["a", "b", "c", "d"]} - self.assertTrue(equal(dict_1, dict_2)) - - def test_nested_list_unequal(self): - dict_1 = {"a": ["a", "b", "c", "d"], "c": "d"} - dict_2 = {"c": "d", "a": ["b", "c", "d", "a"]} - self.assertFalse(equal(dict_1, dict_2)) - - -class TestListEqual(TestCase): - def test_equal_lists(self): - list_1 = ["a", "b", "c"] - list_2 = ["a", "b", "c"] - self.assertTrue(equal(list_1, list_2)) - - def test_unsorted_lists(self): - list_1 = ["a", "b", "c"] - list_2 = ["b", "b", "a"] - self.assertFalse(equal(list_1, list_2)) - - def test_first_list_larger(self): - list_1 = ["a", "b", "c"] - list_2 = ["a", "b"] - self.assertFalse(equal(list_1, list_2)) - - def test_second_list_larger(self): - list_1 = ["a", "b"] - list_2 = ["a", "b", "c"] - self.assertFalse(equal(list_1, list_2)) - - def test_list_with_none_unequal(self): - list_1 = ["a", "b", None] - list_2 = ["a", "b", "c"] - self.assertFalse(equal(list_1, list_2)) - - list_1 = ["a", "b", None] - list_2 = [None, "b", "c"] - self.assertFalse(equal(list_1, list_2)) - - def test_list_with_none_equal(self): - list_1 = ["a", None, "c"] - list_2 = ["a", None, "c"] - self.assertTrue(equal(list_1, list_2)) - - def test_empty_list(self): - list_1 = [] - list_2 = [] - self.assertTrue(equal(list_1, list_2)) - - def test_one_none(self): - list_1 = None - list_2 = [] - self.assertFalse(equal(list_1, list_2)) - - def test_same_list(self): - list_1 = ["a", "b", "c"] - self.assertTrue(equal(list_1, list_1)) - - def test_equal_nested_lists(self): - list_1 = ["a", ["b", "c"], "d"] - list_2 = ["a", ["b", "c"], "d"] - self.assertTrue(equal(list_1, list_2)) - - def test_unequal_nested_lists(self): - list_1 = ["a", ["b", "c"], "d"] - list_2 = ["a", [], "c"] - self.assertFalse(equal(list_1, list_2)) diff --git a/jsonschema/tests/test_validators.py b/jsonschema/tests/test_validators.py deleted file mode 100644 index 16fa9ec..0000000 --- a/jsonschema/tests/test_validators.py +++ /dev/null @@ -1,2183 +0,0 @@ -from __future__ import annotations - -from collections import deque, namedtuple -from contextlib import contextmanager -from decimal import Decimal -from io import BytesIO -from unittest import TestCase, mock -from urllib.request import pathname2url -import json -import os -import sys -import tempfile -import unittest -import warnings - -import attr - -from jsonschema import ( - FormatChecker, - TypeChecker, - exceptions, - protocols, - validators, -) -from jsonschema.tests._helpers import bug - - -def fail(validator, errors, instance, schema): - for each in errors: - each.setdefault("message", "You told me to fail!") - yield exceptions.ValidationError(**each) - - -class TestCreateAndExtend(TestCase): - def setUp(self): - self.addCleanup( - self.assertEqual, - validators._META_SCHEMAS, - dict(validators._META_SCHEMAS), - ) - - self.meta_schema = {"$id": "some://meta/schema"} - self.validators = {"fail": fail} - self.type_checker = TypeChecker() - self.Validator = validators.create( - meta_schema=self.meta_schema, - validators=self.validators, - type_checker=self.type_checker, - ) - - def test_attrs(self): - self.assertEqual( - ( - self.Validator.VALIDATORS, - self.Validator.META_SCHEMA, - self.Validator.TYPE_CHECKER, - ), ( - self.validators, - self.meta_schema, - self.type_checker, - ), - ) - - def test_init(self): - schema = {"fail": []} - self.assertEqual(self.Validator(schema).schema, schema) - - def test_iter_errors_successful(self): - schema = {"fail": []} - validator = self.Validator(schema) - - errors = list(validator.iter_errors("hello")) - self.assertEqual(errors, []) - - def test_iter_errors_one_error(self): - schema = {"fail": [{"message": "Whoops!"}]} - validator = self.Validator(schema) - - expected_error = exceptions.ValidationError( - "Whoops!", - instance="goodbye", - schema=schema, - validator="fail", - validator_value=[{"message": "Whoops!"}], - schema_path=deque(["fail"]), - ) - - errors = list(validator.iter_errors("goodbye")) - self.assertEqual(len(errors), 1) - self.assertEqual(errors[0]._contents(), expected_error._contents()) - - def test_iter_errors_multiple_errors(self): - schema = { - "fail": [ - {"message": "First"}, - {"message": "Second!", "validator": "asdf"}, - {"message": "Third"}, - ], - } - validator = self.Validator(schema) - - errors = list(validator.iter_errors("goodbye")) - self.assertEqual(len(errors), 3) - - def test_if_a_version_is_provided_it_is_registered(self): - Validator = validators.create( - meta_schema={"$id": "something"}, - version="my version", - ) - self.addCleanup(validators._META_SCHEMAS.pop, "something") - self.assertEqual(Validator.__name__, "MyVersionValidator") - self.assertEqual(Validator.__qualname__, "MyVersionValidator") - - def test_repr(self): - Validator = validators.create( - meta_schema={"$id": "something"}, - version="my version", - ) - self.addCleanup(validators._META_SCHEMAS.pop, "something") - self.assertEqual( - repr(Validator({})), - "MyVersionValidator(schema={}, format_checker=None)", - ) - - def test_long_repr(self): - Validator = validators.create( - meta_schema={"$id": "something"}, - version="my version", - ) - self.addCleanup(validators._META_SCHEMAS.pop, "something") - self.assertEqual( - repr(Validator({"a": list(range(1000))})), ( - "MyVersionValidator(schema={'a': [0, 1, 2, 3, 4, 5, ...]}, " - "format_checker=None)" - ), - ) - - def test_repr_no_version(self): - Validator = validators.create(meta_schema={}) - self.assertEqual( - repr(Validator({})), - "Validator(schema={}, format_checker=None)", - ) - - def test_dashes_are_stripped_from_validator_names(self): - Validator = validators.create( - meta_schema={"$id": "something"}, - version="foo-bar", - ) - self.addCleanup(validators._META_SCHEMAS.pop, "something") - self.assertEqual(Validator.__qualname__, "FooBarValidator") - - def test_if_a_version_is_not_provided_it_is_not_registered(self): - original = dict(validators._META_SCHEMAS) - validators.create(meta_schema={"id": "id"}) - self.assertEqual(validators._META_SCHEMAS, original) - - def test_validates_registers_meta_schema_id(self): - meta_schema_key = "meta schema id" - my_meta_schema = {"id": meta_schema_key} - - validators.create( - meta_schema=my_meta_schema, - version="my version", - id_of=lambda s: s.get("id", ""), - ) - self.addCleanup(validators._META_SCHEMAS.pop, meta_schema_key) - - self.assertIn(meta_schema_key, validators._META_SCHEMAS) - - def test_validates_registers_meta_schema_draft6_id(self): - meta_schema_key = "meta schema $id" - my_meta_schema = {"$id": meta_schema_key} - - validators.create( - meta_schema=my_meta_schema, - version="my version", - ) - self.addCleanup(validators._META_SCHEMAS.pop, meta_schema_key) - - self.assertIn(meta_schema_key, validators._META_SCHEMAS) - - def test_create_default_types(self): - Validator = validators.create(meta_schema={}, validators=()) - self.assertTrue( - all( - Validator({}).is_type(instance=instance, type=type) - for type, instance in [ - ("array", []), - ("boolean", True), - ("integer", 12), - ("null", None), - ("number", 12.0), - ("object", {}), - ("string", "foo"), - ] - ), - ) - - def test_extend(self): - original = dict(self.Validator.VALIDATORS) - new = object() - - Extended = validators.extend( - self.Validator, - validators={"new": new}, - ) - self.assertEqual( - ( - Extended.VALIDATORS, - Extended.META_SCHEMA, - Extended.TYPE_CHECKER, - self.Validator.VALIDATORS, - ), ( - dict(original, new=new), - self.Validator.META_SCHEMA, - self.Validator.TYPE_CHECKER, - original, - ), - ) - - def test_extend_idof(self): - """ - Extending a validator preserves its notion of schema IDs. - """ - def id_of(schema): - return schema.get("__test__", self.Validator.ID_OF(schema)) - correct_id = "the://correct/id/" - meta_schema = { - "$id": "the://wrong/id/", - "__test__": correct_id, - } - Original = validators.create( - meta_schema=meta_schema, - validators=self.validators, - type_checker=self.type_checker, - id_of=id_of, - ) - self.assertEqual(Original.ID_OF(Original.META_SCHEMA), correct_id) - - Derived = validators.extend(Original) - self.assertEqual(Derived.ID_OF(Derived.META_SCHEMA), correct_id) - - -class TestValidationErrorMessages(TestCase): - def message_for(self, instance, schema, *args, **kwargs): - cls = kwargs.pop("cls", validators._LATEST_VERSION) - cls.check_schema(schema) - validator = cls(schema, *args, **kwargs) - errors = list(validator.iter_errors(instance)) - self.assertTrue(errors, msg=f"No errors were raised for {instance!r}") - self.assertEqual( - len(errors), - 1, - msg=f"Expected exactly one error, found {errors!r}", - ) - return errors[0].message - - def test_single_type_failure(self): - message = self.message_for(instance=1, schema={"type": "string"}) - self.assertEqual(message, "1 is not of type 'string'") - - def test_single_type_list_failure(self): - message = self.message_for(instance=1, schema={"type": ["string"]}) - self.assertEqual(message, "1 is not of type 'string'") - - def test_multiple_type_failure(self): - types = "string", "object" - message = self.message_for(instance=1, schema={"type": list(types)}) - self.assertEqual(message, "1 is not of type 'string', 'object'") - - def test_object_without_title_type_failure(self): - type = {"type": [{"minimum": 3}]} - message = self.message_for( - instance=1, - schema={"type": [type]}, - cls=validators.Draft3Validator, - ) - self.assertEqual( - message, - "1 is not of type {'type': [{'minimum': 3}]}", - ) - - def test_object_with_named_type_failure(self): - schema = {"type": [{"name": "Foo", "minimum": 3}]} - message = self.message_for( - instance=1, - schema=schema, - cls=validators.Draft3Validator, - ) - self.assertEqual(message, "1 is not of type 'Foo'") - - def test_minimum(self): - message = self.message_for(instance=1, schema={"minimum": 2}) - self.assertEqual(message, "1 is less than the minimum of 2") - - def test_maximum(self): - message = self.message_for(instance=1, schema={"maximum": 0}) - self.assertEqual(message, "1 is greater than the maximum of 0") - - def test_dependencies_single_element(self): - depend, on = "bar", "foo" - schema = {"dependencies": {depend: on}} - message = self.message_for( - instance={"bar": 2}, - schema=schema, - cls=validators.Draft3Validator, - ) - self.assertEqual(message, "'foo' is a dependency of 'bar'") - - def test_dependencies_list_draft3(self): - depend, on = "bar", "foo" - schema = {"dependencies": {depend: [on]}} - message = self.message_for( - instance={"bar": 2}, - schema=schema, - cls=validators.Draft3Validator, - ) - self.assertEqual(message, "'foo' is a dependency of 'bar'") - - def test_dependencies_list_draft7(self): - depend, on = "bar", "foo" - schema = {"dependencies": {depend: [on]}} - message = self.message_for( - instance={"bar": 2}, - schema=schema, - cls=validators.Draft7Validator, - ) - self.assertEqual(message, "'foo' is a dependency of 'bar'") - - def test_additionalItems_single_failure(self): - message = self.message_for( - instance=[2], - schema={"items": [], "additionalItems": False}, - cls=validators.Draft3Validator, - ) - self.assertIn("(2 was unexpected)", message) - - def test_additionalItems_multiple_failures(self): - message = self.message_for( - instance=[1, 2, 3], - schema={"items": [], "additionalItems": False}, - cls=validators.Draft3Validator, - ) - self.assertIn("(1, 2, 3 were unexpected)", message) - - def test_additionalProperties_single_failure(self): - additional = "foo" - schema = {"additionalProperties": False} - message = self.message_for(instance={additional: 2}, schema=schema) - self.assertIn("('foo' was unexpected)", message) - - def test_additionalProperties_multiple_failures(self): - schema = {"additionalProperties": False} - message = self.message_for( - instance=dict.fromkeys(["foo", "bar"]), - schema=schema, - ) - - self.assertIn(repr("foo"), message) - self.assertIn(repr("bar"), message) - self.assertIn("were unexpected)", message) - - def test_const(self): - schema = {"const": 12} - message = self.message_for( - instance={"foo": "bar"}, - schema=schema, - ) - self.assertIn("12 was expected", message) - - def test_contains_draft_6(self): - schema = {"contains": {"const": 12}} - message = self.message_for( - instance=[2, {}, []], - schema=schema, - cls=validators.Draft6Validator, - ) - self.assertEqual( - message, - "None of [2, {}, []] are valid under the given schema", - ) - - def test_invalid_format_default_message(self): - checker = FormatChecker(formats=()) - checker.checks("thing")(lambda value: False) - - schema = {"format": "thing"} - message = self.message_for( - instance="bla", - schema=schema, - format_checker=checker, - ) - - self.assertIn(repr("bla"), message) - self.assertIn(repr("thing"), message) - self.assertIn("is not a", message) - - def test_additionalProperties_false_patternProperties(self): - schema = {"type": "object", - "additionalProperties": False, - "patternProperties": { - "^abc$": {"type": "string"}, - "^def$": {"type": "string"}, - }} - message = self.message_for( - instance={"zebra": 123}, - schema=schema, - cls=validators.Draft4Validator, - ) - self.assertEqual( - message, - "{} does not match any of the regexes: {}, {}".format( - repr("zebra"), repr("^abc$"), repr("^def$"), - ), - ) - message = self.message_for( - instance={"zebra": 123, "fish": 456}, - schema=schema, - cls=validators.Draft4Validator, - ) - self.assertEqual( - message, - "{}, {} do not match any of the regexes: {}, {}".format( - repr("fish"), repr("zebra"), repr("^abc$"), repr("^def$"), - ), - ) - - def test_False_schema(self): - message = self.message_for( - instance="something", - schema=False, - ) - self.assertEqual(message, "False schema does not allow 'something'") - - def test_multipleOf(self): - message = self.message_for( - instance=3, - schema={"multipleOf": 2}, - ) - self.assertEqual(message, "3 is not a multiple of 2") - - def test_minItems(self): - message = self.message_for(instance=[], schema={"minItems": 2}) - self.assertEqual(message, "[] is too short") - - def test_maxItems(self): - message = self.message_for(instance=[1, 2, 3], schema={"maxItems": 2}) - self.assertEqual(message, "[1, 2, 3] is too long") - - def test_prefixItems_with_items(self): - message = self.message_for( - instance=[1, 2, "foo", 5], - schema={"items": False, "prefixItems": [{}, {}]}, - ) - self.assertEqual(message, "Expected at most 2 items, but found 4") - - def test_minLength(self): - message = self.message_for( - instance="", - schema={"minLength": 2}, - ) - self.assertEqual(message, "'' is too short") - - def test_maxLength(self): - message = self.message_for( - instance="abc", - schema={"maxLength": 2}, - ) - self.assertEqual(message, "'abc' is too long") - - def test_pattern(self): - message = self.message_for( - instance="bbb", - schema={"pattern": "^a*$"}, - ) - self.assertEqual(message, "'bbb' does not match '^a*$'") - - def test_does_not_contain(self): - message = self.message_for( - instance=[], - schema={"contains": {"type": "string"}}, - ) - self.assertEqual( - message, - "[] does not contain items matching the given schema", - ) - - def test_contains_too_few(self): - message = self.message_for( - instance=["foo", 1], - schema={"contains": {"type": "string"}, "minContains": 2}, - ) - self.assertEqual( - message, - "Too few items match the given schema " - "(expected at least 2 but only 1 matched)", - ) - - def test_contains_too_few_both_constrained(self): - message = self.message_for( - instance=["foo", 1], - schema={ - "contains": {"type": "string"}, - "minContains": 2, - "maxContains": 4, - }, - ) - self.assertEqual( - message, - "Too few items match the given schema (expected at least 2 but " - "only 1 matched)", - ) - - def test_contains_too_many(self): - message = self.message_for( - instance=["foo", "bar", "baz"], - schema={"contains": {"type": "string"}, "maxContains": 2}, - ) - self.assertEqual( - message, - "Too many items match the given schema (expected at most 2)", - ) - - def test_contains_too_many_both_constrained(self): - message = self.message_for( - instance=["foo"] * 5, - schema={ - "contains": {"type": "string"}, - "minContains": 2, - "maxContains": 4, - }, - ) - self.assertEqual( - message, - "Too many items match the given schema (expected at most 4)", - ) - - def test_exclusiveMinimum(self): - message = self.message_for( - instance=3, - schema={"exclusiveMinimum": 5}, - ) - self.assertEqual( - message, - "3 is less than or equal to the minimum of 5", - ) - - def test_exclusiveMaximum(self): - message = self.message_for(instance=3, schema={"exclusiveMaximum": 2}) - self.assertEqual( - message, - "3 is greater than or equal to the maximum of 2", - ) - - def test_required(self): - message = self.message_for(instance={}, schema={"required": ["foo"]}) - self.assertEqual(message, "'foo' is a required property") - - def test_dependentRequired(self): - message = self.message_for( - instance={"foo": {}}, - schema={"dependentRequired": {"foo": ["bar"]}}, - ) - self.assertEqual(message, "'bar' is a dependency of 'foo'") - - def test_minProperties(self): - message = self.message_for(instance={}, schema={"minProperties": 2}) - self.assertEqual(message, "{} does not have enough properties") - - def test_maxProperties(self): - message = self.message_for( - instance={"a": {}, "b": {}, "c": {}}, - schema={"maxProperties": 2}, - ) - self.assertEqual( - message, - "{'a': {}, 'b': {}, 'c': {}} has too many properties", - ) - - def test_oneOf_matches_none(self): - message = self.message_for(instance={}, schema={"oneOf": [False]}) - self.assertEqual( - message, - "{} is not valid under any of the given schemas", - ) - - def test_oneOf_matches_too_many(self): - message = self.message_for(instance={}, schema={"oneOf": [True, True]}) - self.assertEqual(message, "{} is valid under each of True, True") - - def test_unevaluated_items(self): - schema = {"type": "array", "unevaluatedItems": False} - message = self.message_for(instance=["foo", "bar"], schema=schema) - self.assertIn( - message, - "Unevaluated items are not allowed ('bar', 'foo' were unexpected)", - ) - - def test_unevaluated_items_on_invalid_type(self): - schema = {"type": "array", "unevaluatedItems": False} - message = self.message_for(instance="foo", schema=schema) - self.assertEqual(message, "'foo' is not of type 'array'") - - def test_unevaluated_properties(self): - schema = {"type": "object", "unevaluatedProperties": False} - message = self.message_for( - instance={ - "foo": "foo", - "bar": "bar", - }, - schema=schema, - ) - self.assertEqual( - message, - "Unevaluated properties are not allowed " - "('bar', 'foo' were unexpected)", - ) - - def test_unevaluated_properties_on_invalid_type(self): - schema = {"type": "object", "unevaluatedProperties": False} - message = self.message_for(instance="foo", schema=schema) - self.assertEqual(message, "'foo' is not of type 'object'") - - -class TestValidationErrorDetails(TestCase): - # TODO: These really need unit tests for each individual validator, rather - # than just these higher level tests. - def test_anyOf(self): - instance = 5 - schema = { - "anyOf": [ - {"minimum": 20}, - {"type": "string"}, - ], - } - - validator = validators.Draft4Validator(schema) - errors = list(validator.iter_errors(instance)) - self.assertEqual(len(errors), 1) - e = errors[0] - - self.assertEqual(e.validator, "anyOf") - self.assertEqual(e.validator_value, schema["anyOf"]) - self.assertEqual(e.instance, instance) - self.assertEqual(e.schema, schema) - self.assertIsNone(e.parent) - - self.assertEqual(e.path, deque([])) - self.assertEqual(e.relative_path, deque([])) - self.assertEqual(e.absolute_path, deque([])) - self.assertEqual(e.json_path, "$") - - self.assertEqual(e.schema_path, deque(["anyOf"])) - self.assertEqual(e.relative_schema_path, deque(["anyOf"])) - self.assertEqual(e.absolute_schema_path, deque(["anyOf"])) - - self.assertEqual(len(e.context), 2) - - e1, e2 = sorted_errors(e.context) - - self.assertEqual(e1.validator, "minimum") - self.assertEqual(e1.validator_value, schema["anyOf"][0]["minimum"]) - self.assertEqual(e1.instance, instance) - self.assertEqual(e1.schema, schema["anyOf"][0]) - self.assertIs(e1.parent, e) - - self.assertEqual(e1.path, deque([])) - self.assertEqual(e1.absolute_path, deque([])) - self.assertEqual(e1.relative_path, deque([])) - self.assertEqual(e1.json_path, "$") - - self.assertEqual(e1.schema_path, deque([0, "minimum"])) - self.assertEqual(e1.relative_schema_path, deque([0, "minimum"])) - self.assertEqual( - e1.absolute_schema_path, deque(["anyOf", 0, "minimum"]), - ) - - self.assertFalse(e1.context) - - self.assertEqual(e2.validator, "type") - self.assertEqual(e2.validator_value, schema["anyOf"][1]["type"]) - self.assertEqual(e2.instance, instance) - self.assertEqual(e2.schema, schema["anyOf"][1]) - self.assertIs(e2.parent, e) - - self.assertEqual(e2.path, deque([])) - self.assertEqual(e2.relative_path, deque([])) - self.assertEqual(e2.absolute_path, deque([])) - self.assertEqual(e2.json_path, "$") - - self.assertEqual(e2.schema_path, deque([1, "type"])) - self.assertEqual(e2.relative_schema_path, deque([1, "type"])) - self.assertEqual(e2.absolute_schema_path, deque(["anyOf", 1, "type"])) - - self.assertEqual(len(e2.context), 0) - - def test_type(self): - instance = {"foo": 1} - schema = { - "type": [ - {"type": "integer"}, - { - "type": "object", - "properties": {"foo": {"enum": [2]}}, - }, - ], - } - - validator = validators.Draft3Validator(schema) - errors = list(validator.iter_errors(instance)) - self.assertEqual(len(errors), 1) - e = errors[0] - - self.assertEqual(e.validator, "type") - self.assertEqual(e.validator_value, schema["type"]) - self.assertEqual(e.instance, instance) - self.assertEqual(e.schema, schema) - self.assertIsNone(e.parent) - - self.assertEqual(e.path, deque([])) - self.assertEqual(e.relative_path, deque([])) - self.assertEqual(e.absolute_path, deque([])) - self.assertEqual(e.json_path, "$") - - self.assertEqual(e.schema_path, deque(["type"])) - self.assertEqual(e.relative_schema_path, deque(["type"])) - self.assertEqual(e.absolute_schema_path, deque(["type"])) - - self.assertEqual(len(e.context), 2) - - e1, e2 = sorted_errors(e.context) - - self.assertEqual(e1.validator, "type") - self.assertEqual(e1.validator_value, schema["type"][0]["type"]) - self.assertEqual(e1.instance, instance) - self.assertEqual(e1.schema, schema["type"][0]) - self.assertIs(e1.parent, e) - - self.assertEqual(e1.path, deque([])) - self.assertEqual(e1.relative_path, deque([])) - self.assertEqual(e1.absolute_path, deque([])) - self.assertEqual(e1.json_path, "$") - - self.assertEqual(e1.schema_path, deque([0, "type"])) - self.assertEqual(e1.relative_schema_path, deque([0, "type"])) - self.assertEqual(e1.absolute_schema_path, deque(["type", 0, "type"])) - - self.assertFalse(e1.context) - - self.assertEqual(e2.validator, "enum") - self.assertEqual(e2.validator_value, [2]) - self.assertEqual(e2.instance, 1) - self.assertEqual(e2.schema, {"enum": [2]}) - self.assertIs(e2.parent, e) - - self.assertEqual(e2.path, deque(["foo"])) - self.assertEqual(e2.relative_path, deque(["foo"])) - self.assertEqual(e2.absolute_path, deque(["foo"])) - self.assertEqual(e2.json_path, "$.foo") - - self.assertEqual( - e2.schema_path, deque([1, "properties", "foo", "enum"]), - ) - self.assertEqual( - e2.relative_schema_path, deque([1, "properties", "foo", "enum"]), - ) - self.assertEqual( - e2.absolute_schema_path, - deque(["type", 1, "properties", "foo", "enum"]), - ) - - self.assertFalse(e2.context) - - def test_single_nesting(self): - instance = {"foo": 2, "bar": [1], "baz": 15, "quux": "spam"} - schema = { - "properties": { - "foo": {"type": "string"}, - "bar": {"minItems": 2}, - "baz": {"maximum": 10, "enum": [2, 4, 6, 8]}, - }, - } - - validator = validators.Draft3Validator(schema) - errors = validator.iter_errors(instance) - e1, e2, e3, e4 = sorted_errors(errors) - - self.assertEqual(e1.path, deque(["bar"])) - self.assertEqual(e2.path, deque(["baz"])) - self.assertEqual(e3.path, deque(["baz"])) - self.assertEqual(e4.path, deque(["foo"])) - - self.assertEqual(e1.relative_path, deque(["bar"])) - self.assertEqual(e2.relative_path, deque(["baz"])) - self.assertEqual(e3.relative_path, deque(["baz"])) - self.assertEqual(e4.relative_path, deque(["foo"])) - - self.assertEqual(e1.absolute_path, deque(["bar"])) - self.assertEqual(e2.absolute_path, deque(["baz"])) - self.assertEqual(e3.absolute_path, deque(["baz"])) - self.assertEqual(e4.absolute_path, deque(["foo"])) - - self.assertEqual(e1.json_path, "$.bar") - self.assertEqual(e2.json_path, "$.baz") - self.assertEqual(e3.json_path, "$.baz") - self.assertEqual(e4.json_path, "$.foo") - - self.assertEqual(e1.validator, "minItems") - self.assertEqual(e2.validator, "enum") - self.assertEqual(e3.validator, "maximum") - self.assertEqual(e4.validator, "type") - - def test_multiple_nesting(self): - instance = [1, {"foo": 2, "bar": {"baz": [1]}}, "quux"] - schema = { - "type": "string", - "items": { - "type": ["string", "object"], - "properties": { - "foo": {"enum": [1, 3]}, - "bar": { - "type": "array", - "properties": { - "bar": {"required": True}, - "baz": {"minItems": 2}, - }, - }, - }, - }, - } - - validator = validators.Draft3Validator(schema) - errors = validator.iter_errors(instance) - e1, e2, e3, e4, e5, e6 = sorted_errors(errors) - - self.assertEqual(e1.path, deque([])) - self.assertEqual(e2.path, deque([0])) - self.assertEqual(e3.path, deque([1, "bar"])) - self.assertEqual(e4.path, deque([1, "bar", "bar"])) - self.assertEqual(e5.path, deque([1, "bar", "baz"])) - self.assertEqual(e6.path, deque([1, "foo"])) - - self.assertEqual(e1.json_path, "$") - self.assertEqual(e2.json_path, "$[0]") - self.assertEqual(e3.json_path, "$[1].bar") - self.assertEqual(e4.json_path, "$[1].bar.bar") - self.assertEqual(e5.json_path, "$[1].bar.baz") - self.assertEqual(e6.json_path, "$[1].foo") - - self.assertEqual(e1.schema_path, deque(["type"])) - self.assertEqual(e2.schema_path, deque(["items", "type"])) - self.assertEqual( - list(e3.schema_path), ["items", "properties", "bar", "type"], - ) - self.assertEqual( - list(e4.schema_path), - ["items", "properties", "bar", "properties", "bar", "required"], - ) - self.assertEqual( - list(e5.schema_path), - ["items", "properties", "bar", "properties", "baz", "minItems"], - ) - self.assertEqual( - list(e6.schema_path), ["items", "properties", "foo", "enum"], - ) - - self.assertEqual(e1.validator, "type") - self.assertEqual(e2.validator, "type") - self.assertEqual(e3.validator, "type") - self.assertEqual(e4.validator, "required") - self.assertEqual(e5.validator, "minItems") - self.assertEqual(e6.validator, "enum") - - def test_recursive(self): - schema = { - "definitions": { - "node": { - "anyOf": [{ - "type": "object", - "required": ["name", "children"], - "properties": { - "name": { - "type": "string", - }, - "children": { - "type": "object", - "patternProperties": { - "^.*$": { - "$ref": "#/definitions/node", - }, - }, - }, - }, - }], - }, - }, - "type": "object", - "required": ["root"], - "properties": {"root": {"$ref": "#/definitions/node"}}, - } - - instance = { - "root": { - "name": "root", - "children": { - "a": { - "name": "a", - "children": { - "ab": { - "name": "ab", - # missing "children" - }, - }, - }, - }, - }, - } - validator = validators.Draft4Validator(schema) - - e, = validator.iter_errors(instance) - self.assertEqual(e.absolute_path, deque(["root"])) - self.assertEqual( - e.absolute_schema_path, deque(["properties", "root", "anyOf"]), - ) - self.assertEqual(e.json_path, "$.root") - - e1, = e.context - self.assertEqual(e1.absolute_path, deque(["root", "children", "a"])) - self.assertEqual( - e1.absolute_schema_path, deque( - [ - "properties", - "root", - "anyOf", - 0, - "properties", - "children", - "patternProperties", - "^.*$", - "anyOf", - ], - ), - ) - self.assertEqual(e1.json_path, "$.root.children.a") - - e2, = e1.context - self.assertEqual( - e2.absolute_path, deque( - ["root", "children", "a", "children", "ab"], - ), - ) - self.assertEqual( - e2.absolute_schema_path, deque( - [ - "properties", - "root", - "anyOf", - 0, - "properties", - "children", - "patternProperties", - "^.*$", - "anyOf", - 0, - "properties", - "children", - "patternProperties", - "^.*$", - "anyOf", - ], - ), - ) - self.assertEqual(e2.json_path, "$.root.children.a.children.ab") - - def test_additionalProperties(self): - instance = {"bar": "bar", "foo": 2} - schema = {"additionalProperties": {"type": "integer", "minimum": 5}} - - validator = validators.Draft3Validator(schema) - errors = validator.iter_errors(instance) - e1, e2 = sorted_errors(errors) - - self.assertEqual(e1.path, deque(["bar"])) - self.assertEqual(e2.path, deque(["foo"])) - - self.assertEqual(e1.json_path, "$.bar") - self.assertEqual(e2.json_path, "$.foo") - - self.assertEqual(e1.validator, "type") - self.assertEqual(e2.validator, "minimum") - - def test_patternProperties(self): - instance = {"bar": 1, "foo": 2} - schema = { - "patternProperties": { - "bar": {"type": "string"}, - "foo": {"minimum": 5}, - }, - } - - validator = validators.Draft3Validator(schema) - errors = validator.iter_errors(instance) - e1, e2 = sorted_errors(errors) - - self.assertEqual(e1.path, deque(["bar"])) - self.assertEqual(e2.path, deque(["foo"])) - - self.assertEqual(e1.json_path, "$.bar") - self.assertEqual(e2.json_path, "$.foo") - - self.assertEqual(e1.validator, "type") - self.assertEqual(e2.validator, "minimum") - - def test_additionalItems(self): - instance = ["foo", 1] - schema = { - "items": [], - "additionalItems": {"type": "integer", "minimum": 5}, - } - - validator = validators.Draft3Validator(schema) - errors = validator.iter_errors(instance) - e1, e2 = sorted_errors(errors) - - self.assertEqual(e1.path, deque([0])) - self.assertEqual(e2.path, deque([1])) - - self.assertEqual(e1.json_path, "$[0]") - self.assertEqual(e2.json_path, "$[1]") - - self.assertEqual(e1.validator, "type") - self.assertEqual(e2.validator, "minimum") - - def test_additionalItems_with_items(self): - instance = ["foo", "bar", 1] - schema = { - "items": [{}], - "additionalItems": {"type": "integer", "minimum": 5}, - } - - validator = validators.Draft3Validator(schema) - errors = validator.iter_errors(instance) - e1, e2 = sorted_errors(errors) - - self.assertEqual(e1.path, deque([1])) - self.assertEqual(e2.path, deque([2])) - - self.assertEqual(e1.json_path, "$[1]") - self.assertEqual(e2.json_path, "$[2]") - - self.assertEqual(e1.validator, "type") - self.assertEqual(e2.validator, "minimum") - - def test_propertyNames(self): - instance = {"foo": 12} - schema = {"propertyNames": {"not": {"const": "foo"}}} - - validator = validators.Draft7Validator(schema) - error, = validator.iter_errors(instance) - - self.assertEqual(error.validator, "not") - self.assertEqual( - error.message, - "'foo' should not be valid under {'const': 'foo'}", - ) - self.assertEqual(error.path, deque([])) - self.assertEqual(error.json_path, "$") - self.assertEqual(error.schema_path, deque(["propertyNames", "not"])) - - def test_if_then(self): - schema = { - "if": {"const": 12}, - "then": {"const": 13}, - } - - validator = validators.Draft7Validator(schema) - error, = validator.iter_errors(12) - - self.assertEqual(error.validator, "const") - self.assertEqual(error.message, "13 was expected") - self.assertEqual(error.path, deque([])) - self.assertEqual(error.json_path, "$") - self.assertEqual(error.schema_path, deque(["then", "const"])) - - def test_if_else(self): - schema = { - "if": {"const": 12}, - "else": {"const": 13}, - } - - validator = validators.Draft7Validator(schema) - error, = validator.iter_errors(15) - - self.assertEqual(error.validator, "const") - self.assertEqual(error.message, "13 was expected") - self.assertEqual(error.path, deque([])) - self.assertEqual(error.json_path, "$") - self.assertEqual(error.schema_path, deque(["else", "const"])) - - def test_boolean_schema_False(self): - validator = validators.Draft7Validator(False) - error, = validator.iter_errors(12) - - self.assertEqual( - ( - error.message, - error.validator, - error.validator_value, - error.instance, - error.schema, - error.schema_path, - error.json_path, - ), - ( - "False schema does not allow 12", - None, - None, - 12, - False, - deque([]), - "$", - ), - ) - - def test_ref(self): - ref, schema = "someRef", {"additionalProperties": {"type": "integer"}} - validator = validators.Draft7Validator( - {"$ref": ref}, - resolver=validators.RefResolver("", {}, store={ref: schema}), - ) - error, = validator.iter_errors({"foo": "notAnInteger"}) - - self.assertEqual( - ( - error.message, - error.validator, - error.validator_value, - error.instance, - error.absolute_path, - error.schema, - error.schema_path, - error.json_path, - ), - ( - "'notAnInteger' is not of type 'integer'", - "type", - "integer", - "notAnInteger", - deque(["foo"]), - {"type": "integer"}, - deque(["additionalProperties", "type"]), - "$.foo", - ), - ) - - def test_prefixItems(self): - schema = {"prefixItems": [{"type": "string"}, {}, {}, {"maximum": 3}]} - validator = validators.Draft202012Validator(schema) - type_error, min_error = validator.iter_errors([1, 2, "foo", 5]) - self.assertEqual( - ( - type_error.message, - type_error.validator, - type_error.validator_value, - type_error.instance, - type_error.absolute_path, - type_error.schema, - type_error.schema_path, - type_error.json_path, - ), - ( - "1 is not of type 'string'", - "type", - "string", - 1, - deque([0]), - {"type": "string"}, - deque(["prefixItems", 0, "type"]), - "$[0]", - ), - ) - self.assertEqual( - ( - min_error.message, - min_error.validator, - min_error.validator_value, - min_error.instance, - min_error.absolute_path, - min_error.schema, - min_error.schema_path, - min_error.json_path, - ), - ( - "5 is greater than the maximum of 3", - "maximum", - 3, - 5, - deque([3]), - {"maximum": 3}, - deque(["prefixItems", 3, "maximum"]), - "$[3]", - ), - ) - - def test_prefixItems_with_items(self): - schema = { - "items": {"type": "string"}, - "prefixItems": [{}], - } - validator = validators.Draft202012Validator(schema) - e1, e2 = validator.iter_errors(["foo", 2, "bar", 4, "baz"]) - self.assertEqual( - ( - e1.message, - e1.validator, - e1.validator_value, - e1.instance, - e1.absolute_path, - e1.schema, - e1.schema_path, - e1.json_path, - ), - ( - "2 is not of type 'string'", - "type", - "string", - 2, - deque([1]), - {"type": "string"}, - deque(["items", "type"]), - "$[1]", - ), - ) - self.assertEqual( - ( - e2.message, - e2.validator, - e2.validator_value, - e2.instance, - e2.absolute_path, - e2.schema, - e2.schema_path, - e2.json_path, - ), - ( - "4 is not of type 'string'", - "type", - "string", - 4, - deque([3]), - {"type": "string"}, - deque(["items", "type"]), - "$[3]", - ), - ) - - def test_contains_too_many(self): - """ - `contains` + `maxContains` produces only one error, even if there are - many more incorrectly matching elements. - """ - schema = {"contains": {"type": "string"}, "maxContains": 2} - validator = validators.Draft202012Validator(schema) - error, = validator.iter_errors(["foo", 2, "bar", 4, "baz", "quux"]) - self.assertEqual( - ( - error.message, - error.validator, - error.validator_value, - error.instance, - error.absolute_path, - error.schema, - error.schema_path, - error.json_path, - ), - ( - "Too many items match the given schema (expected at most 2)", - "maxContains", - 2, - ["foo", 2, "bar", 4, "baz", "quux"], - deque([]), - {"contains": {"type": "string"}, "maxContains": 2}, - deque(["contains"]), - "$", - ), - ) - - def test_contains_too_few(self): - schema = {"contains": {"type": "string"}, "minContains": 2} - validator = validators.Draft202012Validator(schema) - error, = validator.iter_errors(["foo", 2, 4]) - self.assertEqual( - ( - error.message, - error.validator, - error.validator_value, - error.instance, - error.absolute_path, - error.schema, - error.schema_path, - error.json_path, - ), - ( - ( - "Too few items match the given schema " - "(expected at least 2 but only 1 matched)" - ), - "minContains", - 2, - ["foo", 2, 4], - deque([]), - {"contains": {"type": "string"}, "minContains": 2}, - deque(["contains"]), - "$", - ), - ) - - def test_contains_none(self): - schema = {"contains": {"type": "string"}, "minContains": 2} - validator = validators.Draft202012Validator(schema) - error, = validator.iter_errors([2, 4]) - self.assertEqual( - ( - error.message, - error.validator, - error.validator_value, - error.instance, - error.absolute_path, - error.schema, - error.schema_path, - error.json_path, - ), - ( - "[2, 4] does not contain items matching the given schema", - "contains", - {"type": "string"}, - [2, 4], - deque([]), - {"contains": {"type": "string"}, "minContains": 2}, - deque(["contains"]), - "$", - ), - ) - - def test_ref_sibling(self): - schema = { - "$defs": {"foo": {"required": ["bar"]}}, - "properties": { - "aprop": { - "$ref": "#/$defs/foo", - "required": ["baz"], - }, - }, - } - - validator = validators.Draft202012Validator(schema) - e1, e2 = validator.iter_errors({"aprop": {}}) - self.assertEqual( - ( - e1.message, - e1.validator, - e1.validator_value, - e1.instance, - e1.absolute_path, - e1.schema, - e1.schema_path, - e1.relative_schema_path, - e1.json_path, - ), - ( - "'bar' is a required property", - "required", - ["bar"], - {}, - deque(["aprop"]), - {"required": ["bar"]}, - deque(["properties", "aprop", "required"]), - deque(["properties", "aprop", "required"]), - "$.aprop", - ), - ) - self.assertEqual( - ( - e2.message, - e2.validator, - e2.validator_value, - e2.instance, - e2.absolute_path, - e2.schema, - e2.schema_path, - e2.relative_schema_path, - e2.json_path, - ), - ( - "'baz' is a required property", - "required", - ["baz"], - {}, - deque(["aprop"]), - {"$ref": "#/$defs/foo", "required": ["baz"]}, - deque(["properties", "aprop", "required"]), - deque(["properties", "aprop", "required"]), - "$.aprop", - ), - ) - - -class MetaSchemaTestsMixin(object): - # TODO: These all belong upstream - def test_invalid_properties(self): - with self.assertRaises(exceptions.SchemaError): - self.Validator.check_schema({"properties": 12}) - - def test_minItems_invalid_string(self): - with self.assertRaises(exceptions.SchemaError): - # needs to be an integer - self.Validator.check_schema({"minItems": "1"}) - - def test_enum_allows_empty_arrays(self): - """ - Technically, all the spec says is they SHOULD have elements, not MUST. - - See #529. - """ - self.Validator.check_schema({"enum": []}) - - def test_enum_allows_non_unique_items(self): - """ - Technically, all the spec says is they SHOULD be unique, not MUST. - - See #529. - """ - self.Validator.check_schema({"enum": [12, 12]}) - - -class ValidatorTestMixin(MetaSchemaTestsMixin, object): - def test_it_implements_the_validator_protocol(self): - self.assertIsInstance(self.Validator({}), protocols.Validator) - - def test_valid_instances_are_valid(self): - schema, instance = self.valid - self.assertTrue(self.Validator(schema).is_valid(instance)) - - def test_invalid_instances_are_not_valid(self): - schema, instance = self.invalid - self.assertFalse(self.Validator(schema).is_valid(instance)) - - def test_non_existent_properties_are_ignored(self): - self.Validator({object(): object()}).validate(instance=object()) - - def test_it_creates_a_ref_resolver_if_not_provided(self): - self.assertIsInstance( - self.Validator({}).resolver, - validators.RefResolver, - ) - - def test_it_delegates_to_a_ref_resolver(self): - ref, schema = "someCoolRef", {"type": "integer"} - resolver = validators.RefResolver("", {}, store={ref: schema}) - validator = self.Validator({"$ref": ref}, resolver=resolver) - - with self.assertRaises(exceptions.ValidationError): - validator.validate(None) - - def test_it_delegates_to_a_legacy_ref_resolver(self): - """ - Legacy RefResolvers support only the context manager form of - resolution. - """ - - class LegacyRefResolver(object): - @contextmanager - def resolving(this, ref): - self.assertEqual(ref, "the ref") - yield {"type": "integer"} - - resolver = LegacyRefResolver() - schema = {"$ref": "the ref"} - - with self.assertRaises(exceptions.ValidationError): - self.Validator(schema, resolver=resolver).validate(None) - - def test_is_type_is_true_for_valid_type(self): - self.assertTrue(self.Validator({}).is_type("foo", "string")) - - def test_is_type_is_false_for_invalid_type(self): - self.assertFalse(self.Validator({}).is_type("foo", "array")) - - def test_is_type_evades_bool_inheriting_from_int(self): - self.assertFalse(self.Validator({}).is_type(True, "integer")) - self.assertFalse(self.Validator({}).is_type(True, "number")) - - def test_it_can_validate_with_decimals(self): - schema = {"items": {"type": "number"}} - Validator = validators.extend( - self.Validator, - type_checker=self.Validator.TYPE_CHECKER.redefine( - "number", - lambda checker, thing: isinstance( - thing, (int, float, Decimal), - ) and not isinstance(thing, bool), - ), - ) - - validator = Validator(schema) - validator.validate([1, 1.1, Decimal(1) / Decimal(8)]) - - invalid = ["foo", {}, [], True, None] - self.assertEqual( - [error.instance for error in validator.iter_errors(invalid)], - invalid, - ) - - def test_it_returns_true_for_formats_it_does_not_know_about(self): - validator = self.Validator( - {"format": "carrot"}, format_checker=FormatChecker(), - ) - validator.validate("bugs") - - def test_it_does_not_validate_formats_by_default(self): - validator = self.Validator({}) - self.assertIsNone(validator.format_checker) - - def test_it_validates_formats_if_a_checker_is_provided(self): - checker = FormatChecker() - bad = ValueError("Bad!") - - @checker.checks("foo", raises=ValueError) - def check(value): - if value == "good": - return True - elif value == "bad": - raise bad - else: # pragma: no cover - self.fail("What is {}? [Baby Don't Hurt Me]".format(value)) - - validator = self.Validator( - {"format": "foo"}, format_checker=checker, - ) - - validator.validate("good") - with self.assertRaises(exceptions.ValidationError) as cm: - validator.validate("bad") - - # Make sure original cause is attached - self.assertIs(cm.exception.cause, bad) - - def test_non_string_custom_type(self): - non_string_type = object() - schema = {"type": [non_string_type]} - Crazy = validators.extend( - self.Validator, - type_checker=self.Validator.TYPE_CHECKER.redefine( - non_string_type, - lambda checker, thing: isinstance(thing, int), - ), - ) - Crazy(schema).validate(15) - - def test_it_properly_formats_tuples_in_errors(self): - """ - A tuple instance properly formats validation errors for uniqueItems. - - See #224 - """ - TupleValidator = validators.extend( - self.Validator, - type_checker=self.Validator.TYPE_CHECKER.redefine( - "array", - lambda checker, thing: isinstance(thing, tuple), - ), - ) - with self.assertRaises(exceptions.ValidationError) as e: - TupleValidator({"uniqueItems": True}).validate((1, 1)) - self.assertIn("(1, 1) has non-unique elements", str(e.exception)) - - def test_check_redefined_sequence(self): - """ - Allow array to validate against another defined sequence type - """ - schema = {"type": "array", "uniqueItems": True} - MyMapping = namedtuple("MyMapping", "a, b") - Validator = validators.extend( - self.Validator, - type_checker=self.Validator.TYPE_CHECKER.redefine_many( - { - "array": lambda checker, thing: isinstance( - thing, (list, deque), - ), - "object": lambda checker, thing: isinstance( - thing, (dict, MyMapping), - ), - }, - ), - ) - validator = Validator(schema) - - valid_instances = [ - deque(["a", None, "1", "", True]), - deque([[False], [0]]), - [deque([False]), deque([0])], - [[deque([False])], [deque([0])]], - [[[[[deque([False])]]]], [[[[deque([0])]]]]], - [deque([deque([False])]), deque([deque([0])])], - [MyMapping("a", 0), MyMapping("a", False)], - [ - MyMapping("a", [deque([0])]), - MyMapping("a", [deque([False])]), - ], - [ - MyMapping("a", [MyMapping("a", deque([0]))]), - MyMapping("a", [MyMapping("a", deque([False]))]), - ], - [deque(deque(deque([False]))), deque(deque(deque([0])))], - ] - - for instance in valid_instances: - validator.validate(instance) - - invalid_instances = [ - deque(["a", "b", "a"]), - deque([[False], [False]]), - [deque([False]), deque([False])], - [[deque([False])], [deque([False])]], - [[[[[deque([False])]]]], [[[[deque([False])]]]]], - [deque([deque([False])]), deque([deque([False])])], - [MyMapping("a", False), MyMapping("a", False)], - [ - MyMapping("a", [deque([False])]), - MyMapping("a", [deque([False])]), - ], - [ - MyMapping("a", [MyMapping("a", deque([False]))]), - MyMapping("a", [MyMapping("a", deque([False]))]), - ], - [deque(deque(deque([False]))), deque(deque(deque([False])))], - ] - - for instance in invalid_instances: - with self.assertRaises(exceptions.ValidationError): - validator.validate(instance) - - -class AntiDraft6LeakMixin(object): - """ - Make sure functionality from draft 6 doesn't leak backwards in time. - """ - - def test_True_is_not_a_schema(self): - with self.assertRaises(exceptions.SchemaError) as e: - self.Validator.check_schema(True) - self.assertIn("True is not of type", str(e.exception)) - - def test_False_is_not_a_schema(self): - with self.assertRaises(exceptions.SchemaError) as e: - self.Validator.check_schema(False) - self.assertIn("False is not of type", str(e.exception)) - - @unittest.skip(bug(523)) - def test_True_is_not_a_schema_even_if_you_forget_to_check(self): - resolver = validators.RefResolver("", {}) - with self.assertRaises(Exception) as e: - self.Validator(True, resolver=resolver).validate(12) - self.assertNotIsInstance(e.exception, exceptions.ValidationError) - - @unittest.skip(bug(523)) - def test_False_is_not_a_schema_even_if_you_forget_to_check(self): - resolver = validators.RefResolver("", {}) - with self.assertRaises(Exception) as e: - self.Validator(False, resolver=resolver).validate(12) - self.assertNotIsInstance(e.exception, exceptions.ValidationError) - - -class TestDraft3Validator(AntiDraft6LeakMixin, ValidatorTestMixin, TestCase): - Validator = validators.Draft3Validator - valid: tuple[dict, dict] = ({}, {}) - invalid = {"type": "integer"}, "foo" - - def test_any_type_is_valid_for_type_any(self): - validator = self.Validator({"type": "any"}) - validator.validate(object()) - - def test_any_type_is_redefinable(self): - """ - Sigh, because why not. - """ - Crazy = validators.extend( - self.Validator, - type_checker=self.Validator.TYPE_CHECKER.redefine( - "any", lambda checker, thing: isinstance(thing, int), - ), - ) - validator = Crazy({"type": "any"}) - validator.validate(12) - with self.assertRaises(exceptions.ValidationError): - validator.validate("foo") - - def test_is_type_is_true_for_any_type(self): - self.assertTrue(self.Validator({"type": "any"}).is_valid(object())) - - def test_is_type_does_not_evade_bool_if_it_is_being_tested(self): - self.assertTrue(self.Validator({}).is_type(True, "boolean")) - self.assertTrue(self.Validator({"type": "any"}).is_valid(True)) - - -class TestDraft4Validator(AntiDraft6LeakMixin, ValidatorTestMixin, TestCase): - Validator = validators.Draft4Validator - valid: tuple[dict, dict] = ({}, {}) - invalid = {"type": "integer"}, "foo" - - -class TestDraft6Validator(ValidatorTestMixin, TestCase): - Validator = validators.Draft6Validator - valid: tuple[dict, dict] = ({}, {}) - invalid = {"type": "integer"}, "foo" - - -class TestDraft7Validator(ValidatorTestMixin, TestCase): - Validator = validators.Draft7Validator - valid: tuple[dict, dict] = ({}, {}) - invalid = {"type": "integer"}, "foo" - - -class TestDraft201909Validator(ValidatorTestMixin, TestCase): - Validator = validators.Draft201909Validator - valid: tuple[dict, dict] = ({}, {}) - invalid = {"type": "integer"}, "foo" - - -class TestDraft202012Validator(ValidatorTestMixin, TestCase): - Validator = validators.Draft202012Validator - valid: tuple[dict, dict] = ({}, {}) - invalid = {"type": "integer"}, "foo" - - -class TestValidatorFor(TestCase): - def test_draft_3(self): - schema = {"$schema": "http://json-schema.org/draft-03/schema"} - self.assertIs( - validators.validator_for(schema), - validators.Draft3Validator, - ) - - schema = {"$schema": "http://json-schema.org/draft-03/schema#"} - self.assertIs( - validators.validator_for(schema), - validators.Draft3Validator, - ) - - def test_draft_4(self): - schema = {"$schema": "http://json-schema.org/draft-04/schema"} - self.assertIs( - validators.validator_for(schema), - validators.Draft4Validator, - ) - - schema = {"$schema": "http://json-schema.org/draft-04/schema#"} - self.assertIs( - validators.validator_for(schema), - validators.Draft4Validator, - ) - - def test_draft_6(self): - schema = {"$schema": "http://json-schema.org/draft-06/schema"} - self.assertIs( - validators.validator_for(schema), - validators.Draft6Validator, - ) - - schema = {"$schema": "http://json-schema.org/draft-06/schema#"} - self.assertIs( - validators.validator_for(schema), - validators.Draft6Validator, - ) - - def test_draft_7(self): - schema = {"$schema": "http://json-schema.org/draft-07/schema"} - self.assertIs( - validators.validator_for(schema), - validators.Draft7Validator, - ) - - schema = {"$schema": "http://json-schema.org/draft-07/schema#"} - self.assertIs( - validators.validator_for(schema), - validators.Draft7Validator, - ) - - def test_draft_201909(self): - schema = {"$schema": "https://json-schema.org/draft/2019-09/schema"} - self.assertIs( - validators.validator_for(schema), - validators.Draft201909Validator, - ) - - schema = {"$schema": "https://json-schema.org/draft/2019-09/schema#"} - self.assertIs( - validators.validator_for(schema), - validators.Draft201909Validator, - ) - - def test_draft_202012(self): - schema = {"$schema": "https://json-schema.org/draft/2020-12/schema"} - self.assertIs( - validators.validator_for(schema), - validators.Draft202012Validator, - ) - - schema = {"$schema": "https://json-schema.org/draft/2020-12/schema#"} - self.assertIs( - validators.validator_for(schema), - validators.Draft202012Validator, - ) - - def test_True(self): - self.assertIs( - validators.validator_for(True), - validators._LATEST_VERSION, - ) - - def test_False(self): - self.assertIs( - validators.validator_for(False), - validators._LATEST_VERSION, - ) - - def test_custom_validator(self): - Validator = validators.create( - meta_schema={"id": "meta schema id"}, - version="12", - id_of=lambda s: s.get("id", ""), - ) - schema = {"$schema": "meta schema id"} - self.assertIs( - validators.validator_for(schema), - Validator, - ) - - def test_custom_validator_draft6(self): - Validator = validators.create( - meta_schema={"$id": "meta schema $id"}, - version="13", - ) - schema = {"$schema": "meta schema $id"} - self.assertIs( - validators.validator_for(schema), - Validator, - ) - - def test_validator_for_jsonschema_default(self): - self.assertIs(validators.validator_for({}), validators._LATEST_VERSION) - - def test_validator_for_custom_default(self): - self.assertIs(validators.validator_for({}, default=None), None) - - def test_warns_if_meta_schema_specified_was_not_found(self): - with self.assertWarns(DeprecationWarning) as cm: - validators.validator_for(schema={"$schema": "unknownSchema"}) - - self.assertEqual(cm.filename, __file__) - self.assertEqual( - str(cm.warning), - "The metaschema specified by $schema was not found. " - "Using the latest draft to validate, but this will raise " - "an error in the future.", - ) - - def test_does_not_warn_if_meta_schema_is_unspecified(self): - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - validators.validator_for(schema={}, default={}) - self.assertFalse(w) - - -class TestValidate(TestCase): - def assertUses(self, schema, Validator): - result = [] - with mock.patch.object(Validator, "check_schema", result.append): - validators.validate({}, schema) - self.assertEqual(result, [schema]) - - def test_draft3_validator_is_chosen(self): - self.assertUses( - schema={"$schema": "http://json-schema.org/draft-03/schema#"}, - Validator=validators.Draft3Validator, - ) - # Make sure it works without the empty fragment - self.assertUses( - schema={"$schema": "http://json-schema.org/draft-03/schema"}, - Validator=validators.Draft3Validator, - ) - - def test_draft4_validator_is_chosen(self): - self.assertUses( - schema={"$schema": "http://json-schema.org/draft-04/schema#"}, - Validator=validators.Draft4Validator, - ) - # Make sure it works without the empty fragment - self.assertUses( - schema={"$schema": "http://json-schema.org/draft-04/schema"}, - Validator=validators.Draft4Validator, - ) - - def test_draft6_validator_is_chosen(self): - self.assertUses( - schema={"$schema": "http://json-schema.org/draft-06/schema#"}, - Validator=validators.Draft6Validator, - ) - # Make sure it works without the empty fragment - self.assertUses( - schema={"$schema": "http://json-schema.org/draft-06/schema"}, - Validator=validators.Draft6Validator, - ) - - def test_draft7_validator_is_chosen(self): - self.assertUses( - schema={"$schema": "http://json-schema.org/draft-07/schema#"}, - Validator=validators.Draft7Validator, - ) - # Make sure it works without the empty fragment - self.assertUses( - schema={"$schema": "http://json-schema.org/draft-07/schema"}, - Validator=validators.Draft7Validator, - ) - - def test_draft202012_validator_is_chosen(self): - self.assertUses( - schema={ - "$schema": "https://json-schema.org/draft/2020-12/schema#", - }, - Validator=validators.Draft202012Validator, - ) - # Make sure it works without the empty fragment - self.assertUses( - schema={ - "$schema": "https://json-schema.org/draft/2020-12/schema", - }, - Validator=validators.Draft202012Validator, - ) - - def test_draft202012_validator_is_the_default(self): - self.assertUses(schema={}, Validator=validators.Draft202012Validator) - - def test_validation_error_message(self): - with self.assertRaises(exceptions.ValidationError) as e: - validators.validate(12, {"type": "string"}) - self.assertRegex( - str(e.exception), - "(?s)Failed validating '.*' in schema.*On instance", - ) - - def test_schema_error_message(self): - with self.assertRaises(exceptions.SchemaError) as e: - validators.validate(12, {"type": 12}) - self.assertRegex( - str(e.exception), - "(?s)Failed validating '.*' in metaschema.*On schema", - ) - - def test_it_uses_best_match(self): - schema = { - "oneOf": [ - {"type": "number", "minimum": 20}, - {"type": "array"}, - ], - } - with self.assertRaises(exceptions.ValidationError) as e: - validators.validate(12, schema) - self.assertIn("12 is less than the minimum of 20", str(e.exception)) - - -class TestRefResolver(TestCase): - - base_uri = "" - stored_uri = "foo://stored" - stored_schema = {"stored": "schema"} - - def setUp(self): - self.referrer = {} - self.store = {self.stored_uri: self.stored_schema} - self.resolver = validators.RefResolver( - self.base_uri, self.referrer, self.store, - ) - - def test_it_does_not_retrieve_schema_urls_from_the_network(self): - ref = validators.Draft3Validator.META_SCHEMA["id"] - with mock.patch.object(self.resolver, "resolve_remote") as patched: - with self.resolver.resolving(ref) as resolved: - pass - self.assertEqual(resolved, validators.Draft3Validator.META_SCHEMA) - self.assertFalse(patched.called) - - def test_it_resolves_local_refs(self): - ref = "#/properties/foo" - self.referrer["properties"] = {"foo": object()} - with self.resolver.resolving(ref) as resolved: - self.assertEqual(resolved, self.referrer["properties"]["foo"]) - - def test_it_resolves_local_refs_with_id(self): - schema = {"id": "http://bar/schema#", "a": {"foo": "bar"}} - resolver = validators.RefResolver.from_schema( - schema, - id_of=lambda schema: schema.get("id", ""), - ) - with resolver.resolving("#/a") as resolved: - self.assertEqual(resolved, schema["a"]) - with resolver.resolving("http://bar/schema#/a") as resolved: - self.assertEqual(resolved, schema["a"]) - - def test_it_retrieves_stored_refs(self): - with self.resolver.resolving(self.stored_uri) as resolved: - self.assertIs(resolved, self.stored_schema) - - self.resolver.store["cached_ref"] = {"foo": 12} - with self.resolver.resolving("cached_ref#/foo") as resolved: - self.assertEqual(resolved, 12) - - def test_it_retrieves_unstored_refs_via_requests(self): - ref = "http://bar#baz" - schema = {"baz": 12} - - if "requests" in sys.modules: - self.addCleanup( - sys.modules.__setitem__, "requests", sys.modules["requests"], - ) - sys.modules["requests"] = ReallyFakeRequests({"http://bar": schema}) - - with self.resolver.resolving(ref) as resolved: - self.assertEqual(resolved, 12) - - def test_it_retrieves_unstored_refs_via_urlopen(self): - ref = "http://bar#baz" - schema = {"baz": 12} - - if "requests" in sys.modules: - self.addCleanup( - sys.modules.__setitem__, "requests", sys.modules["requests"], - ) - sys.modules["requests"] = None - - @contextmanager - def fake_urlopen(url): - self.assertEqual(url, "http://bar") - yield BytesIO(json.dumps(schema).encode("utf8")) - - self.addCleanup(setattr, validators, "urlopen", validators.urlopen) - validators.urlopen = fake_urlopen - - with self.resolver.resolving(ref) as resolved: - pass - self.assertEqual(resolved, 12) - - def test_it_retrieves_local_refs_via_urlopen(self): - with tempfile.NamedTemporaryFile(delete=False, mode="wt") as tempf: - self.addCleanup(os.remove, tempf.name) - json.dump({"foo": "bar"}, tempf) - - ref = "file://{}#foo".format(pathname2url(tempf.name)) - with self.resolver.resolving(ref) as resolved: - self.assertEqual(resolved, "bar") - - def test_it_can_construct_a_base_uri_from_a_schema(self): - schema = {"id": "foo"} - resolver = validators.RefResolver.from_schema( - schema, - id_of=lambda schema: schema.get("id", ""), - ) - self.assertEqual(resolver.base_uri, "foo") - self.assertEqual(resolver.resolution_scope, "foo") - with resolver.resolving("") as resolved: - self.assertEqual(resolved, schema) - with resolver.resolving("#") as resolved: - self.assertEqual(resolved, schema) - with resolver.resolving("foo") as resolved: - self.assertEqual(resolved, schema) - with resolver.resolving("foo#") as resolved: - self.assertEqual(resolved, schema) - - def test_it_can_construct_a_base_uri_from_a_schema_without_id(self): - schema = {} - resolver = validators.RefResolver.from_schema(schema) - self.assertEqual(resolver.base_uri, "") - self.assertEqual(resolver.resolution_scope, "") - with resolver.resolving("") as resolved: - self.assertEqual(resolved, schema) - with resolver.resolving("#") as resolved: - self.assertEqual(resolved, schema) - - def test_custom_uri_scheme_handlers(self): - def handler(url): - self.assertEqual(url, ref) - return schema - - schema = {"foo": "bar"} - ref = "foo://bar" - resolver = validators.RefResolver("", {}, handlers={"foo": handler}) - with resolver.resolving(ref) as resolved: - self.assertEqual(resolved, schema) - - def test_cache_remote_on(self): - response = [object()] - - def handler(url): - try: - return response.pop() - except IndexError: # pragma: no cover - self.fail("Response must not have been cached!") - - ref = "foo://bar" - resolver = validators.RefResolver( - "", {}, cache_remote=True, handlers={"foo": handler}, - ) - with resolver.resolving(ref): - pass - with resolver.resolving(ref): - pass - - def test_cache_remote_off(self): - response = [object()] - - def handler(url): - try: - return response.pop() - except IndexError: # pragma: no cover - self.fail("Handler called twice!") - - ref = "foo://bar" - resolver = validators.RefResolver( - "", {}, cache_remote=False, handlers={"foo": handler}, - ) - with resolver.resolving(ref): - pass - - def test_if_you_give_it_junk_you_get_a_resolution_error(self): - error = ValueError("Oh no! What's this?") - - def handler(url): - raise error - - ref = "foo://bar" - resolver = validators.RefResolver("", {}, handlers={"foo": handler}) - with self.assertRaises(exceptions.RefResolutionError) as err: - with resolver.resolving(ref): - self.fail("Shouldn't get this far!") # pragma: no cover - self.assertEqual(err.exception, exceptions.RefResolutionError(error)) - - def test_helpful_error_message_on_failed_pop_scope(self): - resolver = validators.RefResolver("", {}) - resolver.pop_scope() - with self.assertRaises(exceptions.RefResolutionError) as exc: - resolver.pop_scope() - self.assertIn("Failed to pop the scope", str(exc.exception)) - - -def sorted_errors(errors): - def key(error): - return ( - [str(e) for e in error.path], - [str(e) for e in error.schema_path], - ) - return sorted(errors, key=key) - - -@attr.s -class ReallyFakeRequests(object): - - _responses = attr.ib() - - def get(self, url): - response = self._responses.get(url) - if url is None: # pragma: no cover - raise ValueError("Unknown URL: " + repr(url)) - return _ReallyFakeJSONResponse(json.dumps(response)) - - -@attr.s -class _ReallyFakeJSONResponse(object): - - _response = attr.ib() - - def json(self): - return json.loads(self._response) diff --git a/jsonschema/validators.py b/jsonschema/validators.py deleted file mode 100644 index 9ead094..0000000 --- a/jsonschema/validators.py +++ /dev/null @@ -1,1099 +0,0 @@ -""" -Creation and extension of validators, with implementations for existing drafts. -""" -from __future__ import annotations - -from collections import deque -from collections.abc import Sequence -from functools import lru_cache -from operator import methodcaller -from urllib.parse import unquote, urldefrag, urljoin, urlsplit -from urllib.request import urlopen -from warnings import warn -import contextlib -import json -import reprlib -import typing -import warnings - -import attr - -from jsonschema import ( - _format, - _legacy_validators, - _types, - _utils, - _validators, - exceptions, -) - -_VALIDATORS: dict[str, typing.Any] = {} -_META_SCHEMAS = _utils.URIDict() -_VOCABULARIES: list[tuple[str, typing.Any]] = [] - - -def __getattr__(name): - if name == "ErrorTree": - warnings.warn( - "Importing ErrorTree from jsonschema.validators is deprecated. " - "Instead import it from jsonschema.exceptions.", - DeprecationWarning, - stacklevel=2, - ) - from jsonschema.exceptions import ErrorTree - return ErrorTree - elif name == "validators": - warnings.warn( - "Accessing jsonschema.validators.validators is deprecated. " - "Use jsonschema.validators.validator_for with a given schema.", - DeprecationWarning, - stacklevel=2, - ) - return _VALIDATORS - elif name == "meta_schemas": - warnings.warn( - "Accessing jsonschema.validators.meta_schemas is deprecated. " - "Use jsonschema.validators.validator_for with a given schema.", - DeprecationWarning, - stacklevel=2, - ) - return _META_SCHEMAS - raise AttributeError(f"module {__name__} has no attribute {name}") - - -def validates(version): - """ - Register the decorated validator for a ``version`` of the specification. - - Registered validators and their meta schemas will be considered when - parsing ``$schema`` properties' URIs. - - Arguments: - - version (str): - - An identifier to use as the version's name - - Returns: - - collections.abc.Callable: - - a class decorator to decorate the validator with the version - """ - - def _validates(cls): - _VALIDATORS[version] = cls - meta_schema_id = cls.ID_OF(cls.META_SCHEMA) - _META_SCHEMAS[meta_schema_id] = cls - return cls - return _validates - - -def _id_of(schema): - """ - Return the ID of a schema for recent JSON Schema drafts. - """ - if schema is True or schema is False: - return "" - return schema.get("$id", "") - - -def _store_schema_list(): - if not _VOCABULARIES: - _VOCABULARIES.extend(_utils.load_schema("vocabularies").items()) - return [ - (id, validator.META_SCHEMA) for id, validator in _META_SCHEMAS.items() - ] + _VOCABULARIES - - -def create( - meta_schema, - validators=(), - version=None, - type_checker=_types.draft202012_type_checker, - format_checker=_format.draft202012_format_checker, - id_of=_id_of, - applicable_validators=methodcaller("items"), -): - """ - Create a new validator class. - - Arguments: - - meta_schema (collections.abc.Mapping): - - the meta schema for the new validator class - - validators (collections.abc.Mapping): - - a mapping from names to callables, where each callable will - validate the schema property with the given name. - - Each callable should take 4 arguments: - - 1. a validator instance, - 2. the value of the property being validated within the - instance - 3. the instance - 4. the schema - - version (str): - - an identifier for the version that this validator class will - validate. If provided, the returned validator class will - have its ``__name__`` set to include the version, and also - will have `jsonschema.validators.validates` automatically - called for the given version. - - type_checker (jsonschema.TypeChecker): - - a type checker, used when applying the :validator:`type` validator. - - If unprovided, a `jsonschema.TypeChecker` will be created - with a set of default types typical of JSON Schema drafts. - - format_checker (jsonschema.FormatChecker): - - a format checker, used when applying the :validator:`format` - validator. - - If unprovided, a `jsonschema.FormatChecker` will be created - with a set of default formats typical of JSON Schema drafts. - - id_of (collections.abc.Callable): - - A function that given a schema, returns its ID. - - applicable_validators (collections.abc.Callable): - - A function that given a schema, returns the list of applicable - validators (names and callables) which will be called to - validate the instance. - - Returns: - - a new `jsonschema.protocols.Validator` class - """ - # preemptively don't shadow the `Validator.format_checker` local - format_checker_arg = format_checker - - @attr.s - class Validator: - - VALIDATORS = dict(validators) - META_SCHEMA = dict(meta_schema) - TYPE_CHECKER = type_checker - FORMAT_CHECKER = format_checker_arg - ID_OF = staticmethod(id_of) - - schema = attr.ib(repr=reprlib.repr) - resolver = attr.ib(default=None, repr=False) - format_checker = attr.ib(default=None) - evolve = attr.evolve - - def __attrs_post_init__(self): - if self.resolver is None: - self.resolver = RefResolver.from_schema( - self.schema, - id_of=id_of, - ) - - @classmethod - def check_schema(cls, schema): - for error in cls(cls.META_SCHEMA).iter_errors(schema): - raise exceptions.SchemaError.create_from(error) - - def iter_errors(self, instance, _schema=None): - if _schema is not None: - warnings.warn( - ( - "Passing a schema to Validator.iter_errors " - "is deprecated and will be removed in a future " - "release. Call validator.evolve(schema=new_schema)." - "iter_errors(...) instead." - ), - DeprecationWarning, - stacklevel=2, - ) - else: - _schema = self.schema - - if _schema is True: - return - elif _schema is False: - yield exceptions.ValidationError( - f"False schema does not allow {instance!r}", - validator=None, - validator_value=None, - instance=instance, - schema=_schema, - ) - return - - scope = id_of(_schema) - if scope: - self.resolver.push_scope(scope) - try: - for k, v in applicable_validators(_schema): - validator = self.VALIDATORS.get(k) - if validator is None: - continue - - errors = validator(self, v, instance, _schema) or () - for error in errors: - # set details if not already set by the called fn - error._set( - validator=k, - validator_value=v, - instance=instance, - schema=_schema, - type_checker=self.TYPE_CHECKER, - ) - if k not in {"if", "$ref"}: - error.schema_path.appendleft(k) - yield error - finally: - if scope: - self.resolver.pop_scope() - - def descend(self, instance, schema, path=None, schema_path=None): - for error in self.evolve(schema=schema).iter_errors(instance): - if path is not None: - error.path.appendleft(path) - if schema_path is not None: - error.schema_path.appendleft(schema_path) - yield error - - def validate(self, *args, **kwargs): - for error in self.iter_errors(*args, **kwargs): - raise error - - def is_type(self, instance, type): - try: - return self.TYPE_CHECKER.is_type(instance, type) - except exceptions.UndefinedTypeCheck: - raise exceptions.UnknownType(type, instance, self.schema) - - def is_valid(self, instance, _schema=None): - if _schema is not None: - warnings.warn( - ( - "Passing a schema to Validator.is_valid is deprecated " - "and will be removed in a future release. Call " - "validator.evolve(schema=new_schema).is_valid(...) " - "instead." - ), - DeprecationWarning, - stacklevel=2, - ) - self = self.evolve(schema=_schema) - - error = next(self.iter_errors(instance), None) - return error is None - - if version is not None: - safe = version.title().replace(" ", "").replace("-", "") - Validator.__name__ = Validator.__qualname__ = f"{safe}Validator" - Validator = validates(version)(Validator) - - return Validator - - -def extend( - validator, - validators=(), - version=None, - type_checker=None, - format_checker=None, -): - """ - Create a new validator class by extending an existing one. - - Arguments: - - validator (jsonschema.protocols.Validator): - - an existing validator class - - validators (collections.abc.Mapping): - - a mapping of new validator callables to extend with, whose - structure is as in `create`. - - .. note:: - - Any validator callables with the same name as an - existing one will (silently) replace the old validator - callable entirely, effectively overriding any validation - done in the "parent" validator class. - - If you wish to instead extend the behavior of a parent's - validator callable, delegate and call it directly in - the new validator function by retrieving it using - ``OldValidator.VALIDATORS["validator_name"]``. - - version (str): - - a version for the new validator class - - type_checker (jsonschema.TypeChecker): - - a type checker, used when applying the :validator:`type` validator. - - If unprovided, the type checker of the extended - `jsonschema.protocols.Validator` will be carried along. - - format_checker (jsonschema.FormatChecker): - - a format checker, used when applying the :validator:`format` - validator. - - If unprovided, the format checker of the extended - `jsonschema.protocols.Validator` will be carried along. - - Returns: - - a new `jsonschema.protocols.Validator` class extending the one - provided - - .. note:: Meta Schemas - - The new validator class will have its parent's meta schema. - - If you wish to change or extend the meta schema in the new - validator class, modify ``META_SCHEMA`` directly on the returned - class. Note that no implicit copying is done, so a copy should - likely be made before modifying it, in order to not affect the - old validator. - """ - - all_validators = dict(validator.VALIDATORS) - all_validators.update(validators) - - if type_checker is None: - type_checker = validator.TYPE_CHECKER - if format_checker is None: - format_checker = validator.FORMAT_CHECKER - return create( - meta_schema=validator.META_SCHEMA, - validators=all_validators, - version=version, - type_checker=type_checker, - format_checker=format_checker, - id_of=validator.ID_OF, - ) - - -Draft3Validator = create( - meta_schema=_utils.load_schema("draft3"), - validators={ - "$ref": _validators.ref, - "additionalItems": _validators.additionalItems, - "additionalProperties": _validators.additionalProperties, - "dependencies": _legacy_validators.dependencies_draft3, - "disallow": _legacy_validators.disallow_draft3, - "divisibleBy": _validators.multipleOf, - "enum": _validators.enum, - "extends": _legacy_validators.extends_draft3, - "format": _validators.format, - "items": _legacy_validators.items_draft3_draft4, - "maxItems": _validators.maxItems, - "maxLength": _validators.maxLength, - "maximum": _legacy_validators.maximum_draft3_draft4, - "minItems": _validators.minItems, - "minLength": _validators.minLength, - "minimum": _legacy_validators.minimum_draft3_draft4, - "pattern": _validators.pattern, - "patternProperties": _validators.patternProperties, - "properties": _legacy_validators.properties_draft3, - "type": _legacy_validators.type_draft3, - "uniqueItems": _validators.uniqueItems, - }, - type_checker=_types.draft3_type_checker, - format_checker=_format.draft3_format_checker, - version="draft3", - id_of=lambda schema: schema.get("id", ""), - applicable_validators=_legacy_validators.ignore_ref_siblings, -) - -Draft4Validator = create( - meta_schema=_utils.load_schema("draft4"), - validators={ - "$ref": _validators.ref, - "additionalItems": _validators.additionalItems, - "additionalProperties": _validators.additionalProperties, - "allOf": _validators.allOf, - "anyOf": _validators.anyOf, - "dependencies": _legacy_validators.dependencies_draft4_draft6_draft7, - "enum": _validators.enum, - "format": _validators.format, - "items": _legacy_validators.items_draft3_draft4, - "maxItems": _validators.maxItems, - "maxLength": _validators.maxLength, - "maxProperties": _validators.maxProperties, - "maximum": _legacy_validators.maximum_draft3_draft4, - "minItems": _validators.minItems, - "minLength": _validators.minLength, - "minProperties": _validators.minProperties, - "minimum": _legacy_validators.minimum_draft3_draft4, - "multipleOf": _validators.multipleOf, - "not": _validators.not_, - "oneOf": _validators.oneOf, - "pattern": _validators.pattern, - "patternProperties": _validators.patternProperties, - "properties": _validators.properties, - "required": _validators.required, - "type": _validators.type, - "uniqueItems": _validators.uniqueItems, - }, - type_checker=_types.draft4_type_checker, - format_checker=_format.draft4_format_checker, - version="draft4", - id_of=lambda schema: schema.get("id", ""), - applicable_validators=_legacy_validators.ignore_ref_siblings, -) - -Draft6Validator = create( - meta_schema=_utils.load_schema("draft6"), - validators={ - "$ref": _validators.ref, - "additionalItems": _validators.additionalItems, - "additionalProperties": _validators.additionalProperties, - "allOf": _validators.allOf, - "anyOf": _validators.anyOf, - "const": _validators.const, - "contains": _legacy_validators.contains_draft6_draft7, - "dependencies": _legacy_validators.dependencies_draft4_draft6_draft7, - "enum": _validators.enum, - "exclusiveMaximum": _validators.exclusiveMaximum, - "exclusiveMinimum": _validators.exclusiveMinimum, - "format": _validators.format, - "items": _legacy_validators.items_draft6_draft7_draft201909, - "maxItems": _validators.maxItems, - "maxLength": _validators.maxLength, - "maxProperties": _validators.maxProperties, - "maximum": _validators.maximum, - "minItems": _validators.minItems, - "minLength": _validators.minLength, - "minProperties": _validators.minProperties, - "minimum": _validators.minimum, - "multipleOf": _validators.multipleOf, - "not": _validators.not_, - "oneOf": _validators.oneOf, - "pattern": _validators.pattern, - "patternProperties": _validators.patternProperties, - "properties": _validators.properties, - "propertyNames": _validators.propertyNames, - "required": _validators.required, - "type": _validators.type, - "uniqueItems": _validators.uniqueItems, - }, - type_checker=_types.draft6_type_checker, - format_checker=_format.draft6_format_checker, - version="draft6", - applicable_validators=_legacy_validators.ignore_ref_siblings, -) - -Draft7Validator = create( - meta_schema=_utils.load_schema("draft7"), - validators={ - "$ref": _validators.ref, - "additionalItems": _validators.additionalItems, - "additionalProperties": _validators.additionalProperties, - "allOf": _validators.allOf, - "anyOf": _validators.anyOf, - "const": _validators.const, - "contains": _legacy_validators.contains_draft6_draft7, - "dependencies": _legacy_validators.dependencies_draft4_draft6_draft7, - "enum": _validators.enum, - "exclusiveMaximum": _validators.exclusiveMaximum, - "exclusiveMinimum": _validators.exclusiveMinimum, - "format": _validators.format, - "if": _validators.if_, - "items": _legacy_validators.items_draft6_draft7_draft201909, - "maxItems": _validators.maxItems, - "maxLength": _validators.maxLength, - "maxProperties": _validators.maxProperties, - "maximum": _validators.maximum, - "minItems": _validators.minItems, - "minLength": _validators.minLength, - "minProperties": _validators.minProperties, - "minimum": _validators.minimum, - "multipleOf": _validators.multipleOf, - "not": _validators.not_, - "oneOf": _validators.oneOf, - "pattern": _validators.pattern, - "patternProperties": _validators.patternProperties, - "properties": _validators.properties, - "propertyNames": _validators.propertyNames, - "required": _validators.required, - "type": _validators.type, - "uniqueItems": _validators.uniqueItems, - }, - type_checker=_types.draft7_type_checker, - format_checker=_format.draft7_format_checker, - version="draft7", - applicable_validators=_legacy_validators.ignore_ref_siblings, -) - -Draft201909Validator = create( - meta_schema=_utils.load_schema("draft2019-09"), - validators={ - "$recursiveRef": _legacy_validators.recursiveRef, - "$ref": _validators.ref, - "additionalItems": _validators.additionalItems, - "additionalProperties": _validators.additionalProperties, - "allOf": _validators.allOf, - "anyOf": _validators.anyOf, - "const": _validators.const, - "contains": _validators.contains, - "dependentRequired": _validators.dependentRequired, - "dependentSchemas": _validators.dependentSchemas, - "enum": _validators.enum, - "exclusiveMaximum": _validators.exclusiveMaximum, - "exclusiveMinimum": _validators.exclusiveMinimum, - "format": _validators.format, - "if": _validators.if_, - "items": _legacy_validators.items_draft6_draft7_draft201909, - "maxItems": _validators.maxItems, - "maxLength": _validators.maxLength, - "maxProperties": _validators.maxProperties, - "maximum": _validators.maximum, - "minItems": _validators.minItems, - "minLength": _validators.minLength, - "minProperties": _validators.minProperties, - "minimum": _validators.minimum, - "multipleOf": _validators.multipleOf, - "not": _validators.not_, - "oneOf": _validators.oneOf, - "pattern": _validators.pattern, - "patternProperties": _validators.patternProperties, - "properties": _validators.properties, - "propertyNames": _validators.propertyNames, - "required": _validators.required, - "type": _validators.type, - "unevaluatedItems": _validators.unevaluatedItems, - "unevaluatedProperties": _validators.unevaluatedProperties, - "uniqueItems": _validators.uniqueItems, - }, - type_checker=_types.draft201909_type_checker, - format_checker=_format.draft201909_format_checker, - version="draft2019-09", -) - -Draft202012Validator = create( - meta_schema=_utils.load_schema("draft2020-12"), - validators={ - "$dynamicRef": _validators.dynamicRef, - "$ref": _validators.ref, - "additionalItems": _validators.additionalItems, - "additionalProperties": _validators.additionalProperties, - "allOf": _validators.allOf, - "anyOf": _validators.anyOf, - "const": _validators.const, - "contains": _validators.contains, - "dependentRequired": _validators.dependentRequired, - "dependentSchemas": _validators.dependentSchemas, - "enum": _validators.enum, - "exclusiveMaximum": _validators.exclusiveMaximum, - "exclusiveMinimum": _validators.exclusiveMinimum, - "format": _validators.format, - "if": _validators.if_, - "items": _validators.items, - "maxItems": _validators.maxItems, - "maxLength": _validators.maxLength, - "maxProperties": _validators.maxProperties, - "maximum": _validators.maximum, - "minItems": _validators.minItems, - "minLength": _validators.minLength, - "minProperties": _validators.minProperties, - "minimum": _validators.minimum, - "multipleOf": _validators.multipleOf, - "not": _validators.not_, - "oneOf": _validators.oneOf, - "pattern": _validators.pattern, - "patternProperties": _validators.patternProperties, - "prefixItems": _validators.prefixItems, - "properties": _validators.properties, - "propertyNames": _validators.propertyNames, - "required": _validators.required, - "type": _validators.type, - "unevaluatedItems": _validators.unevaluatedItems, - "unevaluatedProperties": _validators.unevaluatedProperties, - "uniqueItems": _validators.uniqueItems, - }, - type_checker=_types.draft202012_type_checker, - format_checker=_format.draft202012_format_checker, - version="draft2020-12", -) - -_LATEST_VERSION = Draft202012Validator - - -class RefResolver(object): - """ - Resolve JSON References. - - Arguments: - - base_uri (str): - - The URI of the referring document - - referrer: - - The actual referring document - - store (dict): - - A mapping from URIs to documents to cache - - cache_remote (bool): - - Whether remote refs should be cached after first resolution - - handlers (dict): - - A mapping from URI schemes to functions that should be used - to retrieve them - - urljoin_cache (:func:`functools.lru_cache`): - - A cache that will be used for caching the results of joining - the resolution scope to subscopes. - - remote_cache (:func:`functools.lru_cache`): - - A cache that will be used for caching the results of - resolved remote URLs. - - Attributes: - - cache_remote (bool): - - Whether remote refs should be cached after first resolution - """ - - def __init__( - self, - base_uri, - referrer, - store=(), - cache_remote=True, - handlers=(), - urljoin_cache=None, - remote_cache=None, - ): - if urljoin_cache is None: - urljoin_cache = lru_cache(1024)(urljoin) - if remote_cache is None: - remote_cache = lru_cache(1024)(self.resolve_from_url) - - self.referrer = referrer - self.cache_remote = cache_remote - self.handlers = dict(handlers) - - self._scopes_stack = [base_uri] - self.store = _utils.URIDict(_store_schema_list()) - self.store.update(store) - self.store[base_uri] = referrer - - self._urljoin_cache = urljoin_cache - self._remote_cache = remote_cache - - @classmethod - def from_schema(cls, schema, id_of=_id_of, *args, **kwargs): - """ - Construct a resolver from a JSON schema object. - - Arguments: - - schema: - - the referring schema - - Returns: - - `RefResolver` - """ - - return cls(base_uri=id_of(schema), referrer=schema, *args, **kwargs) - - def push_scope(self, scope): - """ - Enter a given sub-scope. - - Treats further dereferences as being performed underneath the - given scope. - """ - self._scopes_stack.append( - self._urljoin_cache(self.resolution_scope, scope), - ) - - def pop_scope(self): - """ - Exit the most recent entered scope. - - Treats further dereferences as being performed underneath the - original scope. - - Don't call this method more times than `push_scope` has been - called. - """ - try: - self._scopes_stack.pop() - except IndexError: - raise exceptions.RefResolutionError( - "Failed to pop the scope from an empty stack. " - "`pop_scope()` should only be called once for every " - "`push_scope()`", - ) - - @property - def resolution_scope(self): - """ - Retrieve the current resolution scope. - """ - return self._scopes_stack[-1] - - @property - def base_uri(self): - """ - Retrieve the current base URI, not including any fragment. - """ - uri, _ = urldefrag(self.resolution_scope) - return uri - - @contextlib.contextmanager - def in_scope(self, scope): - """ - Temporarily enter the given scope for the duration of the context. - """ - warnings.warn( - "jsonschema.RefResolver.in_scope is deprecated and will be " - "removed in a future release.", - DeprecationWarning, - stacklevel=3, - ) - self.push_scope(scope) - try: - yield - finally: - self.pop_scope() - - @contextlib.contextmanager - def resolving(self, ref): - """ - Resolve the given ``ref`` and enter its resolution scope. - - Exits the scope on exit of this context manager. - - Arguments: - - ref (str): - - The reference to resolve - """ - - url, resolved = self.resolve(ref) - self.push_scope(url) - try: - yield resolved - finally: - self.pop_scope() - - def _find_in_referrer(self, key): - return self._get_subschemas_cache()[key] - - @lru_cache() # noqa: B019 - def _get_subschemas_cache(self): - cache = {key: [] for key in _SUBSCHEMAS_KEYWORDS} - for keyword, subschema in _search_schema( - self.referrer, _match_subschema_keywords, - ): - cache[keyword].append(subschema) - return cache - - @lru_cache() # noqa: B019 - def _find_in_subschemas(self, url): - subschemas = self._get_subschemas_cache()["$id"] - if not subschemas: - return None - uri, fragment = urldefrag(url) - for subschema in subschemas: - target_uri = self._urljoin_cache( - self.resolution_scope, subschema["$id"], - ) - if target_uri.rstrip("/") == uri.rstrip("/"): - if fragment: - subschema = self.resolve_fragment(subschema, fragment) - return url, subschema - return None - - def resolve(self, ref): - """ - Resolve the given reference. - """ - url = self._urljoin_cache(self.resolution_scope, ref).rstrip("/") - - match = self._find_in_subschemas(url) - if match is not None: - return match - - return url, self._remote_cache(url) - - def resolve_from_url(self, url): - """ - Resolve the given URL. - """ - url, fragment = urldefrag(url) - if url: - try: - document = self.store[url] - except KeyError: - try: - document = self.resolve_remote(url) - except Exception as exc: - raise exceptions.RefResolutionError(exc) - else: - document = self.referrer - - return self.resolve_fragment(document, fragment) - - def resolve_fragment(self, document, fragment): - """ - Resolve a ``fragment`` within the referenced ``document``. - - Arguments: - - document: - - The referent document - - fragment (str): - - a URI fragment to resolve within it - """ - - fragment = fragment.lstrip("/") - - if not fragment: - return document - - if document is self.referrer: - find = self._find_in_referrer - else: - - def find(key): - yield from _search_schema(document, _match_keyword(key)) - - for keyword in ["$anchor", "$dynamicAnchor"]: - for subschema in find(keyword): - if fragment == subschema[keyword]: - return subschema - for keyword in ["id", "$id"]: - for subschema in find(keyword): - if "#" + fragment == subschema[keyword]: - return subschema - - # Resolve via path - parts = unquote(fragment).split("/") if fragment else [] - for part in parts: - part = part.replace("~1", "/").replace("~0", "~") - - if isinstance(document, Sequence): - # Array indexes should be turned into integers - try: - part = int(part) - except ValueError: - pass - try: - document = document[part] - except (TypeError, LookupError): - raise exceptions.RefResolutionError( - f"Unresolvable JSON pointer: {fragment!r}", - ) - - return document - - def resolve_remote(self, uri): - """ - Resolve a remote ``uri``. - - If called directly, does not check the store first, but after - retrieving the document at the specified URI it will be saved in - the store if :attr:`cache_remote` is True. - - .. note:: - - If the requests_ library is present, ``jsonschema`` will use it to - request the remote ``uri``, so that the correct encoding is - detected and used. - - If it isn't, or if the scheme of the ``uri`` is not ``http`` or - ``https``, UTF-8 is assumed. - - Arguments: - - uri (str): - - The URI to resolve - - Returns: - - The retrieved document - - .. _requests: https://pypi.org/project/requests/ - """ - try: - import requests - except ImportError: - requests = None - - scheme = urlsplit(uri).scheme - - if scheme in self.handlers: - result = self.handlers[scheme](uri) - elif scheme in ["http", "https"] and requests: - # Requests has support for detecting the correct encoding of - # json over http - result = requests.get(uri).json() - else: - # Otherwise, pass off to urllib and assume utf-8 - with urlopen(uri) as url: - result = json.loads(url.read().decode("utf-8")) - - if self.cache_remote: - self.store[uri] = result - return result - - -_SUBSCHEMAS_KEYWORDS = ("$id", "id", "$anchor", "$dynamicAnchor") - - -def _match_keyword(keyword): - - def matcher(value): - if keyword in value: - yield value - - return matcher - - -def _match_subschema_keywords(value): - for keyword in _SUBSCHEMAS_KEYWORDS: - if keyword in value: - yield keyword, value - - -def _search_schema(schema, matcher): - """Breadth-first search routine.""" - values = deque([schema]) - while values: - value = values.pop() - if not isinstance(value, dict): - continue - yield from matcher(value) - values.extendleft(value.values()) - - -def validate(instance, schema, cls=None, *args, **kwargs): - """ - Validate an instance under the given schema. - - >>> validate([2, 3, 4], {"maxItems": 2}) - Traceback (most recent call last): - ... - ValidationError: [2, 3, 4] is too long - - :func:`validate` will first verify that the provided schema is - itself valid, since not doing so can lead to less obvious error - messages and fail in less obvious or consistent ways. - - If you know you have a valid schema already, especially if you - intend to validate multiple instances with the same schema, you - likely would prefer using the `Validator.validate` method directly - on a specific validator (e.g. ``Draft7Validator.validate``). - - - Arguments: - - instance: - - The instance to validate - - schema: - - The schema to validate with - - cls (Validator): - - The class that will be used to validate the instance. - - If the ``cls`` argument is not provided, two things will happen - in accordance with the specification. First, if the schema has a - :validator:`$schema` property containing a known meta-schema [#]_ - then the proper validator will be used. The specification recommends - that all schemas contain :validator:`$schema` properties for this - reason. If no :validator:`$schema` property is found, the default - validator class is the latest released draft. - - Any other provided positional and keyword arguments will be passed - on when instantiating the ``cls``. - - Raises: - - `jsonschema.exceptions.ValidationError` if the instance - is invalid - - `jsonschema.exceptions.SchemaError` if the schema itself - is invalid - - .. rubric:: Footnotes - .. [#] known by a validator registered with - `jsonschema.validators.validates` - """ - if cls is None: - cls = validator_for(schema) - - cls.check_schema(schema) - validator = cls(schema, *args, **kwargs) - error = exceptions.best_match(validator.iter_errors(instance)) - if error is not None: - raise error - - -def validator_for(schema, default=_LATEST_VERSION): - """ - Retrieve the validator class appropriate for validating the given schema. - - Uses the :validator:`$schema` property that should be present in the - given schema to look up the appropriate validator class. - - Arguments: - - schema (collections.abc.Mapping or bool): - - the schema to look at - - default: - - the default to return if the appropriate validator class - cannot be determined. - - If unprovided, the default is to return the latest supported - draft. - """ - if schema is True or schema is False or "$schema" not in schema: - return default - if schema["$schema"] not in _META_SCHEMAS: - warn( - ( - "The metaschema specified by $schema was not found. " - "Using the latest draft to validate, but this will raise " - "an error in the future." - ), - DeprecationWarning, - stacklevel=2, - ) - return _META_SCHEMAS.get(schema["$schema"], _LATEST_VERSION) diff --git a/json/package.json b/package.json index 75da9e2..75da9e2 100644 --- a/json/package.json +++ b/package.json diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 5041a10..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,99 +0,0 @@ -[build-system] -requires = ["hatchling", "hatch-vcs"] -build-backend = "hatchling.build" - -[tool.hatch.version] -source = "vcs" - -[project] -name = "jsonschema" -description = "An implementation of JSON Schema validation for Python" -readme = "README.rst" -requires-python = ">=3.7" -license = {text = "MIT"} -keywords = ["validation", "data validation", "jsonschema", "json"] -authors = [ - {email = "Julian+jsonschema@GrayVines.com"}, - {name = "Julian Berman"}, -] -classifiers = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", -] -dynamic = ["version"] - -dependencies = [ - "attrs>=17.4.0", - "pyrsistent>=0.14.0,!=0.17.0,!=0.17.1,!=0.17.2", - - "importlib_metadata;python_version<'3.8'", - "typing_extensions;python_version<'3.8'", - - "importlib_resources>=1.4.0;python_version<'3.9'", - "pkgutil_resolve_name>=1.3.10;python_version<'3.9'", -] - -[project.optional-dependencies] -format = [ - "fqdn", - "idna", - "isoduration", - "jsonpointer>1.13", - "rfc3339-validator", - "rfc3987", - "uri_template", - "webcolors>=1.11", -] -format-nongpl = [ - "fqdn", - "idna", - "isoduration", - "jsonpointer>1.13", - "rfc3339-validator", - "rfc3986-validator>0.1.0", - "uri_template", - "webcolors>=1.11", -] - -[project.scripts] -jsonschema = "jsonschema.cli:main" - -[project.urls] -Homepage = "https://github.com/python-jsonschema/jsonschema" -Documentation = "https://python-jsonschema.readthedocs.io/" -Issues = "https://github.com/python-jsonschema/jsonschema/issues/" -Funding = "https://github.com/sponsors/Julian" -Tidelift = "https://tidelift.com/subscription/pkg/pypi-jsonschema?utm_source=pypi-jsonschema&utm_medium=referral&utm_campaign=pypi-link" -Changelog = "https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst" -Source = "https://github.com/python-jsonschema/jsonschema" - -[tool.isort] -from_first = true -include_trailing_comma = true -multi_line_output = 3 - -[tool.mypy] -ignore_missing_imports = true - -[tool.pydocstyle] -match = "(?!(test_|_|compat|cli)).*\\.py" # see PyCQA/pydocstyle#323 -add-select = [ - "D410", # Trailing whitespace plz -] -add-ignore = [ - "D107", # Hah, no - "D200", # 1-line docstrings don't need to be on one line - "D202", # One line is fine. - "D412", # Trailing whitespace plz - "D413", # No trailing whitespace plz -] diff --git a/json/remotes/baseUriChange/folderInteger.json b/remotes/baseUriChange/folderInteger.json index 8b50ea3..8b50ea3 100644 --- a/json/remotes/baseUriChange/folderInteger.json +++ b/remotes/baseUriChange/folderInteger.json diff --git a/json/remotes/baseUriChangeFolder/folderInteger.json b/remotes/baseUriChangeFolder/folderInteger.json index 8b50ea3..8b50ea3 100644 --- a/json/remotes/baseUriChangeFolder/folderInteger.json +++ b/remotes/baseUriChangeFolder/folderInteger.json diff --git a/json/remotes/baseUriChangeFolderInSubschema/folderInteger.json b/remotes/baseUriChangeFolderInSubschema/folderInteger.json index 8b50ea3..8b50ea3 100644 --- a/json/remotes/baseUriChangeFolderInSubschema/folderInteger.json +++ b/remotes/baseUriChangeFolderInSubschema/folderInteger.json diff --git a/json/remotes/draft-next/format-assertion-false.json b/remotes/draft-next/format-assertion-false.json index 1a55fed..1a55fed 100644 --- a/json/remotes/draft-next/format-assertion-false.json +++ b/remotes/draft-next/format-assertion-false.json diff --git a/json/remotes/draft-next/format-assertion-true.json b/remotes/draft-next/format-assertion-true.json index 5862dfe..5862dfe 100644 --- a/json/remotes/draft-next/format-assertion-true.json +++ b/remotes/draft-next/format-assertion-true.json diff --git a/json/remotes/draft-next/metaschema-no-validation.json b/remotes/draft-next/metaschema-no-validation.json index 2b50c05..2b50c05 100644 --- a/json/remotes/draft-next/metaschema-no-validation.json +++ b/remotes/draft-next/metaschema-no-validation.json diff --git a/json/remotes/draft2019-09/metaschema-no-validation.json b/remotes/draft2019-09/metaschema-no-validation.json index 9a54944..9a54944 100644 --- a/json/remotes/draft2019-09/metaschema-no-validation.json +++ b/remotes/draft2019-09/metaschema-no-validation.json diff --git a/json/remotes/draft2020-12/format-assertion-false.json b/remotes/draft2020-12/format-assertion-false.json index f1c64d2..f1c64d2 100644 --- a/json/remotes/draft2020-12/format-assertion-false.json +++ b/remotes/draft2020-12/format-assertion-false.json diff --git a/json/remotes/draft2020-12/format-assertion-true.json b/remotes/draft2020-12/format-assertion-true.json index e3d12c8..e3d12c8 100644 --- a/json/remotes/draft2020-12/format-assertion-true.json +++ b/remotes/draft2020-12/format-assertion-true.json diff --git a/json/remotes/draft2020-12/metaschema-no-validation.json b/remotes/draft2020-12/metaschema-no-validation.json index d71f440..d71f440 100644 --- a/json/remotes/draft2020-12/metaschema-no-validation.json +++ b/remotes/draft2020-12/metaschema-no-validation.json diff --git a/json/remotes/extendible-dynamic-ref.json b/remotes/extendible-dynamic-ref.json index d0bcd37..d0bcd37 100644 --- a/json/remotes/extendible-dynamic-ref.json +++ b/remotes/extendible-dynamic-ref.json diff --git a/json/remotes/integer.json b/remotes/integer.json index 8b50ea3..8b50ea3 100644 --- a/json/remotes/integer.json +++ b/remotes/integer.json diff --git a/json/remotes/locationIndependentIdentifier.json b/remotes/locationIndependentIdentifier.json index 96b17c3..96b17c3 100644 --- a/json/remotes/locationIndependentIdentifier.json +++ b/remotes/locationIndependentIdentifier.json diff --git a/json/remotes/locationIndependentIdentifierDraft4.json b/remotes/locationIndependentIdentifierDraft4.json index eeff1eb..eeff1eb 100644 --- a/json/remotes/locationIndependentIdentifierDraft4.json +++ b/remotes/locationIndependentIdentifierDraft4.json diff --git a/json/remotes/locationIndependentIdentifierPre2019.json b/remotes/locationIndependentIdentifierPre2019.json index e72815c..e72815c 100644 --- a/json/remotes/locationIndependentIdentifierPre2019.json +++ b/remotes/locationIndependentIdentifierPre2019.json diff --git a/json/remotes/name-defs.json b/remotes/name-defs.json index 1dab4a4..1dab4a4 100644 --- a/json/remotes/name-defs.json +++ b/remotes/name-defs.json diff --git a/json/remotes/name.json b/remotes/name.json index fceacb8..fceacb8 100644 --- a/json/remotes/name.json +++ b/remotes/name.json diff --git a/json/remotes/nested/foo-ref-string.json b/remotes/nested/foo-ref-string.json index 9cd2527..9cd2527 100644 --- a/json/remotes/nested/foo-ref-string.json +++ b/remotes/nested/foo-ref-string.json diff --git a/json/remotes/nested/string.json b/remotes/nested/string.json index c2d48c0..c2d48c0 100644 --- a/json/remotes/nested/string.json +++ b/remotes/nested/string.json diff --git a/json/remotes/ref-and-definitions.json b/remotes/ref-and-definitions.json index e0ee802..e0ee802 100644 --- a/json/remotes/ref-and-definitions.json +++ b/remotes/ref-and-definitions.json diff --git a/json/remotes/ref-and-defs.json b/remotes/ref-and-defs.json index 85d06c3..85d06c3 100644 --- a/json/remotes/ref-and-defs.json +++ b/remotes/ref-and-defs.json diff --git a/json/remotes/subSchemas-defs.json b/remotes/subSchemas-defs.json index 50b7b6d..50b7b6d 100644 --- a/json/remotes/subSchemas-defs.json +++ b/remotes/subSchemas-defs.json diff --git a/json/remotes/subSchemas.json b/remotes/subSchemas.json index 9f8030b..9f8030b 100644 --- a/json/remotes/subSchemas.json +++ b/remotes/subSchemas.json diff --git a/json/remotes/tree.json b/remotes/tree.json index a12d98b..a12d98b 100644 --- a/json/remotes/tree.json +++ b/remotes/tree.json diff --git a/json/test-schema.json b/test-schema.json index 5d25031..5d25031 100644 --- a/json/test-schema.json +++ b/test-schema.json diff --git a/json/tests/draft-next/additionalProperties.json b/tests/draft-next/additionalProperties.json index 98b8842..98b8842 100644 --- a/json/tests/draft-next/additionalProperties.json +++ b/tests/draft-next/additionalProperties.json diff --git a/json/tests/draft-next/allOf.json b/tests/draft-next/allOf.json index ec9319e..ec9319e 100644 --- a/json/tests/draft-next/allOf.json +++ b/tests/draft-next/allOf.json diff --git a/json/tests/draft-next/anchor.json b/tests/draft-next/anchor.json index f0fcf02..9744a3c 100644 --- a/json/tests/draft-next/anchor.json +++ b/tests/draft-next/anchor.json @@ -159,12 +159,12 @@ }, "tests": [ { - "description": "$ref should resolve to /$defs/A/allOf/1", + "description": "$ref resolves to /$defs/A/allOf/1", "data": "a", "valid": true }, { - "description": "$ref should not resolve to /$defs/A/allOf/0", + "description": "$ref does not resolve to /$defs/A/allOf/0", "data": 1, "valid": false } diff --git a/json/tests/draft-next/anyOf.json b/tests/draft-next/anyOf.json index ab5eb38..ab5eb38 100644 --- a/json/tests/draft-next/anyOf.json +++ b/tests/draft-next/anyOf.json diff --git a/json/tests/draft-next/boolean_schema.json b/tests/draft-next/boolean_schema.json index 6d40f23..6d40f23 100644 --- a/json/tests/draft-next/boolean_schema.json +++ b/tests/draft-next/boolean_schema.json diff --git a/json/tests/draft-next/const.json b/tests/draft-next/const.json index 1c2cafc..1c2cafc 100644 --- a/json/tests/draft-next/const.json +++ b/tests/draft-next/const.json diff --git a/json/tests/draft-next/contains.json b/tests/draft-next/contains.json index 5f3d05a..5f3d05a 100644 --- a/json/tests/draft-next/contains.json +++ b/tests/draft-next/contains.json diff --git a/json/tests/draft-next/content.json b/tests/draft-next/content.json index 44688e8..44688e8 100644 --- a/json/tests/draft-next/content.json +++ b/tests/draft-next/content.json diff --git a/json/tests/draft-next/default.json b/tests/draft-next/default.json index 289a9b6..289a9b6 100644 --- a/json/tests/draft-next/default.json +++ b/tests/draft-next/default.json diff --git a/json/tests/draft-next/defs.json b/tests/draft-next/defs.json index 1282164..1282164 100644 --- a/json/tests/draft-next/defs.json +++ b/tests/draft-next/defs.json diff --git a/json/tests/draft-next/dependentRequired.json b/tests/draft-next/dependentRequired.json index c817120..c817120 100644 --- a/json/tests/draft-next/dependentRequired.json +++ b/tests/draft-next/dependentRequired.json diff --git a/json/tests/draft-next/dependentSchemas.json b/tests/draft-next/dependentSchemas.json index 2ba1a75..2ba1a75 100644 --- a/json/tests/draft-next/dependentSchemas.json +++ b/tests/draft-next/dependentSchemas.json diff --git a/json/tests/draft-next/dynamicRef.json b/tests/draft-next/dynamicRef.json index d022856..79f04b5 100644 --- a/json/tests/draft-next/dynamicRef.json +++ b/tests/draft-next/dynamicRef.json @@ -374,7 +374,7 @@ ] }, { - "description": "Tests for implementation dynamic anchor and reference link. Reference should be independent of any possible ordering.", + "description": "$ref and $dynamicAnchor are independent of order - $defs first", "schema": { "$id": "http://localhost:1234/strict-extendible-allof-defs-first.json", "allOf": [ @@ -424,7 +424,7 @@ ] }, { - "description": "Tests for implementation dynamic anchor and reference link. Reference should be independent of any possible ordering.", + "description": "$ref and $dynamicAnchor are independent of order - $ref first", "schema": { "$id": "http://localhost:1234/strict-extendible-allof-ref-first.json", "allOf": [ diff --git a/json/tests/draft-next/enum.json b/tests/draft-next/enum.json index f085097..f085097 100644 --- a/json/tests/draft-next/enum.json +++ b/tests/draft-next/enum.json diff --git a/json/tests/draft-next/exclusiveMaximum.json b/tests/draft-next/exclusiveMaximum.json index dc3cd70..dc3cd70 100644 --- a/json/tests/draft-next/exclusiveMaximum.json +++ b/tests/draft-next/exclusiveMaximum.json diff --git a/json/tests/draft-next/exclusiveMinimum.json b/tests/draft-next/exclusiveMinimum.json index b38d7ec..b38d7ec 100644 --- a/json/tests/draft-next/exclusiveMinimum.json +++ b/tests/draft-next/exclusiveMinimum.json diff --git a/json/tests/draft-next/format.json b/tests/draft-next/format.json index a4b51d2..a4b51d2 100644 --- a/json/tests/draft-next/format.json +++ b/tests/draft-next/format.json diff --git a/json/tests/draft-next/id.json b/tests/draft-next/id.json index db7afaf..db7afaf 100644 --- a/json/tests/draft-next/id.json +++ b/tests/draft-next/id.json diff --git a/json/tests/draft-next/if-then-else.json b/tests/draft-next/if-then-else.json index 284e919..284e919 100644 --- a/json/tests/draft-next/if-then-else.json +++ b/tests/draft-next/if-then-else.json diff --git a/json/tests/draft-next/infinite-loop-detection.json b/tests/draft-next/infinite-loop-detection.json index 9c3c362..9c3c362 100644 --- a/json/tests/draft-next/infinite-loop-detection.json +++ b/tests/draft-next/infinite-loop-detection.json diff --git a/json/tests/draft-next/items.json b/tests/draft-next/items.json index 1f0bdcf..01f20e6 100644 --- a/json/tests/draft-next/items.json +++ b/tests/draft-next/items.json @@ -214,7 +214,7 @@ ] }, { - "description": "items should not look in applicators, valid case", + "description": "items does not look in applicators, valid case", "schema": { "allOf": [ { "prefixItems": [ { "minimum": 3 } ] } @@ -223,12 +223,12 @@ }, "tests": [ { - "description": "prefixItems in allOf should not constrain items, invalid case", + "description": "prefixItems in allOf does not constrain items, invalid case", "data": [ 3, 5 ], "valid": false }, { - "description": "prefixItems in allOf should not constrain items, valid case", + "description": "prefixItems in allOf does not constrain items, valid case", "data": [ 5, 5 ], "valid": true } @@ -254,7 +254,7 @@ ] }, { - "description": "items should properly handle null data", + "description": "items with null", "schema": { "items": { "type": "null" @@ -262,7 +262,7 @@ }, "tests": [ { - "description": "null items allowed", + "description": "allows null elements", "data": [ null ], "valid": true } diff --git a/json/tests/draft-next/maxContains.json b/tests/draft-next/maxContains.json index 7ed1dcf..7ed1dcf 100644 --- a/json/tests/draft-next/maxContains.json +++ b/tests/draft-next/maxContains.json diff --git a/json/tests/draft-next/maxItems.json b/tests/draft-next/maxItems.json index f0c36ab..f0c36ab 100644 --- a/json/tests/draft-next/maxItems.json +++ b/tests/draft-next/maxItems.json diff --git a/json/tests/draft-next/maxLength.json b/tests/draft-next/maxLength.json index 748b4da..748b4da 100644 --- a/json/tests/draft-next/maxLength.json +++ b/tests/draft-next/maxLength.json diff --git a/json/tests/draft-next/maxProperties.json b/tests/draft-next/maxProperties.json index acec142..acec142 100644 --- a/json/tests/draft-next/maxProperties.json +++ b/tests/draft-next/maxProperties.json diff --git a/json/tests/draft-next/maximum.json b/tests/draft-next/maximum.json index 6844a39..6844a39 100644 --- a/json/tests/draft-next/maximum.json +++ b/tests/draft-next/maximum.json diff --git a/json/tests/draft-next/minContains.json b/tests/draft-next/minContains.json index b83d1bd..b83d1bd 100644 --- a/json/tests/draft-next/minContains.json +++ b/tests/draft-next/minContains.json diff --git a/json/tests/draft-next/minItems.json b/tests/draft-next/minItems.json index d3b1872..d3b1872 100644 --- a/json/tests/draft-next/minItems.json +++ b/tests/draft-next/minItems.json diff --git a/json/tests/draft-next/minLength.json b/tests/draft-next/minLength.json index 64db948..64db948 100644 --- a/json/tests/draft-next/minLength.json +++ b/tests/draft-next/minLength.json diff --git a/json/tests/draft-next/minProperties.json b/tests/draft-next/minProperties.json index 9f74f78..9f74f78 100644 --- a/json/tests/draft-next/minProperties.json +++ b/tests/draft-next/minProperties.json diff --git a/json/tests/draft-next/minimum.json b/tests/draft-next/minimum.json index 21ae50e..21ae50e 100644 --- a/json/tests/draft-next/minimum.json +++ b/tests/draft-next/minimum.json diff --git a/json/tests/draft-next/multipleOf.json b/tests/draft-next/multipleOf.json index faa87cf..faa87cf 100644 --- a/json/tests/draft-next/multipleOf.json +++ b/tests/draft-next/multipleOf.json diff --git a/json/tests/draft-next/not.json b/tests/draft-next/not.json index 98de0ed..98de0ed 100644 --- a/json/tests/draft-next/not.json +++ b/tests/draft-next/not.json diff --git a/json/tests/draft-next/oneOf.json b/tests/draft-next/oneOf.json index eeb7ae8..eeb7ae8 100644 --- a/json/tests/draft-next/oneOf.json +++ b/tests/draft-next/oneOf.json diff --git a/json/tests/draft2020-12/optional/bignum.json b/tests/draft-next/optional/bignum.json index 3f49226..94b4a4e 100644 --- a/json/tests/draft2020-12/optional/bignum.json +++ b/tests/draft-next/optional/bignum.json @@ -43,7 +43,7 @@ ] }, { - "description": "integer comparison", + "description": "maximum integer comparison", "schema": { "maximum": 18446744073709551615 }, "tests": [ { @@ -67,7 +67,7 @@ ] }, { - "description": "integer comparison", + "description": "minimum integer comparison", "schema": { "minimum": -18446744073709551615 }, "tests": [ { diff --git a/json/tests/draft-next/optional/dependencies-compatibility.json b/tests/draft-next/optional/dependencies-compatibility.json index 6eafaf0..6eafaf0 100644 --- a/json/tests/draft-next/optional/dependencies-compatibility.json +++ b/tests/draft-next/optional/dependencies-compatibility.json diff --git a/json/tests/draft-next/optional/ecmascript-regex.json b/tests/draft-next/optional/ecmascript-regex.json index 5bbfc45..9f79d42 100644 --- a/json/tests/draft-next/optional/ecmascript-regex.json +++ b/tests/draft-next/optional/ecmascript-regex.json @@ -7,12 +7,12 @@ }, "tests": [ { - "description": "matches in Python, but should not in jsonschema", + "description": "matches in Python, but not in ECMA 262", "data": "abc\\n", "valid": false }, { - "description": "should match", + "description": "matches", "data": "abc", "valid": true } @@ -342,7 +342,7 @@ ] }, { - "description": "unicode characters do not match ascii ranges", + "description": "pattern with ASCII ranges", "schema": { "pattern": "[a-z]cole" }, "tests": [ { @@ -395,7 +395,7 @@ ] }, { - "description": "unicode digits are more than 0 through 9", + "description": "pattern with non-ASCII digits", "schema": { "pattern": "^\\p{digit}+$" }, "tests": [ { @@ -480,7 +480,7 @@ ] }, { - "description": "unicode characters do not match ascii ranges", + "description": "patternProperties with ASCII ranges", "schema": { "type": "object", "patternProperties": { @@ -534,7 +534,7 @@ ] }, { - "description": "unicode digits are more than 0 through 9", + "description": "patternProperties with non-ASCII digits", "schema": { "type": "object", "patternProperties": { diff --git a/json/tests/draft-next/optional/float-overflow.json b/tests/draft-next/optional/float-overflow.json index 52ff982..52ff982 100644 --- a/json/tests/draft-next/optional/float-overflow.json +++ b/tests/draft-next/optional/float-overflow.json diff --git a/json/tests/draft-next/optional/format-assertion.json b/tests/draft-next/optional/format-assertion.json index ede922a..ede922a 100644 --- a/json/tests/draft-next/optional/format-assertion.json +++ b/tests/draft-next/optional/format-assertion.json diff --git a/json/tests/draft2020-12/optional/format/date-time.json b/tests/draft-next/optional/format/date-time.json index f4f9933..0911273 100644 --- a/json/tests/draft2020-12/optional/format/date-time.json +++ b/tests/draft-next/optional/format/date-time.json @@ -119,12 +119,12 @@ "valid": false }, { - "description": "non-ascii digits should be rejected in the date portion", + "description": "invalid non-ASCII '৪' (a Bengali 4) in date portion", "data": "1963-06-1৪T00:00:00Z", "valid": false }, { - "description": "non-ascii digits should be rejected in the time portion", + "description": "invalid non-ASCII '৪' (a Bengali 4) in time portion", "data": "1963-06-11T0৪:00:00Z", "valid": false } diff --git a/json/tests/draft2019-09/optional/format/date.json b/tests/draft-next/optional/format/date.json index b4f61ee..06c9ea0 100644 --- a/json/tests/draft2019-09/optional/format/date.json +++ b/tests/draft-next/optional/format/date.json @@ -214,7 +214,7 @@ "valid": true }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '৪' (a Bengali 4)", "data": "1963-06-1৪", "valid": false } diff --git a/json/tests/draft2019-09/optional/format/duration.json b/tests/draft-next/optional/format/duration.json index 741348a..a6acdc1 100644 --- a/json/tests/draft2019-09/optional/format/duration.json +++ b/tests/draft-next/optional/format/duration.json @@ -119,7 +119,7 @@ "valid": false }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '২' (a Bengali 2)", "data": "P২Y", "valid": false } diff --git a/json/tests/draft-next/optional/format/email.json b/tests/draft-next/optional/format/email.json index 5ce1c70..5ce1c70 100644 --- a/json/tests/draft-next/optional/format/email.json +++ b/tests/draft-next/optional/format/email.json diff --git a/json/tests/draft-next/optional/format/hostname.json b/tests/draft-next/optional/format/hostname.json index 8a67fda..8a67fda 100644 --- a/json/tests/draft-next/optional/format/hostname.json +++ b/tests/draft-next/optional/format/hostname.json diff --git a/json/tests/draft-next/optional/format/idn-email.json b/tests/draft-next/optional/format/idn-email.json index 6e21374..6e21374 100644 --- a/json/tests/draft-next/optional/format/idn-email.json +++ b/tests/draft-next/optional/format/idn-email.json diff --git a/json/tests/draft-next/optional/format/idn-hostname.json b/tests/draft-next/optional/format/idn-hostname.json index 6c8f86a..6c8f86a 100644 --- a/json/tests/draft-next/optional/format/idn-hostname.json +++ b/tests/draft-next/optional/format/idn-hostname.json diff --git a/json/tests/draft2019-09/optional/format/ipv4.json b/tests/draft-next/optional/format/ipv4.json index 6b166c7..4706581 100644 --- a/json/tests/draft2019-09/optional/format/ipv4.json +++ b/tests/draft-next/optional/format/ipv4.json @@ -64,7 +64,7 @@ "valid": false }, { - "description": "leading zeroes should be rejected, as they are treated as octals", + "description": "invalid leading zeroes, as they are treated as octals", "comment": "see https://sick.codes/universal-netmask-npm-package-used-by-270000-projects-vulnerable-to-octal-input-data-server-side-request-forgery-remote-file-inclusion-local-file-inclusion-and-more-cve-2021-28918/", "data": "087.10.0.1", "valid": false @@ -75,7 +75,7 @@ "valid": true }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '২' (a Bengali 2)", "data": "1২7.0.0.1", "valid": false } diff --git a/json/tests/draft-next/optional/format/ipv6.json b/tests/draft-next/optional/format/ipv6.json index 6379927..94368f2 100644 --- a/json/tests/draft-next/optional/format/ipv6.json +++ b/tests/draft-next/optional/format/ipv6.json @@ -194,12 +194,12 @@ "valid": false }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '৪' (a Bengali 4)", "data": "1:2:3:4:5:6:7:৪", "valid": false }, { - "description": "non-ascii digits should be rejected in the ipv4 portion also", + "description": "invalid non-ASCII '৪' (a Bengali 4) in the IPv4 portion", "data": "1:2::192.16৪.0.1", "valid": false } diff --git a/json/tests/draft-next/optional/format/iri-reference.json b/tests/draft-next/optional/format/iri-reference.json index c6b4c22..c6b4c22 100644 --- a/json/tests/draft-next/optional/format/iri-reference.json +++ b/tests/draft-next/optional/format/iri-reference.json diff --git a/json/tests/draft-next/optional/format/iri.json b/tests/draft-next/optional/format/iri.json index a0d12ae..a0d12ae 100644 --- a/json/tests/draft-next/optional/format/iri.json +++ b/tests/draft-next/optional/format/iri.json diff --git a/json/tests/draft-next/optional/format/json-pointer.json b/tests/draft-next/optional/format/json-pointer.json index a0346b5..a0346b5 100644 --- a/json/tests/draft-next/optional/format/json-pointer.json +++ b/tests/draft-next/optional/format/json-pointer.json diff --git a/json/tests/draft-next/optional/format/regex.json b/tests/draft-next/optional/format/regex.json index 3449177..3449177 100644 --- a/json/tests/draft-next/optional/format/regex.json +++ b/tests/draft-next/optional/format/regex.json diff --git a/json/tests/draft-next/optional/format/relative-json-pointer.json b/tests/draft-next/optional/format/relative-json-pointer.json index 9309986..9309986 100644 --- a/json/tests/draft-next/optional/format/relative-json-pointer.json +++ b/tests/draft-next/optional/format/relative-json-pointer.json diff --git a/json/tests/draft2020-12/optional/format/time.json b/tests/draft-next/optional/format/time.json index 5011d78..3142587 100644 --- a/json/tests/draft2020-12/optional/format/time.json +++ b/tests/draft-next/optional/format/time.json @@ -189,7 +189,7 @@ "valid": false }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '২' (a Bengali 2)", "data": "1২:00:00Z", "valid": false } diff --git a/json/tests/draft-next/optional/format/uri-reference.json b/tests/draft-next/optional/format/uri-reference.json index 7cdf228..7cdf228 100644 --- a/json/tests/draft-next/optional/format/uri-reference.json +++ b/tests/draft-next/optional/format/uri-reference.json diff --git a/json/tests/draft-next/optional/format/uri-template.json b/tests/draft-next/optional/format/uri-template.json index df355c5..df355c5 100644 --- a/json/tests/draft-next/optional/format/uri-template.json +++ b/tests/draft-next/optional/format/uri-template.json diff --git a/json/tests/draft-next/optional/format/uri.json b/tests/draft-next/optional/format/uri.json index 792d71a..792d71a 100644 --- a/json/tests/draft-next/optional/format/uri.json +++ b/tests/draft-next/optional/format/uri.json diff --git a/json/tests/draft-next/optional/format/uuid.json b/tests/draft-next/optional/format/uuid.json index e54cbc0..e54cbc0 100644 --- a/json/tests/draft-next/optional/format/uuid.json +++ b/tests/draft-next/optional/format/uuid.json diff --git a/json/tests/draft-next/optional/non-bmp-regex.json b/tests/draft-next/optional/non-bmp-regex.json index dd67af2..dd67af2 100644 --- a/json/tests/draft-next/optional/non-bmp-regex.json +++ b/tests/draft-next/optional/non-bmp-regex.json diff --git a/json/tests/draft-next/optional/refOfUnknownKeyword.json b/tests/draft-next/optional/refOfUnknownKeyword.json index 5b150df..5b150df 100644 --- a/json/tests/draft-next/optional/refOfUnknownKeyword.json +++ b/tests/draft-next/optional/refOfUnknownKeyword.json diff --git a/json/tests/draft-next/pattern.json b/tests/draft-next/pattern.json index 92db0f9..92db0f9 100644 --- a/json/tests/draft-next/pattern.json +++ b/tests/draft-next/pattern.json diff --git a/json/tests/draft-next/patternProperties.json b/tests/draft-next/patternProperties.json index 34b2e85..34b2e85 100644 --- a/json/tests/draft-next/patternProperties.json +++ b/tests/draft-next/patternProperties.json diff --git a/json/tests/draft2020-12/prefixItems.json b/tests/draft-next/prefixItems.json index f72da11..8dc58ed 100644 --- a/json/tests/draft2020-12/prefixItems.json +++ b/tests/draft-next/prefixItems.json @@ -79,7 +79,7 @@ ] }, { - "description": "prefixItems should properly handle null data", + "description": "prefixItems properly handles null data", "schema": { "prefixItems": [ { diff --git a/json/tests/draft-next/properties.json b/tests/draft-next/properties.json index 8c3ed35..8c3ed35 100644 --- a/json/tests/draft-next/properties.json +++ b/tests/draft-next/properties.json diff --git a/json/tests/draft-next/propertyNames.json b/tests/draft-next/propertyNames.json index 8423690..8423690 100644 --- a/json/tests/draft-next/propertyNames.json +++ b/tests/draft-next/propertyNames.json diff --git a/json/tests/draft-next/ref.json b/tests/draft-next/ref.json index 05fea36..189eb41 100644 --- a/json/tests/draft-next/ref.json +++ b/tests/draft-next/ref.json @@ -567,12 +567,12 @@ }, "tests": [ { - "description": "number should pass", + "description": "number is valid", "data": 1, "valid": true }, { - "description": "non-number should fail", + "description": "non-number is invalid", "data": "a", "valid": false } diff --git a/json/tests/draft-next/refRemote.json b/tests/draft-next/refRemote.json index a844039..a844039 100644 --- a/json/tests/draft-next/refRemote.json +++ b/tests/draft-next/refRemote.json diff --git a/json/tests/draft-next/required.json b/tests/draft-next/required.json index abf18f3..abf18f3 100644 --- a/json/tests/draft-next/required.json +++ b/tests/draft-next/required.json diff --git a/json/tests/draft-next/type.json b/tests/draft-next/type.json index 8304647..8304647 100644 --- a/json/tests/draft-next/type.json +++ b/tests/draft-next/type.json diff --git a/json/tests/draft-next/unevaluatedItems.json b/tests/draft-next/unevaluatedItems.json index eedb19f..eedb19f 100644 --- a/json/tests/draft-next/unevaluatedItems.json +++ b/tests/draft-next/unevaluatedItems.json diff --git a/json/tests/draft-next/unevaluatedProperties.json b/tests/draft-next/unevaluatedProperties.json index e7865d1..e7865d1 100644 --- a/json/tests/draft-next/unevaluatedProperties.json +++ b/tests/draft-next/unevaluatedProperties.json diff --git a/json/tests/draft-next/uniqueItems.json b/tests/draft-next/uniqueItems.json index 85c619d..85c619d 100644 --- a/json/tests/draft-next/uniqueItems.json +++ b/tests/draft-next/uniqueItems.json diff --git a/json/tests/draft-next/unknownKeyword.json b/tests/draft-next/unknownKeyword.json index e46657d..e46657d 100644 --- a/json/tests/draft-next/unknownKeyword.json +++ b/tests/draft-next/unknownKeyword.json diff --git a/json/tests/draft-next/vocabulary.json b/tests/draft-next/vocabulary.json index 65b81ea..65b81ea 100644 --- a/json/tests/draft-next/vocabulary.json +++ b/tests/draft-next/vocabulary.json diff --git a/json/tests/draft2019-09/additionalItems.json b/tests/draft2019-09/additionalItems.json index 454142b..454142b 100644 --- a/json/tests/draft2019-09/additionalItems.json +++ b/tests/draft2019-09/additionalItems.json diff --git a/json/tests/draft2019-09/additionalProperties.json b/tests/draft2019-09/additionalProperties.json index 98b8842..98b8842 100644 --- a/json/tests/draft2019-09/additionalProperties.json +++ b/tests/draft2019-09/additionalProperties.json diff --git a/json/tests/draft2019-09/allOf.json b/tests/draft2019-09/allOf.json index ec9319e..ec9319e 100644 --- a/json/tests/draft2019-09/allOf.json +++ b/tests/draft2019-09/allOf.json diff --git a/json/tests/draft2019-09/anchor.json b/tests/draft2019-09/anchor.json index 4143d1f..7a9e32d 100644 --- a/json/tests/draft2019-09/anchor.json +++ b/tests/draft2019-09/anchor.json @@ -159,12 +159,12 @@ }, "tests": [ { - "description": "$ref should resolve to /$defs/A/allOf/1", + "description": "$ref resolves to /$defs/A/allOf/1", "data": "a", "valid": true }, { - "description": "$ref should not resolve to /$defs/A/allOf/0", + "description": "$ref does not resolve to /$defs/A/allOf/0", "data": 1, "valid": false } diff --git a/json/tests/draft2019-09/anyOf.json b/tests/draft2019-09/anyOf.json index ab5eb38..ab5eb38 100644 --- a/json/tests/draft2019-09/anyOf.json +++ b/tests/draft2019-09/anyOf.json diff --git a/json/tests/draft2019-09/boolean_schema.json b/tests/draft2019-09/boolean_schema.json index 6d40f23..6d40f23 100644 --- a/json/tests/draft2019-09/boolean_schema.json +++ b/tests/draft2019-09/boolean_schema.json diff --git a/json/tests/draft2019-09/const.json b/tests/draft2019-09/const.json index 1c2cafc..1c2cafc 100644 --- a/json/tests/draft2019-09/const.json +++ b/tests/draft2019-09/const.json diff --git a/json/tests/draft2019-09/contains.json b/tests/draft2019-09/contains.json index a6add6b..a6add6b 100644 --- a/json/tests/draft2019-09/contains.json +++ b/tests/draft2019-09/contains.json diff --git a/json/tests/draft2019-09/content.json b/tests/draft2019-09/content.json index 44688e8..44688e8 100644 --- a/json/tests/draft2019-09/content.json +++ b/tests/draft2019-09/content.json diff --git a/json/tests/draft2019-09/default.json b/tests/draft2019-09/default.json index 289a9b6..289a9b6 100644 --- a/json/tests/draft2019-09/default.json +++ b/tests/draft2019-09/default.json diff --git a/json/tests/draft2019-09/defs.json b/tests/draft2019-09/defs.json index 70e9dc0..70e9dc0 100644 --- a/json/tests/draft2019-09/defs.json +++ b/tests/draft2019-09/defs.json diff --git a/json/tests/draft2019-09/dependentRequired.json b/tests/draft2019-09/dependentRequired.json index c817120..c817120 100644 --- a/json/tests/draft2019-09/dependentRequired.json +++ b/tests/draft2019-09/dependentRequired.json diff --git a/json/tests/draft2019-09/dependentSchemas.json b/tests/draft2019-09/dependentSchemas.json index 2ba1a75..2ba1a75 100644 --- a/json/tests/draft2019-09/dependentSchemas.json +++ b/tests/draft2019-09/dependentSchemas.json diff --git a/json/tests/draft2019-09/enum.json b/tests/draft2019-09/enum.json index f085097..f085097 100644 --- a/json/tests/draft2019-09/enum.json +++ b/tests/draft2019-09/enum.json diff --git a/json/tests/draft2019-09/exclusiveMaximum.json b/tests/draft2019-09/exclusiveMaximum.json index dc3cd70..dc3cd70 100644 --- a/json/tests/draft2019-09/exclusiveMaximum.json +++ b/tests/draft2019-09/exclusiveMaximum.json diff --git a/json/tests/draft2019-09/exclusiveMinimum.json b/tests/draft2019-09/exclusiveMinimum.json index b38d7ec..b38d7ec 100644 --- a/json/tests/draft2019-09/exclusiveMinimum.json +++ b/tests/draft2019-09/exclusiveMinimum.json diff --git a/json/tests/draft2019-09/format.json b/tests/draft2019-09/format.json index a4b51d2..a4b51d2 100644 --- a/json/tests/draft2019-09/format.json +++ b/tests/draft2019-09/format.json diff --git a/json/tests/draft2019-09/id.json b/tests/draft2019-09/id.json index 0d825ea..0d825ea 100644 --- a/json/tests/draft2019-09/id.json +++ b/tests/draft2019-09/id.json diff --git a/json/tests/draft2019-09/if-then-else.json b/tests/draft2019-09/if-then-else.json index 284e919..284e919 100644 --- a/json/tests/draft2019-09/if-then-else.json +++ b/tests/draft2019-09/if-then-else.json diff --git a/json/tests/draft2019-09/infinite-loop-detection.json b/tests/draft2019-09/infinite-loop-detection.json index 9c3c362..9c3c362 100644 --- a/json/tests/draft2019-09/infinite-loop-detection.json +++ b/tests/draft2019-09/infinite-loop-detection.json diff --git a/json/tests/draft2019-09/items.json b/tests/draft2019-09/items.json index 58992fc..c77ba0b 100644 --- a/json/tests/draft2019-09/items.json +++ b/tests/draft2019-09/items.json @@ -263,7 +263,7 @@ ] }, { - "description": "array-form items should properly handle null data", + "description": "array-form items with null instance elements", "schema": { "items": [ { @@ -273,7 +273,7 @@ }, "tests": [ { - "description": "null items allowed", + "description": "allows null elements", "data": [ null ], "valid": true } diff --git a/json/tests/draft2019-09/maxContains.json b/tests/draft2019-09/maxContains.json index 61c967d..61c967d 100644 --- a/json/tests/draft2019-09/maxContains.json +++ b/tests/draft2019-09/maxContains.json diff --git a/json/tests/draft2019-09/maxItems.json b/tests/draft2019-09/maxItems.json index f0c36ab..f0c36ab 100644 --- a/json/tests/draft2019-09/maxItems.json +++ b/tests/draft2019-09/maxItems.json diff --git a/json/tests/draft2019-09/maxLength.json b/tests/draft2019-09/maxLength.json index 748b4da..748b4da 100644 --- a/json/tests/draft2019-09/maxLength.json +++ b/tests/draft2019-09/maxLength.json diff --git a/json/tests/draft2019-09/maxProperties.json b/tests/draft2019-09/maxProperties.json index acec142..acec142 100644 --- a/json/tests/draft2019-09/maxProperties.json +++ b/tests/draft2019-09/maxProperties.json diff --git a/json/tests/draft2019-09/maximum.json b/tests/draft2019-09/maximum.json index 6844a39..6844a39 100644 --- a/json/tests/draft2019-09/maximum.json +++ b/tests/draft2019-09/maximum.json diff --git a/json/tests/draft2019-09/minContains.json b/tests/draft2019-09/minContains.json index 1d3b5a5..1d3b5a5 100644 --- a/json/tests/draft2019-09/minContains.json +++ b/tests/draft2019-09/minContains.json diff --git a/json/tests/draft2019-09/minItems.json b/tests/draft2019-09/minItems.json index d3b1872..d3b1872 100644 --- a/json/tests/draft2019-09/minItems.json +++ b/tests/draft2019-09/minItems.json diff --git a/json/tests/draft2019-09/minLength.json b/tests/draft2019-09/minLength.json index 64db948..64db948 100644 --- a/json/tests/draft2019-09/minLength.json +++ b/tests/draft2019-09/minLength.json diff --git a/json/tests/draft2019-09/minProperties.json b/tests/draft2019-09/minProperties.json index 9f74f78..9f74f78 100644 --- a/json/tests/draft2019-09/minProperties.json +++ b/tests/draft2019-09/minProperties.json diff --git a/json/tests/draft2019-09/minimum.json b/tests/draft2019-09/minimum.json index 21ae50e..21ae50e 100644 --- a/json/tests/draft2019-09/minimum.json +++ b/tests/draft2019-09/minimum.json diff --git a/json/tests/draft2019-09/multipleOf.json b/tests/draft2019-09/multipleOf.json index faa87cf..faa87cf 100644 --- a/json/tests/draft2019-09/multipleOf.json +++ b/tests/draft2019-09/multipleOf.json diff --git a/json/tests/draft2019-09/not.json b/tests/draft2019-09/not.json index 98de0ed..98de0ed 100644 --- a/json/tests/draft2019-09/not.json +++ b/tests/draft2019-09/not.json diff --git a/json/tests/draft2019-09/oneOf.json b/tests/draft2019-09/oneOf.json index eeb7ae8..eeb7ae8 100644 --- a/json/tests/draft2019-09/oneOf.json +++ b/tests/draft2019-09/oneOf.json diff --git a/json/tests/draft2019-09/optional/bignum.json b/tests/draft2019-09/optional/bignum.json index 3f49226..94b4a4e 100644 --- a/json/tests/draft2019-09/optional/bignum.json +++ b/tests/draft2019-09/optional/bignum.json @@ -43,7 +43,7 @@ ] }, { - "description": "integer comparison", + "description": "maximum integer comparison", "schema": { "maximum": 18446744073709551615 }, "tests": [ { @@ -67,7 +67,7 @@ ] }, { - "description": "integer comparison", + "description": "minimum integer comparison", "schema": { "minimum": -18446744073709551615 }, "tests": [ { diff --git a/json/tests/draft2019-09/optional/dependencies-compatibility.json b/tests/draft2019-09/optional/dependencies-compatibility.json index 6eafaf0..6eafaf0 100644 --- a/json/tests/draft2019-09/optional/dependencies-compatibility.json +++ b/tests/draft2019-09/optional/dependencies-compatibility.json diff --git a/json/tests/draft2019-09/optional/ecmascript-regex.json b/tests/draft2019-09/optional/ecmascript-regex.json index 1beb0b3..764248f 100644 --- a/json/tests/draft2019-09/optional/ecmascript-regex.json +++ b/tests/draft2019-09/optional/ecmascript-regex.json @@ -7,12 +7,12 @@ }, "tests": [ { - "description": "matches in Python, but should not in jsonschema", + "description": "matches in Python, but not in ECMA 262", "data": "abc\\n", "valid": false }, { - "description": "should match", + "description": "matches", "data": "abc", "valid": true } @@ -342,7 +342,7 @@ ] }, { - "description": "unicode characters do not match ascii ranges", + "description": "pattern with ASCII ranges", "schema": { "pattern": "[a-z]cole" }, "tests": [ { @@ -384,7 +384,7 @@ ] }, { - "description": "unicode digits are more than 0 through 9", + "description": "pattern with non-ASCII digits", "schema": { "pattern": "^\\p{digit}+$" }, "tests": [ { @@ -469,7 +469,7 @@ ] }, { - "description": "unicode characters do not match ascii ranges", + "description": "patternProperties with ASCII ranges", "schema": { "type": "object", "patternProperties": { @@ -523,7 +523,7 @@ ] }, { - "description": "unicode digits are more than 0 through 9", + "description": "patternProperties with non-ASCII digits", "schema": { "type": "object", "patternProperties": { diff --git a/json/tests/draft2019-09/optional/float-overflow.json b/tests/draft2019-09/optional/float-overflow.json index 52ff982..52ff982 100644 --- a/json/tests/draft2019-09/optional/float-overflow.json +++ b/tests/draft2019-09/optional/float-overflow.json diff --git a/json/tests/draft2019-09/optional/format/date-time.json b/tests/draft2019-09/optional/format/date-time.json index f4f9933..0911273 100644 --- a/json/tests/draft2019-09/optional/format/date-time.json +++ b/tests/draft2019-09/optional/format/date-time.json @@ -119,12 +119,12 @@ "valid": false }, { - "description": "non-ascii digits should be rejected in the date portion", + "description": "invalid non-ASCII '৪' (a Bengali 4) in date portion", "data": "1963-06-1৪T00:00:00Z", "valid": false }, { - "description": "non-ascii digits should be rejected in the time portion", + "description": "invalid non-ASCII '৪' (a Bengali 4) in time portion", "data": "1963-06-11T0৪:00:00Z", "valid": false } diff --git a/json/tests/draft2020-12/optional/format/date.json b/tests/draft2019-09/optional/format/date.json index b4f61ee..06c9ea0 100644 --- a/json/tests/draft2020-12/optional/format/date.json +++ b/tests/draft2019-09/optional/format/date.json @@ -214,7 +214,7 @@ "valid": true }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '৪' (a Bengali 4)", "data": "1963-06-1৪", "valid": false } diff --git a/json/tests/draft2020-12/optional/format/duration.json b/tests/draft2019-09/optional/format/duration.json index 741348a..a6acdc1 100644 --- a/json/tests/draft2020-12/optional/format/duration.json +++ b/tests/draft2019-09/optional/format/duration.json @@ -119,7 +119,7 @@ "valid": false }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '২' (a Bengali 2)", "data": "P২Y", "valid": false } diff --git a/json/tests/draft2019-09/optional/format/email.json b/tests/draft2019-09/optional/format/email.json index d6761a4..d6761a4 100644 --- a/json/tests/draft2019-09/optional/format/email.json +++ b/tests/draft2019-09/optional/format/email.json diff --git a/json/tests/draft2019-09/optional/format/hostname.json b/tests/draft2019-09/optional/format/hostname.json index 8a67fda..8a67fda 100644 --- a/json/tests/draft2019-09/optional/format/hostname.json +++ b/tests/draft2019-09/optional/format/hostname.json diff --git a/json/tests/draft2019-09/optional/format/idn-email.json b/tests/draft2019-09/optional/format/idn-email.json index 6e21374..6e21374 100644 --- a/json/tests/draft2019-09/optional/format/idn-email.json +++ b/tests/draft2019-09/optional/format/idn-email.json diff --git a/json/tests/draft2019-09/optional/format/idn-hostname.json b/tests/draft2019-09/optional/format/idn-hostname.json index 6c8f86a..6c8f86a 100644 --- a/json/tests/draft2019-09/optional/format/idn-hostname.json +++ b/tests/draft2019-09/optional/format/idn-hostname.json diff --git a/json/tests/draft2020-12/optional/format/ipv4.json b/tests/draft2019-09/optional/format/ipv4.json index 6b166c7..4706581 100644 --- a/json/tests/draft2020-12/optional/format/ipv4.json +++ b/tests/draft2019-09/optional/format/ipv4.json @@ -64,7 +64,7 @@ "valid": false }, { - "description": "leading zeroes should be rejected, as they are treated as octals", + "description": "invalid leading zeroes, as they are treated as octals", "comment": "see https://sick.codes/universal-netmask-npm-package-used-by-270000-projects-vulnerable-to-octal-input-data-server-side-request-forgery-remote-file-inclusion-local-file-inclusion-and-more-cve-2021-28918/", "data": "087.10.0.1", "valid": false @@ -75,7 +75,7 @@ "valid": true }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '২' (a Bengali 2)", "data": "1২7.0.0.1", "valid": false } diff --git a/json/tests/draft2020-12/optional/format/ipv6.json b/tests/draft2019-09/optional/format/ipv6.json index 6379927..94368f2 100644 --- a/json/tests/draft2020-12/optional/format/ipv6.json +++ b/tests/draft2019-09/optional/format/ipv6.json @@ -194,12 +194,12 @@ "valid": false }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '৪' (a Bengali 4)", "data": "1:2:3:4:5:6:7:৪", "valid": false }, { - "description": "non-ascii digits should be rejected in the ipv4 portion also", + "description": "invalid non-ASCII '৪' (a Bengali 4) in the IPv4 portion", "data": "1:2::192.16৪.0.1", "valid": false } diff --git a/json/tests/draft2019-09/optional/format/iri-reference.json b/tests/draft2019-09/optional/format/iri-reference.json index c6b4c22..c6b4c22 100644 --- a/json/tests/draft2019-09/optional/format/iri-reference.json +++ b/tests/draft2019-09/optional/format/iri-reference.json diff --git a/json/tests/draft2019-09/optional/format/iri.json b/tests/draft2019-09/optional/format/iri.json index a0d12ae..a0d12ae 100644 --- a/json/tests/draft2019-09/optional/format/iri.json +++ b/tests/draft2019-09/optional/format/iri.json diff --git a/json/tests/draft2019-09/optional/format/json-pointer.json b/tests/draft2019-09/optional/format/json-pointer.json index a0346b5..a0346b5 100644 --- a/json/tests/draft2019-09/optional/format/json-pointer.json +++ b/tests/draft2019-09/optional/format/json-pointer.json diff --git a/json/tests/draft2019-09/optional/format/regex.json b/tests/draft2019-09/optional/format/regex.json index 3449177..3449177 100644 --- a/json/tests/draft2019-09/optional/format/regex.json +++ b/tests/draft2019-09/optional/format/regex.json diff --git a/json/tests/draft2019-09/optional/format/relative-json-pointer.json b/tests/draft2019-09/optional/format/relative-json-pointer.json index 9309986..9309986 100644 --- a/json/tests/draft2019-09/optional/format/relative-json-pointer.json +++ b/tests/draft2019-09/optional/format/relative-json-pointer.json diff --git a/json/tests/draft7/optional/format/time.json b/tests/draft2019-09/optional/format/time.json index 5011d78..3142587 100644 --- a/json/tests/draft7/optional/format/time.json +++ b/tests/draft2019-09/optional/format/time.json @@ -189,7 +189,7 @@ "valid": false }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '২' (a Bengali 2)", "data": "1২:00:00Z", "valid": false } diff --git a/json/tests/draft2019-09/optional/format/unknown.json b/tests/draft2019-09/optional/format/unknown.json index 12339ae..12339ae 100644 --- a/json/tests/draft2019-09/optional/format/unknown.json +++ b/tests/draft2019-09/optional/format/unknown.json diff --git a/json/tests/draft2019-09/optional/format/uri-reference.json b/tests/draft2019-09/optional/format/uri-reference.json index 7cdf228..7cdf228 100644 --- a/json/tests/draft2019-09/optional/format/uri-reference.json +++ b/tests/draft2019-09/optional/format/uri-reference.json diff --git a/json/tests/draft2019-09/optional/format/uri-template.json b/tests/draft2019-09/optional/format/uri-template.json index df355c5..df355c5 100644 --- a/json/tests/draft2019-09/optional/format/uri-template.json +++ b/tests/draft2019-09/optional/format/uri-template.json diff --git a/json/tests/draft2019-09/optional/format/uri.json b/tests/draft2019-09/optional/format/uri.json index 792d71a..792d71a 100644 --- a/json/tests/draft2019-09/optional/format/uri.json +++ b/tests/draft2019-09/optional/format/uri.json diff --git a/json/tests/draft2019-09/optional/format/uuid.json b/tests/draft2019-09/optional/format/uuid.json index e54cbc0..e54cbc0 100644 --- a/json/tests/draft2019-09/optional/format/uuid.json +++ b/tests/draft2019-09/optional/format/uuid.json diff --git a/json/tests/draft2019-09/optional/non-bmp-regex.json b/tests/draft2019-09/optional/non-bmp-regex.json index dd67af2..dd67af2 100644 --- a/json/tests/draft2019-09/optional/non-bmp-regex.json +++ b/tests/draft2019-09/optional/non-bmp-regex.json diff --git a/json/tests/draft2019-09/optional/refOfUnknownKeyword.json b/tests/draft2019-09/optional/refOfUnknownKeyword.json index 5b150df..5b150df 100644 --- a/json/tests/draft2019-09/optional/refOfUnknownKeyword.json +++ b/tests/draft2019-09/optional/refOfUnknownKeyword.json diff --git a/json/tests/draft2019-09/pattern.json b/tests/draft2019-09/pattern.json index 92db0f9..92db0f9 100644 --- a/json/tests/draft2019-09/pattern.json +++ b/tests/draft2019-09/pattern.json diff --git a/json/tests/draft2019-09/patternProperties.json b/tests/draft2019-09/patternProperties.json index 34b2e85..34b2e85 100644 --- a/json/tests/draft2019-09/patternProperties.json +++ b/tests/draft2019-09/patternProperties.json diff --git a/json/tests/draft2019-09/properties.json b/tests/draft2019-09/properties.json index 8c3ed35..8c3ed35 100644 --- a/json/tests/draft2019-09/properties.json +++ b/tests/draft2019-09/properties.json diff --git a/json/tests/draft2019-09/propertyNames.json b/tests/draft2019-09/propertyNames.json index f0788e6..f0788e6 100644 --- a/json/tests/draft2019-09/propertyNames.json +++ b/tests/draft2019-09/propertyNames.json diff --git a/json/tests/draft2019-09/recursiveRef.json b/tests/draft2019-09/recursiveRef.json index ebb098c..ebb098c 100644 --- a/json/tests/draft2019-09/recursiveRef.json +++ b/tests/draft2019-09/recursiveRef.json diff --git a/json/tests/draft2019-09/ref.json b/tests/draft2019-09/ref.json index 32e3c66..6d1e90e 100644 --- a/json/tests/draft2019-09/ref.json +++ b/tests/draft2019-09/ref.json @@ -567,12 +567,12 @@ }, "tests": [ { - "description": "number should pass", + "description": "number is valid", "data": 1, "valid": true }, { - "description": "non-number should fail", + "description": "non-number is invalid", "data": "a", "valid": false } diff --git a/json/tests/draft2019-09/refRemote.json b/tests/draft2019-09/refRemote.json index a844039..a844039 100644 --- a/json/tests/draft2019-09/refRemote.json +++ b/tests/draft2019-09/refRemote.json diff --git a/json/tests/draft2019-09/required.json b/tests/draft2019-09/required.json index abf18f3..abf18f3 100644 --- a/json/tests/draft2019-09/required.json +++ b/tests/draft2019-09/required.json diff --git a/json/tests/draft2019-09/type.json b/tests/draft2019-09/type.json index 8304647..8304647 100644 --- a/json/tests/draft2019-09/type.json +++ b/tests/draft2019-09/type.json diff --git a/json/tests/draft2019-09/unevaluatedItems.json b/tests/draft2019-09/unevaluatedItems.json index 3bf8483..3bf8483 100644 --- a/json/tests/draft2019-09/unevaluatedItems.json +++ b/tests/draft2019-09/unevaluatedItems.json diff --git a/json/tests/draft2019-09/unevaluatedProperties.json b/tests/draft2019-09/unevaluatedProperties.json index 894f683..894f683 100644 --- a/json/tests/draft2019-09/unevaluatedProperties.json +++ b/tests/draft2019-09/unevaluatedProperties.json diff --git a/json/tests/draft2019-09/uniqueItems.json b/tests/draft2019-09/uniqueItems.json index 2ccf666..2ccf666 100644 --- a/json/tests/draft2019-09/uniqueItems.json +++ b/tests/draft2019-09/uniqueItems.json diff --git a/json/tests/draft2019-09/unknownKeyword.json b/tests/draft2019-09/unknownKeyword.json index e46657d..e46657d 100644 --- a/json/tests/draft2019-09/unknownKeyword.json +++ b/tests/draft2019-09/unknownKeyword.json diff --git a/json/tests/draft2019-09/vocabulary.json b/tests/draft2019-09/vocabulary.json index 982e673..982e673 100644 --- a/json/tests/draft2019-09/vocabulary.json +++ b/tests/draft2019-09/vocabulary.json diff --git a/json/tests/draft2020-12/additionalProperties.json b/tests/draft2020-12/additionalProperties.json index 98b8842..98b8842 100644 --- a/json/tests/draft2020-12/additionalProperties.json +++ b/tests/draft2020-12/additionalProperties.json diff --git a/json/tests/draft2020-12/allOf.json b/tests/draft2020-12/allOf.json index ec9319e..ec9319e 100644 --- a/json/tests/draft2020-12/allOf.json +++ b/tests/draft2020-12/allOf.json diff --git a/json/tests/draft2020-12/anchor.json b/tests/draft2020-12/anchor.json index 17e9080..8a6a5ea 100644 --- a/json/tests/draft2020-12/anchor.json +++ b/tests/draft2020-12/anchor.json @@ -159,12 +159,12 @@ }, "tests": [ { - "description": "$ref should resolve to /$defs/A/allOf/1", + "description": "$ref resolves to /$defs/A/allOf/1", "data": "a", "valid": true }, { - "description": "$ref should not resolve to /$defs/A/allOf/0", + "description": "$ref does not resolve to /$defs/A/allOf/0", "data": 1, "valid": false } diff --git a/json/tests/draft2020-12/anyOf.json b/tests/draft2020-12/anyOf.json index ab5eb38..ab5eb38 100644 --- a/json/tests/draft2020-12/anyOf.json +++ b/tests/draft2020-12/anyOf.json diff --git a/json/tests/draft2020-12/boolean_schema.json b/tests/draft2020-12/boolean_schema.json index 6d40f23..6d40f23 100644 --- a/json/tests/draft2020-12/boolean_schema.json +++ b/tests/draft2020-12/boolean_schema.json diff --git a/json/tests/draft2020-12/const.json b/tests/draft2020-12/const.json index 1c2cafc..1c2cafc 100644 --- a/json/tests/draft2020-12/const.json +++ b/tests/draft2020-12/const.json diff --git a/json/tests/draft2020-12/contains.json b/tests/draft2020-12/contains.json index a6add6b..a6add6b 100644 --- a/json/tests/draft2020-12/contains.json +++ b/tests/draft2020-12/contains.json diff --git a/json/tests/draft2020-12/content.json b/tests/draft2020-12/content.json index 44688e8..44688e8 100644 --- a/json/tests/draft2020-12/content.json +++ b/tests/draft2020-12/content.json diff --git a/json/tests/draft2020-12/default.json b/tests/draft2020-12/default.json index 289a9b6..289a9b6 100644 --- a/json/tests/draft2020-12/default.json +++ b/tests/draft2020-12/default.json diff --git a/json/tests/draft2020-12/defs.json b/tests/draft2020-12/defs.json index c738be2..c738be2 100644 --- a/json/tests/draft2020-12/defs.json +++ b/tests/draft2020-12/defs.json diff --git a/json/tests/draft2020-12/dependentRequired.json b/tests/draft2020-12/dependentRequired.json index c817120..c817120 100644 --- a/json/tests/draft2020-12/dependentRequired.json +++ b/tests/draft2020-12/dependentRequired.json diff --git a/json/tests/draft2020-12/dependentSchemas.json b/tests/draft2020-12/dependentSchemas.json index 2ba1a75..2ba1a75 100644 --- a/json/tests/draft2020-12/dependentSchemas.json +++ b/tests/draft2020-12/dependentSchemas.json diff --git a/json/tests/draft2020-12/dynamicRef.json b/tests/draft2020-12/dynamicRef.json index 618d836..3a51356 100644 --- a/json/tests/draft2020-12/dynamicRef.json +++ b/tests/draft2020-12/dynamicRef.json @@ -517,7 +517,7 @@ ] }, { - "description": "Tests for implementation dynamic anchor and reference link. Reference should be independent of any possible ordering.", + "description": "$ref and $dynamicAnchor are independent of order - $defs first", "schema": { "$id": "http://localhost:1234/strict-extendible-allof-defs-first.json", "allOf": [ @@ -567,7 +567,7 @@ ] }, { - "description": "Tests for implementation dynamic anchor and reference link. Reference should be independent of any possible ordering.", + "description": "$ref and $dynamicAnchor are independent of order - $ref first", "schema": { "$id": "http://localhost:1234/strict-extendible-allof-ref-first.json", "allOf": [ diff --git a/json/tests/draft2020-12/enum.json b/tests/draft2020-12/enum.json index f085097..f085097 100644 --- a/json/tests/draft2020-12/enum.json +++ b/tests/draft2020-12/enum.json diff --git a/json/tests/draft2020-12/exclusiveMaximum.json b/tests/draft2020-12/exclusiveMaximum.json index dc3cd70..dc3cd70 100644 --- a/json/tests/draft2020-12/exclusiveMaximum.json +++ b/tests/draft2020-12/exclusiveMaximum.json diff --git a/json/tests/draft2020-12/exclusiveMinimum.json b/tests/draft2020-12/exclusiveMinimum.json index b38d7ec..b38d7ec 100644 --- a/json/tests/draft2020-12/exclusiveMinimum.json +++ b/tests/draft2020-12/exclusiveMinimum.json diff --git a/json/tests/draft2020-12/format.json b/tests/draft2020-12/format.json index a4b51d2..a4b51d2 100644 --- a/json/tests/draft2020-12/format.json +++ b/tests/draft2020-12/format.json diff --git a/json/tests/draft2020-12/id.json b/tests/draft2020-12/id.json index 37fb429..37fb429 100644 --- a/json/tests/draft2020-12/id.json +++ b/tests/draft2020-12/id.json diff --git a/json/tests/draft2020-12/if-then-else.json b/tests/draft2020-12/if-then-else.json index 284e919..284e919 100644 --- a/json/tests/draft2020-12/if-then-else.json +++ b/tests/draft2020-12/if-then-else.json diff --git a/json/tests/draft2020-12/infinite-loop-detection.json b/tests/draft2020-12/infinite-loop-detection.json index 9c3c362..9c3c362 100644 --- a/json/tests/draft2020-12/infinite-loop-detection.json +++ b/tests/draft2020-12/infinite-loop-detection.json diff --git a/json/tests/draft2020-12/items.json b/tests/draft2020-12/items.json index 1f0bdcf..38ab0e0 100644 --- a/json/tests/draft2020-12/items.json +++ b/tests/draft2020-12/items.json @@ -214,7 +214,7 @@ ] }, { - "description": "items should not look in applicators, valid case", + "description": "items does not look in applicators, valid case", "schema": { "allOf": [ { "prefixItems": [ { "minimum": 3 } ] } @@ -223,12 +223,12 @@ }, "tests": [ { - "description": "prefixItems in allOf should not constrain items, invalid case", + "description": "prefixItems in allOf does not constrain items, invalid case", "data": [ 3, 5 ], "valid": false }, { - "description": "prefixItems in allOf should not constrain items, valid case", + "description": "prefixItems in allOf does not constrain items, valid case", "data": [ 5, 5 ], "valid": true } @@ -254,7 +254,7 @@ ] }, { - "description": "items should properly handle null data", + "description": "items with null instance elements", "schema": { "items": { "type": "null" @@ -262,7 +262,7 @@ }, "tests": [ { - "description": "null items allowed", + "description": "allows null elements", "data": [ null ], "valid": true } diff --git a/json/tests/draft2020-12/maxContains.json b/tests/draft2020-12/maxContains.json index 61c967d..61c967d 100644 --- a/json/tests/draft2020-12/maxContains.json +++ b/tests/draft2020-12/maxContains.json diff --git a/json/tests/draft2020-12/maxItems.json b/tests/draft2020-12/maxItems.json index f0c36ab..f0c36ab 100644 --- a/json/tests/draft2020-12/maxItems.json +++ b/tests/draft2020-12/maxItems.json diff --git a/json/tests/draft2020-12/maxLength.json b/tests/draft2020-12/maxLength.json index 748b4da..748b4da 100644 --- a/json/tests/draft2020-12/maxLength.json +++ b/tests/draft2020-12/maxLength.json diff --git a/json/tests/draft2020-12/maxProperties.json b/tests/draft2020-12/maxProperties.json index acec142..acec142 100644 --- a/json/tests/draft2020-12/maxProperties.json +++ b/tests/draft2020-12/maxProperties.json diff --git a/json/tests/draft2020-12/maximum.json b/tests/draft2020-12/maximum.json index 6844a39..6844a39 100644 --- a/json/tests/draft2020-12/maximum.json +++ b/tests/draft2020-12/maximum.json diff --git a/json/tests/draft2020-12/minContains.json b/tests/draft2020-12/minContains.json index 851e262..851e262 100644 --- a/json/tests/draft2020-12/minContains.json +++ b/tests/draft2020-12/minContains.json diff --git a/json/tests/draft2020-12/minItems.json b/tests/draft2020-12/minItems.json index d3b1872..d3b1872 100644 --- a/json/tests/draft2020-12/minItems.json +++ b/tests/draft2020-12/minItems.json diff --git a/json/tests/draft2020-12/minLength.json b/tests/draft2020-12/minLength.json index 64db948..64db948 100644 --- a/json/tests/draft2020-12/minLength.json +++ b/tests/draft2020-12/minLength.json diff --git a/json/tests/draft2020-12/minProperties.json b/tests/draft2020-12/minProperties.json index 9f74f78..9f74f78 100644 --- a/json/tests/draft2020-12/minProperties.json +++ b/tests/draft2020-12/minProperties.json diff --git a/json/tests/draft2020-12/minimum.json b/tests/draft2020-12/minimum.json index 21ae50e..21ae50e 100644 --- a/json/tests/draft2020-12/minimum.json +++ b/tests/draft2020-12/minimum.json diff --git a/json/tests/draft2020-12/multipleOf.json b/tests/draft2020-12/multipleOf.json index faa87cf..faa87cf 100644 --- a/json/tests/draft2020-12/multipleOf.json +++ b/tests/draft2020-12/multipleOf.json diff --git a/json/tests/draft2020-12/not.json b/tests/draft2020-12/not.json index 98de0ed..98de0ed 100644 --- a/json/tests/draft2020-12/not.json +++ b/tests/draft2020-12/not.json diff --git a/json/tests/draft2020-12/oneOf.json b/tests/draft2020-12/oneOf.json index eeb7ae8..eeb7ae8 100644 --- a/json/tests/draft2020-12/oneOf.json +++ b/tests/draft2020-12/oneOf.json diff --git a/json/tests/draft6/optional/bignum.json b/tests/draft2020-12/optional/bignum.json index 3f49226..94b4a4e 100644 --- a/json/tests/draft6/optional/bignum.json +++ b/tests/draft2020-12/optional/bignum.json @@ -43,7 +43,7 @@ ] }, { - "description": "integer comparison", + "description": "maximum integer comparison", "schema": { "maximum": 18446744073709551615 }, "tests": [ { @@ -67,7 +67,7 @@ ] }, { - "description": "integer comparison", + "description": "minimum integer comparison", "schema": { "minimum": -18446744073709551615 }, "tests": [ { diff --git a/json/tests/draft2020-12/optional/dependencies-compatibility.json b/tests/draft2020-12/optional/dependencies-compatibility.json index 6eafaf0..6eafaf0 100644 --- a/json/tests/draft2020-12/optional/dependencies-compatibility.json +++ b/tests/draft2020-12/optional/dependencies-compatibility.json diff --git a/json/tests/draft2020-12/optional/ecmascript-regex.json b/tests/draft2020-12/optional/ecmascript-regex.json index bb92acd..4d57efa 100644 --- a/json/tests/draft2020-12/optional/ecmascript-regex.json +++ b/tests/draft2020-12/optional/ecmascript-regex.json @@ -7,12 +7,12 @@ }, "tests": [ { - "description": "matches in Python, but should not in jsonschema", + "description": "matches in Python, but not in ECMA 262", "data": "abc\\n", "valid": false }, { - "description": "should match", + "description": "matches", "data": "abc", "valid": true } @@ -342,7 +342,7 @@ ] }, { - "description": "unicode characters do not match ascii ranges", + "description": "pattern with ASCII ranges", "schema": { "pattern": "[a-z]cole" }, "tests": [ { @@ -395,7 +395,7 @@ ] }, { - "description": "unicode digits are more than 0 through 9", + "description": "pattern with non-ASCII digits", "schema": { "pattern": "^\\p{digit}+$" }, "tests": [ { @@ -480,7 +480,7 @@ ] }, { - "description": "unicode characters do not match ascii ranges", + "description": "patternProperties with ASCII ranges", "schema": { "type": "object", "patternProperties": { @@ -534,7 +534,7 @@ ] }, { - "description": "unicode digits are more than 0 through 9", + "description": "patternProperties with non-ASCII digits", "schema": { "type": "object", "patternProperties": { diff --git a/json/tests/draft2020-12/optional/float-overflow.json b/tests/draft2020-12/optional/float-overflow.json index 52ff982..52ff982 100644 --- a/json/tests/draft2020-12/optional/float-overflow.json +++ b/tests/draft2020-12/optional/float-overflow.json diff --git a/json/tests/draft2020-12/optional/format-assertion.json b/tests/draft2020-12/optional/format-assertion.json index 0340037..0340037 100644 --- a/json/tests/draft2020-12/optional/format-assertion.json +++ b/tests/draft2020-12/optional/format-assertion.json diff --git a/json/tests/draft-next/optional/format/date-time.json b/tests/draft2020-12/optional/format/date-time.json index f4f9933..0911273 100644 --- a/json/tests/draft-next/optional/format/date-time.json +++ b/tests/draft2020-12/optional/format/date-time.json @@ -119,12 +119,12 @@ "valid": false }, { - "description": "non-ascii digits should be rejected in the date portion", + "description": "invalid non-ASCII '৪' (a Bengali 4) in date portion", "data": "1963-06-1৪T00:00:00Z", "valid": false }, { - "description": "non-ascii digits should be rejected in the time portion", + "description": "invalid non-ASCII '৪' (a Bengali 4) in time portion", "data": "1963-06-11T0৪:00:00Z", "valid": false } diff --git a/json/tests/draft7/optional/format/date.json b/tests/draft2020-12/optional/format/date.json index b4f61ee..06c9ea0 100644 --- a/json/tests/draft7/optional/format/date.json +++ b/tests/draft2020-12/optional/format/date.json @@ -214,7 +214,7 @@ "valid": true }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '৪' (a Bengali 4)", "data": "1963-06-1৪", "valid": false } diff --git a/json/tests/draft-next/optional/format/duration.json b/tests/draft2020-12/optional/format/duration.json index 741348a..a6acdc1 100644 --- a/json/tests/draft-next/optional/format/duration.json +++ b/tests/draft2020-12/optional/format/duration.json @@ -119,7 +119,7 @@ "valid": false }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '২' (a Bengali 2)", "data": "P২Y", "valid": false } diff --git a/json/tests/draft2020-12/optional/format/email.json b/tests/draft2020-12/optional/format/email.json index 5ce1c70..5ce1c70 100644 --- a/json/tests/draft2020-12/optional/format/email.json +++ b/tests/draft2020-12/optional/format/email.json diff --git a/json/tests/draft2020-12/optional/format/hostname.json b/tests/draft2020-12/optional/format/hostname.json index 8a67fda..8a67fda 100644 --- a/json/tests/draft2020-12/optional/format/hostname.json +++ b/tests/draft2020-12/optional/format/hostname.json diff --git a/json/tests/draft2020-12/optional/format/idn-email.json b/tests/draft2020-12/optional/format/idn-email.json index 6e21374..6e21374 100644 --- a/json/tests/draft2020-12/optional/format/idn-email.json +++ b/tests/draft2020-12/optional/format/idn-email.json diff --git a/json/tests/draft2020-12/optional/format/idn-hostname.json b/tests/draft2020-12/optional/format/idn-hostname.json index 6c8f86a..6c8f86a 100644 --- a/json/tests/draft2020-12/optional/format/idn-hostname.json +++ b/tests/draft2020-12/optional/format/idn-hostname.json diff --git a/json/tests/draft4/optional/format/ipv4.json b/tests/draft2020-12/optional/format/ipv4.json index 6b166c7..4706581 100644 --- a/json/tests/draft4/optional/format/ipv4.json +++ b/tests/draft2020-12/optional/format/ipv4.json @@ -64,7 +64,7 @@ "valid": false }, { - "description": "leading zeroes should be rejected, as they are treated as octals", + "description": "invalid leading zeroes, as they are treated as octals", "comment": "see https://sick.codes/universal-netmask-npm-package-used-by-270000-projects-vulnerable-to-octal-input-data-server-side-request-forgery-remote-file-inclusion-local-file-inclusion-and-more-cve-2021-28918/", "data": "087.10.0.1", "valid": false @@ -75,7 +75,7 @@ "valid": true }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '২' (a Bengali 2)", "data": "1২7.0.0.1", "valid": false } diff --git a/json/tests/draft2019-09/optional/format/ipv6.json b/tests/draft2020-12/optional/format/ipv6.json index 6379927..94368f2 100644 --- a/json/tests/draft2019-09/optional/format/ipv6.json +++ b/tests/draft2020-12/optional/format/ipv6.json @@ -194,12 +194,12 @@ "valid": false }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '৪' (a Bengali 4)", "data": "1:2:3:4:5:6:7:৪", "valid": false }, { - "description": "non-ascii digits should be rejected in the ipv4 portion also", + "description": "invalid non-ASCII '৪' (a Bengali 4) in the IPv4 portion", "data": "1:2::192.16৪.0.1", "valid": false } diff --git a/json/tests/draft2020-12/optional/format/iri-reference.json b/tests/draft2020-12/optional/format/iri-reference.json index c6b4c22..c6b4c22 100644 --- a/json/tests/draft2020-12/optional/format/iri-reference.json +++ b/tests/draft2020-12/optional/format/iri-reference.json diff --git a/json/tests/draft2020-12/optional/format/iri.json b/tests/draft2020-12/optional/format/iri.json index a0d12ae..a0d12ae 100644 --- a/json/tests/draft2020-12/optional/format/iri.json +++ b/tests/draft2020-12/optional/format/iri.json diff --git a/json/tests/draft2020-12/optional/format/json-pointer.json b/tests/draft2020-12/optional/format/json-pointer.json index a0346b5..a0346b5 100644 --- a/json/tests/draft2020-12/optional/format/json-pointer.json +++ b/tests/draft2020-12/optional/format/json-pointer.json diff --git a/json/tests/draft2020-12/optional/format/regex.json b/tests/draft2020-12/optional/format/regex.json index 3449177..3449177 100644 --- a/json/tests/draft2020-12/optional/format/regex.json +++ b/tests/draft2020-12/optional/format/regex.json diff --git a/json/tests/draft2020-12/optional/format/relative-json-pointer.json b/tests/draft2020-12/optional/format/relative-json-pointer.json index 9309986..9309986 100644 --- a/json/tests/draft2020-12/optional/format/relative-json-pointer.json +++ b/tests/draft2020-12/optional/format/relative-json-pointer.json diff --git a/json/tests/draft2019-09/optional/format/time.json b/tests/draft2020-12/optional/format/time.json index 5011d78..3142587 100644 --- a/json/tests/draft2019-09/optional/format/time.json +++ b/tests/draft2020-12/optional/format/time.json @@ -189,7 +189,7 @@ "valid": false }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '২' (a Bengali 2)", "data": "1২:00:00Z", "valid": false } diff --git a/json/tests/draft2020-12/optional/format/unknown.json b/tests/draft2020-12/optional/format/unknown.json index 12339ae..12339ae 100644 --- a/json/tests/draft2020-12/optional/format/unknown.json +++ b/tests/draft2020-12/optional/format/unknown.json diff --git a/json/tests/draft2020-12/optional/format/uri-reference.json b/tests/draft2020-12/optional/format/uri-reference.json index 7cdf228..7cdf228 100644 --- a/json/tests/draft2020-12/optional/format/uri-reference.json +++ b/tests/draft2020-12/optional/format/uri-reference.json diff --git a/json/tests/draft2020-12/optional/format/uri-template.json b/tests/draft2020-12/optional/format/uri-template.json index df355c5..df355c5 100644 --- a/json/tests/draft2020-12/optional/format/uri-template.json +++ b/tests/draft2020-12/optional/format/uri-template.json diff --git a/json/tests/draft2020-12/optional/format/uri.json b/tests/draft2020-12/optional/format/uri.json index 792d71a..792d71a 100644 --- a/json/tests/draft2020-12/optional/format/uri.json +++ b/tests/draft2020-12/optional/format/uri.json diff --git a/json/tests/draft2020-12/optional/format/uuid.json b/tests/draft2020-12/optional/format/uuid.json index e54cbc0..e54cbc0 100644 --- a/json/tests/draft2020-12/optional/format/uuid.json +++ b/tests/draft2020-12/optional/format/uuid.json diff --git a/json/tests/draft2020-12/optional/non-bmp-regex.json b/tests/draft2020-12/optional/non-bmp-regex.json index dd67af2..dd67af2 100644 --- a/json/tests/draft2020-12/optional/non-bmp-regex.json +++ b/tests/draft2020-12/optional/non-bmp-regex.json diff --git a/json/tests/draft2020-12/optional/refOfUnknownKeyword.json b/tests/draft2020-12/optional/refOfUnknownKeyword.json index 5b150df..5b150df 100644 --- a/json/tests/draft2020-12/optional/refOfUnknownKeyword.json +++ b/tests/draft2020-12/optional/refOfUnknownKeyword.json diff --git a/json/tests/draft2020-12/pattern.json b/tests/draft2020-12/pattern.json index 92db0f9..92db0f9 100644 --- a/json/tests/draft2020-12/pattern.json +++ b/tests/draft2020-12/pattern.json diff --git a/json/tests/draft2020-12/patternProperties.json b/tests/draft2020-12/patternProperties.json index 34b2e85..34b2e85 100644 --- a/json/tests/draft2020-12/patternProperties.json +++ b/tests/draft2020-12/patternProperties.json diff --git a/json/tests/draft-next/prefixItems.json b/tests/draft2020-12/prefixItems.json index f72da11..f72da11 100644 --- a/json/tests/draft-next/prefixItems.json +++ b/tests/draft2020-12/prefixItems.json diff --git a/json/tests/draft2020-12/properties.json b/tests/draft2020-12/properties.json index 8c3ed35..8c3ed35 100644 --- a/json/tests/draft2020-12/properties.json +++ b/tests/draft2020-12/properties.json diff --git a/json/tests/draft2020-12/propertyNames.json b/tests/draft2020-12/propertyNames.json index 8423690..8423690 100644 --- a/json/tests/draft2020-12/propertyNames.json +++ b/tests/draft2020-12/propertyNames.json diff --git a/json/tests/draft2020-12/ref.json b/tests/draft2020-12/ref.json index bc8ac44..d630047 100644 --- a/json/tests/draft2020-12/ref.json +++ b/tests/draft2020-12/ref.json @@ -567,12 +567,12 @@ }, "tests": [ { - "description": "number should pass", + "description": "number is valid", "data": 1, "valid": true }, { - "description": "non-number should fail", + "description": "non-number is invalid", "data": "a", "valid": false } diff --git a/json/tests/draft2020-12/refRemote.json b/tests/draft2020-12/refRemote.json index a844039..a844039 100644 --- a/json/tests/draft2020-12/refRemote.json +++ b/tests/draft2020-12/refRemote.json diff --git a/json/tests/draft2020-12/required.json b/tests/draft2020-12/required.json index abf18f3..abf18f3 100644 --- a/json/tests/draft2020-12/required.json +++ b/tests/draft2020-12/required.json diff --git a/json/tests/draft2020-12/type.json b/tests/draft2020-12/type.json index 8304647..8304647 100644 --- a/json/tests/draft2020-12/type.json +++ b/tests/draft2020-12/type.json diff --git a/json/tests/draft2020-12/unevaluatedItems.json b/tests/draft2020-12/unevaluatedItems.json index eedb19f..eedb19f 100644 --- a/json/tests/draft2020-12/unevaluatedItems.json +++ b/tests/draft2020-12/unevaluatedItems.json diff --git a/json/tests/draft2020-12/unevaluatedProperties.json b/tests/draft2020-12/unevaluatedProperties.json index 894f683..894f683 100644 --- a/json/tests/draft2020-12/unevaluatedProperties.json +++ b/tests/draft2020-12/unevaluatedProperties.json diff --git a/json/tests/draft2020-12/uniqueItems.json b/tests/draft2020-12/uniqueItems.json index 85c619d..85c619d 100644 --- a/json/tests/draft2020-12/uniqueItems.json +++ b/tests/draft2020-12/uniqueItems.json diff --git a/json/tests/draft2020-12/unknownKeyword.json b/tests/draft2020-12/unknownKeyword.json index e46657d..e46657d 100644 --- a/json/tests/draft2020-12/unknownKeyword.json +++ b/tests/draft2020-12/unknownKeyword.json diff --git a/json/tests/draft2020-12/vocabulary.json b/tests/draft2020-12/vocabulary.json index d84f8f1..d84f8f1 100644 --- a/json/tests/draft2020-12/vocabulary.json +++ b/tests/draft2020-12/vocabulary.json diff --git a/json/tests/draft3/additionalItems.json b/tests/draft3/additionalItems.json index 24b1d86..24b1d86 100644 --- a/json/tests/draft3/additionalItems.json +++ b/tests/draft3/additionalItems.json diff --git a/json/tests/draft3/additionalProperties.json b/tests/draft3/additionalProperties.json index 0a33b3b..0a33b3b 100644 --- a/json/tests/draft3/additionalProperties.json +++ b/tests/draft3/additionalProperties.json diff --git a/json/tests/draft3/default.json b/tests/draft3/default.json index 289a9b6..289a9b6 100644 --- a/json/tests/draft3/default.json +++ b/tests/draft3/default.json diff --git a/json/tests/draft3/dependencies.json b/tests/draft3/dependencies.json index 0ffa6bf..0ffa6bf 100644 --- a/json/tests/draft3/dependencies.json +++ b/tests/draft3/dependencies.json diff --git a/json/tests/draft3/disallow.json b/tests/draft3/disallow.json index a5c9d90..a5c9d90 100644 --- a/json/tests/draft3/disallow.json +++ b/tests/draft3/disallow.json diff --git a/json/tests/draft3/divisibleBy.json b/tests/draft3/divisibleBy.json index ef7cc14..ef7cc14 100644 --- a/json/tests/draft3/divisibleBy.json +++ b/tests/draft3/divisibleBy.json diff --git a/json/tests/draft3/enum.json b/tests/draft3/enum.json index 5a1ab3b..5a1ab3b 100644 --- a/json/tests/draft3/enum.json +++ b/tests/draft3/enum.json diff --git a/json/tests/draft3/extends.json b/tests/draft3/extends.json index 909bce5..909bce5 100644 --- a/json/tests/draft3/extends.json +++ b/tests/draft3/extends.json diff --git a/json/tests/draft3/format.json b/tests/draft3/format.json index a5447c9..a5447c9 100644 --- a/json/tests/draft3/format.json +++ b/tests/draft3/format.json diff --git a/json/tests/draft3/infinite-loop-detection.json b/tests/draft3/infinite-loop-detection.json index 090f49a..090f49a 100644 --- a/json/tests/draft3/infinite-loop-detection.json +++ b/tests/draft3/infinite-loop-detection.json diff --git a/json/tests/draft3/items.json b/tests/draft3/items.json index 586a559..586a559 100644 --- a/json/tests/draft3/items.json +++ b/tests/draft3/items.json diff --git a/json/tests/draft3/maxItems.json b/tests/draft3/maxItems.json index 3b53a6b..3b53a6b 100644 --- a/json/tests/draft3/maxItems.json +++ b/tests/draft3/maxItems.json diff --git a/json/tests/draft3/maxLength.json b/tests/draft3/maxLength.json index 4de42bc..4de42bc 100644 --- a/json/tests/draft3/maxLength.json +++ b/tests/draft3/maxLength.json diff --git a/json/tests/draft3/maximum.json b/tests/draft3/maximum.json index ccb79c6..ccb79c6 100644 --- a/json/tests/draft3/maximum.json +++ b/tests/draft3/maximum.json diff --git a/json/tests/draft3/minItems.json b/tests/draft3/minItems.json index ed51188..ed51188 100644 --- a/json/tests/draft3/minItems.json +++ b/tests/draft3/minItems.json diff --git a/json/tests/draft3/minLength.json b/tests/draft3/minLength.json index 3f09158..3f09158 100644 --- a/json/tests/draft3/minLength.json +++ b/tests/draft3/minLength.json diff --git a/json/tests/draft3/minimum.json b/tests/draft3/minimum.json index d579536..d579536 100644 --- a/json/tests/draft3/minimum.json +++ b/tests/draft3/minimum.json diff --git a/json/tests/draft4/optional/bignum.json b/tests/draft3/optional/bignum.json index 7a622de..1bc8eb2 100644 --- a/json/tests/draft4/optional/bignum.json +++ b/tests/draft3/optional/bignum.json @@ -43,7 +43,7 @@ ] }, { - "description": "integer comparison", + "description": "maximum integer comparison", "schema": { "maximum": 18446744073709551615 }, "tests": [ { @@ -68,7 +68,7 @@ ] }, { - "description": "integer comparison", + "description": "minimum integer comparison", "schema": { "minimum": -18446744073709551615 }, "tests": [ { diff --git a/json/tests/draft3/optional/ecmascript-regex.json b/tests/draft3/optional/ecmascript-regex.json index 03fe977..03fe977 100644 --- a/json/tests/draft3/optional/ecmascript-regex.json +++ b/tests/draft3/optional/ecmascript-regex.json diff --git a/json/tests/draft3/optional/format/color.json b/tests/draft3/optional/format/color.json index 0c0b534..0c0b534 100644 --- a/json/tests/draft3/optional/format/color.json +++ b/tests/draft3/optional/format/color.json diff --git a/json/tests/draft3/optional/format/date-time.json b/tests/draft3/optional/format/date-time.json index 1f1e6fb..1f1e6fb 100644 --- a/json/tests/draft3/optional/format/date-time.json +++ b/tests/draft3/optional/format/date-time.json diff --git a/json/tests/draft3/optional/format/date.json b/tests/draft3/optional/format/date.json index 796bc46..796bc46 100644 --- a/json/tests/draft3/optional/format/date.json +++ b/tests/draft3/optional/format/date.json diff --git a/json/tests/draft3/optional/format/email.json b/tests/draft3/optional/format/email.json index 059615a..059615a 100644 --- a/json/tests/draft3/optional/format/email.json +++ b/tests/draft3/optional/format/email.json diff --git a/json/tests/draft3/optional/format/host-name.json b/tests/draft3/optional/format/host-name.json index d418f37..d418f37 100644 --- a/json/tests/draft3/optional/format/host-name.json +++ b/tests/draft3/optional/format/host-name.json diff --git a/json/tests/draft3/optional/format/ip-address.json b/tests/draft3/optional/format/ip-address.json index 91cac9f..91cac9f 100644 --- a/json/tests/draft3/optional/format/ip-address.json +++ b/tests/draft3/optional/format/ip-address.json diff --git a/json/tests/draft3/optional/format/ipv6.json b/tests/draft3/optional/format/ipv6.json index c3ef379..c3ef379 100644 --- a/json/tests/draft3/optional/format/ipv6.json +++ b/tests/draft3/optional/format/ipv6.json diff --git a/json/tests/draft3/optional/format/regex.json b/tests/draft3/optional/format/regex.json index 8a37763..8a37763 100644 --- a/json/tests/draft3/optional/format/regex.json +++ b/tests/draft3/optional/format/regex.json diff --git a/json/tests/draft3/optional/format/time.json b/tests/draft3/optional/format/time.json index 36c823e..36c823e 100644 --- a/json/tests/draft3/optional/format/time.json +++ b/tests/draft3/optional/format/time.json diff --git a/json/tests/draft3/optional/format/uri.json b/tests/draft3/optional/format/uri.json index f024b62..f024b62 100644 --- a/json/tests/draft3/optional/format/uri.json +++ b/tests/draft3/optional/format/uri.json diff --git a/json/tests/draft3/optional/non-bmp-regex.json b/tests/draft3/optional/non-bmp-regex.json index dd67af2..dd67af2 100644 --- a/json/tests/draft3/optional/non-bmp-regex.json +++ b/tests/draft3/optional/non-bmp-regex.json diff --git a/json/tests/draft3/optional/zeroTerminatedFloats.json b/tests/draft3/optional/zeroTerminatedFloats.json index 9b50ea2..9b50ea2 100644 --- a/json/tests/draft3/optional/zeroTerminatedFloats.json +++ b/tests/draft3/optional/zeroTerminatedFloats.json diff --git a/json/tests/draft3/pattern.json b/tests/draft3/pattern.json index 92db0f9..92db0f9 100644 --- a/json/tests/draft3/pattern.json +++ b/tests/draft3/pattern.json diff --git a/json/tests/draft3/patternProperties.json b/tests/draft3/patternProperties.json index 71954fd..71954fd 100644 --- a/json/tests/draft3/patternProperties.json +++ b/tests/draft3/patternProperties.json diff --git a/json/tests/draft3/properties.json b/tests/draft3/properties.json index 5b6a833..5b6a833 100644 --- a/json/tests/draft3/properties.json +++ b/tests/draft3/properties.json diff --git a/json/tests/draft3/ref.json b/tests/draft3/ref.json index 924db76..924db76 100644 --- a/json/tests/draft3/ref.json +++ b/tests/draft3/ref.json diff --git a/json/tests/draft3/refRemote.json b/tests/draft3/refRemote.json index de0cb43..de0cb43 100644 --- a/json/tests/draft3/refRemote.json +++ b/tests/draft3/refRemote.json diff --git a/json/tests/draft3/required.json b/tests/draft3/required.json index aaaf024..aaaf024 100644 --- a/json/tests/draft3/required.json +++ b/tests/draft3/required.json diff --git a/json/tests/draft3/type.json b/tests/draft3/type.json index f962cc3..f962cc3 100644 --- a/json/tests/draft3/type.json +++ b/tests/draft3/type.json diff --git a/json/tests/draft3/uniqueItems.json b/tests/draft3/uniqueItems.json index c48c6a0..c48c6a0 100644 --- a/json/tests/draft3/uniqueItems.json +++ b/tests/draft3/uniqueItems.json diff --git a/json/tests/draft4/additionalItems.json b/tests/draft4/additionalItems.json index 454142b..454142b 100644 --- a/json/tests/draft4/additionalItems.json +++ b/tests/draft4/additionalItems.json diff --git a/json/tests/draft4/additionalProperties.json b/tests/draft4/additionalProperties.json index 98b8842..98b8842 100644 --- a/json/tests/draft4/additionalProperties.json +++ b/tests/draft4/additionalProperties.json diff --git a/json/tests/draft4/allOf.json b/tests/draft4/allOf.json index fc7dec5..fc7dec5 100644 --- a/json/tests/draft4/allOf.json +++ b/tests/draft4/allOf.json diff --git a/json/tests/draft4/anyOf.json b/tests/draft4/anyOf.json index f8d82e8..09cc3c2 100644 --- a/json/tests/draft4/anyOf.json +++ b/tests/draft4/anyOf.json @@ -152,31 +152,5 @@ "valid": false } ] - }, - { - "description": "nested anyOf, to check validation semantics", - "schema": { - "anyOf": [ - { - "anyOf": [ - { - "type": "null" - } - ] - } - ] - }, - "tests": [ - { - "description": "null is valid", - "data": null, - "valid": true - }, - { - "description": "anything non-null is invalid", - "data": 123, - "valid": false - } - ] } ] diff --git a/json/tests/draft4/default.json b/tests/draft4/default.json index 289a9b6..289a9b6 100644 --- a/json/tests/draft4/default.json +++ b/tests/draft4/default.json diff --git a/json/tests/draft4/definitions.json b/tests/draft4/definitions.json index 482823b..482823b 100644 --- a/json/tests/draft4/definitions.json +++ b/tests/draft4/definitions.json diff --git a/json/tests/draft4/dependencies.json b/tests/draft4/dependencies.json index 51eeddf..51eeddf 100644 --- a/json/tests/draft4/dependencies.json +++ b/tests/draft4/dependencies.json diff --git a/json/tests/draft4/enum.json b/tests/draft4/enum.json index f085097..f085097 100644 --- a/json/tests/draft4/enum.json +++ b/tests/draft4/enum.json diff --git a/json/tests/draft4/format.json b/tests/draft4/format.json index 5bd83cc..5bd83cc 100644 --- a/json/tests/draft4/format.json +++ b/tests/draft4/format.json diff --git a/json/tests/draft4/id.json b/tests/draft4/id.json index 1c91d33..1c91d33 100644 --- a/json/tests/draft4/id.json +++ b/tests/draft4/id.json diff --git a/json/tests/draft4/infinite-loop-detection.json b/tests/draft4/infinite-loop-detection.json index f98c74f..f98c74f 100644 --- a/json/tests/draft4/infinite-loop-detection.json +++ b/tests/draft4/infinite-loop-detection.json diff --git a/json/tests/draft4/items.json b/tests/draft4/items.json index 89801db..89801db 100644 --- a/json/tests/draft4/items.json +++ b/tests/draft4/items.json diff --git a/json/tests/draft4/maxItems.json b/tests/draft4/maxItems.json index 3b53a6b..3b53a6b 100644 --- a/json/tests/draft4/maxItems.json +++ b/tests/draft4/maxItems.json diff --git a/json/tests/draft4/maxLength.json b/tests/draft4/maxLength.json index 811d35b..811d35b 100644 --- a/json/tests/draft4/maxLength.json +++ b/tests/draft4/maxLength.json diff --git a/json/tests/draft4/maxProperties.json b/tests/draft4/maxProperties.json index aa7209f..aa7209f 100644 --- a/json/tests/draft4/maxProperties.json +++ b/tests/draft4/maxProperties.json diff --git a/json/tests/draft4/maximum.json b/tests/draft4/maximum.json index ccb79c6..ccb79c6 100644 --- a/json/tests/draft4/maximum.json +++ b/tests/draft4/maximum.json diff --git a/json/tests/draft4/minItems.json b/tests/draft4/minItems.json index ed51188..ed51188 100644 --- a/json/tests/draft4/minItems.json +++ b/tests/draft4/minItems.json diff --git a/json/tests/draft4/minLength.json b/tests/draft4/minLength.json index 3f09158..3f09158 100644 --- a/json/tests/draft4/minLength.json +++ b/tests/draft4/minLength.json diff --git a/json/tests/draft4/minProperties.json b/tests/draft4/minProperties.json index 49a0726..49a0726 100644 --- a/json/tests/draft4/minProperties.json +++ b/tests/draft4/minProperties.json diff --git a/json/tests/draft4/minimum.json b/tests/draft4/minimum.json index 22d310e..22d310e 100644 --- a/json/tests/draft4/minimum.json +++ b/tests/draft4/minimum.json diff --git a/json/tests/draft4/multipleOf.json b/tests/draft4/multipleOf.json index faa87cf..faa87cf 100644 --- a/json/tests/draft4/multipleOf.json +++ b/tests/draft4/multipleOf.json diff --git a/json/tests/draft4/not.json b/tests/draft4/not.json index cbb7f46..cbb7f46 100644 --- a/json/tests/draft4/not.json +++ b/tests/draft4/not.json diff --git a/json/tests/draft4/oneOf.json b/tests/draft4/oneOf.json index fb63b08..fb63b08 100644 --- a/json/tests/draft4/oneOf.json +++ b/tests/draft4/oneOf.json diff --git a/tests/draft4/optional/bignum.json b/tests/draft4/optional/bignum.json new file mode 100644 index 0000000..1bc8eb2 --- /dev/null +++ b/tests/draft4/optional/bignum.json @@ -0,0 +1,95 @@ +[ + { + "description": "integer", + "schema": { "type": "integer" }, + "tests": [ + { + "description": "a bignum is an integer", + "data": 12345678910111213141516171819202122232425262728293031, + "valid": true + }, + { + "description": "a negative bignum is an integer", + "data": -12345678910111213141516171819202122232425262728293031, + "valid": true + } + ] + }, + { + "description": "number", + "schema": { "type": "number" }, + "tests": [ + { + "description": "a bignum is a number", + "data": 98249283749234923498293171823948729348710298301928331, + "valid": true + }, + { + "description": "a negative bignum is a number", + "data": -98249283749234923498293171823948729348710298301928331, + "valid": true + } + ] + }, + { + "description": "string", + "schema": { "type": "string" }, + "tests": [ + { + "description": "a bignum is not a string", + "data": 98249283749234923498293171823948729348710298301928331, + "valid": false + } + ] + }, + { + "description": "maximum integer comparison", + "schema": { "maximum": 18446744073709551615 }, + "tests": [ + { + "description": "comparison works for high numbers", + "data": 18446744073709551600, + "valid": true + } + ] + }, + { + "description": "float comparison with high precision", + "schema": { + "maximum": 972783798187987123879878123.18878137, + "exclusiveMaximum": true + }, + "tests": [ + { + "description": "comparison works for high numbers", + "data": 972783798187987123879878123.188781371, + "valid": false + } + ] + }, + { + "description": "minimum integer comparison", + "schema": { "minimum": -18446744073709551615 }, + "tests": [ + { + "description": "comparison works for very negative numbers", + "data": -18446744073709551600, + "valid": true + } + ] + }, + { + "description": "float comparison with high precision on negative numbers", + "schema": { + "minimum": -972783798187987123879878123.18878137, + "exclusiveMinimum": true + }, + "tests": [ + { + "description": "comparison works for very negative numbers", + "data": -972783798187987123879878123.188781371, + "valid": false + } + ] + } +] diff --git a/json/tests/draft4/optional/ecmascript-regex.json b/tests/draft4/optional/ecmascript-regex.json index 77624cf..9266c04 100644 --- a/json/tests/draft4/optional/ecmascript-regex.json +++ b/tests/draft4/optional/ecmascript-regex.json @@ -7,12 +7,12 @@ }, "tests": [ { - "description": "matches in Python, but should not in jsonschema", + "description": "matches in Python, but not in ECMA 262", "data": "abc\\n", "valid": false }, { - "description": "should match", + "description": "matches", "data": "abc", "valid": true } @@ -342,7 +342,7 @@ ] }, { - "description": "unicode characters do not match ascii ranges", + "description": "pattern with ASCII ranges", "schema": { "pattern": "[a-z]cole" }, "tests": [ { @@ -384,7 +384,7 @@ ] }, { - "description": "unicode digits are more than 0 through 9", + "description": "pattern with non-ASCII digits", "schema": { "pattern": "^\\p{digit}+$" }, "tests": [ { @@ -469,7 +469,7 @@ ] }, { - "description": "unicode characters do not match ascii ranges", + "description": "patternProperties with ASCII ranges", "schema": { "type": "object", "patternProperties": { @@ -523,7 +523,7 @@ ] }, { - "description": "unicode digits are more than 0 through 9", + "description": "patternProperties with non-ASCII digits", "schema": { "type": "object", "patternProperties": { diff --git a/json/tests/draft4/optional/float-overflow.json b/tests/draft4/optional/float-overflow.json index 47fd5ba..47fd5ba 100644 --- a/json/tests/draft4/optional/float-overflow.json +++ b/tests/draft4/optional/float-overflow.json diff --git a/json/tests/draft4/optional/format/date-time.json b/tests/draft4/optional/format/date-time.json index f4f9933..0911273 100644 --- a/json/tests/draft4/optional/format/date-time.json +++ b/tests/draft4/optional/format/date-time.json @@ -119,12 +119,12 @@ "valid": false }, { - "description": "non-ascii digits should be rejected in the date portion", + "description": "invalid non-ASCII '৪' (a Bengali 4) in date portion", "data": "1963-06-1৪T00:00:00Z", "valid": false }, { - "description": "non-ascii digits should be rejected in the time portion", + "description": "invalid non-ASCII '৪' (a Bengali 4) in time portion", "data": "1963-06-11T0৪:00:00Z", "valid": false } diff --git a/json/tests/draft4/optional/format/email.json b/tests/draft4/optional/format/email.json index d6761a4..d6761a4 100644 --- a/json/tests/draft4/optional/format/email.json +++ b/tests/draft4/optional/format/email.json diff --git a/json/tests/draft4/optional/format/hostname.json b/tests/draft4/optional/format/hostname.json index 8a67fda..8a67fda 100644 --- a/json/tests/draft4/optional/format/hostname.json +++ b/tests/draft4/optional/format/hostname.json diff --git a/json/tests/draft-next/optional/format/ipv4.json b/tests/draft4/optional/format/ipv4.json index 6b166c7..4706581 100644 --- a/json/tests/draft-next/optional/format/ipv4.json +++ b/tests/draft4/optional/format/ipv4.json @@ -64,7 +64,7 @@ "valid": false }, { - "description": "leading zeroes should be rejected, as they are treated as octals", + "description": "invalid leading zeroes, as they are treated as octals", "comment": "see https://sick.codes/universal-netmask-npm-package-used-by-270000-projects-vulnerable-to-octal-input-data-server-side-request-forgery-remote-file-inclusion-local-file-inclusion-and-more-cve-2021-28918/", "data": "087.10.0.1", "valid": false @@ -75,7 +75,7 @@ "valid": true }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '২' (a Bengali 2)", "data": "1২7.0.0.1", "valid": false } diff --git a/json/tests/draft4/optional/format/ipv6.json b/tests/draft4/optional/format/ipv6.json index 6379927..94368f2 100644 --- a/json/tests/draft4/optional/format/ipv6.json +++ b/tests/draft4/optional/format/ipv6.json @@ -194,12 +194,12 @@ "valid": false }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '৪' (a Bengali 4)", "data": "1:2:3:4:5:6:7:৪", "valid": false }, { - "description": "non-ascii digits should be rejected in the ipv4 portion also", + "description": "invalid non-ASCII '৪' (a Bengali 4) in the IPv4 portion", "data": "1:2::192.16৪.0.1", "valid": false } diff --git a/json/tests/draft4/optional/format/unknown.json b/tests/draft4/optional/format/unknown.json index 12339ae..12339ae 100644 --- a/json/tests/draft4/optional/format/unknown.json +++ b/tests/draft4/optional/format/unknown.json diff --git a/json/tests/draft4/optional/format/uri.json b/tests/draft4/optional/format/uri.json index 792d71a..792d71a 100644 --- a/json/tests/draft4/optional/format/uri.json +++ b/tests/draft4/optional/format/uri.json diff --git a/json/tests/draft4/optional/non-bmp-regex.json b/tests/draft4/optional/non-bmp-regex.json index dd67af2..dd67af2 100644 --- a/json/tests/draft4/optional/non-bmp-regex.json +++ b/tests/draft4/optional/non-bmp-regex.json diff --git a/json/tests/draft4/optional/zeroTerminatedFloats.json b/tests/draft4/optional/zeroTerminatedFloats.json index 9b50ea2..9b50ea2 100644 --- a/json/tests/draft4/optional/zeroTerminatedFloats.json +++ b/tests/draft4/optional/zeroTerminatedFloats.json diff --git a/json/tests/draft4/pattern.json b/tests/draft4/pattern.json index 92db0f9..92db0f9 100644 --- a/json/tests/draft4/pattern.json +++ b/tests/draft4/pattern.json diff --git a/json/tests/draft4/patternProperties.json b/tests/draft4/patternProperties.json index 0511763..0511763 100644 --- a/json/tests/draft4/patternProperties.json +++ b/tests/draft4/patternProperties.json diff --git a/json/tests/draft4/properties.json b/tests/draft4/properties.json index 9fcb601..9fcb601 100644 --- a/json/tests/draft4/properties.json +++ b/tests/draft4/properties.json diff --git a/json/tests/draft4/ref.json b/tests/draft4/ref.json index d9978e9..b714fb0 100644 --- a/json/tests/draft4/ref.json +++ b/tests/draft4/ref.json @@ -493,12 +493,12 @@ }, "tests": [ { - "description": "number should pass", + "description": "number is valid", "data": 1, "valid": true }, { - "description": "non-number should fail", + "description": "non-number is invalid", "data": "a", "valid": false } diff --git a/json/tests/draft4/refRemote.json b/tests/draft4/refRemote.json index 412c9ff..412c9ff 100644 --- a/json/tests/draft4/refRemote.json +++ b/tests/draft4/refRemote.json diff --git a/json/tests/draft4/required.json b/tests/draft4/required.json index 9b05318..9b05318 100644 --- a/json/tests/draft4/required.json +++ b/tests/draft4/required.json diff --git a/json/tests/draft4/type.json b/tests/draft4/type.json index df46677..df46677 100644 --- a/json/tests/draft4/type.json +++ b/tests/draft4/type.json diff --git a/json/tests/draft4/uniqueItems.json b/tests/draft4/uniqueItems.json index 2ccf666..2ccf666 100644 --- a/json/tests/draft4/uniqueItems.json +++ b/tests/draft4/uniqueItems.json diff --git a/json/tests/draft6/additionalItems.json b/tests/draft6/additionalItems.json index 454142b..454142b 100644 --- a/json/tests/draft6/additionalItems.json +++ b/tests/draft6/additionalItems.json diff --git a/json/tests/draft6/additionalProperties.json b/tests/draft6/additionalProperties.json index 98b8842..98b8842 100644 --- a/json/tests/draft6/additionalProperties.json +++ b/tests/draft6/additionalProperties.json diff --git a/json/tests/draft6/allOf.json b/tests/draft6/allOf.json index ec9319e..ec9319e 100644 --- a/json/tests/draft6/allOf.json +++ b/tests/draft6/allOf.json diff --git a/json/tests/draft6/anyOf.json b/tests/draft6/anyOf.json index b720afa..ab5eb38 100644 --- a/json/tests/draft6/anyOf.json +++ b/tests/draft6/anyOf.json @@ -185,31 +185,5 @@ "valid": false } ] - }, - { - "description": "nested anyOf, to check validation semantics", - "schema": { - "anyOf": [ - { - "anyOf": [ - { - "type": "null" - } - ] - } - ] - }, - "tests": [ - { - "description": "null is valid", - "data": null, - "valid": true - }, - { - "description": "anything non-null is invalid", - "data": 123, - "valid": false - } - ] } ] diff --git a/json/tests/draft6/boolean_schema.json b/tests/draft6/boolean_schema.json index 6d40f23..6d40f23 100644 --- a/json/tests/draft6/boolean_schema.json +++ b/tests/draft6/boolean_schema.json diff --git a/json/tests/draft6/const.json b/tests/draft6/const.json index 1c2cafc..1c2cafc 100644 --- a/json/tests/draft6/const.json +++ b/tests/draft6/const.json diff --git a/json/tests/draft6/contains.json b/tests/draft6/contains.json index be87c97..be87c97 100644 --- a/json/tests/draft6/contains.json +++ b/tests/draft6/contains.json diff --git a/json/tests/draft6/default.json b/tests/draft6/default.json index 289a9b6..289a9b6 100644 --- a/json/tests/draft6/default.json +++ b/tests/draft6/default.json diff --git a/json/tests/draft6/definitions.json b/tests/draft6/definitions.json index d772fde..d772fde 100644 --- a/json/tests/draft6/definitions.json +++ b/tests/draft6/definitions.json diff --git a/json/tests/draft6/dependencies.json b/tests/draft6/dependencies.json index a5e5428..a5e5428 100644 --- a/json/tests/draft6/dependencies.json +++ b/tests/draft6/dependencies.json diff --git a/json/tests/draft6/enum.json b/tests/draft6/enum.json index f085097..f085097 100644 --- a/json/tests/draft6/enum.json +++ b/tests/draft6/enum.json diff --git a/json/tests/draft6/exclusiveMaximum.json b/tests/draft6/exclusiveMaximum.json index dc3cd70..dc3cd70 100644 --- a/json/tests/draft6/exclusiveMaximum.json +++ b/tests/draft6/exclusiveMaximum.json diff --git a/json/tests/draft6/exclusiveMinimum.json b/tests/draft6/exclusiveMinimum.json index b38d7ec..b38d7ec 100644 --- a/json/tests/draft6/exclusiveMinimum.json +++ b/tests/draft6/exclusiveMinimum.json diff --git a/json/tests/draft6/format.json b/tests/draft6/format.json index 2df2a9f..2df2a9f 100644 --- a/json/tests/draft6/format.json +++ b/tests/draft6/format.json diff --git a/json/tests/draft6/id.json b/tests/draft6/id.json index 0cbff5a..0cbff5a 100644 --- a/json/tests/draft6/id.json +++ b/tests/draft6/id.json diff --git a/json/tests/draft6/infinite-loop-detection.json b/tests/draft6/infinite-loop-detection.json index f98c74f..f98c74f 100644 --- a/json/tests/draft6/infinite-loop-detection.json +++ b/tests/draft6/infinite-loop-detection.json diff --git a/json/tests/draft6/items.json b/tests/draft6/items.json index dc56e7c..dc56e7c 100644 --- a/json/tests/draft6/items.json +++ b/tests/draft6/items.json diff --git a/json/tests/draft6/maxItems.json b/tests/draft6/maxItems.json index f0c36ab..f0c36ab 100644 --- a/json/tests/draft6/maxItems.json +++ b/tests/draft6/maxItems.json diff --git a/json/tests/draft6/maxLength.json b/tests/draft6/maxLength.json index 748b4da..748b4da 100644 --- a/json/tests/draft6/maxLength.json +++ b/tests/draft6/maxLength.json diff --git a/json/tests/draft6/maxProperties.json b/tests/draft6/maxProperties.json index acec142..acec142 100644 --- a/json/tests/draft6/maxProperties.json +++ b/tests/draft6/maxProperties.json diff --git a/json/tests/draft6/maximum.json b/tests/draft6/maximum.json index 6844a39..6844a39 100644 --- a/json/tests/draft6/maximum.json +++ b/tests/draft6/maximum.json diff --git a/json/tests/draft6/minItems.json b/tests/draft6/minItems.json index d3b1872..d3b1872 100644 --- a/json/tests/draft6/minItems.json +++ b/tests/draft6/minItems.json diff --git a/json/tests/draft6/minLength.json b/tests/draft6/minLength.json index 64db948..64db948 100644 --- a/json/tests/draft6/minLength.json +++ b/tests/draft6/minLength.json diff --git a/json/tests/draft6/minProperties.json b/tests/draft6/minProperties.json index 9f74f78..9f74f78 100644 --- a/json/tests/draft6/minProperties.json +++ b/tests/draft6/minProperties.json diff --git a/json/tests/draft6/minimum.json b/tests/draft6/minimum.json index 21ae50e..21ae50e 100644 --- a/json/tests/draft6/minimum.json +++ b/tests/draft6/minimum.json diff --git a/json/tests/draft6/multipleOf.json b/tests/draft6/multipleOf.json index faa87cf..faa87cf 100644 --- a/json/tests/draft6/multipleOf.json +++ b/tests/draft6/multipleOf.json diff --git a/json/tests/draft6/not.json b/tests/draft6/not.json index 98de0ed..98de0ed 100644 --- a/json/tests/draft6/not.json +++ b/tests/draft6/not.json diff --git a/json/tests/draft6/oneOf.json b/tests/draft6/oneOf.json index eeb7ae8..eeb7ae8 100644 --- a/json/tests/draft6/oneOf.json +++ b/tests/draft6/oneOf.json diff --git a/json/tests/draft-next/optional/bignum.json b/tests/draft6/optional/bignum.json index 3f49226..94b4a4e 100644 --- a/json/tests/draft-next/optional/bignum.json +++ b/tests/draft6/optional/bignum.json @@ -43,7 +43,7 @@ ] }, { - "description": "integer comparison", + "description": "maximum integer comparison", "schema": { "maximum": 18446744073709551615 }, "tests": [ { @@ -67,7 +67,7 @@ ] }, { - "description": "integer comparison", + "description": "minimum integer comparison", "schema": { "minimum": -18446744073709551615 }, "tests": [ { diff --git a/json/tests/draft7/optional/ecmascript-regex.json b/tests/draft6/optional/ecmascript-regex.json index 1beb0b3..764248f 100644 --- a/json/tests/draft7/optional/ecmascript-regex.json +++ b/tests/draft6/optional/ecmascript-regex.json @@ -7,12 +7,12 @@ }, "tests": [ { - "description": "matches in Python, but should not in jsonschema", + "description": "matches in Python, but not in ECMA 262", "data": "abc\\n", "valid": false }, { - "description": "should match", + "description": "matches", "data": "abc", "valid": true } @@ -342,7 +342,7 @@ ] }, { - "description": "unicode characters do not match ascii ranges", + "description": "pattern with ASCII ranges", "schema": { "pattern": "[a-z]cole" }, "tests": [ { @@ -384,7 +384,7 @@ ] }, { - "description": "unicode digits are more than 0 through 9", + "description": "pattern with non-ASCII digits", "schema": { "pattern": "^\\p{digit}+$" }, "tests": [ { @@ -469,7 +469,7 @@ ] }, { - "description": "unicode characters do not match ascii ranges", + "description": "patternProperties with ASCII ranges", "schema": { "type": "object", "patternProperties": { @@ -523,7 +523,7 @@ ] }, { - "description": "unicode digits are more than 0 through 9", + "description": "patternProperties with non-ASCII digits", "schema": { "type": "object", "patternProperties": { diff --git a/json/tests/draft6/optional/float-overflow.json b/tests/draft6/optional/float-overflow.json index 52ff982..52ff982 100644 --- a/json/tests/draft6/optional/float-overflow.json +++ b/tests/draft6/optional/float-overflow.json diff --git a/tests/draft6/optional/format/date-time.json b/tests/draft6/optional/format/date-time.json new file mode 100644 index 0000000..0911273 --- /dev/null +++ b/tests/draft6/optional/format/date-time.json @@ -0,0 +1,133 @@ +[ + { + "description": "validation of date-time strings", + "schema": { "format": "date-time" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + }, + { + "description": "a valid date-time string", + "data": "1963-06-19T08:30:06.283185Z", + "valid": true + }, + { + "description": "a valid date-time string without second fraction", + "data": "1963-06-19T08:30:06Z", + "valid": true + }, + { + "description": "a valid date-time string with plus offset", + "data": "1937-01-01T12:00:27.87+00:20", + "valid": true + }, + { + "description": "a valid date-time string with minus offset", + "data": "1990-12-31T15:59:50.123-08:00", + "valid": true + }, + { + "description": "a valid date-time with a leap second, UTC", + "data": "1998-12-31T23:59:60Z", + "valid": true + }, + { + "description": "a valid date-time with a leap second, with minus offset", + "data": "1998-12-31T15:59:60.123-08:00", + "valid": true + }, + { + "description": "an invalid date-time past leap second, UTC", + "data": "1998-12-31T23:59:61Z", + "valid": false + }, + { + "description": "an invalid date-time with leap second on a wrong minute, UTC", + "data": "1998-12-31T23:58:60Z", + "valid": false + }, + { + "description": "an invalid date-time with leap second on a wrong hour, UTC", + "data": "1998-12-31T22:59:60Z", + "valid": false + }, + { + "description": "an invalid day in date-time string", + "data": "1990-02-31T15:59:59.123-08:00", + "valid": false + }, + { + "description": "an invalid offset in date-time string", + "data": "1990-12-31T15:59:59-24:00", + "valid": false + }, + { + "description": "an invalid closing Z after time-zone offset", + "data": "1963-06-19T08:30:06.28123+01:00Z", + "valid": false + }, + { + "description": "an invalid date-time string", + "data": "06/19/1963 08:30:06 PST", + "valid": false + }, + { + "description": "case-insensitive T and Z", + "data": "1963-06-19t08:30:06.283185z", + "valid": true + }, + { + "description": "only RFC3339 not all of ISO 8601 are valid", + "data": "2013-350T01:01:01", + "valid": false + }, + { + "description": "invalid non-padded month dates", + "data": "1963-6-19T08:30:06.283185Z", + "valid": false + }, + { + "description": "invalid non-padded day dates", + "data": "1963-06-1T08:30:06.283185Z", + "valid": false + }, + { + "description": "invalid non-ASCII '৪' (a Bengali 4) in date portion", + "data": "1963-06-1৪T00:00:00Z", + "valid": false + }, + { + "description": "invalid non-ASCII '৪' (a Bengali 4) in time portion", + "data": "1963-06-11T0৪:00:00Z", + "valid": false + } + ] + } +] diff --git a/json/tests/draft6/optional/format/email.json b/tests/draft6/optional/format/email.json index d6761a4..d6761a4 100644 --- a/json/tests/draft6/optional/format/email.json +++ b/tests/draft6/optional/format/email.json diff --git a/json/tests/draft6/optional/format/hostname.json b/tests/draft6/optional/format/hostname.json index 8a67fda..8a67fda 100644 --- a/json/tests/draft6/optional/format/hostname.json +++ b/tests/draft6/optional/format/hostname.json diff --git a/tests/draft6/optional/format/ipv4.json b/tests/draft6/optional/format/ipv4.json new file mode 100644 index 0000000..4706581 --- /dev/null +++ b/tests/draft6/optional/format/ipv4.json @@ -0,0 +1,84 @@ +[ + { + "description": "validation of IP addresses", + "schema": { "format": "ipv4" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + }, + { + "description": "a valid IP address", + "data": "192.168.0.1", + "valid": true + }, + { + "description": "an IP address with too many components", + "data": "127.0.0.0.1", + "valid": false + }, + { + "description": "an IP address with out-of-range values", + "data": "256.256.256.256", + "valid": false + }, + { + "description": "an IP address without 4 components", + "data": "127.0", + "valid": false + }, + { + "description": "an IP address as an integer", + "data": "0x7f000001", + "valid": false + }, + { + "description": "an IP address as an integer (decimal)", + "data": "2130706433", + "valid": false + }, + { + "description": "invalid leading zeroes, as they are treated as octals", + "comment": "see https://sick.codes/universal-netmask-npm-package-used-by-270000-projects-vulnerable-to-octal-input-data-server-side-request-forgery-remote-file-inclusion-local-file-inclusion-and-more-cve-2021-28918/", + "data": "087.10.0.1", + "valid": false + }, + { + "description": "value without leading zero is valid", + "data": "87.10.0.1", + "valid": true + }, + { + "description": "invalid non-ASCII '২' (a Bengali 2)", + "data": "1২7.0.0.1", + "valid": false + } + ] + } +] diff --git a/tests/draft6/optional/format/ipv6.json b/tests/draft6/optional/format/ipv6.json new file mode 100644 index 0000000..94368f2 --- /dev/null +++ b/tests/draft6/optional/format/ipv6.json @@ -0,0 +1,208 @@ +[ + { + "description": "validation of IPv6 addresses", + "schema": { "format": "ipv6" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + }, + { + "description": "a valid IPv6 address", + "data": "::1", + "valid": true + }, + { + "description": "an IPv6 address with out-of-range values", + "data": "12345::", + "valid": false + }, + { + "description": "trailing 4 hex symbols is valid", + "data": "::abef", + "valid": true + }, + { + "description": "trailing 5 hex symbols is invalid", + "data": "::abcef", + "valid": false + }, + { + "description": "an IPv6 address with too many components", + "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", + "valid": false + }, + { + "description": "an IPv6 address containing illegal characters", + "data": "::laptop", + "valid": false + }, + { + "description": "no digits is valid", + "data": "::", + "valid": true + }, + { + "description": "leading colons is valid", + "data": "::42:ff:1", + "valid": true + }, + { + "description": "trailing colons is valid", + "data": "d6::", + "valid": true + }, + { + "description": "missing leading octet is invalid", + "data": ":2:3:4:5:6:7:8", + "valid": false + }, + { + "description": "missing trailing octet is invalid", + "data": "1:2:3:4:5:6:7:", + "valid": false + }, + { + "description": "missing leading octet with omitted octets later", + "data": ":2:3:4::8", + "valid": false + }, + { + "description": "single set of double colons in the middle is valid", + "data": "1:d6::42", + "valid": true + }, + { + "description": "two sets of double colons is invalid", + "data": "1::d6::42", + "valid": false + }, + { + "description": "mixed format with the ipv4 section as decimal octets", + "data": "1::d6:192.168.0.1", + "valid": true + }, + { + "description": "mixed format with double colons between the sections", + "data": "1:2::192.168.0.1", + "valid": true + }, + { + "description": "mixed format with ipv4 section with octet out of range", + "data": "1::2:192.168.256.1", + "valid": false + }, + { + "description": "mixed format with ipv4 section with a hex octet", + "data": "1::2:192.168.ff.1", + "valid": false + }, + { + "description": "mixed format with leading double colons (ipv4-mapped ipv6 address)", + "data": "::ffff:192.168.0.1", + "valid": true + }, + { + "description": "triple colons is invalid", + "data": "1:2:3:4:5:::8", + "valid": false + }, + { + "description": "8 octets", + "data": "1:2:3:4:5:6:7:8", + "valid": true + }, + { + "description": "insufficient octets without double colons", + "data": "1:2:3:4:5:6:7", + "valid": false + }, + { + "description": "no colons is invalid", + "data": "1", + "valid": false + }, + { + "description": "ipv4 is not ipv6", + "data": "127.0.0.1", + "valid": false + }, + { + "description": "ipv4 segment must have 4 octets", + "data": "1:2:3:4:1.2.3", + "valid": false + }, + { + "description": "leading whitespace is invalid", + "data": " ::1", + "valid": false + }, + { + "description": "trailing whitespace is invalid", + "data": "::1 ", + "valid": false + }, + { + "description": "netmask is not a part of ipv6 address", + "data": "fe80::/64", + "valid": false + }, + { + "description": "zone id is not a part of ipv6 address", + "data": "fe80::a%eth1", + "valid": false + }, + { + "description": "a long valid ipv6", + "data": "1000:1000:1000:1000:1000:1000:255.255.255.255", + "valid": true + }, + { + "description": "a long invalid ipv6, below length limit, first", + "data": "100:100:100:100:100:100:255.255.255.255.255", + "valid": false + }, + { + "description": "a long invalid ipv6, below length limit, second", + "data": "100:100:100:100:100:100:100:255.255.255.255", + "valid": false + }, + { + "description": "invalid non-ASCII '৪' (a Bengali 4)", + "data": "1:2:3:4:5:6:7:৪", + "valid": false + }, + { + "description": "invalid non-ASCII '৪' (a Bengali 4) in the IPv4 portion", + "data": "1:2::192.16৪.0.1", + "valid": false + } + ] + } +] diff --git a/json/tests/draft6/optional/format/json-pointer.json b/tests/draft6/optional/format/json-pointer.json index a0346b5..a0346b5 100644 --- a/json/tests/draft6/optional/format/json-pointer.json +++ b/tests/draft6/optional/format/json-pointer.json diff --git a/json/tests/draft6/optional/format/unknown.json b/tests/draft6/optional/format/unknown.json index 12339ae..12339ae 100644 --- a/json/tests/draft6/optional/format/unknown.json +++ b/tests/draft6/optional/format/unknown.json diff --git a/json/tests/draft6/optional/format/uri-reference.json b/tests/draft6/optional/format/uri-reference.json index 7cdf228..7cdf228 100644 --- a/json/tests/draft6/optional/format/uri-reference.json +++ b/tests/draft6/optional/format/uri-reference.json diff --git a/json/tests/draft6/optional/format/uri-template.json b/tests/draft6/optional/format/uri-template.json index df355c5..df355c5 100644 --- a/json/tests/draft6/optional/format/uri-template.json +++ b/tests/draft6/optional/format/uri-template.json diff --git a/json/tests/draft6/optional/format/uri.json b/tests/draft6/optional/format/uri.json index 792d71a..792d71a 100644 --- a/json/tests/draft6/optional/format/uri.json +++ b/tests/draft6/optional/format/uri.json diff --git a/json/tests/draft6/optional/non-bmp-regex.json b/tests/draft6/optional/non-bmp-regex.json index dd67af2..dd67af2 100644 --- a/json/tests/draft6/optional/non-bmp-regex.json +++ b/tests/draft6/optional/non-bmp-regex.json diff --git a/json/tests/draft6/pattern.json b/tests/draft6/pattern.json index 92db0f9..92db0f9 100644 --- a/json/tests/draft6/pattern.json +++ b/tests/draft6/pattern.json diff --git a/json/tests/draft6/patternProperties.json b/tests/draft6/patternProperties.json index 34b2e85..34b2e85 100644 --- a/json/tests/draft6/patternProperties.json +++ b/tests/draft6/patternProperties.json diff --git a/json/tests/draft6/properties.json b/tests/draft6/properties.json index 8c3ed35..8c3ed35 100644 --- a/json/tests/draft6/properties.json +++ b/tests/draft6/properties.json diff --git a/json/tests/draft6/propertyNames.json b/tests/draft6/propertyNames.json index f0788e6..f0788e6 100644 --- a/json/tests/draft6/propertyNames.json +++ b/tests/draft6/propertyNames.json diff --git a/json/tests/draft6/ref.json b/tests/draft6/ref.json index 3e72a59..3e72a59 100644 --- a/json/tests/draft6/ref.json +++ b/tests/draft6/ref.json diff --git a/json/tests/draft6/refRemote.json b/tests/draft6/refRemote.json index c2b2002..c2b2002 100644 --- a/json/tests/draft6/refRemote.json +++ b/tests/draft6/refRemote.json diff --git a/json/tests/draft6/required.json b/tests/draft6/required.json index abf18f3..abf18f3 100644 --- a/json/tests/draft6/required.json +++ b/tests/draft6/required.json diff --git a/json/tests/draft6/type.json b/tests/draft6/type.json index 8304647..8304647 100644 --- a/json/tests/draft6/type.json +++ b/tests/draft6/type.json diff --git a/json/tests/draft6/uniqueItems.json b/tests/draft6/uniqueItems.json index 2ccf666..2ccf666 100644 --- a/json/tests/draft6/uniqueItems.json +++ b/tests/draft6/uniqueItems.json diff --git a/json/tests/draft6/unknownKeyword.json b/tests/draft6/unknownKeyword.json index 1f58d97..1f58d97 100644 --- a/json/tests/draft6/unknownKeyword.json +++ b/tests/draft6/unknownKeyword.json diff --git a/json/tests/draft7/additionalItems.json b/tests/draft7/additionalItems.json index 454142b..454142b 100644 --- a/json/tests/draft7/additionalItems.json +++ b/tests/draft7/additionalItems.json diff --git a/json/tests/draft7/additionalProperties.json b/tests/draft7/additionalProperties.json index 98b8842..98b8842 100644 --- a/json/tests/draft7/additionalProperties.json +++ b/tests/draft7/additionalProperties.json diff --git a/json/tests/draft7/allOf.json b/tests/draft7/allOf.json index ec9319e..ec9319e 100644 --- a/json/tests/draft7/allOf.json +++ b/tests/draft7/allOf.json diff --git a/tests/draft7/anyOf.json b/tests/draft7/anyOf.json new file mode 100644 index 0000000..ab5eb38 --- /dev/null +++ b/tests/draft7/anyOf.json @@ -0,0 +1,189 @@ +[ + { + "description": "anyOf", + "schema": { + "anyOf": [ + { + "type": "integer" + }, + { + "minimum": 2 + } + ] + }, + "tests": [ + { + "description": "first anyOf valid", + "data": 1, + "valid": true + }, + { + "description": "second anyOf valid", + "data": 2.5, + "valid": true + }, + { + "description": "both anyOf valid", + "data": 3, + "valid": true + }, + { + "description": "neither anyOf valid", + "data": 1.5, + "valid": false + } + ] + }, + { + "description": "anyOf with base schema", + "schema": { + "type": "string", + "anyOf" : [ + { + "maxLength": 2 + }, + { + "minLength": 4 + } + ] + }, + "tests": [ + { + "description": "mismatch base schema", + "data": 3, + "valid": false + }, + { + "description": "one anyOf valid", + "data": "foobar", + "valid": true + }, + { + "description": "both anyOf invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "anyOf with boolean schemas, all true", + "schema": {"anyOf": [true, true]}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "anyOf with boolean schemas, some true", + "schema": {"anyOf": [true, false]}, + "tests": [ + { + "description": "any value is valid", + "data": "foo", + "valid": true + } + ] + }, + { + "description": "anyOf with boolean schemas, all false", + "schema": {"anyOf": [false, false]}, + "tests": [ + { + "description": "any value is invalid", + "data": "foo", + "valid": false + } + ] + }, + { + "description": "anyOf complex types", + "schema": { + "anyOf": [ + { + "properties": { + "bar": {"type": "integer"} + }, + "required": ["bar"] + }, + { + "properties": { + "foo": {"type": "string"} + }, + "required": ["foo"] + } + ] + }, + "tests": [ + { + "description": "first anyOf valid (complex)", + "data": {"bar": 2}, + "valid": true + }, + { + "description": "second anyOf valid (complex)", + "data": {"foo": "baz"}, + "valid": true + }, + { + "description": "both anyOf valid (complex)", + "data": {"foo": "baz", "bar": 2}, + "valid": true + }, + { + "description": "neither anyOf valid (complex)", + "data": {"foo": 2, "bar": "quux"}, + "valid": false + } + ] + }, + { + "description": "anyOf with one empty schema", + "schema": { + "anyOf": [ + { "type": "number" }, + {} + ] + }, + "tests": [ + { + "description": "string is valid", + "data": "foo", + "valid": true + }, + { + "description": "number is valid", + "data": 123, + "valid": true + } + ] + }, + { + "description": "nested anyOf, to check validation semantics", + "schema": { + "anyOf": [ + { + "anyOf": [ + { + "type": "null" + } + ] + } + ] + }, + "tests": [ + { + "description": "null is valid", + "data": null, + "valid": true + }, + { + "description": "anything non-null is invalid", + "data": 123, + "valid": false + } + ] + } +] diff --git a/json/tests/draft7/boolean_schema.json b/tests/draft7/boolean_schema.json index 6d40f23..6d40f23 100644 --- a/json/tests/draft7/boolean_schema.json +++ b/tests/draft7/boolean_schema.json diff --git a/json/tests/draft7/const.json b/tests/draft7/const.json index 1c2cafc..1c2cafc 100644 --- a/json/tests/draft7/const.json +++ b/tests/draft7/const.json diff --git a/json/tests/draft7/contains.json b/tests/draft7/contains.json index b1c36a4..b1c36a4 100644 --- a/json/tests/draft7/contains.json +++ b/tests/draft7/contains.json diff --git a/json/tests/draft7/default.json b/tests/draft7/default.json index 289a9b6..289a9b6 100644 --- a/json/tests/draft7/default.json +++ b/tests/draft7/default.json diff --git a/json/tests/draft7/definitions.json b/tests/draft7/definitions.json index afe396e..afe396e 100644 --- a/json/tests/draft7/definitions.json +++ b/tests/draft7/definitions.json diff --git a/json/tests/draft7/dependencies.json b/tests/draft7/dependencies.json index a5e5428..a5e5428 100644 --- a/json/tests/draft7/dependencies.json +++ b/tests/draft7/dependencies.json diff --git a/json/tests/draft7/enum.json b/tests/draft7/enum.json index f085097..f085097 100644 --- a/json/tests/draft7/enum.json +++ b/tests/draft7/enum.json diff --git a/json/tests/draft7/exclusiveMaximum.json b/tests/draft7/exclusiveMaximum.json index dc3cd70..dc3cd70 100644 --- a/json/tests/draft7/exclusiveMaximum.json +++ b/tests/draft7/exclusiveMaximum.json diff --git a/json/tests/draft7/exclusiveMinimum.json b/tests/draft7/exclusiveMinimum.json index b38d7ec..b38d7ec 100644 --- a/json/tests/draft7/exclusiveMinimum.json +++ b/tests/draft7/exclusiveMinimum.json diff --git a/json/tests/draft7/format.json b/tests/draft7/format.json index e2447d6..e2447d6 100644 --- a/json/tests/draft7/format.json +++ b/tests/draft7/format.json diff --git a/json/tests/draft7/id.json b/tests/draft7/id.json index b03248b..b03248b 100644 --- a/json/tests/draft7/id.json +++ b/tests/draft7/id.json diff --git a/json/tests/draft7/if-then-else.json b/tests/draft7/if-then-else.json index 284e919..284e919 100644 --- a/json/tests/draft7/if-then-else.json +++ b/tests/draft7/if-then-else.json diff --git a/json/tests/draft7/infinite-loop-detection.json b/tests/draft7/infinite-loop-detection.json index f98c74f..f98c74f 100644 --- a/json/tests/draft7/infinite-loop-detection.json +++ b/tests/draft7/infinite-loop-detection.json diff --git a/json/tests/draft7/items.json b/tests/draft7/items.json index dc56e7c..dc56e7c 100644 --- a/json/tests/draft7/items.json +++ b/tests/draft7/items.json diff --git a/json/tests/draft7/maxItems.json b/tests/draft7/maxItems.json index f0c36ab..f0c36ab 100644 --- a/json/tests/draft7/maxItems.json +++ b/tests/draft7/maxItems.json diff --git a/json/tests/draft7/maxLength.json b/tests/draft7/maxLength.json index 748b4da..748b4da 100644 --- a/json/tests/draft7/maxLength.json +++ b/tests/draft7/maxLength.json diff --git a/json/tests/draft7/maxProperties.json b/tests/draft7/maxProperties.json index acec142..acec142 100644 --- a/json/tests/draft7/maxProperties.json +++ b/tests/draft7/maxProperties.json diff --git a/json/tests/draft7/maximum.json b/tests/draft7/maximum.json index 6844a39..6844a39 100644 --- a/json/tests/draft7/maximum.json +++ b/tests/draft7/maximum.json diff --git a/json/tests/draft7/minItems.json b/tests/draft7/minItems.json index d3b1872..d3b1872 100644 --- a/json/tests/draft7/minItems.json +++ b/tests/draft7/minItems.json diff --git a/json/tests/draft7/minLength.json b/tests/draft7/minLength.json index 64db948..64db948 100644 --- a/json/tests/draft7/minLength.json +++ b/tests/draft7/minLength.json diff --git a/json/tests/draft7/minProperties.json b/tests/draft7/minProperties.json index 9f74f78..9f74f78 100644 --- a/json/tests/draft7/minProperties.json +++ b/tests/draft7/minProperties.json diff --git a/json/tests/draft7/minimum.json b/tests/draft7/minimum.json index 21ae50e..21ae50e 100644 --- a/json/tests/draft7/minimum.json +++ b/tests/draft7/minimum.json diff --git a/json/tests/draft7/multipleOf.json b/tests/draft7/multipleOf.json index faa87cf..faa87cf 100644 --- a/json/tests/draft7/multipleOf.json +++ b/tests/draft7/multipleOf.json diff --git a/json/tests/draft7/not.json b/tests/draft7/not.json index 98de0ed..98de0ed 100644 --- a/json/tests/draft7/not.json +++ b/tests/draft7/not.json diff --git a/json/tests/draft7/oneOf.json b/tests/draft7/oneOf.json index eeb7ae8..eeb7ae8 100644 --- a/json/tests/draft7/oneOf.json +++ b/tests/draft7/oneOf.json diff --git a/tests/draft7/optional/bignum.json b/tests/draft7/optional/bignum.json new file mode 100644 index 0000000..94b4a4e --- /dev/null +++ b/tests/draft7/optional/bignum.json @@ -0,0 +1,93 @@ +[ + { + "description": "integer", + "schema": { "type": "integer" }, + "tests": [ + { + "description": "a bignum is an integer", + "data": 12345678910111213141516171819202122232425262728293031, + "valid": true + }, + { + "description": "a negative bignum is an integer", + "data": -12345678910111213141516171819202122232425262728293031, + "valid": true + } + ] + }, + { + "description": "number", + "schema": { "type": "number" }, + "tests": [ + { + "description": "a bignum is a number", + "data": 98249283749234923498293171823948729348710298301928331, + "valid": true + }, + { + "description": "a negative bignum is a number", + "data": -98249283749234923498293171823948729348710298301928331, + "valid": true + } + ] + }, + { + "description": "string", + "schema": { "type": "string" }, + "tests": [ + { + "description": "a bignum is not a string", + "data": 98249283749234923498293171823948729348710298301928331, + "valid": false + } + ] + }, + { + "description": "maximum integer comparison", + "schema": { "maximum": 18446744073709551615 }, + "tests": [ + { + "description": "comparison works for high numbers", + "data": 18446744073709551600, + "valid": true + } + ] + }, + { + "description": "float comparison with high precision", + "schema": { + "exclusiveMaximum": 972783798187987123879878123.18878137 + }, + "tests": [ + { + "description": "comparison works for high numbers", + "data": 972783798187987123879878123.188781371, + "valid": false + } + ] + }, + { + "description": "minimum integer comparison", + "schema": { "minimum": -18446744073709551615 }, + "tests": [ + { + "description": "comparison works for very negative numbers", + "data": -18446744073709551600, + "valid": true + } + ] + }, + { + "description": "float comparison with high precision on negative numbers", + "schema": { + "exclusiveMinimum": -972783798187987123879878123.18878137 + }, + "tests": [ + { + "description": "comparison works for very negative numbers", + "data": -972783798187987123879878123.188781371, + "valid": false + } + ] + } +] diff --git a/json/tests/draft7/optional/content.json b/tests/draft7/optional/content.json index 3f5a743..3f5a743 100644 --- a/json/tests/draft7/optional/content.json +++ b/tests/draft7/optional/content.json diff --git a/json/tests/draft6/optional/ecmascript-regex.json b/tests/draft7/optional/ecmascript-regex.json index 1beb0b3..764248f 100644 --- a/json/tests/draft6/optional/ecmascript-regex.json +++ b/tests/draft7/optional/ecmascript-regex.json @@ -7,12 +7,12 @@ }, "tests": [ { - "description": "matches in Python, but should not in jsonschema", + "description": "matches in Python, but not in ECMA 262", "data": "abc\\n", "valid": false }, { - "description": "should match", + "description": "matches", "data": "abc", "valid": true } @@ -342,7 +342,7 @@ ] }, { - "description": "unicode characters do not match ascii ranges", + "description": "pattern with ASCII ranges", "schema": { "pattern": "[a-z]cole" }, "tests": [ { @@ -384,7 +384,7 @@ ] }, { - "description": "unicode digits are more than 0 through 9", + "description": "pattern with non-ASCII digits", "schema": { "pattern": "^\\p{digit}+$" }, "tests": [ { @@ -469,7 +469,7 @@ ] }, { - "description": "unicode characters do not match ascii ranges", + "description": "patternProperties with ASCII ranges", "schema": { "type": "object", "patternProperties": { @@ -523,7 +523,7 @@ ] }, { - "description": "unicode digits are more than 0 through 9", + "description": "patternProperties with non-ASCII digits", "schema": { "type": "object", "patternProperties": { diff --git a/json/tests/draft7/optional/float-overflow.json b/tests/draft7/optional/float-overflow.json index 52ff982..52ff982 100644 --- a/json/tests/draft7/optional/float-overflow.json +++ b/tests/draft7/optional/float-overflow.json diff --git a/tests/draft7/optional/format/date-time.json b/tests/draft7/optional/format/date-time.json new file mode 100644 index 0000000..0911273 --- /dev/null +++ b/tests/draft7/optional/format/date-time.json @@ -0,0 +1,133 @@ +[ + { + "description": "validation of date-time strings", + "schema": { "format": "date-time" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + }, + { + "description": "a valid date-time string", + "data": "1963-06-19T08:30:06.283185Z", + "valid": true + }, + { + "description": "a valid date-time string without second fraction", + "data": "1963-06-19T08:30:06Z", + "valid": true + }, + { + "description": "a valid date-time string with plus offset", + "data": "1937-01-01T12:00:27.87+00:20", + "valid": true + }, + { + "description": "a valid date-time string with minus offset", + "data": "1990-12-31T15:59:50.123-08:00", + "valid": true + }, + { + "description": "a valid date-time with a leap second, UTC", + "data": "1998-12-31T23:59:60Z", + "valid": true + }, + { + "description": "a valid date-time with a leap second, with minus offset", + "data": "1998-12-31T15:59:60.123-08:00", + "valid": true + }, + { + "description": "an invalid date-time past leap second, UTC", + "data": "1998-12-31T23:59:61Z", + "valid": false + }, + { + "description": "an invalid date-time with leap second on a wrong minute, UTC", + "data": "1998-12-31T23:58:60Z", + "valid": false + }, + { + "description": "an invalid date-time with leap second on a wrong hour, UTC", + "data": "1998-12-31T22:59:60Z", + "valid": false + }, + { + "description": "an invalid day in date-time string", + "data": "1990-02-31T15:59:59.123-08:00", + "valid": false + }, + { + "description": "an invalid offset in date-time string", + "data": "1990-12-31T15:59:59-24:00", + "valid": false + }, + { + "description": "an invalid closing Z after time-zone offset", + "data": "1963-06-19T08:30:06.28123+01:00Z", + "valid": false + }, + { + "description": "an invalid date-time string", + "data": "06/19/1963 08:30:06 PST", + "valid": false + }, + { + "description": "case-insensitive T and Z", + "data": "1963-06-19t08:30:06.283185z", + "valid": true + }, + { + "description": "only RFC3339 not all of ISO 8601 are valid", + "data": "2013-350T01:01:01", + "valid": false + }, + { + "description": "invalid non-padded month dates", + "data": "1963-6-19T08:30:06.283185Z", + "valid": false + }, + { + "description": "invalid non-padded day dates", + "data": "1963-06-1T08:30:06.283185Z", + "valid": false + }, + { + "description": "invalid non-ASCII '৪' (a Bengali 4) in date portion", + "data": "1963-06-1৪T00:00:00Z", + "valid": false + }, + { + "description": "invalid non-ASCII '৪' (a Bengali 4) in time portion", + "data": "1963-06-11T0৪:00:00Z", + "valid": false + } + ] + } +] diff --git a/json/tests/draft-next/optional/format/date.json b/tests/draft7/optional/format/date.json index b4f61ee..06c9ea0 100644 --- a/json/tests/draft-next/optional/format/date.json +++ b/tests/draft7/optional/format/date.json @@ -214,7 +214,7 @@ "valid": true }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '৪' (a Bengali 4)", "data": "1963-06-1৪", "valid": false } diff --git a/json/tests/draft7/optional/format/email.json b/tests/draft7/optional/format/email.json index d6761a4..d6761a4 100644 --- a/json/tests/draft7/optional/format/email.json +++ b/tests/draft7/optional/format/email.json diff --git a/json/tests/draft7/optional/format/hostname.json b/tests/draft7/optional/format/hostname.json index 8a67fda..8a67fda 100644 --- a/json/tests/draft7/optional/format/hostname.json +++ b/tests/draft7/optional/format/hostname.json diff --git a/json/tests/draft7/optional/format/idn-email.json b/tests/draft7/optional/format/idn-email.json index 6e21374..6e21374 100644 --- a/json/tests/draft7/optional/format/idn-email.json +++ b/tests/draft7/optional/format/idn-email.json diff --git a/json/tests/draft7/optional/format/idn-hostname.json b/tests/draft7/optional/format/idn-hostname.json index 6c8f86a..6c8f86a 100644 --- a/json/tests/draft7/optional/format/idn-hostname.json +++ b/tests/draft7/optional/format/idn-hostname.json diff --git a/tests/draft7/optional/format/ipv4.json b/tests/draft7/optional/format/ipv4.json new file mode 100644 index 0000000..4706581 --- /dev/null +++ b/tests/draft7/optional/format/ipv4.json @@ -0,0 +1,84 @@ +[ + { + "description": "validation of IP addresses", + "schema": { "format": "ipv4" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + }, + { + "description": "a valid IP address", + "data": "192.168.0.1", + "valid": true + }, + { + "description": "an IP address with too many components", + "data": "127.0.0.0.1", + "valid": false + }, + { + "description": "an IP address with out-of-range values", + "data": "256.256.256.256", + "valid": false + }, + { + "description": "an IP address without 4 components", + "data": "127.0", + "valid": false + }, + { + "description": "an IP address as an integer", + "data": "0x7f000001", + "valid": false + }, + { + "description": "an IP address as an integer (decimal)", + "data": "2130706433", + "valid": false + }, + { + "description": "invalid leading zeroes, as they are treated as octals", + "comment": "see https://sick.codes/universal-netmask-npm-package-used-by-270000-projects-vulnerable-to-octal-input-data-server-side-request-forgery-remote-file-inclusion-local-file-inclusion-and-more-cve-2021-28918/", + "data": "087.10.0.1", + "valid": false + }, + { + "description": "value without leading zero is valid", + "data": "87.10.0.1", + "valid": true + }, + { + "description": "invalid non-ASCII '২' (a Bengali 2)", + "data": "1২7.0.0.1", + "valid": false + } + ] + } +] diff --git a/tests/draft7/optional/format/ipv6.json b/tests/draft7/optional/format/ipv6.json new file mode 100644 index 0000000..94368f2 --- /dev/null +++ b/tests/draft7/optional/format/ipv6.json @@ -0,0 +1,208 @@ +[ + { + "description": "validation of IPv6 addresses", + "schema": { "format": "ipv6" }, + "tests": [ + { + "description": "all string formats ignore integers", + "data": 12, + "valid": true + }, + { + "description": "all string formats ignore floats", + "data": 13.7, + "valid": true + }, + { + "description": "all string formats ignore objects", + "data": {}, + "valid": true + }, + { + "description": "all string formats ignore arrays", + "data": [], + "valid": true + }, + { + "description": "all string formats ignore booleans", + "data": false, + "valid": true + }, + { + "description": "all string formats ignore nulls", + "data": null, + "valid": true + }, + { + "description": "a valid IPv6 address", + "data": "::1", + "valid": true + }, + { + "description": "an IPv6 address with out-of-range values", + "data": "12345::", + "valid": false + }, + { + "description": "trailing 4 hex symbols is valid", + "data": "::abef", + "valid": true + }, + { + "description": "trailing 5 hex symbols is invalid", + "data": "::abcef", + "valid": false + }, + { + "description": "an IPv6 address with too many components", + "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", + "valid": false + }, + { + "description": "an IPv6 address containing illegal characters", + "data": "::laptop", + "valid": false + }, + { + "description": "no digits is valid", + "data": "::", + "valid": true + }, + { + "description": "leading colons is valid", + "data": "::42:ff:1", + "valid": true + }, + { + "description": "trailing colons is valid", + "data": "d6::", + "valid": true + }, + { + "description": "missing leading octet is invalid", + "data": ":2:3:4:5:6:7:8", + "valid": false + }, + { + "description": "missing trailing octet is invalid", + "data": "1:2:3:4:5:6:7:", + "valid": false + }, + { + "description": "missing leading octet with omitted octets later", + "data": ":2:3:4::8", + "valid": false + }, + { + "description": "single set of double colons in the middle is valid", + "data": "1:d6::42", + "valid": true + }, + { + "description": "two sets of double colons is invalid", + "data": "1::d6::42", + "valid": false + }, + { + "description": "mixed format with the ipv4 section as decimal octets", + "data": "1::d6:192.168.0.1", + "valid": true + }, + { + "description": "mixed format with double colons between the sections", + "data": "1:2::192.168.0.1", + "valid": true + }, + { + "description": "mixed format with ipv4 section with octet out of range", + "data": "1::2:192.168.256.1", + "valid": false + }, + { + "description": "mixed format with ipv4 section with a hex octet", + "data": "1::2:192.168.ff.1", + "valid": false + }, + { + "description": "mixed format with leading double colons (ipv4-mapped ipv6 address)", + "data": "::ffff:192.168.0.1", + "valid": true + }, + { + "description": "triple colons is invalid", + "data": "1:2:3:4:5:::8", + "valid": false + }, + { + "description": "8 octets", + "data": "1:2:3:4:5:6:7:8", + "valid": true + }, + { + "description": "insufficient octets without double colons", + "data": "1:2:3:4:5:6:7", + "valid": false + }, + { + "description": "no colons is invalid", + "data": "1", + "valid": false + }, + { + "description": "ipv4 is not ipv6", + "data": "127.0.0.1", + "valid": false + }, + { + "description": "ipv4 segment must have 4 octets", + "data": "1:2:3:4:1.2.3", + "valid": false + }, + { + "description": "leading whitespace is invalid", + "data": " ::1", + "valid": false + }, + { + "description": "trailing whitespace is invalid", + "data": "::1 ", + "valid": false + }, + { + "description": "netmask is not a part of ipv6 address", + "data": "fe80::/64", + "valid": false + }, + { + "description": "zone id is not a part of ipv6 address", + "data": "fe80::a%eth1", + "valid": false + }, + { + "description": "a long valid ipv6", + "data": "1000:1000:1000:1000:1000:1000:255.255.255.255", + "valid": true + }, + { + "description": "a long invalid ipv6, below length limit, first", + "data": "100:100:100:100:100:100:255.255.255.255.255", + "valid": false + }, + { + "description": "a long invalid ipv6, below length limit, second", + "data": "100:100:100:100:100:100:100:255.255.255.255", + "valid": false + }, + { + "description": "invalid non-ASCII '৪' (a Bengali 4)", + "data": "1:2:3:4:5:6:7:৪", + "valid": false + }, + { + "description": "invalid non-ASCII '৪' (a Bengali 4) in the IPv4 portion", + "data": "1:2::192.16৪.0.1", + "valid": false + } + ] + } +] diff --git a/json/tests/draft7/optional/format/iri-reference.json b/tests/draft7/optional/format/iri-reference.json index c6b4c22..c6b4c22 100644 --- a/json/tests/draft7/optional/format/iri-reference.json +++ b/tests/draft7/optional/format/iri-reference.json diff --git a/json/tests/draft7/optional/format/iri.json b/tests/draft7/optional/format/iri.json index a0d12ae..a0d12ae 100644 --- a/json/tests/draft7/optional/format/iri.json +++ b/tests/draft7/optional/format/iri.json diff --git a/json/tests/draft7/optional/format/json-pointer.json b/tests/draft7/optional/format/json-pointer.json index a0346b5..a0346b5 100644 --- a/json/tests/draft7/optional/format/json-pointer.json +++ b/tests/draft7/optional/format/json-pointer.json diff --git a/json/tests/draft7/optional/format/regex.json b/tests/draft7/optional/format/regex.json index 3449177..3449177 100644 --- a/json/tests/draft7/optional/format/regex.json +++ b/tests/draft7/optional/format/regex.json diff --git a/json/tests/draft7/optional/format/relative-json-pointer.json b/tests/draft7/optional/format/relative-json-pointer.json index 9309986..9309986 100644 --- a/json/tests/draft7/optional/format/relative-json-pointer.json +++ b/tests/draft7/optional/format/relative-json-pointer.json diff --git a/json/tests/draft-next/optional/format/time.json b/tests/draft7/optional/format/time.json index 5011d78..3142587 100644 --- a/json/tests/draft-next/optional/format/time.json +++ b/tests/draft7/optional/format/time.json @@ -189,7 +189,7 @@ "valid": false }, { - "description": "non-ascii digits should be rejected", + "description": "invalid non-ASCII '২' (a Bengali 2)", "data": "1২:00:00Z", "valid": false } diff --git a/json/tests/draft7/optional/format/unknown.json b/tests/draft7/optional/format/unknown.json index 12339ae..12339ae 100644 --- a/json/tests/draft7/optional/format/unknown.json +++ b/tests/draft7/optional/format/unknown.json diff --git a/json/tests/draft7/optional/format/uri-reference.json b/tests/draft7/optional/format/uri-reference.json index 7cdf228..7cdf228 100644 --- a/json/tests/draft7/optional/format/uri-reference.json +++ b/tests/draft7/optional/format/uri-reference.json diff --git a/json/tests/draft7/optional/format/uri-template.json b/tests/draft7/optional/format/uri-template.json index df355c5..df355c5 100644 --- a/json/tests/draft7/optional/format/uri-template.json +++ b/tests/draft7/optional/format/uri-template.json diff --git a/json/tests/draft7/optional/format/uri.json b/tests/draft7/optional/format/uri.json index 792d71a..792d71a 100644 --- a/json/tests/draft7/optional/format/uri.json +++ b/tests/draft7/optional/format/uri.json diff --git a/json/tests/draft7/optional/non-bmp-regex.json b/tests/draft7/optional/non-bmp-regex.json index dd67af2..dd67af2 100644 --- a/json/tests/draft7/optional/non-bmp-regex.json +++ b/tests/draft7/optional/non-bmp-regex.json diff --git a/json/tests/draft7/pattern.json b/tests/draft7/pattern.json index 92db0f9..92db0f9 100644 --- a/json/tests/draft7/pattern.json +++ b/tests/draft7/pattern.json diff --git a/json/tests/draft7/patternProperties.json b/tests/draft7/patternProperties.json index 34b2e85..34b2e85 100644 --- a/json/tests/draft7/patternProperties.json +++ b/tests/draft7/patternProperties.json diff --git a/json/tests/draft7/properties.json b/tests/draft7/properties.json index 8c3ed35..8c3ed35 100644 --- a/json/tests/draft7/properties.json +++ b/tests/draft7/properties.json diff --git a/json/tests/draft7/propertyNames.json b/tests/draft7/propertyNames.json index f0788e6..f0788e6 100644 --- a/json/tests/draft7/propertyNames.json +++ b/tests/draft7/propertyNames.json diff --git a/json/tests/draft7/ref.json b/tests/draft7/ref.json index 52e5168..dbf0595 100644 --- a/json/tests/draft7/ref.json +++ b/tests/draft7/ref.json @@ -634,12 +634,12 @@ }, "tests": [ { - "description": "number should pass", + "description": "number is valid", "data": 1, "valid": true }, { - "description": "non-number should fail", + "description": "non-number is invalid", "data": "a", "valid": false } diff --git a/json/tests/draft7/refRemote.json b/tests/draft7/refRemote.json index c2b2002..c2b2002 100644 --- a/json/tests/draft7/refRemote.json +++ b/tests/draft7/refRemote.json diff --git a/json/tests/draft7/required.json b/tests/draft7/required.json index abf18f3..abf18f3 100644 --- a/json/tests/draft7/required.json +++ b/tests/draft7/required.json diff --git a/json/tests/draft7/type.json b/tests/draft7/type.json index 8304647..8304647 100644 --- a/json/tests/draft7/type.json +++ b/tests/draft7/type.json diff --git a/json/tests/draft7/uniqueItems.json b/tests/draft7/uniqueItems.json index 2ccf666..2ccf666 100644 --- a/json/tests/draft7/uniqueItems.json +++ b/tests/draft7/uniqueItems.json diff --git a/json/tests/draft7/unknownKeyword.json b/tests/draft7/unknownKeyword.json index 1f58d97..1f58d97 100644 --- a/json/tests/draft7/unknownKeyword.json +++ b/tests/draft7/unknownKeyword.json diff --git a/json/tests/latest b/tests/latest index 9a4784d..9a4784d 120000 --- a/json/tests/latest +++ b/tests/latest @@ -1,118 +1,9 @@ [tox] -envlist = - py{37,38,39,310,311,py3}-{noextra,format,formatnongpl}-{build,tests}, - readme - safety - secrets - style - typing - docs-{dirhtml,doctest,linkcheck,spelling,style} +minversion = 1.6 +envlist = sanity skipsdist = True -[testenv] -changedir = {envtmpdir} -passenv = CODECOV* CI -setenv = - JSON_SCHEMA_TEST_SUITE = {toxinidir}/json - - coverage,codecov: MAYBE_COVERAGE = coverage run -m - coverage,codecov: COVERAGE_RCFILE={toxinidir}/.coveragerc - coverage,codecov: COVERAGE_DEBUG_FILE={envtmpdir}/coverage-debug - coverage,codecov: COVERAGE_FILE={envtmpdir}/coverage-data -whitelist_externals = - mkdir -commands = - noextra: {envpython} -m pip install --disable-pip-version-check {toxinidir} - format,perf: {envpython} -m pip install --disable-pip-version-check '{toxinidir}[format]' - formatnongpl: {envpython} -m pip install --disable-pip-version-check '{toxinidir}[format-nongpl]' - - # Ignore the deprecation warning until pypa/setuptools#3276 is released - tests,coverage,codecov: {envpython} -Werror -W"ignore:module 'sre_constants' is deprecated:DeprecationWarning" -m {env:MAYBE_COVERAGE:} twisted.trial {posargs:jsonschema} - tests: {envpython} -m doctest {toxinidir}/README.rst - - coverage: {envpython} -m coverage report --show-missing - coverage: {envpython} -m coverage html --directory={envtmpdir}/htmlcov - codecov: {envpython} -m coverage xml -o {envtmpdir}/coverage.xml - codecov: codecov --required --disable gcov --file {envtmpdir}/coverage.xml - - perf: {envpython} {toxinidir}/jsonschema/benchmarks/issue232.py --inherit-environ JSON_SCHEMA_TEST_SUITE {posargs:--output {envtmpdir}/bench-issue232.json} - perfsuite: {envpython} {toxinidir}/jsonschema/benchmarks/json_schema_test_suite.py --inherit-environ JSON_SCHEMA_TEST_SUITE {posargs:--output {envtmpdir}/bench-json_schema_test_suite.json} - - build: {envpython} -m build {toxinidir} --outdir {envtmpdir}/dist -deps = - build: build - - perf,perfsuite: pyperf - - tests,coverage,codecov: twisted - - coverage,codecov: coverage - codecov: codecov - -[testenv:bandit] -deps = bandit -commands = {envbindir}/bandit --recursive {toxinidir}/jsonschema - -[testenv:readme] -deps = - build - docutils - twine -commands = - {envpython} -m build --outdir {envtmpdir}/dist {toxinidir} - {envpython} -m twine check {envtmpdir}/dist/* - {envbindir}/rst2html5.py --halt=warning {toxinidir}/CHANGELOG.rst /dev/null - -[testenv:safety] -deps = safety -commands = - {envpython} -m pip install --disable-pip-version-check '{toxinidir}[format]' - {envpython} -m safety check - -[testenv:secrets] -deps = detect-secrets -commands = {envbindir}/detect-secrets scan {toxinidir} - -[testenv:style] -deps = - flake8 - flake8-broken-line - flake8-bugbear - flake8-commas - flake8-quotes - flake8-tidy-imports -commands = - {envpython} -m flake8 {posargs} {toxinidir}/jsonschema {toxinidir}/docs - -[testenv:typing] -skip_install = true -deps = - mypy - pyrsistent - types-attrs - types-requests -commands = {envpython} -m mypy --config {toxinidir}/pyproject.toml {posargs} {toxinidir}/jsonschema - -[testenv:docs-dirhtml] -commands = {envpython} -m sphinx -b dirhtml {toxinidir}/docs/ {envtmpdir}/build {posargs:-a -n -q -T -W} -deps = - -r{toxinidir}/docs/requirements.txt - -[testenv:docs-doctest] -commands = {envpython} -m sphinx -b doctest {toxinidir}/docs/ {envtmpdir}/build {posargs:-a -n -q -T -W} -deps = {[testenv:docs-dirhtml]deps} - -[testenv:docs-linkcheck] -commands = {envpython} -m sphinx -b linkcheck {toxinidir}/docs/ {envtmpdir}/build {posargs:-a -n -q -T -W} -deps = {[testenv:docs-dirhtml]deps} - -[testenv:docs-spelling] -commands = {envpython} -m sphinx -b spelling {toxinidir}/docs/ {envtmpdir}/build {posargs:-a -n -T -W} -deps = {[testenv:docs-dirhtml]deps} - -[testenv:docs-style] -commands = doc8 {posargs} {toxinidir}/docs -deps = - doc8 - pygments - pygments-github-lexers +[testenv:sanity] +# used just for validating the structure of the test case files themselves +deps = jsonschema==4.6.1 +commands = {envpython} bin/jsonschema_suite check |