15
15
import asyncio
16
16
import sys
17
17
import traceback
18
- from typing import Any , Callable , Dict , List , Optional
18
+ from typing import Any , Callable , Dict , Optional , Union
19
19
20
20
from greenlet import greenlet
21
21
from pyee import BaseEventEmitter
26
26
27
27
28
28
class Channel (BaseEventEmitter ):
29
- def __init__ (self , scope : "ConnectionScope " , guid : str ) -> None :
29
+ def __init__ (self , connection : "Connection " , guid : str ) -> None :
30
30
super ().__init__ ()
31
- self ._scope : ConnectionScope = scope
31
+ self ._connection : Connection = connection
32
32
self ._guid = guid
33
33
self ._object : Optional [ChannelOwner ] = None
34
34
35
35
async def send (self , method : str , params : dict = None ) -> Any :
36
36
if params is None :
37
37
params = {}
38
- result = await self ._scope .send_message_to_server (self ._guid , method , params )
38
+ callback = self ._connection ._send_message_to_server (self ._guid , method , params )
39
+ result = await callback .future
39
40
# Protocol now has named return values, assume result is one level deeper unless
40
41
# there is explicit ambiguity.
41
42
if not result :
@@ -50,79 +51,46 @@ async def send(self, method: str, params: dict = None) -> Any:
50
51
def send_no_reply (self , method : str , params : dict = None ) -> None :
51
52
if params is None :
52
53
params = {}
53
- self ._scope . send_message_to_server_no_reply (self ._guid , method , params )
54
+ self ._connection . _send_message_to_server (self ._guid , method , params )
54
55
55
56
56
57
class ChannelOwner (BaseEventEmitter ):
57
58
def __init__ (
58
59
self ,
59
- scope : "ConnectionScope" ,
60
+ parent : Union ["ChannelOwner" , "Connection" ],
61
+ type : str ,
60
62
guid : str ,
61
63
initializer : Dict ,
62
- is_scope : bool = False ,
63
64
) -> None :
64
65
super ().__init__ ()
66
+ self ._loop : asyncio .AbstractEventLoop = parent ._loop
67
+ self ._type = type
65
68
self ._guid = guid
66
- self ._scope = scope .create_child (guid ) if is_scope else scope
67
- self ._loop = self ._scope ._loop
68
- self ._channel = Channel (self ._scope , guid )
69
+ self ._connection : Connection = parent ._connection if isinstance (
70
+ parent , ChannelOwner
71
+ ) else parent
72
+ self ._parent : Optional [ChannelOwner ] = parent if isinstance (
73
+ parent , ChannelOwner
74
+ ) else None
75
+ self ._objects : Dict [str , "ChannelOwner" ] = {}
76
+ self ._channel = Channel (self ._connection , guid )
69
77
self ._channel ._object = self
70
78
self ._initializer = initializer
71
79
72
-
73
- class ConnectionScope :
74
- def __init__ (
75
- self , connection : "Connection" , guid : str , parent : Optional ["ConnectionScope" ]
76
- ) -> None :
77
- self ._connection : "Connection" = connection
78
- self ._loop : asyncio .AbstractEventLoop = connection ._loop
79
- self ._guid : str = guid
80
- self ._children : List ["ConnectionScope" ] = []
81
- self ._objects : Dict [str , ChannelOwner ] = {}
82
- self ._parent = parent
83
-
84
- def create_child (self , guid : str ) -> "ConnectionScope" :
85
- scope = self ._connection .create_scope (guid , self )
86
- self ._children .append (scope )
87
- return scope
88
-
89
- def dispose (self ) -> None :
90
- # Take care of hierarchy.
91
- for child in self ._children :
92
- child .dispose ()
93
- self ._children .clear ()
94
-
95
- # Delete self from scopes and objects.
96
- self ._connection ._scopes .pop (self ._guid )
97
- self ._connection ._objects .pop (self ._guid )
98
-
99
- # Delete all of the objects from connection.
100
- for guid in self ._objects :
101
- self ._connection ._objects .pop (guid )
102
-
103
- # Clean up from parent.
80
+ self ._connection ._objects [guid ] = self
104
81
if self ._parent :
105
- self ._parent ._objects .pop (self ._guid )
106
- self ._parent ._children .remove (self )
82
+ self ._parent ._objects [guid ] = self
107
83
108
- async def send_message_to_server (self , guid : str , method : str , params : Dict ) -> Any :
109
- callback = self ._connection ._send_message_to_server (guid , method , params )
110
- return await callback .future
111
-
112
- def send_message_to_server_no_reply (
113
- self , guid : str , method : str , params : Dict
114
- ) -> Any :
115
- self ._connection ._send_message_to_server (guid , method , params )
84
+ def _dispose (self ) -> None :
85
+ # Clean up from parent and connection.
86
+ if self ._parent :
87
+ del self ._parent ._objects [self ._guid ]
88
+ del self ._connection ._objects [self ._guid ]
116
89
117
- def create_remote_object (self , type : str , guid : str , initializer : Dict ) -> Any :
118
- result : ChannelOwner
119
- initializer = self ._connection ._replace_guids_with_channels (initializer )
120
- result = self ._connection ._object_factory (self , type , guid , initializer )
121
- self ._connection ._objects [guid ] = result
122
- self ._objects [guid ] = result
123
- if guid in self ._connection ._waiting_for_object :
124
- self ._connection ._waiting_for_object .pop (guid )(result )
125
- return result
90
+ # Dispose all children.
91
+ for object in list (self ._objects .values ()):
92
+ object ._dispose ()
93
+ self ._objects .clear ()
126
94
127
95
128
96
class ProtocolCallback :
@@ -131,6 +99,11 @@ def __init__(self, loop: asyncio.AbstractEventLoop) -> None:
131
99
self .future = loop .create_future ()
132
100
133
101
102
+ class RootChannelOwner (ChannelOwner ):
103
+ def __init__ (self , connection : "Connection" ) -> None :
104
+ super ().__init__ (connection , "" , "" , {})
105
+
106
+
134
107
class Connection :
135
108
def __init__ (
136
109
self ,
@@ -145,9 +118,8 @@ def __init__(
145
118
self ._last_id = 0
146
119
self ._loop = loop
147
120
self ._objects : Dict [str , ChannelOwner ] = {}
148
- self ._scopes : Dict [str , ConnectionScope ] = {}
149
121
self ._callbacks : Dict [int , ProtocolCallback ] = {}
150
- self ._root_scope = self . create_scope ( "" , None )
122
+ self ._root_object = RootChannelOwner ( self )
151
123
self ._object_factory = object_factory
152
124
self ._is_sync = False
153
125
@@ -215,11 +187,14 @@ def _dispatch(self, msg: ParsedMessagePayload) -> None:
215
187
method = msg .get ("method" )
216
188
params = msg ["params" ]
217
189
if method == "__create__" :
218
- scope = self ._scopes [guid ]
219
- scope . create_remote_object (
220
- params ["type" ], params ["guid" ], params ["initializer" ]
190
+ parent = self ._objects [guid ]
191
+ self . _create_remote_object (
192
+ parent , params ["type" ], params ["guid" ], params ["initializer" ]
221
193
)
222
194
return
195
+ if method == "__dispose__" :
196
+ self ._objects [guid ]._dispose ()
197
+ return
223
198
224
199
object = self ._objects [guid ]
225
200
try :
@@ -235,6 +210,16 @@ def _dispatch(self, msg: ParsedMessagePayload) -> None:
235
210
"" .join (traceback .format_exception (* sys .exc_info ())),
236
211
)
237
212
213
+ def _create_remote_object (
214
+ self , parent : ChannelOwner , type : str , guid : str , initializer : Dict
215
+ ) -> Any :
216
+ result : ChannelOwner
217
+ initializer = self ._replace_guids_with_channels (initializer )
218
+ result = self ._object_factory (parent , type , guid , initializer )
219
+ if guid in self ._waiting_for_object :
220
+ self ._waiting_for_object .pop (guid )(result )
221
+ return result
222
+
238
223
def _replace_channels_with_guids (self , payload : Any ) -> Any :
239
224
if payload is None :
240
225
return payload
@@ -263,13 +248,6 @@ def _replace_guids_with_channels(self, payload: Any) -> Any:
263
248
return result
264
249
return payload
265
250
266
- def create_scope (
267
- self , guid : str , parent : Optional [ConnectionScope ]
268
- ) -> ConnectionScope :
269
- scope = ConnectionScope (self , guid , parent )
270
- self ._scopes [guid ] = scope
271
- return scope
272
-
273
251
274
252
def from_channel (channel : Channel ) -> Any :
275
253
return channel ._object
0 commit comments