From 76b403a47c262ff3b7137fc81b82a8eb4a25493b Mon Sep 17 00:00:00 2001 From: Pallab Pain Date: Fri, 21 Apr 2023 23:01:03 +0530 Subject: [PATCH] fix(jsonschema): sets default values defined in the schema When we moved to validate `jsonschemas` on the fly instead of using the pre-compiled validation code, we regressed the existing implementation by not realizing that the validation isn't setting defaults anymore. In order to solve the issue, we referred to the following link, https://python-jsonschema.readthedocs.io/en/stable/faq/#why-doesn-t-my-schema-s-default-property-set-the-default-on-my-instance Since we are using the draft07 of JSONSchema, we referred to the article and updated the code to define a default validator by extending the Draft7Validator class to set defaults. We now use this default validator instead of the `jsonschema.validate` method. --- riocli/jsonschema/validate.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/riocli/jsonschema/validate.py b/riocli/jsonschema/validate.py index 5a82bfc4..17ca9544 100644 --- a/riocli/jsonschema/validate.py +++ b/riocli/jsonschema/validate.py @@ -16,8 +16,7 @@ from pathlib import Path import yaml - -import jsonschema +from jsonschema import validators, Draft7Validator @lru_cache(maxsize=None) @@ -30,8 +29,33 @@ def load_schema(resource: str) -> dict: return yaml.safe_load(f) +def extend_with_default(validator_class): + validate_properties = validator_class.VALIDATORS["properties"] + + def set_defaults(validator, properties, instance, schema): + for p, sub_schema in properties.items(): + if "default" in sub_schema: + if isinstance(instance, dict): + instance.setdefault(p, sub_schema["default"]) + if isinstance(instance, list): + for i in instance: + i.setdefault(p, sub_schema["default"]) + + for error in validate_properties( + validator, properties, instance, schema, + ): + yield error + + return validators.extend( + validator_class, {"properties": set_defaults}, + ) + + +DefaultValidator = extend_with_default(Draft7Validator) + + def validate_manifest(instance, schema) -> None: """ Validates a manifest against a JSON schema. """ - jsonschema.validate(instance, schema) + DefaultValidator(schema).validate(instance)