async def create_subscription( pubsub, schema: GraphQLSchema = email_schema, document=default_subscription_ast ): data: Dict[str, Any] = { "inbox": { "emails": [ { "from": "*****@*****.**", "subject": "Hello", "message": "Hello World", "unread": False, } ] }, "importantEmail": lambda _info, priority=None: EventEmitterAsyncIterator( pubsub, "importantEmail" ), } def send_important_email(new_email): data["inbox"]["emails"].append(new_email) # Returns True if the event was consumed by a subscriber. return pubsub.emit( "importantEmail", {"importantEmail": {"email": new_email, "inbox": data["inbox"]}}, ) # `subscribe` yields AsyncIterator or ExecutionResult return ( send_important_email, await subscribe(schema=schema, document=document, root_value=data), )
async def subscribe_async_iterator_mock(): # Create an AsyncIterator from an EventEmitter emitter = EventEmitter() iterator = EventEmitterAsyncIterator(emitter, "publish") # Make sure it works as an async iterator assert iterator.__aiter__() is iterator assert callable(iterator.__anext__) # Queue up publishes assert emitter.emit("publish", "Apple") is True assert emitter.emit("publish", "Banana") is True # Read payloads assert await iterator.__anext__() == "Apple" assert await iterator.__anext__() == "Banana" # Read ahead i3 = iterator.__anext__() i4 = iterator.__anext__() # Publish assert emitter.emit("publish", "Coconut") is True assert emitter.emit("publish", "Durian") is True # Await results assert await i3 == "Coconut" assert await i4 == "Durian" # Read ahead i5 = iterator.__anext__() # Terminate emitter await iterator.aclose() # Publish is not caught after terminate assert emitter.emit("publish", "Fig") is False # Find that cancelled read-ahead got a "done" result with raises(StopAsyncIteration): await i5 # And next returns empty completion value with raises(StopAsyncIteration): await iterator.__anext__()
async def resolves_to_an_error_if_variables_were_wrong_type(): # If we receive variables that cannot be coerced correctly, subscribe() # will resolve to an ExecutionResult that contains an informative error # description. ast = parse( """ subscription ($priority: Int) { importantEmail(priority: $priority) { email { from subject } inbox { unread total } } } """ ) pubsub = EventEmitter() data = { "inbox": { "emails": [ { "from": "*****@*****.**", "subject": "Hello", "message": "Hello World", "unread": False, } ] }, "importantEmail": lambda _info: EventEmitterAsyncIterator( pubsub, "importantEmail" ), } result = await subscribe( email_schema, ast, data, variable_values={"priority": "meow"} ) assert result == ( None, [ { "message": "Variable '$priority' got invalid value 'meow'; Expected" " type Int; Int cannot represent non-integer value: 'meow'", "locations": [(2, 27)], } ], ) assert result.errors[0].original_error is not None
async def subscribe_async_iterator_mock(): # Create an AsyncIterator from an EventEmitter emitter = EventEmitter() iterator = EventEmitterAsyncIterator(emitter, 'publish') # Queue up publishes assert emitter.emit('publish', 'Apple') is True assert emitter.emit('publish', 'Banana') is True # Read payloads assert await iterator.__anext__() == 'Apple' assert await iterator.__anext__() == 'Banana' # Read ahead i3 = iterator.__anext__() i4 = iterator.__anext__() # Publish assert emitter.emit('publish', 'Coconut') is True assert emitter.emit('publish', 'Durian') is True # Await results assert await i3 == 'Coconut' assert await i4 == 'Durian' # Read ahead i5 = iterator.__anext__() # Terminate emitter await iterator.aclose() # Publish is not caught after terminate assert emitter.emit('publish', 'Fig') is False # Find that cancelled read-ahead got a "done" result with raises(StopAsyncIteration): await i5 # And next returns empty completion value with raises(StopAsyncIteration): await iterator.__anext__()
async def create_subscription(pubsub, schema: GraphQLSchema = email_schema, ast=None, variables=None): data = { "inbox": { "emails": [{ "from": "*****@*****.**", "subject": "Hello", "message": "Hello World", "unread": False, }] }, "importantEmail": lambda _info, priority=None: EventEmitterAsyncIterator( pubsub, "importantEmail"), } def send_important_email(new_email): data["inbox"]["emails"].append(new_email) # Returns True if the event was consumed by a subscriber. return pubsub.emit( "importantEmail", {"importantEmail": { "email": new_email, "inbox": data["inbox"] }}, ) default_ast = parse(""" subscription ($priority: Int = 0) { importantEmail(priority: $priority) { email { from subject } inbox { unread total } } } """) # `subscribe` yields AsyncIterator or ExecutionResult return ( send_important_email, await subscribe(schema, ast or default_ast, data, variable_values=variables), )
async def aclose_cleans_up(): emitter = EventEmitter() assert emitter.listeners["publish"] == [] iterator = EventEmitterAsyncIterator(emitter, "publish") assert emitter.listeners["publish"] == [iterator.queue.put] assert not iterator.closed for value in range(3): emitter.emit("publish", value) await sleep(0) assert iterator.queue.qsize() == 3 await iterator.aclose() assert emitter.listeners["publish"] == [] assert iterator.queue.empty() assert iterator.closed
async def create_subscription(pubsub, schema: GraphQLSchema = email_schema, ast=None, variables=None): data = { 'inbox': { 'emails': [{ 'from': '*****@*****.**', 'subject': 'Hello', 'message': 'Hello World', 'unread': False }] }, 'importantEmail': lambda _info, priority=None: EventEmitterAsyncIterator( pubsub, 'importantEmail') } def send_important_email(new_email): data['inbox']['emails'].append(new_email) # Returns true if the event was consumed by a subscriber. return pubsub.emit( 'importantEmail', {'importantEmail': { 'email': new_email, 'inbox': data['inbox'] }}) default_ast = parse(""" subscription ($priority: Int = 0) { importantEmail(priority: $priority) { email { from subject } inbox { unread total } } } """) # `subscribe` yields AsyncIterator or ExecutionResult return send_important_email, await subscribe(schema, ast or default_ast, data, variable_values=variables)
async def resolves_to_an_error_if_variables_were_wrong_type(): # If we receive variables that cannot be coerced correctly, subscribe() # will resolve to an ExecutionResult that contains an informative error # description. ast = parse(""" subscription ($priority: Int) { importantEmail(priority: $priority) { email { from subject } inbox { unread total } } } """) pubsub = EventEmitter() data = { 'inbox': { 'emails': [{ 'from': '*****@*****.**', 'subject': 'Hello', 'message': 'Hello World', 'unread': False }] }, 'importantEmail': lambda _info: EventEmitterAsyncIterator(pubsub, 'importantEmail') } result = await subscribe(email_schema, ast, data, variable_values={'priority': 'meow'}) assert result == (None, [{ 'message': "Variable '$priority' got invalid value 'meow'; Expected" " type Int; Int cannot represent non-integer value: 'meow'", 'locations': [(2, 27)] }]) assert result.errors[0].original_error is not None
def subscribe_non_important(_inbox, _info): did_resolve["nonImportantEmail"] = True return EventEmitterAsyncIterator(EventEmitter(), "event")
async def subscribe_email(_inbox, _info): return EventEmitterAsyncIterator(pubsub, "importantEmail")
def event_iterator(self, id_: str) -> EventEmitterAsyncIterator: event_name = "User" if id_ is None else f"User_{id_}" return EventEmitterAsyncIterator(self._emitter, event_name)
def subscribe_messages(root, info): return EventEmitterAsyncIterator(pubsub, "message")
def __init__(self): self.emitter = EventEmitter() self.queue = EventEmitterAsyncIterator(self.emitter, "library")
def subscribe(self, channel: str): return EventEmitterAsyncIterator(self.emitter, channel)
def subscribe_important(_inbox, _info): did_resolve['importantEmail'] = True return EventEmitterAsyncIterator(EventEmitter(), 'event')
def subscribe_messages(_root, _info): """new post event listener""" return EventEmitterAsyncIterator(PUBSUB, "new_post")