Asynchronous context manager
Since Python 3.7, you can write:
from contextlib import asynccontextmanager@asynccontextmanagerasync def smtp_connection(): client = SMTPAsync() ... try: await client.connect(smtp_url, smtp_port) await client.starttls() await client.login(smtp_username, smtp_password) yield client finally: await client.quit()
Before 3.7, you can use the async_generator
package for this. On 3.6, you can write:
# This import changed, everything else is the samefrom async_generator import asynccontextmanager@asynccontextmanagerasync def smtp_connection(): client = SMTPAsync() ... try: await client.connect(smtp_url, smtp_port) await client.starttls() await client.login(smtp_username, smtp_password) yield client finally: await client.quit()
And if you want to work all the way back to 3.5, you can write:
# This import changed again:from async_generator import asynccontextmanager, async_generator, yield_@asynccontextmanager@async_generator # <-- added thisasync def smtp_connection(): client = SMTPAsync() ... try: await client.connect(smtp_url, smtp_port) await client.starttls() await client.login(smtp_username, smtp_password) await yield_(client) # <-- this line changed finally: await client.quit()
Thanks to @jonrsharpe was able to make an async context manager.
Here's what mine ended up looking like for anyone who want's some example code:
class SMTPConnection(): def __init__(self, url, port, username, password): self.client = SMTPAsync() self.url = url self.port = port self.username = username self.password = password async def __aenter__(self): await self.client.connect(self.url, self.port) await self.client.starttls() await self.client.login(self.username, self.password) return self.client async def __aexit__(self, exc_type, exc, tb): await self.client.quit()
usage:
async with SMTPConnection(url, port, username, password) as client: await client.sendmail(...)
Feel free to point out if I've done anything stupid.
The asyncio_extras package has a nice solution for this:
import asyncio_extras@asyncio_extras.async_contextmanagerasync def smtp_connection(): client = SMTPAsync() ...
For Python < 3.6, you'd also need the async_generator package and replace yield client
with await yield_(client)
.