From d2aeb7a29d0b6e7f32375046130b68d7e81e0a3e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 22:59:43 +0000 Subject: [PATCH 01/16] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.0.281 → v0.0.282](https://github.com/astral-sh/ruff-pre-commit/compare/v0.0.281...v0.0.282) - [github.com/pre-commit/mirrors-prettier: v3.0.0 → v3.0.1](https://github.com/pre-commit/mirrors-prettier/compare/v3.0.0...v3.0.1) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e94e7f79c..b6014f6c6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: args: [--fix, lf] - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.0.281" + rev: "v0.0.282" hooks: - id: ruff - repo: https://github.com/PyCQA/isort @@ -24,7 +24,7 @@ repos: hooks: - id: isort - repo: https://github.com/pre-commit/mirrors-prettier - rev: "v3.0.0" + rev: "v3.0.1" hooks: - id: prettier exclude: "^jsonschema/benchmarks/issue232/issue.json$" From 931323043b4409a0416f373403bfb52408fc282f Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Wed, 9 Aug 2023 16:39:03 +0100 Subject: [PATCH 02/16] More closely match modern JSON Schema vocabulary in internal module names. These are private, so it's easy to rename them to use preferred modern terminology, namely that individual keywords are called 'keywords' rather than 'validators'. This leaves the latter ('validator') to have one fewer overloaded meaning in this library, leaving it primarily referring to class objects such as DraftNValidator objects, however there are still at least 2 public places where we conflate terminology: * In the VALIDATORS attribute on validator classes, where this attribute is a mapping from str to callable but really the callables are callables for each *keyword* * ValidationError.validator, which is really the *keyword* which failed validation These are of course public API and need deprecating, which hasn't been done thus far mostly to not create API churn simply to rename. In the future however, it's likely that broader deprecations will help us deprecate these. Specifically when we implement fuller support for vocabularies and/or deprecate jsonschema.validators.create in favor of newer objects, we may get a chance to replace VALIDATORS, and when we implement more robust exception types (e.g. to address #119) we likely will deprecate .validator. --- docs/creating.rst | 4 +- docs/errors.rst | 9 +- docs/faq.rst | 7 +- jsonschema/{_validators.py => _keywords.py} | 0 ...gacy_validators.py => _legacy_keywords.py} | 0 jsonschema/tests/test_types.py | 6 +- jsonschema/validators.py | 378 +++++++++--------- 7 files changed, 197 insertions(+), 207 deletions(-) rename jsonschema/{_validators.py => _keywords.py} (100%) rename jsonschema/{_legacy_validators.py => _legacy_keywords.py} (100%) diff --git a/docs/creating.rst b/docs/creating.rst index 8405f3483..72b3590bc 100644 --- a/docs/creating.rst +++ b/docs/creating.rst @@ -31,8 +31,6 @@ where in the instance or schema respectively the error occurred. The Validator Protocol ---------------------- -``jsonschema`` defines a `protocol `, -`jsonschema.protocols.Validator` which can be used in type annotations to -describe the type of a validator object. +``jsonschema`` defines a `protocol `, `jsonschema.protocols.Validator` which can be used in type annotations to describe the type of a validator. For full details, see `validator-protocol`. diff --git a/docs/errors.rst b/docs/errors.rst index 5b0230f7e..79c830e9e 100644 --- a/docs/errors.rst +++ b/docs/errors.rst @@ -238,9 +238,7 @@ failed when validating a given instance, you may want to do so using .. attribute:: errors - The mapping of validator keywords to the error objects (usually - `jsonschema.exceptions.ValidationError`\s) at this level - of the tree. + The mapping of validation keywords to the error objects (usually `jsonschema.exceptions.ValidationError`\s) at this level of the tree. Consider the following example: @@ -276,10 +274,7 @@ error objects. from jsonschema.exceptions import ErrorTree 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. +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'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 diff --git a/docs/faq.rst b/docs/faq.rst index 5ae3e62e4..b724f4f1c 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -50,12 +50,9 @@ This library made the choice to leave it off by default, for two reasons: implementations they were using to ensure they too were explicitly enabled for :kw:`format` validation. -As of ``draft2019-09`` however, the opt-out by default behavior -mentioned here is now *required* for all validators. +As of ``draft2019-09`` however, the opt-out by default behavior mentioned here is now *required* for all implementations of JSON Schema. -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. +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:: diff --git a/jsonschema/_validators.py b/jsonschema/_keywords.py similarity index 100% rename from jsonschema/_validators.py rename to jsonschema/_keywords.py diff --git a/jsonschema/_legacy_validators.py b/jsonschema/_legacy_keywords.py similarity index 100% rename from jsonschema/_legacy_validators.py rename to jsonschema/_legacy_keywords.py diff --git a/jsonschema/tests/test_types.py b/jsonschema/tests/test_types.py index 3eacc7235..bd97b1800 100644 --- a/jsonschema/tests/test_types.py +++ b/jsonschema/tests/test_types.py @@ -8,7 +8,7 @@ from collections import namedtuple from unittest import TestCase -from jsonschema import ValidationError, _validators +from jsonschema import ValidationError, _keywords from jsonschema._types import TypeChecker from jsonschema.exceptions import UndefinedTypeCheck, UnknownType from jsonschema.validators import Draft202012Validator, extend @@ -191,8 +191,8 @@ def coerced(validator, value, instance, schema): return fn(validator, value, instance, schema) return coerced - required = coerce_named_tuple(_validators.required) - properties = coerce_named_tuple(_validators.properties) + required = coerce_named_tuple(_keywords.required) + properties = coerce_named_tuple(_keywords.properties) CustomValidator = extend( Draft202012Validator, diff --git a/jsonschema/validators.py b/jsonschema/validators.py index 8049e8b24..3acee870a 100644 --- a/jsonschema/validators.py +++ b/jsonschema/validators.py @@ -23,11 +23,11 @@ from jsonschema import ( _format, - _legacy_validators, + _keywords, + _legacy_keywords, _types, _typing, _utils, - _validators, exceptions, ) from jsonschema.protocols import Validator @@ -586,33 +586,33 @@ def extend( "http://json-schema.org/draft-03/schema#", ), 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, + "$ref": _keywords.ref, + "additionalItems": _keywords.additionalItems, + "additionalProperties": _keywords.additionalProperties, + "dependencies": _legacy_keywords.dependencies_draft3, + "disallow": _legacy_keywords.disallow_draft3, + "divisibleBy": _keywords.multipleOf, + "enum": _keywords.enum, + "extends": _legacy_keywords.extends_draft3, + "format": _keywords.format, + "items": _legacy_keywords.items_draft3_draft4, + "maxItems": _keywords.maxItems, + "maxLength": _keywords.maxLength, + "maximum": _legacy_keywords.maximum_draft3_draft4, + "minItems": _keywords.minItems, + "minLength": _keywords.minLength, + "minimum": _legacy_keywords.minimum_draft3_draft4, + "pattern": _keywords.pattern, + "patternProperties": _keywords.patternProperties, + "properties": _legacy_keywords.properties_draft3, + "type": _legacy_keywords.type_draft3, + "uniqueItems": _keywords.uniqueItems, }, type_checker=_types.draft3_type_checker, format_checker=_format.draft3_format_checker, version="draft3", id_of=referencing.jsonschema.DRAFT3.id_of, - applicable_validators=_legacy_validators.ignore_ref_siblings, + applicable_validators=_legacy_keywords.ignore_ref_siblings, ) Draft4Validator = create( @@ -620,38 +620,38 @@ def extend( "http://json-schema.org/draft-04/schema#", ), 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, + "$ref": _keywords.ref, + "additionalItems": _keywords.additionalItems, + "additionalProperties": _keywords.additionalProperties, + "allOf": _keywords.allOf, + "anyOf": _keywords.anyOf, + "dependencies": _legacy_keywords.dependencies_draft4_draft6_draft7, + "enum": _keywords.enum, + "format": _keywords.format, + "items": _legacy_keywords.items_draft3_draft4, + "maxItems": _keywords.maxItems, + "maxLength": _keywords.maxLength, + "maxProperties": _keywords.maxProperties, + "maximum": _legacy_keywords.maximum_draft3_draft4, + "minItems": _keywords.minItems, + "minLength": _keywords.minLength, + "minProperties": _keywords.minProperties, + "minimum": _legacy_keywords.minimum_draft3_draft4, + "multipleOf": _keywords.multipleOf, + "not": _keywords.not_, + "oneOf": _keywords.oneOf, + "pattern": _keywords.pattern, + "patternProperties": _keywords.patternProperties, + "properties": _keywords.properties, + "required": _keywords.required, + "type": _keywords.type, + "uniqueItems": _keywords.uniqueItems, }, type_checker=_types.draft4_type_checker, format_checker=_format.draft4_format_checker, version="draft4", id_of=referencing.jsonschema.DRAFT4.id_of, - applicable_validators=_legacy_validators.ignore_ref_siblings, + applicable_validators=_legacy_keywords.ignore_ref_siblings, ) Draft6Validator = create( @@ -659,43 +659,43 @@ def extend( "http://json-schema.org/draft-06/schema#", ), 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, + "$ref": _keywords.ref, + "additionalItems": _keywords.additionalItems, + "additionalProperties": _keywords.additionalProperties, + "allOf": _keywords.allOf, + "anyOf": _keywords.anyOf, + "const": _keywords.const, + "contains": _legacy_keywords.contains_draft6_draft7, + "dependencies": _legacy_keywords.dependencies_draft4_draft6_draft7, + "enum": _keywords.enum, + "exclusiveMaximum": _keywords.exclusiveMaximum, + "exclusiveMinimum": _keywords.exclusiveMinimum, + "format": _keywords.format, + "items": _legacy_keywords.items_draft6_draft7_draft201909, + "maxItems": _keywords.maxItems, + "maxLength": _keywords.maxLength, + "maxProperties": _keywords.maxProperties, + "maximum": _keywords.maximum, + "minItems": _keywords.minItems, + "minLength": _keywords.minLength, + "minProperties": _keywords.minProperties, + "minimum": _keywords.minimum, + "multipleOf": _keywords.multipleOf, + "not": _keywords.not_, + "oneOf": _keywords.oneOf, + "pattern": _keywords.pattern, + "patternProperties": _keywords.patternProperties, + "properties": _keywords.properties, + "propertyNames": _keywords.propertyNames, + "required": _keywords.required, + "type": _keywords.type, + "uniqueItems": _keywords.uniqueItems, }, type_checker=_types.draft6_type_checker, format_checker=_format.draft6_format_checker, version="draft6", id_of=referencing.jsonschema.DRAFT6.id_of, - applicable_validators=_legacy_validators.ignore_ref_siblings, + applicable_validators=_legacy_keywords.ignore_ref_siblings, ) Draft7Validator = create( @@ -703,44 +703,44 @@ def extend( "http://json-schema.org/draft-07/schema#", ), 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, + "$ref": _keywords.ref, + "additionalItems": _keywords.additionalItems, + "additionalProperties": _keywords.additionalProperties, + "allOf": _keywords.allOf, + "anyOf": _keywords.anyOf, + "const": _keywords.const, + "contains": _legacy_keywords.contains_draft6_draft7, + "dependencies": _legacy_keywords.dependencies_draft4_draft6_draft7, + "enum": _keywords.enum, + "exclusiveMaximum": _keywords.exclusiveMaximum, + "exclusiveMinimum": _keywords.exclusiveMinimum, + "format": _keywords.format, + "if": _keywords.if_, + "items": _legacy_keywords.items_draft6_draft7_draft201909, + "maxItems": _keywords.maxItems, + "maxLength": _keywords.maxLength, + "maxProperties": _keywords.maxProperties, + "maximum": _keywords.maximum, + "minItems": _keywords.minItems, + "minLength": _keywords.minLength, + "minProperties": _keywords.minProperties, + "minimum": _keywords.minimum, + "multipleOf": _keywords.multipleOf, + "not": _keywords.not_, + "oneOf": _keywords.oneOf, + "pattern": _keywords.pattern, + "patternProperties": _keywords.patternProperties, + "properties": _keywords.properties, + "propertyNames": _keywords.propertyNames, + "required": _keywords.required, + "type": _keywords.type, + "uniqueItems": _keywords.uniqueItems, }, type_checker=_types.draft7_type_checker, format_checker=_format.draft7_format_checker, version="draft7", id_of=referencing.jsonschema.DRAFT7.id_of, - applicable_validators=_legacy_validators.ignore_ref_siblings, + applicable_validators=_legacy_keywords.ignore_ref_siblings, ) Draft201909Validator = create( @@ -748,42 +748,42 @@ def extend( "https://json-schema.org/draft/2019-09/schema", ), 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": _legacy_validators.unevaluatedItems_draft2019, - "unevaluatedProperties": _validators.unevaluatedProperties, - "uniqueItems": _validators.uniqueItems, + "$recursiveRef": _legacy_keywords.recursiveRef, + "$ref": _keywords.ref, + "additionalItems": _keywords.additionalItems, + "additionalProperties": _keywords.additionalProperties, + "allOf": _keywords.allOf, + "anyOf": _keywords.anyOf, + "const": _keywords.const, + "contains": _keywords.contains, + "dependentRequired": _keywords.dependentRequired, + "dependentSchemas": _keywords.dependentSchemas, + "enum": _keywords.enum, + "exclusiveMaximum": _keywords.exclusiveMaximum, + "exclusiveMinimum": _keywords.exclusiveMinimum, + "format": _keywords.format, + "if": _keywords.if_, + "items": _legacy_keywords.items_draft6_draft7_draft201909, + "maxItems": _keywords.maxItems, + "maxLength": _keywords.maxLength, + "maxProperties": _keywords.maxProperties, + "maximum": _keywords.maximum, + "minItems": _keywords.minItems, + "minLength": _keywords.minLength, + "minProperties": _keywords.minProperties, + "minimum": _keywords.minimum, + "multipleOf": _keywords.multipleOf, + "not": _keywords.not_, + "oneOf": _keywords.oneOf, + "pattern": _keywords.pattern, + "patternProperties": _keywords.patternProperties, + "properties": _keywords.properties, + "propertyNames": _keywords.propertyNames, + "required": _keywords.required, + "type": _keywords.type, + "unevaluatedItems": _legacy_keywords.unevaluatedItems_draft2019, + "unevaluatedProperties": _keywords.unevaluatedProperties, + "uniqueItems": _keywords.uniqueItems, }, type_checker=_types.draft201909_type_checker, format_checker=_format.draft201909_format_checker, @@ -795,43 +795,43 @@ def extend( "https://json-schema.org/draft/2020-12/schema", ), 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, + "$dynamicRef": _keywords.dynamicRef, + "$ref": _keywords.ref, + "additionalItems": _keywords.additionalItems, + "additionalProperties": _keywords.additionalProperties, + "allOf": _keywords.allOf, + "anyOf": _keywords.anyOf, + "const": _keywords.const, + "contains": _keywords.contains, + "dependentRequired": _keywords.dependentRequired, + "dependentSchemas": _keywords.dependentSchemas, + "enum": _keywords.enum, + "exclusiveMaximum": _keywords.exclusiveMaximum, + "exclusiveMinimum": _keywords.exclusiveMinimum, + "format": _keywords.format, + "if": _keywords.if_, + "items": _keywords.items, + "maxItems": _keywords.maxItems, + "maxLength": _keywords.maxLength, + "maxProperties": _keywords.maxProperties, + "maximum": _keywords.maximum, + "minItems": _keywords.minItems, + "minLength": _keywords.minLength, + "minProperties": _keywords.minProperties, + "minimum": _keywords.minimum, + "multipleOf": _keywords.multipleOf, + "not": _keywords.not_, + "oneOf": _keywords.oneOf, + "pattern": _keywords.pattern, + "patternProperties": _keywords.patternProperties, + "prefixItems": _keywords.prefixItems, + "properties": _keywords.properties, + "propertyNames": _keywords.propertyNames, + "required": _keywords.required, + "type": _keywords.type, + "unevaluatedItems": _keywords.unevaluatedItems, + "unevaluatedProperties": _keywords.unevaluatedProperties, + "uniqueItems": _keywords.uniqueItems, }, type_checker=_types.draft202012_type_checker, format_checker=_format.draft202012_format_checker, From 40733195ec975da5cd86c98522959f9162b338b0 Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Wed, 9 Aug 2023 16:51:57 +0100 Subject: [PATCH 03/16] Stress that the filesystem referencing example is less useful than it looks. --- docs/referencing.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/referencing.rst b/docs/referencing.rst index e3f0e7f45..8a180161f 100644 --- a/docs/referencing.rst +++ b/docs/referencing.rst @@ -149,7 +149,8 @@ Resolving References from the File System ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Another common request from schema authors is to be able to map URIs to the file system, perhaps while developing a set of schemas in different local files. -The referencing library supports doing so dynamically by configuring a callable which can be used to retrieve any schema which is *not* already pre-loaded in the manner described `above `. +If you have a set of *fixed* or *static* schemas in a few files, you still likely will want to follow the `above in-memory instructions `, and simply load all of your files by reading them in-memory from your program. +If however you wish to *dynamically* read files off of the file system, perhaps because they may change during the lifetime of your process, then the referencing library supports doing so fully dynamically by configuring a callable which can be used to retrieve any schema which is *not* already pre-loaded in-memory. Here we resolve any schema beginning with ``http://localhost`` to a directory ``/tmp/schemas`` on the local filesystem (note of course that this will not work if run directly unless you have populated that directory with some schemas): From 926fab1a1ed626b875829106167ddb91576cfd46 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Aug 2023 23:09:25 +0000 Subject: [PATCH 04/16] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.0.282 → v0.0.285](https://github.com/astral-sh/ruff-pre-commit/compare/v0.0.282...v0.0.285) - [github.com/pre-commit/mirrors-prettier: v3.0.1 → v3.0.2](https://github.com/pre-commit/mirrors-prettier/compare/v3.0.1...v3.0.2) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b6014f6c6..653fdf46a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: args: [--fix, lf] - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.0.282" + rev: "v0.0.285" hooks: - id: ruff - repo: https://github.com/PyCQA/isort @@ -24,7 +24,7 @@ repos: hooks: - id: isort - repo: https://github.com/pre-commit/mirrors-prettier - rev: "v3.0.1" + rev: "v3.0.2" hooks: - id: prettier exclude: "^jsonschema/benchmarks/issue232/issue.json$" From c5eddf59c11d70c91908d7d16db844bed62db4ec Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 28 Aug 2023 22:47:36 +0000 Subject: [PATCH 05/16] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.0.285 → v0.0.286](https://github.com/astral-sh/ruff-pre-commit/compare/v0.0.285...v0.0.286) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 653fdf46a..f09e6bcf9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: args: [--fix, lf] - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.0.285" + rev: "v0.0.286" hooks: - id: ruff - repo: https://github.com/PyCQA/isort From 74277a4f3f6086d7bd49d94cce2ff83db68a0bfa Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 23:16:56 +0000 Subject: [PATCH 06/16] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.0.286 → v0.0.287](https://github.com/astral-sh/ruff-pre-commit/compare/v0.0.286...v0.0.287) - [github.com/pre-commit/mirrors-prettier: v3.0.2 → v3.0.3](https://github.com/pre-commit/mirrors-prettier/compare/v3.0.2...v3.0.3) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f09e6bcf9..fbd1c38c8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: args: [--fix, lf] - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.0.286" + rev: "v0.0.287" hooks: - id: ruff - repo: https://github.com/PyCQA/isort @@ -24,7 +24,7 @@ repos: hooks: - id: isort - repo: https://github.com/pre-commit/mirrors-prettier - rev: "v3.0.2" + rev: "v3.0.3" hooks: - id: prettier exclude: "^jsonschema/benchmarks/issue232/issue.json$" From cd886db914498909549803037c6b1a9474861171 Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Sun, 10 Sep 2023 09:56:36 -0400 Subject: [PATCH 07/16] Document the nox envs. --- noxfile.py | 41 +++++++++++++++++++++++++++++++++-------- pyproject.toml | 2 +- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/noxfile.py b/noxfile.py index 6c19a021a..80fbd60b8 100644 --- a/noxfile.py +++ b/noxfile.py @@ -33,7 +33,7 @@ nox.options.sessions = [] -def session(default=True, **kwargs): +def session(default=True, **kwargs): # noqa: D103 def _session(fn): if default: nox.options.sessions.append(kwargs.get("name", fn.__name__)) @@ -45,7 +45,9 @@ def _session(fn): @session(python=["3.8", "3.9", "3.10", "3.11", "3.12", "pypy3"]) @nox.parametrize("installable", INSTALLABLE) def tests(session, installable): - + """ + Run the test suite with a corresponding Python version. + """ env = dict(JSON_SCHEMA_TEST_SUITE=str(ROOT / "json")) session.install("virtue", installable) @@ -87,6 +89,9 @@ def tests(session, installable): @session() @nox.parametrize("installable", INSTALLABLE) def audit(session, installable): + """ + Audit dependencies for vulnerabilities. + """ session.install("pip-audit", installable) session.run("python", "-m", "pip_audit") @@ -107,6 +112,9 @@ def audit(session, installable): @session(tags=["build"]) def build(session): + """ + Build a distribution suitable for PyPI and check its validity. + """ session.install("build", "docutils", "twine") with TemporaryDirectory() as tmpdir: session.run("python", "-m", "build", ROOT, "--outdir", tmpdir) @@ -118,18 +126,27 @@ def build(session): @session() def secrets(session): + """ + Check for accidentally committed secrets. + """ session.install("detect-secrets") session.run("detect-secrets", "scan", ROOT) @session(tags=["style"]) def style(session): + """ + Check Python code style. + """ session.install("ruff") session.run("ruff", "check", ROOT) @session() def typing(session): + """ + Check static typing. + """ session.install("mypy", "types-requests", ROOT) session.run("mypy", "--config", PYPROJECT, PACKAGE) @@ -149,6 +166,9 @@ def typing(session): ], ) def docs(session, builder): + """ + Build the documentation using a specific Sphinx builder. + """ session.install("-r", DOCS / "requirements.txt") with TemporaryDirectory() as tmpdir_str: tmpdir = Path(tmpdir_str) @@ -170,6 +190,9 @@ def docs(session, builder): @session(tags=["docs", "style"], name="docs(style)") def docs_style(session): + """ + Check the documentation style. + """ session.install( "doc8", "pygments", @@ -178,12 +201,6 @@ def docs_style(session): session.run("python", "-m", "doc8", "--config", PYPROJECT, DOCS) -@session(default=False) -def bandit(session): - session.install("bandit") - session.run("bandit", "--recursive", PACKAGE) - - @session(default=False) @nox.parametrize( "benchmark", @@ -193,6 +210,9 @@ def bandit(session): ], ) def perf(session, benchmark): + """ + Run a performance benchmark. + """ session.install("pyperf", f"{ROOT}[format]") tmpdir = Path(session.create_tmp()) output = tmpdir / f"bench-{benchmark}.json" @@ -201,6 +221,11 @@ def perf(session, benchmark): @session(default=False) def requirements(session): + """ + Update the project's pinned requirements. + + You should commit the result afterwards. + """ session.install("pip-tools") for each in [DOCS / "requirements.in"]: session.run( diff --git a/pyproject.toml b/pyproject.toml index 7e1347716..26d299a36 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -180,7 +180,7 @@ extend-exclude = ["json"] docstring-quotes = "double" [tool.ruff.per-file-ignores] -"noxfile.py" = ["ANN", "D"] +"noxfile.py" = ["ANN", "D100"] "docs/*" = ["ANN", "D"] "jsonschema/cli.py" = ["D", "SIM", "UP"] "jsonschema/_utils.py" = ["D"] From 4d5876160256b8f22f910310fd95e0a10fb248ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 09:36:41 +0000 Subject: [PATCH 08/16] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7b1a163cf..b038704e4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: python-version: "3.x" @@ -28,7 +28,7 @@ jobs: outputs: noxenvs: ${{ steps.noxenvs-matrix.outputs.noxenvs }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up nox uses: wntrblm/nox@2023.04.22 - id: noxenvs-matrix @@ -66,7 +66,7 @@ jobs: noxenv: "docs(style)" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install dependencies run: sudo apt-get update && sudo apt-get install -y libenchant-2-dev if: runner.os == 'Linux' && startsWith(matrix.noxenv, 'docs') @@ -103,7 +103,7 @@ jobs: id-token: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Python From 158d73f8a0c74f760de0646fbf6d50408584b53b Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Mon, 11 Sep 2023 11:22:12 -0400 Subject: [PATCH 09/16] Update docs requirements. --- docs/requirements.txt | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 2c3cf53b7..14cd4603a 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile with Python 3.11 # by the following command: # -# pip-compile --config=pyproject.toml docs/requirements.in +# pip-compile docs/requirements.in # alabaster==0.7.13 # via sphinx @@ -28,9 +28,9 @@ cycler==0.11.0 # via matplotlib docutils==0.20.1 # via sphinx -fonttools==4.41.1 +fonttools==4.42.1 # via matplotlib -furo==2023.7.26 +furo==2023.9.10 # via -r docs/requirements.in idna==3.4 # via requests @@ -44,7 +44,7 @@ file:.#egg=jsonschema # via -r docs/requirements.in jsonschema-specifications==2023.7.1 # via jsonschema -kiwisolver==1.4.4 +kiwisolver==1.4.5 # via matplotlib lazy-object-proxy==1.9.0 # via astroid @@ -56,7 +56,7 @@ markupsafe==2.1.3 # via jinja2 matplotlib==3.7.2 # via sphinxext-opengraph -numpy==1.25.1 +numpy==1.25.2 # via # contourpy # matplotlib @@ -68,7 +68,7 @@ pillow==10.0.0 # via matplotlib pyenchant==3.2.2 # via sphinxcontrib-spelling -pygments==2.15.1 +pygments==2.16.1 # via # furo # sphinx @@ -78,13 +78,13 @@ python-dateutil==2.8.2 # via matplotlib pyyaml==6.0.1 # via sphinx-autoapi -referencing==0.30.0 +referencing==0.30.2 # via # jsonschema # jsonschema-specifications requests==2.31.0 # via sphinx -rpds-py==0.9.2 +rpds-py==0.10.2 # via # jsonschema # referencing @@ -92,9 +92,9 @@ six==1.16.0 # via python-dateutil snowballstemmer==2.2.0 # via sphinx -soupsieve==2.4.1 +soupsieve==2.5 # via beautifulsoup4 -sphinx==7.1.1 +sphinx==7.2.5 # via # -r docs/requirements.in # furo @@ -103,6 +103,11 @@ sphinx==7.1.1 # sphinx-basic-ng # sphinx-copybutton # sphinx-json-schema-spec + # sphinxcontrib-applehelp + # sphinxcontrib-devhelp + # sphinxcontrib-htmlhelp + # sphinxcontrib-qthelp + # sphinxcontrib-serializinghtml # sphinxcontrib-spelling # sphinxext-opengraph sphinx-autoapi==2.1.1 @@ -113,19 +118,19 @@ sphinx-basic-ng==1.0.0b2 # via furo sphinx-copybutton==0.5.2 # via -r docs/requirements.in -sphinx-json-schema-spec==2023.7.2 +sphinx-json-schema-spec==2023.8.1 # via -r docs/requirements.in -sphinxcontrib-applehelp==1.0.4 +sphinxcontrib-applehelp==1.0.7 # via sphinx -sphinxcontrib-devhelp==1.0.2 +sphinxcontrib-devhelp==1.0.5 # via sphinx -sphinxcontrib-htmlhelp==2.0.1 +sphinxcontrib-htmlhelp==2.0.4 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.3 +sphinxcontrib-qthelp==1.0.6 # via sphinx -sphinxcontrib-serializinghtml==1.1.5 +sphinxcontrib-serializinghtml==1.1.9 # via sphinx sphinxcontrib-spelling==8.0.0 # via -r docs/requirements.in From ef6906a83b098738996ac71e66fb3b5773b951a7 Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Mon, 11 Sep 2023 11:27:19 -0400 Subject: [PATCH 10/16] Split the pip-licenses noxenv off to its own noxenv. Dependencies of pip-tools shouldn't be included in the license check. I was lazy before and knew this could be the case, but now some CI is failing because of a new pip-tools dependency (albeit one whose license is fine just not on the known list) but it's good to make this properly go away as a possibility. --- noxfile.py | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/noxfile.py b/noxfile.py index 80fbd60b8..15482d902 100644 --- a/noxfile.py +++ b/noxfile.py @@ -95,19 +95,24 @@ def audit(session, installable): session.install("pip-audit", installable) session.run("python", "-m", "pip_audit") - if "format-nongpl" in installable: - session.install("pip-licenses") - session.run( - "python", - "-m", - "piplicenses", - "--ignore-packages", - "pip-requirements-parser", - "pip_audit", - "pip-api", - "--allow-only", - ";".join(NONGPL_LICENSES), - ) + +@session() +def license_check(session): + """ + Check that the non-GPL extra does not allow arbitrary licenses. + """ + session.install("pip-licenses", f"{ROOT}[format-nongpl]") + session.run( + "python", + "-m", + "piplicenses", + "--ignore-packages", + "pip-requirements-parser", + "pip_audit", + "pip-api", + "--allow-only", + ";".join(NONGPL_LICENSES), + ) @session(tags=["build"]) From a323d830a24e545b6211c437cc9f3a0beab99b6f Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Mon, 11 Sep 2023 11:54:31 -0400 Subject: [PATCH 11/16] Evade a Sphinx/PyO3 bug (temporarily) in docs builds. See sphinx-doc/sphinx#11662 which seems like it will be resolved with an upstream PyO3 release. May have to come back and change this pin to be an upper pin if need be / the upstream issue doesn't merge soon. --- docs/requirements.in | 2 +- docs/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/requirements.in b/docs/requirements.in index 0a686cfcf..6e4dd0381 100644 --- a/docs/requirements.in +++ b/docs/requirements.in @@ -1,7 +1,7 @@ file:.#egg=jsonschema furo lxml -sphinx +sphinx!=7.2.5 sphinx-autoapi sphinx-autodoc-typehints sphinx-copybutton diff --git a/docs/requirements.txt b/docs/requirements.txt index 14cd4603a..434ec7f64 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -94,7 +94,7 @@ snowballstemmer==2.2.0 # via sphinx soupsieve==2.5 # via beautifulsoup4 -sphinx==7.2.5 +sphinx==7.2.4 # via # -r docs/requirements.in # furo From 6da8230f9791123ac52822c1312d91cdd12604d4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 23:53:04 +0000 Subject: [PATCH 12/16] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.0.287 → v0.0.288](https://github.com/astral-sh/ruff-pre-commit/compare/v0.0.287...v0.0.288) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fbd1c38c8..69fc51c50 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: args: [--fix, lf] - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.0.287" + rev: "v0.0.288" hooks: - id: ruff - repo: https://github.com/PyCQA/isort From fa91642b6ed5a2a134f53276fc5762672114e7d3 Mon Sep 17 00:00:00 2001 From: Stephan Wurm <121798939+swaeberle@users.noreply.github.com> Date: Wed, 5 Jul 2023 16:09:28 +0200 Subject: [PATCH 13/16] Allow single label hostname in format string When validating hostname format strings with module fqdn, only FQDNs were accepted, as the minimum label length of the FQDN class is 2. Therefore, single label hostnames like "localhost" were rejected. Fixed this by validating with a minimum label length of 1. Signed-off-by: Stephan Wurm --- jsonschema/_format.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsonschema/_format.py b/jsonschema/_format.py index f9f82bbe4..25d4caa7f 100644 --- a/jsonschema/_format.py +++ b/jsonschema/_format.py @@ -274,7 +274,7 @@ def is_ipv6(instance: object) -> bool: def is_host_name(instance: object) -> bool: if not isinstance(instance, str): return True - return FQDN(instance).is_valid + return FQDN(instance, min_labels=1).is_valid with suppress(ImportError): From 44d2b7b0127ecc260437e37e6ed6da3534458fc3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 23:28:46 +0000 Subject: [PATCH 14/16] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.0.288 → v0.0.290](https://github.com/astral-sh/ruff-pre-commit/compare/v0.0.288...v0.0.290) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 69fc51c50..7cbd0b6aa 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: args: [--fix, lf] - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.0.288" + rev: "v0.0.290" hooks: - id: ruff - repo: https://github.com/PyCQA/isort From 64b8c575640dcf7c9e7a5a434de6a331881ab4ec Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Wed, 20 Sep 2023 09:53:14 -0400 Subject: [PATCH 15/16] Squashed 'json/' changes from 5cc9214e8..4ecd01f30 4ecd01f30 Merge pull request #687 from swaeberle/check-single-label-idn-hostnames 732e7275a test single label IDN hostnames ab3924a66 Merge pull request #685 from swaeberle/check-single-label-hostnames 9265a4fa9 do not test hostname with leading digit for older drafts 261b52db1 do not allow starting digits in hostnames for older drafts 9fc231ea4 test digits in hostnames e9b20158e test plain single label hostnames c8b57093d test valid single label hostnames 299aa7fe5 Merge pull request #682 from json-schema-org/useless-branch fbb3cac60 Bump the sanity check to use a released version of jsonschema git-subtree-dir: json git-subtree-split: 4ecd01f30bce36a61224fa0f46c2c3f0cf7481dc --- bin/jsonschema_suite | 9 +++---- .../draft-next/optional/format/hostname.json | 25 +++++++++++++++++++ .../optional/format/idn-hostname.json | 25 +++++++++++++++++++ .../optional/format/hostname.json | 25 +++++++++++++++++++ .../optional/format/idn-hostname.json | 25 +++++++++++++++++++ .../optional/format/hostname.json | 25 +++++++++++++++++++ .../optional/format/idn-hostname.json | 25 +++++++++++++++++++ tests/draft4/optional/format/hostname.json | 20 +++++++++++++++ tests/draft6/optional/format/hostname.json | 20 +++++++++++++++ tests/draft7/optional/format/hostname.json | 20 +++++++++++++++ .../draft7/optional/format/idn-hostname.json | 20 +++++++++++++++ tox.ini | 2 +- 12 files changed, 235 insertions(+), 6 deletions(-) diff --git a/bin/jsonschema_suite b/bin/jsonschema_suite index 9fee8d7ba..c83e7cb2c 100755 --- a/bin/jsonschema_suite +++ b/bin/jsonschema_suite @@ -14,9 +14,11 @@ import warnings try: import jsonschema.validators except ImportError: - jsonschema = None + jsonschema = Unresolvable = None VALIDATORS = {} else: + from referencing.exceptions import Unresolvable + VALIDATORS = { "draft3": jsonschema.validators.Draft3Validator, "draft4": jsonschema.validators.Draft4Validator, @@ -587,7 +589,7 @@ class SanityTests(unittest.TestCase): with self.subTest(case=case, version=version.name): try: Validator(case["schema"]).is_valid(12) - except jsonschema.exceptions.RefResolutionError: + except Unresolvable: pass @unittest.skipIf(jsonschema is None, "Validation library not present!") @@ -615,9 +617,6 @@ class SanityTests(unittest.TestCase): with self.subTest(path=path): try: validator.validate(cases) - except jsonschema.exceptions.RefResolutionError: - # python-jsonschema/jsonschema#884 - pass except jsonschema.ValidationError as error: self.fail(str(error)) diff --git a/tests/draft-next/optional/format/hostname.json b/tests/draft-next/optional/format/hostname.json index 967848653..bfb306363 100644 --- a/tests/draft-next/optional/format/hostname.json +++ b/tests/draft-next/optional/format/hostname.json @@ -95,6 +95,31 @@ "description": "exceeds maximum label length", "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl.com", "valid": false + }, + { + "description": "single label", + "data": "hostname", + "valid": true + }, + { + "description": "single label with hyphen", + "data": "host-name", + "valid": true + }, + { + "description": "single label with digits", + "data": "h0stn4me", + "valid": true + }, + { + "description": "single label starting with digit", + "data": "1host", + "valid": true + }, + { + "description": "single label ending with digit", + "data": "hostnam3", + "valid": true } ] } diff --git a/tests/draft-next/optional/format/idn-hostname.json b/tests/draft-next/optional/format/idn-hostname.json index ee2e792fa..109bf73c9 100644 --- a/tests/draft-next/optional/format/idn-hostname.json +++ b/tests/draft-next/optional/format/idn-hostname.json @@ -301,6 +301,31 @@ "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.1 https://www.w3.org/TR/alreq/#h_disjoining_enforcement", "data": "\u0628\u064a\u200c\u0628\u064a", "valid": true + }, + { + "description": "single label", + "data": "hostname", + "valid": true + }, + { + "description": "single label with hyphen", + "data": "host-name", + "valid": true + }, + { + "description": "single label with digits", + "data": "h0stn4me", + "valid": true + }, + { + "description": "single label starting with digit", + "data": "1host", + "valid": true + }, + { + "description": "single label ending with digit", + "data": "hostnam3", + "valid": true } ] } diff --git a/tests/draft2019-09/optional/format/hostname.json b/tests/draft2019-09/optional/format/hostname.json index eac8cac6f..f3b7181c8 100644 --- a/tests/draft2019-09/optional/format/hostname.json +++ b/tests/draft2019-09/optional/format/hostname.json @@ -95,6 +95,31 @@ "description": "exceeds maximum label length", "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl.com", "valid": false + }, + { + "description": "single label", + "data": "hostname", + "valid": true + }, + { + "description": "single label with hyphen", + "data": "host-name", + "valid": true + }, + { + "description": "single label with digits", + "data": "h0stn4me", + "valid": true + }, + { + "description": "single label starting with digit", + "data": "1host", + "valid": true + }, + { + "description": "single label ending with digit", + "data": "hostnam3", + "valid": true } ] } diff --git a/tests/draft2019-09/optional/format/idn-hostname.json b/tests/draft2019-09/optional/format/idn-hostname.json index 72f179751..072a6b08e 100644 --- a/tests/draft2019-09/optional/format/idn-hostname.json +++ b/tests/draft2019-09/optional/format/idn-hostname.json @@ -301,6 +301,31 @@ "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.1 https://www.w3.org/TR/alreq/#h_disjoining_enforcement", "data": "\u0628\u064a\u200c\u0628\u064a", "valid": true + }, + { + "description": "single label", + "data": "hostname", + "valid": true + }, + { + "description": "single label with hyphen", + "data": "host-name", + "valid": true + }, + { + "description": "single label with digits", + "data": "h0stn4me", + "valid": true + }, + { + "description": "single label starting with digit", + "data": "1host", + "valid": true + }, + { + "description": "single label ending with digit", + "data": "hostnam3", + "valid": true } ] } diff --git a/tests/draft2020-12/optional/format/hostname.json b/tests/draft2020-12/optional/format/hostname.json index c8db9770e..41418dd4a 100644 --- a/tests/draft2020-12/optional/format/hostname.json +++ b/tests/draft2020-12/optional/format/hostname.json @@ -95,6 +95,31 @@ "description": "exceeds maximum label length", "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl.com", "valid": false + }, + { + "description": "single label", + "data": "hostname", + "valid": true + }, + { + "description": "single label with hyphen", + "data": "host-name", + "valid": true + }, + { + "description": "single label with digits", + "data": "h0stn4me", + "valid": true + }, + { + "description": "single label starting with digit", + "data": "1host", + "valid": true + }, + { + "description": "single label ending with digit", + "data": "hostnam3", + "valid": true } ] } diff --git a/tests/draft2020-12/optional/format/idn-hostname.json b/tests/draft2020-12/optional/format/idn-hostname.json index 5549c0550..bc7d92f66 100644 --- a/tests/draft2020-12/optional/format/idn-hostname.json +++ b/tests/draft2020-12/optional/format/idn-hostname.json @@ -301,6 +301,31 @@ "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.1 https://www.w3.org/TR/alreq/#h_disjoining_enforcement", "data": "\u0628\u064a\u200c\u0628\u064a", "valid": true + }, + { + "description": "single label", + "data": "hostname", + "valid": true + }, + { + "description": "single label with hyphen", + "data": "host-name", + "valid": true + }, + { + "description": "single label with digits", + "data": "h0stn4me", + "valid": true + }, + { + "description": "single label starting with digit", + "data": "1host", + "valid": true + }, + { + "description": "single label ending with digit", + "data": "hostnam3", + "valid": true } ] } diff --git a/tests/draft4/optional/format/hostname.json b/tests/draft4/optional/format/hostname.json index 8a67fda88..a8ecd194f 100644 --- a/tests/draft4/optional/format/hostname.json +++ b/tests/draft4/optional/format/hostname.json @@ -92,6 +92,26 @@ "description": "exceeds maximum label length", "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl.com", "valid": false + }, + { + "description": "single label", + "data": "hostname", + "valid": true + }, + { + "description": "single label with hyphen", + "data": "host-name", + "valid": true + }, + { + "description": "single label with digits", + "data": "h0stn4me", + "valid": true + }, + { + "description": "single label ending with digit", + "data": "hostnam3", + "valid": true } ] } diff --git a/tests/draft6/optional/format/hostname.json b/tests/draft6/optional/format/hostname.json index 8a67fda88..a8ecd194f 100644 --- a/tests/draft6/optional/format/hostname.json +++ b/tests/draft6/optional/format/hostname.json @@ -92,6 +92,26 @@ "description": "exceeds maximum label length", "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl.com", "valid": false + }, + { + "description": "single label", + "data": "hostname", + "valid": true + }, + { + "description": "single label with hyphen", + "data": "host-name", + "valid": true + }, + { + "description": "single label with digits", + "data": "h0stn4me", + "valid": true + }, + { + "description": "single label ending with digit", + "data": "hostnam3", + "valid": true } ] } diff --git a/tests/draft7/optional/format/hostname.json b/tests/draft7/optional/format/hostname.json index 8a67fda88..a8ecd194f 100644 --- a/tests/draft7/optional/format/hostname.json +++ b/tests/draft7/optional/format/hostname.json @@ -92,6 +92,26 @@ "description": "exceeds maximum label length", "data": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl.com", "valid": false + }, + { + "description": "single label", + "data": "hostname", + "valid": true + }, + { + "description": "single label with hyphen", + "data": "host-name", + "valid": true + }, + { + "description": "single label with digits", + "data": "h0stn4me", + "valid": true + }, + { + "description": "single label ending with digit", + "data": "hostnam3", + "valid": true } ] } diff --git a/tests/draft7/optional/format/idn-hostname.json b/tests/draft7/optional/format/idn-hostname.json index 6c8f86a3a..dc47f7b5c 100644 --- a/tests/draft7/optional/format/idn-hostname.json +++ b/tests/draft7/optional/format/idn-hostname.json @@ -298,6 +298,26 @@ "comment": "https://tools.ietf.org/html/rfc5891#section-4.2.3.3 https://tools.ietf.org/html/rfc5892#appendix-A.1 https://www.w3.org/TR/alreq/#h_disjoining_enforcement", "data": "\u0628\u064a\u200c\u0628\u064a", "valid": true + }, + { + "description": "single label", + "data": "hostname", + "valid": true + }, + { + "description": "single label with hyphen", + "data": "host-name", + "valid": true + }, + { + "description": "single label with digits", + "data": "h0stn4me", + "valid": true + }, + { + "description": "single label ending with digit", + "data": "hostnam3", + "valid": true } ] } diff --git a/tox.ini b/tox.ini index dcc0dce6d..a5ded970e 100644 --- a/tox.ini +++ b/tox.ini @@ -5,5 +5,5 @@ skipsdist = True [testenv:sanity] # used just for validating the structure of the test case files themselves -deps = jsonschema==4.18.0a4 +deps = jsonschema==4.19.0 commands = {envpython} bin/jsonschema_suite check From bbe0b5b113c547e8508f9ad9c0afddd203748989 Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Wed, 20 Sep 2023 09:56:23 -0400 Subject: [PATCH 16/16] Update the CHANGELOG. --- CHANGELOG.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8d77ddb54..2d89bf225 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,10 @@ +v4.19.1 +======= + +* Single label hostnames are now properly considered valid according to the ``hostname`` format. + This is the behavior specified by the relevant RFC (1123). + IDN hostname behavior was already correct. + v4.19.0 =======