From a8c3b140a0134aa8c07fd7720d4e40f1bf759545 Mon Sep 17 00:00:00 2001 From: Julian Berman Date: Wed, 17 Aug 2022 18:25:27 +0300 Subject: [PATCH] Fix one more Validator.evolve issue for downstream Validators. Here for renamed attributes out of attrs-using classes. Refs: 'https://github.com/python-jsonschema/jsonschema/issues/982#issuecomment-1218117191' --- CHANGELOG.rst | 5 +++++ jsonschema/tests/test_validators.py | 4 +++- jsonschema/validators.py | 10 ++++++---- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index add473fbe..59fe78c4c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,8 @@ +v4.10.2 +------- + +* Fix a second place where subclasses may have added attrs attributes (#982). + v4.10.1 ------- diff --git a/jsonschema/tests/test_validators.py b/jsonschema/tests/test_validators.py index 87fa1edeb..e6452d81f 100644 --- a/jsonschema/tests/test_validators.py +++ b/jsonschema/tests/test_validators.py @@ -1488,12 +1488,14 @@ def test_evolve_with_subclass(self): @attr.s class OhNo(self.Validator): foo = attr.ib(factory=lambda: [1, 2, 3]) + _bar = attr.ib(default=37) - validator = OhNo({}) + validator = OhNo({}, bar=12) self.assertEqual(validator.foo, [1, 2, 3]) new = validator.evolve(schema={"type": "integer"}) self.assertEqual(new.foo, [1, 2, 3]) + self.assertEqual(new._bar, 12) def test_it_delegates_to_a_legacy_ref_resolver(self): """ diff --git a/jsonschema/validators.py b/jsonschema/validators.py index c799d4075..ab510d30e 100644 --- a/jsonschema/validators.py +++ b/jsonschema/validators.py @@ -202,12 +202,14 @@ def check_schema(cls, schema): raise exceptions.SchemaError.create_from(error) def evolve(self, **changes): - schema = changes.setdefault("schema", self.schema) - NewValidator = validator_for(schema, default=self.__class__) - # Essentially reproduces attr.evolve, but may involve instantiating # a different class than this one. - for field in attr.fields(Validator): + 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 # To deal with private attributes.