瀏覽代碼

introduce indexes in shared data

Bastien Sevajol 8 年之前
父節點
當前提交
bdfd0ddf6d
共有 2 個文件被更改,包括 113 次插入4 次删除
  1. 38 1
      synergine2/share.py
  2. 75 3
      tests/test_share.py

+ 38 - 1
synergine2/share.py 查看文件

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 查看文件

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)]