When an invariant is defined in an interface, it's found by
`validateInvariants` in all interfaces inheriting from that interface. Make sure to call each invariant only once when validating invariants.
This commit is contained in:
parent
255db9d3c0
commit
1025519cb6
|
@ -2,6 +2,7 @@
|
|||
*.pyc
|
||||
*.pyo
|
||||
*.so
|
||||
*.swp
|
||||
__pycache__
|
||||
.coverage
|
||||
.coverage.*
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
that argument. See `issue 208
|
||||
<https://github.com/zopefoundation/zope.interface/issues/208>`_.
|
||||
|
||||
- When an invariant is defined in an interface, it's found by
|
||||
`validateInvariants` in all interfaces inheriting from that interface.
|
||||
Make sure to call each invariant only once when validating invariants.
|
||||
|
||||
5.1.0 (2020-04-08)
|
||||
==================
|
||||
|
|
|
@ -875,9 +875,14 @@ class InterfaceClass(_InterfaceClassBase):
|
|||
def queryDescriptionFor(self, name, default=None):
|
||||
return self.get(name, default)
|
||||
|
||||
def validateInvariants(self, obj, errors=None):
|
||||
def validateInvariants(self, obj, errors=None, seen=None):
|
||||
"""validate object to defined invariants."""
|
||||
if seen is None:
|
||||
seen = set()
|
||||
for call in self.queryTaggedValue('invariants', []):
|
||||
if call in seen:
|
||||
continue
|
||||
seen.add(call)
|
||||
try:
|
||||
call(obj)
|
||||
except Invalid as e:
|
||||
|
@ -886,7 +891,7 @@ class InterfaceClass(_InterfaceClassBase):
|
|||
errors.append(e)
|
||||
for base in self.__bases__:
|
||||
try:
|
||||
base.validateInvariants(obj, errors)
|
||||
base.validateInvariants(obj, errors, seen=seen)
|
||||
except Invalid:
|
||||
if errors is None:
|
||||
raise
|
||||
|
|
|
@ -1014,6 +1014,20 @@ class InterfaceClassTests(unittest.TestCase):
|
|||
self.assertEqual(len(_errors), 1)
|
||||
self.assertTrue(isinstance(_errors[0], Invalid))
|
||||
|
||||
def test_validateInvariants_inherited_not_called_multiple_times(self):
|
||||
_passable_called_with = []
|
||||
|
||||
def _passable(*args, **kw):
|
||||
_passable_called_with.append((args, kw))
|
||||
return True
|
||||
|
||||
obj = object()
|
||||
base = self._makeOne('IBase')
|
||||
base.setTaggedValue('invariants', [_passable])
|
||||
derived = self._makeOne('IDerived', (base,))
|
||||
derived.validateInvariants(obj)
|
||||
self.assertEqual(1, len(_passable_called_with))
|
||||
|
||||
def test___reduce__(self):
|
||||
iface = self._makeOne('PickleMe')
|
||||
self.assertEqual(iface.__reduce__(), 'PickleMe')
|
||||
|
|
Loading…
Reference in New Issue