Browse Source

Disabled deterministic __hash__ method and renamed it d_hash() + tests

Yann Weber 9 years ago
parent
commit
0ad46e9e37

+ 12
- 12
lodel/editorial_model/components.py View File

@@ -30,13 +30,13 @@ class EmComponent(object):
30 30
             return str(self.uid)
31 31
         return str(self.display_name)
32 32
 
33
-    def __hash__(self):
33
+    def d_hash(self):
34 34
         m = hashlib.md5()
35 35
         for data in (
36 36
                         self.uid,
37
-                        str(hash(self.display_name)),
38
-                        str(hash(self.help_text)),
39
-                        str(hash(self.group)),
37
+                        'NODISPNAME' if self.display_name is None else str(self.display_name.d_hash()),
38
+                        'NOHELP' if self.help_text is None else str(self.help_text.d_hash()),
39
+                        'NOGROUP' if self.group is None else str(self.group.d_hash()),
40 40
         ):
41 41
             m.update(bytes(data, 'utf-8'))
42 42
         return int.from_bytes(m.digest(), byteorder='big')
@@ -105,11 +105,11 @@ class EmClass(EmComponent):
105 105
     def new_field(self, uid, **field_kwargs):
106 106
         return self.add_field(EmField(uid, **field_kwargs))
107 107
 
108
-    def __hash__(self):
108
+    def d_hash(self):
109 109
         m = hashlib.md5()
110
-        payload = str(super().__hash__()) + "1" if self.abstract else "0"
110
+        payload = str(super().d_hash()) + ("1" if self.abstract else "0")
111 111
         for p in sorted(self.parents):
112
-            payload += str(hash(p))
112
+            payload += str(p.d_hash())
113 113
         m.update(bytes(payload, 'utf-8'))
114 114
         return int.from_bytes(m.digest(), byteorder='big')
115 115
 
@@ -133,11 +133,11 @@ class EmField(EmComponent):
133 133
 
134 134
     ## @warning Not complete !
135 135
     # @todo Complete the hash when data handlers becomes available
136
-    def __hash__(self):
136
+    def d_hash(self):
137 137
         return int.from_bytes(hashlib.md5(
138 138
                         bytes(
139
-                                "%s%s" % (  super().__hash__(),
140
-                                            hash(self.data_handler)), 
139
+                                "%s%s" % (  super().d_hash(),
140
+                                            self.data_handler), 
141 141
                                 'utf-8')
142 142
         ).digest(), byteorder='big')
143 143
 
@@ -224,13 +224,13 @@ class EmGroup(object):
224 224
         else:
225 225
             return self.display_name.get()
226 226
 
227
-    def __hash__(self):
227
+    def d_hash(self):
228 228
         
229 229
         payload = "%s%s%s" % (self.uid, hash(self.display_name), hash(self.help_text))
230 230
         for recurs in (False, True):
231 231
             deps = self.dependencies(recurs)
232 232
             for dep_uid in sorted(deps.keys()):
233
-                payload += str(hash(deps[dep_uid]))
233
+                payload += str(deps[dep_uid].d_hash())
234 234
         for req_by_uid in self.required_by:
235 235
             payload += req_by_uid
236 236
         return int.from_bytes(

+ 5
- 4
lodel/editorial_model/model.py View File

@@ -90,13 +90,14 @@ class EditorialModel(object):
90 90
     # @see classes() groups()
91 91
     def __elt_getter(self, elts, uid):
92 92
         return iter(elts.values()) if uid is None else elts[uid]
93
-
94
-    def __hash__(self):
93
+    
94
+    ## @brief Lodel hash
95
+    def d_hash(self):
95 96
         payload = "%s%s" % (self.name,hash(self.description))
96 97
         for guid in sorted(self.__groups):
97
-            payload += str(hash(self.__groups[guid]))
98
+            payload += str(self.__groups[guid].d_hash())
98 99
         for cuid in sorted(self.__classes):
99
-            payload += str(hash(self.__classes[cuid]))
100
+            payload += str(self.__classes[cuid].d_hash())
100 101
         return int.from_bytes(
101 102
                                 hashlib.md5(bytes(payload, 'utf-8')).digest(),
102 103
                                 byteorder='big'

+ 6
- 0
lodel/utils/mlstring.py View File

@@ -80,6 +80,12 @@ class MlString(object):
80 80
         return MlString(json.loads(json_str))
81 81
 
82 82
     def __hash__(self):
83
+        res = ''
84
+        for lang in sorted(list(self.values.keys())):
85
+            res = hash((res, lang, self.values[lang]))
86
+        return res
87
+
88
+    def d_hash(self):
83 89
         m = hashlib.md5()
84 90
         for lang in sorted(list(self.values.keys())):
85 91
             m.update(bytes(lang+";"+self.values[lang], 'utf-8'))

+ 43
- 0
tests/editorial_model/test_translator_picklefile.py View File

@@ -0,0 +1,43 @@
1
+#-*- coding: utf-8 -*-
2
+
3
+import unittest
4
+import tempfile
5
+import os
6
+
7
+from lodel.editorial_model.translator import picklefile
8
+from lodel.editorial_model.model import EditorialModel
9
+from lodel.editorial_model.components import *
10
+from lodel.editorial_model.exceptions import *
11
+
12
+class PickleFileTestCase(unittest.TestCase):
13
+    
14
+    def test_save(self):
15
+        model = EditorialModel("test model", description = "Test EM")
16
+        cls1 = model.new_class('testclass1', display_name = 'Classe de test 1', help_text = 'super aide')
17
+        c1f1 = cls1.new_field('testfield1', data_handler = None)
18
+        c1f2 = cls1.new_field('testfield2', data_handler = None)
19
+        cls2 = model.new_class('testclass2')
20
+        c2f1 = cls2.new_field('testfield1', data_handler = None)
21
+        c2f2 = cls2.new_field('testfield2', data_handler = None)
22
+
23
+        grp1 = model.new_group('testgroup1')
24
+        grp1.add_components((cls1, c1f1))
25
+        grp2 = model.new_group('testgroup2')
26
+        grp2.add_components((cls2, c1f2, c2f1, c2f2))
27
+
28
+        grp2.add_dependencie(grp1)
29
+        
30
+        tmpfd, temp_file = tempfile.mkstemp()
31
+        os.close(tmpfd)
32
+        os.unlink(temp_file)
33
+
34
+        model.save(picklefile, filename=temp_file)
35
+        new_model = model.load(picklefile, filename=temp_file)
36
+
37
+        self.assertNotEqual(id(new_model), id(model))
38
+        self.assertEqual(new_model.d_hash(), model.d_hash())
39
+
40
+        os.unlink(temp_file)
41
+
42
+
43
+

+ 2
- 2
tests/test_utils_mlstrings.py View File

@@ -81,7 +81,7 @@ class MlStringTestCase(unittest.TestCase):
81 81
         self.assertNotEqual(hash(mls1), hash(mls2))
82 82
 
83 83
 
84
-    def test_hash(self):
84
+    def test_d_hash(self):
85 85
         """ Test if the hash method is deterministic """
86 86
         mls1 = MlString('Hello world !')
87
-        self.assertEqual(hash(mls1),1631096711380631894)
87
+        self.assertEqual(mls1.d_hash(),305033383450738439650269714534939972534)

Loading…
Cancel
Save