The core idea here is a good one.
It’s already possible to use these with task groups by passing a synchronous callback instead of a coroutine, which then spawns the task in the group:
async with asyncio.TaskGroup() as tg:
def handle_in_taskgroup(r, w):
tg.create_task(handle_connection(r, w))
server = await asyncio.start_server(handle_in_taskgroup, port=port)
tg.create_task(server.serve_forever())
(This is unsafe unless eager task execution is turned on)
Certainly it would be useful to have a more convenient way of doing it. The OP suggestion of task_factory would look like this:
server = await asyncio.start_server(handle_connection, port=port, task_factory=tg.create_task)
Certainly simpler, but why not have a task group parameter?
server = await asyncio.start_server(handle_connection, port=port, task_group=tg)
The obvious answer is that this is less general, but you can always use the style of first snippet if you want more flexibility. I think making the common case be extra convenient is best. Also, this makes the documentation a bit more evocative: it suggests to readers that perhaps they could be using task factories, even if they hadn’t previously considered the possibility, so it could push people in the right direction. task_factory sounds really abstract so I don’t think that prompt anyone to consider task factories if they weren’t already.