浏览代码

introduce indexes in shared data

Bastien Sevajol 7 年前
父节点
当前提交
bdfd0ddf6d
共有 2 个文件被更改,包括 113 次插入4 次删除
  1. 38 1
      synergine2/share.py
  2. 75 3
      tests/test_share.py

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

@@ -8,6 +8,22 @@ from synergine2.exceptions import SynergineException
8 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 27
 class SharedDataManager(object):
12 28
     """
13 29
     This object is designed to own shared memory between processes. It must be feed (with set method) before
@@ -44,12 +60,23 @@ class SharedDataManager(object):
44 60
     def refresh(self) -> None:
45 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 72
     def create(
48 73
         self,
49 74
         key: str,
50 75
         value,
51
-        indexes=None,
76
+        indexes: typing.List[SharedDataIndex]=None,
52 77
     ):
78
+        indexes = indexes or []
79
+
53 80
         def get_key(obj):
54 81
             return key
55 82
 
@@ -66,8 +93,18 @@ class SharedDataManager(object):
66 93
             return self.get(key)
67 94
 
68 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 103
             self.set(key_formatter(self_), value_)
70 104
 
105
+            for index in indexes:
106
+                index.add(value_)
107
+
71 108
         def fdel(self_):
72 109
             raise SynergineException('You cannot delete a shared data')
73 110
 

+ 75 - 3
tests/test_share.py 查看文件

@@ -3,6 +3,7 @@ import pytest
3 3
 
4 4
 from synergine2.exceptions import UnknownSharedData
5 5
 from synergine2.share import SharedDataManager
6
+from synergine2.share import SharedDataIndex
6 7
 from tests import BaseTest
7 8
 
8 9
 
@@ -28,7 +29,7 @@ class TestShare(BaseTest):
28 29
         class Foo(object):
29 30
             counter = shared.create(
30 31
                 '{id}_counter',
31
-                (0, 0, 0),
32
+                0,
32 33
                 indexes=[],
33 34
             )
34 35
 
@@ -45,6 +46,31 @@ class TestShare(BaseTest):
45 46
 
46 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 74
     def test_update_dict_with_pointer(self):
49 75
         shared = SharedDataManager()
50 76
 
@@ -103,5 +129,51 @@ class TestShare(BaseTest):
103 129
         shared.refresh()
104 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)]