88
99import builtins
1010import threading
11+ import uuid
12+ import functools
13+
14+
15+ # This is used as the default argument for some methods of DictProxy
16+ _None = object ()
1117
1218
1319class dict (builtins .dict ):
@@ -16,24 +22,117 @@ class dict(builtins.dict):
1622 pass
1723
1824
25+ class SharedObject :
26+
27+ def __init__ (self , type ):
28+ self .type = type
29+ self .children = {}
30+
31+ if type == "dict" :
32+ self .value = dict ()
33+
34+ def add_children (self , object ):
35+ """Register a new children"""
36+ self .children .add (object )
37+
38+
1939class LocalDriver :
2040 """Local driver for the shared memory"""
2141
2242 def __init__ (self ):
23- self ._memories = {}
43+ self ._objects = {}
2444 self ._locks = {}
2545
2646 def __reduce__ (self ):
2747 return rebuild_local_driver , (self .export_data (),)
2848
29- def get (self , component ):
30- # Create the shared memory if it doesn't exist
31- new = False
32- if component not in self ._memories :
33- self ._memories [component ] = dict ()
34- new = True
35-
36- return self ._memories [component ], new
49+ def create_object (self , type , id = None , parent = None ):
50+ """Create a new object"""
51+ if id is None :
52+ id = uuid .uuid4 ()
53+
54+ self ._objects [id ] = SharedObject (type )
55+ if parent is not None :
56+ self ._objects [parent ].add_children (id )
57+
58+ return self ._objects [id ]
59+
60+ def delete_object (self , id ):
61+ """Delete an object"""
62+ obj = self ._objects .pop (id )
63+
64+ # Recursively delete every children
65+ for child in obj .children :
66+ self .delete_object (child )
67+
68+ def _ensure_object (type ):
69+ """Ensure the object exists and it's of that type"""
70+ def decorator (f ):
71+ @functools .wraps (f )
72+ def wrapper (self , object_id , * args , ** kwargs ):
73+ if object_id not in self ._objects :
74+ raise ValueError ("Object doesn't exist: %s" % object_id )
75+
76+ obj = self ._objects [object_id ]
77+ if obj .type != type :
78+ raise TypeError ("Operation not supported on the %s type" %
79+ obj .type )
80+
81+ return f (self , obj .value , * args , ** kwargs )
82+ return wrapper
83+ return decorator
84+
85+ ############################
86+ # dicts implementation #
87+ ############################
88+
89+ @_ensure_object ("dict" )
90+ def dict_length (self , obj ):
91+ return len (obj )
92+
93+ @_ensure_object ("dict" )
94+ def dict_item_get (self , obj , key ):
95+ return obj [key ]
96+
97+ @_ensure_object ("dict" )
98+ def dict_item_set (self , obj , key , value ):
99+ obj [key ] = value
100+
101+ @_ensure_object ("dict" )
102+ def dict_item_delete (self , obj , key ):
103+ del obj [key ]
104+
105+ @_ensure_object ("dict" )
106+ def dict_contains (self , obj , key ):
107+ return key in obj
108+
109+ @_ensure_object ("dict" )
110+ def dict_keys (self , obj ):
111+ return tuple (obj .keys ())
112+
113+ @_ensure_object ("dict" )
114+ def dict_values (self , obj ):
115+ return tuple (obj .values ())
116+
117+ @_ensure_object ("dict" )
118+ def dict_items (self , obj ):
119+ return tuple (obj .items ())
120+
121+ @_ensure_object ("dict" )
122+ def dict_clear (self , obj ):
123+ obj .clear ()
124+
125+ @_ensure_object ("dict" )
126+ def dict_pop (self , obj , key = _None ):
127+ # If no keys are provided pop a random item
128+ if key is _None :
129+ return obj .popitem ()
130+ else :
131+ return obj .pop (key )
132+
133+ ############################
134+ # Locks implementation #
135+ ############################
37136
38137 def lock_acquire (self , lock_id ):
39138 # Create a new lock if it doesn't exist yet
@@ -56,17 +155,30 @@ def lock_status(self, lock_id):
56155
57156 return self ._locks [lock_id ]["acquired" ]
58157
158+ ###############################
159+ # Importing and exporting #
160+ ###############################
161+
59162 def import_data (self , data ):
60- self ._memories = dict (data ["storage" ])
163+ # Rebuild the objects
164+ self ._objects = {}
165+ for id , value in data ["objects" ]:
166+ if type (value ) == dict :
167+ self ._objects [id ] = SharedObject ("dict" )
168+ self ._objects [id ].value = value
169+ else :
170+ raise ValueError ("Unsupported type: %s" % type (value ))
61171
62172 # Rebuild the locks
63173 self ._locks = {}
64174 for lock_id in data ["locks" ]:
65175 self .lock_acquire (lock_id )
66176
67177 def export_data (self ):
178+ objects = {id : obj .value for id , obj in self ._objects .items ()}
68179 locks = [lock_id for lock_id , d in self ._locks if not d ["acquired" ]]
69- return {"storage" : self ._memories .copy (), "locks" : locks }
180+
181+ return {"storage" : objects , "locks" : locks }
70182
71183
72184def rebuild_local_driver (memories ):
0 commit comments