diff options
Diffstat (limited to 'jsonschema')
-rw-r--r-- | jsonschema/validators.py | 78 |
1 files changed, 61 insertions, 17 deletions
diff --git a/jsonschema/validators.py b/jsonschema/validators.py index 3182d13..62e86df 100644 --- a/jsonschema/validators.py +++ b/jsonschema/validators.py @@ -217,6 +217,23 @@ def create( stacklevel=2, ) + def evolve(self, **changes): + cls = self.__class__ + schema = changes.setdefault("schema", self.schema) + NewValidator = validator_for(schema, default=cls) + + for field in attr.fields(cls): + if not field.init: + continue + attr_name = field.name + init_name = field.alias + if init_name not in changes: + changes[init_name] = getattr(self, attr_name) + + return NewValidator(**changes) + + cls.evolve = evolve + def __attrs_post_init__(self): if self._resolver is None: self._resolver = self._registry.resolver_with_root( @@ -257,18 +274,10 @@ def create( return self._ref_resolver def evolve(self, **changes): - # Essentially reproduces attr.evolve, but may involve instantiating - # a different class than this one. - cls = self.__class__ - schema = changes.setdefault("schema", self.schema) - NewValidator = validator_for(schema, default=cls) + NewValidator = validator_for(schema, default=self.__class__) - for field in attr.fields(cls): - if not field.init: - continue - attr_name = field.name # To deal with private attributes. - init_name = field.alias + for (attr_name, init_name) in evolve_fields: if init_name not in changes: changes[init_name] = getattr(self, attr_name) @@ -328,17 +337,46 @@ def create( schema_path=None, resolver=None, ): + 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 + if resolver is None: resolver = self._resolver.in_subresource( specification.create_resource(schema), ) - validator = self.evolve(schema=schema, _resolver=resolver) - for error in validator.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 + evolved = self.evolve(schema=schema, _resolver=resolver) + + for k, v in applicable_validators(schema): + validator = evolved.VALIDATORS.get(k) + if validator is None: + continue + + errors = validator(evolved, 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=evolved.TYPE_CHECKER, + ) + if k not in {"if", "$ref"}: + error.schema_path.appendleft(k) + 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): @@ -389,6 +427,12 @@ def create( error = next(self.iter_errors(instance), None) return error is None + evolve_fields = [ + (field.name, field.alias) + for field in attr.fields(Validator) + if field.init + ] + if version is not None: safe = version.title().replace(" ", "").replace("-", "") Validator.__name__ = Validator.__qualname__ = f"{safe}Validator" |