[constraints] provide proper comparison and hashability between constraints

closes #294378.

authorAurelien Campeas <aurelien.campeas@pythonian.fr>
changeset9e0e59671d5f
branchdefault
phasepublic
hiddenno
parent revision#53c8caa43cc0 handle none or unset attribute in BoundaryConstraint
child revision#12fe776d5042 fix message generated when Attribute is used in a constraint: we want to see the name of the attribute, not Attribute('attr name'), #a1257c74fe60 support for calling unicode/str on a validation error before its actual translation., #7ac70945c667 [reader] bring back obsolete and import_erschema
files modified by this revision
constraints.py
test/unittest_constraints.py
# HG changeset patch
# User Aurelien Campeas <aurelien.campeas@pythonian.fr>
# Date 1435594555 -7200
# Mon Jun 29 18:15:55 2015 +0200
# Node ID 9e0e59671d5f49b48cf22cb4602c04f3ded845bc
# Parent 53c8caa43cc0ef55a254300ec20427e6bf4b70fb
[constraints] provide proper comparison and hashability between constraints

closes #294378.

diff --git a/constraints.py b/constraints.py
@@ -57,10 +57,20 @@
1      def failed_message(self, key, value):
2          return _('%(KEY-cstr)s constraint failed for value %(KEY-value)r'), {
3              key+'-cstr': self,
4              key+'-value': value}
5 
6 +    def __eq__(self, other):
7 +        return (self.type(), self.serialize()) == (other.type(), other.serialize())
8 +
9 +    def __ne__(self, other):
10 +        return not self == other
11 +
12 +    def __hash__(self):
13 +        return hash((self.type(), self.serialize()))
14 +
15 +
16  # possible constraints ########################################################
17 
18  class UniqueConstraint(BaseConstraint):
19      """object of relation must be unique"""
20 
diff --git a/test/unittest_constraints.py b/test/unittest_constraints.py
@@ -21,10 +21,24 @@
21  # after import *
22  from datetime import datetime, date, timedelta
23 
24  class ConstraintTC(TestCase):
25 
26 +    def test_membership(self):
27 +        s = set()
28 +        cstrs = [UniqueConstraint(),
29 +                 SizeConstraint(min=0, max=42),
30 +                 RegexpConstraint('babar', 0),
31 +                 BoundaryConstraint('>', 1),
32 +                 IntervalBoundConstraint(minvalue=0, maxvalue=42),
33 +                 StaticVocabularyConstraint((1, 2, 3)),
34 +                 FormatConstraint()]
35 +        for cstr in cstrs:
36 +            s.add(cstr)
37 +            s.add(type(cstr).deserialize(cstr.serialize()))
38 +        self.assertEqual(7, len(s))
39 +
40      def test_interval_serialization_integers(self):
41          cstr = IntervalBoundConstraint(12, 13)
42          self.assertEqual(cstr.serialize(), '12;13')
43          cstr = IntervalBoundConstraint(maxvalue=13)
44          self.assertEqual(cstr.serialize(), 'None;13')