Browse Source

introduce indexes in shared data

Bastien Sevajol 7 years ago
parent
commit
bdfd0ddf6d
2 changed files with 113 additions and 4 deletions
  1. 38 1
      synergine2/share.py
  2. 75 3
      tests/test_share.py

+ 38 - 1
synergine2/share.py View File

8
 from synergine2.exceptions import UnknownSharedData
8
 from synergine2.exceptions import UnknownSharedData
9
 
9
 
10
 
10
 
11
+class SharedDataIndex(object):
12
+    def __init__(
13
+        self,
14
+        shared_data_manager: 'SharedDataManager',
15
+        key: str,
16
+    ) -> None:
17
+        self.shared_data_manager = shared_data_manager
18
+        self.key = key
19
+
20
+    def add(self, value: typing.Any) -> None:
21
+        raise NotImplementedError()
22
+
23
+    def remove(self, value: typing.Any) -> None:
24
+        raise NotImplementedError()
25
+
26
+
11
 class SharedDataManager(object):
27
 class SharedDataManager(object):
12
     """
28
     """
13
     This object is designed to own shared memory between processes. It must be feed (with set method) before
29
     This object is designed to own shared memory between processes. It must be feed (with set method) before
44
     def refresh(self) -> None:
60
     def refresh(self) -> None:
45
         self._data = {}
61
         self._data = {}
46
 
62
 
63
+    def make_index(
64
+        self,
65
+        shared_data_index_class: typing.Type[SharedDataIndex],
66
+        key: str,
67
+        *args: typing.Any,
68
+        **kwargs: typing.Any
69
+    ) -> SharedDataIndex:
70
+        return shared_data_index_class(self, key, *args, **kwargs)
71
+
47
     def create(
72
     def create(
48
         self,
73
         self,
49
         key: str,
74
         key: str,
50
         value,
75
         value,
51
-        indexes=None,
76
+        indexes: typing.List[SharedDataIndex]=None,
52
     ):
77
     ):
78
+        indexes = indexes or []
79
+
53
         def get_key(obj):
80
         def get_key(obj):
54
             return key
81
             return key
55
 
82
 
66
             return self.get(key)
93
             return self.get(key)
67
 
94
 
68
         def fset(self_, value_):
95
         def fset(self_, value_):
96
+            try:
97
+                previous_value = self.get(key_formatter(self_))
98
+                for index in indexes:
99
+                    index.remove(previous_value)
100
+            except UnknownSharedData:
101
+                pass  # If no shared data, no previous value to remove
102
+
69
             self.set(key_formatter(self_), value_)
103
             self.set(key_formatter(self_), value_)
70
 
104
 
105
+            for index in indexes:
106
+                index.add(value_)
107
+
71
         def fdel(self_):
108
         def fdel(self_):
72
             raise SynergineException('You cannot delete a shared data')
109
             raise SynergineException('You cannot delete a shared data')
73
 
110
 

+ 75 - 3
tests/test_share.py View File

3
 
3
 
4
 from synergine2.exceptions import UnknownSharedData
4
 from synergine2.exceptions import UnknownSharedData
5
 from synergine2.share import SharedDataManager
5
 from synergine2.share import SharedDataManager
6
+from synergine2.share import SharedDataIndex
6
 from tests import BaseTest
7
 from tests import BaseTest
7
 
8
 
8
 
9
 
28
         class Foo(object):
29
         class Foo(object):
29
             counter = shared.create(
30
             counter = shared.create(
30
                 '{id}_counter',
31
                 '{id}_counter',
31
-                (0, 0, 0),
32
+                0,
32
                 indexes=[],
33
                 indexes=[],
33
             )
34
             )
34
 
35
 
45
 
46
 
46
         assert shared.get('{}_counter'.format(foo.id)) == 48
47
         assert shared.get('{}_counter'.format(foo.id)) == 48
47
 
48
 
49
+    def test_multiple_uses(self):
50
+        shared = SharedDataManager()
51
+
52
+        class Foo(object):
53
+            position = shared.create(
54
+                '{id}_position',
55
+                (0, 0, 0),
56
+                indexes=[],
57
+            )
58
+
59
+            @property
60
+            def id(self):
61
+                return id(self)
62
+
63
+        foo = Foo()
64
+        foo.position = (0, 1, 2)
65
+
66
+        assert shared.get('{}_position'.format(foo.id)) == (0, 1, 2)
67
+
68
+        foo2 = Foo()
69
+        foo2.position = (3, 4, 5)
70
+
71
+        assert shared.get('{}_position'.format(foo.id)) == (0, 1, 2)
72
+        assert shared.get('{}_position'.format(foo2.id)) == (3, 4, 5)
73
+
48
     def test_update_dict_with_pointer(self):
74
     def test_update_dict_with_pointer(self):
49
         shared = SharedDataManager()
75
         shared = SharedDataManager()
50
 
76
 
103
         shared.refresh()
129
         shared.refresh()
104
         assert shared.get('counter') == 42
130
         assert shared.get('counter') == 42
105
 
131
 
106
-    def test_indexes(self):
107
-        pass
132
+    def test_position_index(self):
133
+        class ListIndex(SharedDataIndex):
134
+            def add(self, value):
135
+                try:
136
+                    values = self.shared_data_manager.get(self.key)
137
+                except UnknownSharedData:
138
+                    values = []
139
+
140
+                values.append(value)
141
+                self.shared_data_manager.set(self.key, values)
142
+
143
+            def remove(self, value):
144
+                values = self.shared_data_manager.get(self.key)
145
+                values.remove(value)
146
+                self.shared_data_manager.set(self.key, values)
147
+
148
+        shared = SharedDataManager()
149
+
150
+        class Foo(object):
151
+            position = shared.create(
152
+                '{id}_position',
153
+                (0, 0, 0),
154
+                indexes=[shared.make_index(ListIndex, 'positions')],
155
+            )
156
+
157
+            @property
158
+            def id(self):
159
+                return id(self)
160
+
161
+        with pytest.raises(UnknownSharedData):
162
+            shared.get('positions')
163
+
164
+        foo = Foo()
165
+        foo.position = (0, 1, 2)
166
+
167
+        assert shared.get('{}_position'.format(foo.id)) == (0, 1, 2)
168
+        assert shared.get('positions') == [(0, 1, 2)]
169
+
170
+        foo2 = Foo()
171
+        foo2.position = (3, 4, 5)
172
+
173
+        assert shared.get('{}_position'.format(foo.id)) == (0, 1, 2)
174
+        assert shared.get('{}_position'.format(foo2.id)) == (3, 4, 5)
175
+        assert shared.get('positions') == [(0, 1, 2), (3, 4, 5)]
176
+
177
+        foo2.position = (6, 7, 8)
178
+        assert shared.get('{}_position'.format(foo2.id)) == (6, 7, 8)
179
+        assert shared.get('positions') == [(0, 1, 2), (6, 7, 8)]