2424 GraphQLInt ,
2525 GraphQLNonNull ,
2626 GraphQLObjectType ,
27- GraphQLResolveInfo ,
2827 GraphQLSchema ,
2928 GraphQLString ,
3029)
@@ -43,42 +42,61 @@ class User(NamedTuple):
4342 verified : bool = False
4443
4544
45+ class MutationEnum (Enum ):
46+ """Mutation event type"""
47+
48+ CREATED = "created"
49+ UPDATED = "updated"
50+ DELETED = "deleted"
51+
52+
4653class UserRegistry :
4754 """"Simulation of a user registry with asynchronous database backend access."""
4855
49- registry : Dict [str , User ]
50-
51- def __init__ (self , ** users ):
52- self .registry = users
56+ def __init__ (self , ** users ) -> None :
57+ self ._registry : Dict [str , User ] = users
58+ self ._emitter = EventEmitter ()
5359
54- async def get (self , id_ ):
60+ async def get (self , id_ : str ) -> User :
61+ """Get a user object from the registry"""
5562 await sleep (0 )
56- return self .registry .get (id_ )
63+ return self ._registry .get (id_ )
5764
58- async def create (self , ** kwargs ):
65+ async def create (self , ** kwargs ) -> User :
66+ """Get a user object in the registry"""
5967 await sleep (0 )
60- id_ = str (len (self .registry ))
68+ id_ = str (len (self ._registry ))
6169 user = User (id = id_ , ** kwargs )
62- self .registry [id_ ] = user
70+ self ._registry [id_ ] = user
71+ self .emit_event (MutationEnum .CREATED , user )
6372 return user
6473
65- async def update (self , id_ , ** kwargs ):
74+ async def update (self , id_ : str , ** kwargs ) -> User :
75+ """Update a user object in the registry"""
6676 await sleep (0 )
67- user = self .registry [id_ ]._replace (** kwargs )
68- self .registry [id_ ] = user
77+ # noinspection PyProtectedMember
78+ user = self ._registry [id_ ]._replace (** kwargs )
79+ self ._registry [id_ ] = user
80+ self .emit_event (MutationEnum .UPDATED , user )
6981 return user
7082
71- async def delete (self , id_ ):
83+ async def delete (self , id_ : str ) -> User :
84+ """Update a user object in the registry"""
7285 await sleep (0 )
73- return self .registry .pop (id_ )
86+ user = self ._registry .pop (id_ )
87+ self .emit_event (MutationEnum .DELETED , user )
88+ return user
7489
90+ def emit_event (self , mutation : MutationEnum , user : User ) -> None :
91+ """Emit mutation events for the given object and its class"""
92+ emit = self ._emitter .emit
93+ payload = {"user" : user , "mutation" : mutation .value }
94+ emit ("User" , payload ) # notify all user subscriptions
95+ emit (f"User_{ user .id } " , payload ) # notify single user subscriptions
7596
76- class MutationEnum (Enum ):
77- """Mutation event type"""
78-
79- CREATED = "created"
80- UPDATED = "updated"
81- DELETED = "deleted"
97+ def event_iterator (self , id_ : str ) -> EventEmitterAsyncIterator :
98+ event_name = "User" if id_ is None else f"User_{ id_ } "
99+ return EventEmitterAsyncIterator (self ._emitter , event_name )
82100
83101
84102mutation_type = GraphQLEnumType ("MutationType" , MutationEnum )
@@ -110,16 +128,6 @@ class MutationEnum(Enum):
110128)
111129
112130
113- def emit_user_mutation_event (
114- info : GraphQLResolveInfo , mutation : MutationEnum , user : User
115- ) -> None :
116- """Emit mutation events for the given object and its class."""
117- emit = info .context ["event_emitter" ].emit
118- payload = {"user" : user , "mutation" : mutation .value }
119- emit ("User" , payload ) # notify all user subscriptions
120- emit (f"User_{ user .id } " , payload ) # notify single user subscriptions
121-
122-
123131async def resolve_user (_root , info , ** args ):
124132 """Resolver function for fetching a user object"""
125133 return await info .context ["registry" ].get (args ["id" ])
@@ -128,15 +136,13 @@ async def resolve_user(_root, info, **args):
128136async def resolve_create_user (_root , info , data ):
129137 """Resolver function for creating a user object"""
130138 user = await info .context ["registry" ].create (** data )
131- emit_user_mutation_event (info , MutationEnum .CREATED , user )
132139 return user
133140
134141
135142# noinspection PyShadowingBuiltins
136143async def resolve_update_user (_root , info , id , data ):
137144 """Resolver function for updating a user object"""
138145 user = await info .context ["registry" ].update (id , ** data )
139- emit_user_mutation_event (info , MutationEnum .UPDATED , user )
140146 return user
141147
142148
@@ -145,16 +151,14 @@ async def resolve_delete_user(_root, info, id):
145151 """Resolver function for deleting a user object"""
146152 user = await info .context ["registry" ].get (id )
147153 await info .context ["registry" ].delete (user .id )
148- emit_user_mutation_event (info , MutationEnum .DELETED , user )
149154 return True
150155
151156
152157# noinspection PyShadowingBuiltins
153158async def subscribe_user (_root , info , id = None ):
154159 """Subscribe to mutations of a specific user object or all user objects"""
155- event_emitter = info .context ["event_emitter" ]
156- event_name = "User" if id is None else f"User_{ id } "
157- async for msg in EventEmitterAsyncIterator (event_emitter , event_name ):
160+ async_iterator = info .context ["registry" ].event_iterator (id )
161+ async for msg in async_iterator :
158162 yield msg
159163
160164
@@ -210,7 +214,7 @@ async def resolve_subscription_user(event, info, id):
210214
211215@fixture
212216def context ():
213- return {"event_emitter" : EventEmitter (), " registry" : UserRegistry ()}
217+ return {"registry" : UserRegistry ()}
214218
215219
216220def describe_query ():
@@ -256,8 +260,10 @@ def receive(msg):
256260
257261 return receive
258262
259- context ["event_emitter" ].add_listener ("User" , receiver ("User" ))
260- context ["event_emitter" ].add_listener ("User_0" , receiver ("User_0" ))
263+ # noinspection PyProtectedMember
264+ add_listener = context ["registry" ]._emitter .add_listener
265+ add_listener ("User" , receiver ("User" ))
266+ add_listener ("User_0" , receiver ("User_0" ))
261267
262268 query = """
263269 mutation ($userData: UserInputType!) {
@@ -301,8 +307,10 @@ def receive(msg):
301307
302308 return receive
303309
304- context ["event_emitter" ].add_listener ("User" , receiver ("User" ))
305- context ["event_emitter" ].add_listener ("User_0" , receiver ("User_0" ))
310+ # noinspection PyProtectedMember
311+ add_listener = context ["registry" ]._emitter .add_listener
312+ add_listener ("User" , receiver ("User" ))
313+ add_listener ("User_0" , receiver ("User_0" ))
306314
307315 user = await context ["registry" ].create (
308316 firstName = "John" , lastName = "Doe" , tweets = 42 , verified = True
@@ -355,8 +363,10 @@ def receive(msg):
355363
356364 return receive
357365
358- context ["event_emitter" ].add_listener ("User" , receiver ("User" ))
359- context ["event_emitter" ].add_listener ("User_0" , receiver ("User_0" ))
366+ # noinspection PyProtectedMember
367+ add_listener = context ["registry" ]._emitter .add_listener
368+ add_listener ("User" , receiver ("User" ))
369+ add_listener ("User_0" , receiver ("User_0" ))
360370
361371 user = await context ["registry" ].create (
362372 firstName = "John" , lastName = "Doe" , tweets = 42 , verified = True
0 commit comments