[3.9] bpo-46469: Make asyncio generic classes return GenericAlias (GH-30777) (GH-30785)

Automerge-Triggered-By: GH:asvetlov
This commit is contained in:
Kumar Aditya 2022-01-22 18:22:24 +05:30 committed by GitHub
parent 3c4a3745b9
commit 6ed874f8c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 29 additions and 24 deletions

View file

@ -8,6 +8,7 @@ import concurrent.futures
import contextvars import contextvars
import logging import logging
import sys import sys
from types import GenericAlias
from . import base_futures from . import base_futures
from . import events from . import events
@ -106,8 +107,7 @@ class Future:
context['source_traceback'] = self._source_traceback context['source_traceback'] = self._source_traceback
self._loop.call_exception_handler(context) self._loop.call_exception_handler(context)
def __class_getitem__(cls, type): __class_getitem__ = classmethod(GenericAlias)
return cls
@property @property
def _log_traceback(self): def _log_traceback(self):

View file

@ -3,6 +3,7 @@ __all__ = ('Queue', 'PriorityQueue', 'LifoQueue', 'QueueFull', 'QueueEmpty')
import collections import collections
import heapq import heapq
import warnings import warnings
from types import GenericAlias
from . import events from . import events
from . import locks from . import locks
@ -76,8 +77,7 @@ class Queue:
def __str__(self): def __str__(self):
return f'<{type(self).__name__} {self._format()}>' return f'<{type(self).__name__} {self._format()}>'
def __class_getitem__(cls, type): __class_getitem__ = classmethod(GenericAlias)
return cls
def _format(self): def _format(self):
result = f'maxsize={self._maxsize!r}' result = f'maxsize={self._maxsize!r}'

View file

@ -17,6 +17,7 @@ import itertools
import types import types
import warnings import warnings
import weakref import weakref
from types import GenericAlias
from . import base_tasks from . import base_tasks
from . import coroutines from . import coroutines
@ -147,8 +148,7 @@ class Task(futures._PyFuture): # Inherit Python Task implementation
self._loop.call_exception_handler(context) self._loop.call_exception_handler(context)
super().__del__() super().__del__()
def __class_getitem__(cls, type): __class_getitem__ = classmethod(GenericAlias)
return cls
def _repr_info(self): def _repr_info(self):
return base_tasks._task_repr_info(self) return base_tasks._task_repr_info(self)

View file

@ -7,7 +7,7 @@ import sys
import threading import threading
import unittest import unittest
from unittest import mock from unittest import mock
from types import GenericAlias
import asyncio import asyncio
from asyncio import futures from asyncio import futures
from test.test_asyncio import utils as test_utils from test.test_asyncio import utils as test_utils
@ -109,6 +109,11 @@ class BaseFutureTests:
self.loop = self.new_test_loop() self.loop = self.new_test_loop()
self.addCleanup(self.loop.close) self.addCleanup(self.loop.close)
def test_generic_alias(self):
future = self.cls[str]
self.assertEqual(future.__args__, (str,))
self.assertIsInstance(future, GenericAlias)
def test_isfuture(self): def test_isfuture(self):
class MyFuture: class MyFuture:
_asyncio_future_blocking = None _asyncio_future_blocking = None

View file

@ -4,6 +4,7 @@ import unittest
from unittest import mock from unittest import mock
import asyncio import asyncio
from types import GenericAlias
from test.test_asyncio import utils as test_utils from test.test_asyncio import utils as test_utils
@ -92,6 +93,11 @@ class QueueBasicTests(_QueueTestBase):
def test_str(self): def test_str(self):
self._test_repr_or_str(str, False) self._test_repr_or_str(str, False)
def test_generic_alias(self):
q = asyncio.Queue[int]
self.assertEqual(q.__args__, (int,))
self.assertIsInstance(q, GenericAlias)
def test_empty(self): def test_empty(self):
with self.assertWarns(DeprecationWarning): with self.assertWarns(DeprecationWarning):
q = asyncio.Queue(loop=self.loop) q = asyncio.Queue(loop=self.loop)

View file

@ -9,12 +9,13 @@ import io
import random import random
import re import re
import sys import sys
import types
import textwrap import textwrap
import traceback import traceback
import types
import unittest import unittest
import weakref import weakref
from unittest import mock from unittest import mock
from types import GenericAlias
import asyncio import asyncio
from asyncio import coroutines from asyncio import coroutines
@ -120,6 +121,12 @@ class BaseTaskTests:
self.loop.set_task_factory(self.new_task) self.loop.set_task_factory(self.new_task)
self.loop.create_future = lambda: self.new_future(self.loop) self.loop.create_future = lambda: self.new_future(self.loop)
def test_generic_alias(self):
task = self.__class__.Task[str]
self.assertEqual(task.__args__, (str,))
self.assertIsInstance(task, GenericAlias)
def test_task_cancel_message_getter(self): def test_task_cancel_message_getter(self):
async def coro(): async def coro():
pass pass

View file

@ -0,0 +1 @@
:mod:`asyncio` generic classes now return :class:`types.GenericAlias` in ``__class_getitem__`` instead of the same class.

View file

@ -1474,13 +1474,6 @@ finally:
PyErr_Restore(error_type, error_value, error_traceback); PyErr_Restore(error_type, error_value, error_traceback);
} }
static PyObject *
future_cls_getitem(PyObject *cls, PyObject *type)
{
Py_INCREF(cls);
return cls;
}
static PyAsyncMethods FutureType_as_async = { static PyAsyncMethods FutureType_as_async = {
(unaryfunc)future_new_iter, /* am_await */ (unaryfunc)future_new_iter, /* am_await */
0, /* am_aiter */ 0, /* am_aiter */
@ -1500,7 +1493,7 @@ static PyMethodDef FutureType_methods[] = {
_ASYNCIO_FUTURE_GET_LOOP_METHODDEF _ASYNCIO_FUTURE_GET_LOOP_METHODDEF
_ASYNCIO_FUTURE__MAKE_CANCELLED_ERROR_METHODDEF _ASYNCIO_FUTURE__MAKE_CANCELLED_ERROR_METHODDEF
_ASYNCIO_FUTURE__REPR_INFO_METHODDEF _ASYNCIO_FUTURE__REPR_INFO_METHODDEF
{"__class_getitem__", future_cls_getitem, METH_O|METH_CLASS, NULL}, {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
{NULL, NULL} /* Sentinel */ {NULL, NULL} /* Sentinel */
}; };
@ -2487,13 +2480,6 @@ done:
FutureObj_finalize((FutureObj*)task); FutureObj_finalize((FutureObj*)task);
} }
static PyObject *
task_cls_getitem(PyObject *cls, PyObject *type)
{
Py_INCREF(cls);
return cls;
}
static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */ static void TaskObj_dealloc(PyObject *); /* Needs Task_CheckExact */
static PyMethodDef TaskType_methods[] = { static PyMethodDef TaskType_methods[] = {
@ -2513,7 +2499,7 @@ static PyMethodDef TaskType_methods[] = {
_ASYNCIO_TASK_GET_NAME_METHODDEF _ASYNCIO_TASK_GET_NAME_METHODDEF
_ASYNCIO_TASK_SET_NAME_METHODDEF _ASYNCIO_TASK_SET_NAME_METHODDEF
_ASYNCIO_TASK_GET_CORO_METHODDEF _ASYNCIO_TASK_GET_CORO_METHODDEF
{"__class_getitem__", task_cls_getitem, METH_O|METH_CLASS, NULL}, {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
{NULL, NULL} /* Sentinel */ {NULL, NULL} /* Sentinel */
}; };