bpo-46752: Slight improvements to TaskGroup API
diff --git a/Lib/asyncio/taskgroups.py b/Lib/asyncio/taskgroups.py
index 718277892c51c9..57b0eafefc16fe 100644
--- a/Lib/asyncio/taskgroups.py
+++ b/Lib/asyncio/taskgroups.py
@@ -3,10 +3,6 @@
 
 __all__ = ["TaskGroup"]
 
-import itertools
-import textwrap
-import traceback
-import types
 import weakref
 
 from . import events
@@ -15,12 +11,7 @@
 
 class TaskGroup:
 
-    def __init__(self, *, name=None):
-        if name is None:
-            self._name = f'tg-{_name_counter()}'
-        else:
-            self._name = str(name)
-
+    def __init__(self):
         self._entered = False
         self._exiting = False
         self._aborting = False
@@ -33,11 +24,8 @@ def __init__(self, *, name=None):
         self._base_error = None
         self._on_completed_fut = None
 
-    def get_name(self):
-        return self._name
-
     def __repr__(self):
-        msg = f'<TaskGroup {self._name!r}'
+        msg = f'<TaskGroup'
         if self._tasks:
             msg += f' tasks:{len(self._tasks)}'
         if self._unfinished_tasks:
@@ -152,12 +140,13 @@ async def __aexit__(self, et, exc, tb):
             me = BaseExceptionGroup('unhandled errors in a TaskGroup', errors)
             raise me from None
 
-    def create_task(self, coro):
+    def create_task(self, coro, *, name=None):
         if not self._entered:
             raise RuntimeError(f"TaskGroup {self!r} has not been entered")
         if self._exiting and self._unfinished_tasks == 0:
             raise RuntimeError(f"TaskGroup {self!r} is finished")
         task = self._loop.create_task(coro)
+        tasks._set_task_name(task, name)
         task.add_done_callback(self._on_task_done)
         self._unfinished_tasks += 1
         self._tasks.add(task)
@@ -230,6 +219,3 @@ def _on_task_done(self, task):
             #                                 # after TaskGroup is finished.
             self._parent_cancel_requested = True
             self._parent_task.cancel()
-
-
-_name_counter = itertools.count(1).__next__
diff --git a/Lib/test/test_asyncio/test_taskgroups.py b/Lib/test/test_asyncio/test_taskgroups.py
index ea6ee2ed43d2f8..aab1fd1ebb38d8 100644
--- a/Lib/test/test_asyncio/test_taskgroups.py
+++ b/Lib/test/test_asyncio/test_taskgroups.py
@@ -368,10 +368,10 @@ async def crash_after(t):
             raise ValueError(t)
 
         async def runner():
-            async with taskgroups.TaskGroup(name='g1') as g1:
+            async with taskgroups.TaskGroup() as g1:
                 g1.create_task(crash_after(0.1))
 
-                async with taskgroups.TaskGroup(name='g2') as g2:
+                async with taskgroups.TaskGroup() as g2:
                     g2.create_task(crash_after(0.2))
 
         r = asyncio.create_task(runner())
@@ -387,10 +387,10 @@ async def crash_after(t):
             raise ValueError(t)
 
         async def runner():
-            async with taskgroups.TaskGroup(name='g1') as g1:
+            async with taskgroups.TaskGroup() as g1:
                 g1.create_task(crash_after(10))
 
-                async with taskgroups.TaskGroup(name='g2') as g2:
+                async with taskgroups.TaskGroup() as g2:
                     g2.create_task(crash_after(0.1))
 
         r = asyncio.create_task(runner())
@@ -407,7 +407,7 @@ async def crash_soon():
             1 / 0
 
         async def runner():
-            async with taskgroups.TaskGroup(name='g1') as g1:
+            async with taskgroups.TaskGroup() as g1:
                 g1.create_task(crash_soon())
                 try:
                     await asyncio.sleep(10)
@@ -430,7 +430,7 @@ async def crash_soon():
             1 / 0
 
         async def nested_runner():
-            async with taskgroups.TaskGroup(name='g1') as g1:
+            async with taskgroups.TaskGroup() as g1:
                 g1.create_task(crash_soon())
                 try:
                     await asyncio.sleep(10)
@@ -692,3 +692,10 @@ async def runner():
 
         self.assertEqual(get_error_types(cm.exception), {ZeroDivisionError})
         self.assertGreaterEqual(nhydras, 10)
+
+    async def test_taskgroup_task_name(self):
+        async def coro():
+            await asyncio.sleep(0)
+        async with taskgroups.TaskGroup() as g:
+            t = g.create_task(coro(), name="yolo")
+            self.assertEqual(t.get_name(), "yolo")

- Remove the optional name argument to the TaskGroup constructor
- Add an optional name argument to the create_task() method
- Some cleanup

Note that there's a big discussion on cancellation edge cases going on in [bpo-46771](https://bugs.python.org/issue46771), this is unrelated to that and uncontroversial.

I'll also update typeshed.

<!--
Thanks for your contribution!
Please read this comment in its entirety. It's quite important.

# Pull Request title

It should be in the following format:

```
bpo-NNNN: Summary of the changes made
```

Where: bpo-NNNN refers to the issue number in the https://bugs.python.org.

Most PRs will require an issue number. Trivial changes, like fixing a typo, do not need an issue.

# Backport Pull Request title

If this is a backport PR (PR made against branches other than `main`),
please ensure that the PR title is in the following format:

```
[X.Y] <title from the original PR> (GH-NNNN)
```

Where: [X.Y] is the branch name, e.g. [3.6].

GH-NNNN refers to the PR number from `main`.

-->


<!-- issue-number: [bpo-46752](https://bugs.python.org/issue46752) -->
https://bugs.python.org/issue46752
<!-- /issue-number -->
