Looks like to be sure everything finished correctly, we'll need to do something like this every time:

loop.run_until_complete(main())

pending = asyncio.Task.all_tasks()
loop.run_until_complete(asyncio.gather(*pending))

loop.close()

Bad thing here I think is that we can't split manually created tasks (wich warnings we might would like to get to complete this tasks in other places) and AG's close tasks wich we can't complete other place then here.

Don't you like idea to await all AG's close tasks done right before event loop is closed? I mean to modify event loop this way:

# asyncio/base_events.py

class BaseEventLoop:
    def _finalize_asyncgen(self, gen):
        task = self.create_task(gen.aclose())
        self._close_tasks.append(task)

    def close():
        self.run_until_complete(
            asyncio.gather(*self._close_tasks)
        )  
        ...
In this case user would be able to use async generators without worring he will get warning.