From 8fde3774bd70824f608302ae671a1fa7eafa3fdf Mon Sep 17 00:00:00 2001 From: Batuhan Taskaya Date: Wed, 8 Apr 2020 02:22:39 +0300 Subject: [PATCH 1/3] bpo-39481: Generic Alias for SimpleQueue, Queue, TemporaryDirectory... --- Lib/queue.py | 5 +++++ Lib/tempfile.py | 2 ++ Lib/test/test_genericalias.py | 6 ++++++ Lib/unittest/case.py | 2 ++ Modules/_queuemodule.c | 2 ++ 5 files changed, 17 insertions(+) diff --git a/Lib/queue.py b/Lib/queue.py index 5bb0431e949461..10dbcbc18ece85 100644 --- a/Lib/queue.py +++ b/Lib/queue.py @@ -1,6 +1,7 @@ '''A multi-producer, multi-consumer queue.''' import threading +import types from collections import deque from heapq import heappush, heappop from time import monotonic as time @@ -216,6 +217,8 @@ def _put(self, item): def _get(self): return self.queue.popleft() + __class_getitem__ = classmethod(types.GenericAlias) + class PriorityQueue(Queue): '''Variant of Queue that retrieves open entries in priority order (lowest first). @@ -316,6 +319,8 @@ def qsize(self): '''Return the approximate size of the queue (not reliable!).''' return len(self._queue) + __class_getitem__ = classmethod(types.GenericAlias) + if SimpleQueue is None: SimpleQueue = _PySimpleQueue diff --git a/Lib/tempfile.py b/Lib/tempfile.py index a398345f108d0f..ed15c0fd1f8afc 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -829,3 +829,5 @@ def __exit__(self, exc, value, tb): def cleanup(self): if self._finalizer.detach(): self._rmtree(self.name) + + __class_getitem__ = classmethod(_types.GenericAlias) diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py index 4241eabed08452..4e0083f713a9d0 100644 --- a/Lib/test/test_genericalias.py +++ b/Lib/test/test_genericalias.py @@ -16,6 +16,9 @@ from os import DirEntry from re import Pattern, Match from types import GenericAlias, MappingProxyType, AsyncGeneratorType +from tempfile import TemporaryDirectory, SpooledTemporaryFile +from unittest.case import _AssertRaisesContext +from queue import Queue, SimpleQueue import typing from typing import TypeVar @@ -49,6 +52,9 @@ def test_subscriptable(self): DirEntry, IPv4Network, IPv4Interface, IPv6Network, IPv6Interface, chain, + TemporaryDirectory, SpooledTemporaryFile, + Queue, SimpleQueue, + _AssertRaisesContext, ): tname = t.__name__ with self.subTest(f"Testing {tname}"): diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py index 5e5d535dc69387..d0ee561a3ae93a 100644 --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -241,6 +241,8 @@ def __exit__(self, exc_type, exc_value, tb): expected_regex.pattern, str(exc_value))) return True + __class_getitem__ = classmethod(types.GenericAlias) + class _AssertWarnsContext(_AssertRaisesBaseContext): """A context manager used to implement TestCase.assertWarns* methods.""" diff --git a/Modules/_queuemodule.c b/Modules/_queuemodule.c index 5eef06252cd326..28bf8991285d82 100644 --- a/Modules/_queuemodule.c +++ b/Modules/_queuemodule.c @@ -302,6 +302,8 @@ static PyMethodDef simplequeue_methods[] = { _QUEUE_SIMPLEQUEUE_PUT_METHODDEF _QUEUE_SIMPLEQUEUE_PUT_NOWAIT_METHODDEF _QUEUE_SIMPLEQUEUE_QSIZE_METHODDEF + {"__class_getitem__", (PyCFunction)Py_GenericAlias, + METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, {NULL, NULL} /* sentinel */ }; From c97c44ddc0a4ce1ff067ed08bf4fc8b8bacdb6b2 Mon Sep 17 00:00:00 2001 From: Batuhan Taskaya Date: Wed, 8 Apr 2020 15:02:36 +0300 Subject: [PATCH 2/3] Append group 2 --- Lib/ctypes/__init__.py | 3 +++ Lib/test/test_genericalias.py | 4 ++++ Lib/urllib/parse.py | 3 +++ Modules/_ctypes/_ctypes.c | 8 +++++++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index 8f0991147d72f2..4afa4ebd422493 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -1,6 +1,7 @@ """create and manipulate C data types in Python""" import os as _os, sys as _sys +import types as _types __version__ = "1.1.0" @@ -450,6 +451,8 @@ def __getitem__(self, name): def LoadLibrary(self, name): return self._dlltype(name) + __class_getitem__ = classmethod(_types.GenericAlias) + cdll = LibraryLoader(CDLL) pydll = LibraryLoader(PyDLL) diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py index 4e0083f713a9d0..6dc2d10972c248 100644 --- a/Lib/test/test_genericalias.py +++ b/Lib/test/test_genericalias.py @@ -7,6 +7,7 @@ ) from collections.abc import * from contextlib import AbstractContextManager, AbstractAsyncContextManager +from ctypes import Array, LibraryLoader from difflib import SequenceMatcher from filecmp import dircmp from fileinput import FileInput @@ -17,6 +18,7 @@ from re import Pattern, Match from types import GenericAlias, MappingProxyType, AsyncGeneratorType from tempfile import TemporaryDirectory, SpooledTemporaryFile +from urllib.parse import SplitResult, ParseResult from unittest.case import _AssertRaisesContext from queue import Queue, SimpleQueue import typing @@ -55,6 +57,8 @@ def test_subscriptable(self): TemporaryDirectory, SpooledTemporaryFile, Queue, SimpleQueue, _AssertRaisesContext, + Array, LibraryLoader, + SplitResult, ParseResult, ): tname = t.__name__ with self.subTest(f"Testing {tname}"): diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index 779278bac598a1..ea897c3032257b 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -29,6 +29,7 @@ import re import sys +import types import collections import warnings @@ -176,6 +177,8 @@ def port(self): raise ValueError("Port out of range 0-65535") return port + __class_getitem__ = classmethod(types.GenericAlias) + class _NetlocResultMixinStr(_NetlocResultMixinBase, _ResultMixinStr): __slots__ = () diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index dab39396476ba4..ba5ef397cf05bf 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -4798,6 +4798,12 @@ Array_length(PyObject *myself) return self->b_length; } +static PyMethodDef Array_methods[] = { + {"__class_getitem__", (PyCFunction)Py_GenericAlias, + METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, + { NULL, NULL } +}; + static PySequenceMethods Array_as_sequence = { Array_length, /* sq_length; */ 0, /* sq_concat; */ @@ -4846,7 +4852,7 @@ PyTypeObject PyCArray_Type = { 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - 0, /* tp_methods */ + Array_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ From c600f03adca7b06376075465e8803024ef23462c Mon Sep 17 00:00:00 2001 From: Batuhan Taskaya Date: Wed, 8 Apr 2020 15:39:41 +0300 Subject: [PATCH 3/3] Add group 3 --- Lib/concurrent/futures/_base.py | 3 +++ Lib/concurrent/futures/thread.py | 3 +++ Lib/http/cookies.py | 3 +++ Lib/multiprocessing/managers.py | 3 +++ Lib/multiprocessing/pool.py | 3 +++ Lib/multiprocessing/queues.py | 3 +++ Lib/multiprocessing/shared_memory.py | 3 +++ Lib/test/test_genericalias.py | 11 +++++++++++ 8 files changed, 32 insertions(+) diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py index fd0acec55d0460..bf546f8ae1d1cc 100644 --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -7,6 +7,7 @@ import logging import threading import time +import types FIRST_COMPLETED = 'FIRST_COMPLETED' FIRST_EXCEPTION = 'FIRST_EXCEPTION' @@ -544,6 +545,8 @@ def set_exception(self, exception): self._condition.notify_all() self._invoke_callbacks() + __class_getitem__ = classmethod(types.GenericAlias) + class Executor(object): """This is an abstract base class for concrete asynchronous executors.""" diff --git a/Lib/concurrent/futures/thread.py b/Lib/concurrent/futures/thread.py index 2aa4e17d47fa7c..2810b357bc1e17 100644 --- a/Lib/concurrent/futures/thread.py +++ b/Lib/concurrent/futures/thread.py @@ -10,6 +10,7 @@ import itertools import queue import threading +import types import weakref import os @@ -57,6 +58,8 @@ def run(self): else: self.future.set_result(result) + __class_getitem__ = classmethod(types.GenericAlias) + def _worker(executor_reference, work_queue, initializer, initargs): if initializer is not None: diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py index 6694f5478bdadf..35ac2dc6ae280c 100644 --- a/Lib/http/cookies.py +++ b/Lib/http/cookies.py @@ -131,6 +131,7 @@ # import re import string +import types __all__ = ["CookieError", "BaseCookie", "SimpleCookie"] @@ -419,6 +420,8 @@ def OutputString(self, attrs=None): # Return the result return _semispacejoin(result) + __class_getitem__ = classmethod(types.GenericAlias) + # # Pattern for finding cookie diff --git a/Lib/multiprocessing/managers.py b/Lib/multiprocessing/managers.py index 1668220c099571..9d490a1d8b3525 100644 --- a/Lib/multiprocessing/managers.py +++ b/Lib/multiprocessing/managers.py @@ -21,6 +21,7 @@ import array import queue import time +import types import os from os import getpid @@ -1129,6 +1130,8 @@ def set(self, value): return self._callmethod('set', (value,)) value = property(get, set) + __class_getitem__ = classmethod(types.GenericAlias) + BaseListProxy = MakeProxyType('BaseListProxy', ( '__add__', '__contains__', '__delitem__', '__getitem__', '__len__', diff --git a/Lib/multiprocessing/pool.py b/Lib/multiprocessing/pool.py index 41dd923d4f9740..b8a0b827635f07 100644 --- a/Lib/multiprocessing/pool.py +++ b/Lib/multiprocessing/pool.py @@ -20,6 +20,7 @@ import threading import time import traceback +import types import warnings from queue import Empty @@ -780,6 +781,8 @@ def _set(self, i, obj): del self._cache[self._job] self._pool = None + __class_getitem__ = classmethod(types.GenericAlias) + AsyncResult = ApplyResult # create alias -- see #17805 # diff --git a/Lib/multiprocessing/queues.py b/Lib/multiprocessing/queues.py index d112db2cd981d1..835070118387ea 100644 --- a/Lib/multiprocessing/queues.py +++ b/Lib/multiprocessing/queues.py @@ -14,6 +14,7 @@ import threading import collections import time +import types import weakref import errno @@ -366,3 +367,5 @@ def put(self, obj): else: with self._wlock: self._writer.send_bytes(obj) + + __class_getitem__ = classmethod(types.GenericAlias) diff --git a/Lib/multiprocessing/shared_memory.py b/Lib/multiprocessing/shared_memory.py index 184e36704baaeb..9f954d9c38febd 100644 --- a/Lib/multiprocessing/shared_memory.py +++ b/Lib/multiprocessing/shared_memory.py @@ -14,6 +14,7 @@ import errno import struct import secrets +import types if os.name == "nt": import _winapi @@ -508,3 +509,5 @@ def index(self, value): return position else: raise ValueError(f"{value!r} not in this container") + + __class_getitem__ = classmethod(types.GenericAlias) diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py index 6dc2d10972c248..a00899f5267d72 100644 --- a/Lib/test/test_genericalias.py +++ b/Lib/test/test_genericalias.py @@ -6,6 +6,8 @@ defaultdict, deque, OrderedDict, Counter, UserDict, UserList ) from collections.abc import * +from concurrent.futures import Future +from concurrent.futures.thread import _WorkItem from contextlib import AbstractContextManager, AbstractAsyncContextManager from ctypes import Array, LibraryLoader from difflib import SequenceMatcher @@ -14,6 +16,11 @@ from mmap import mmap from ipaddress import IPv4Network, IPv4Interface, IPv6Network, IPv6Interface from itertools import chain +from http.cookies import Morsel +from multiprocessing.managers import ValueProxy +from multiprocessing.pool import ApplyResult +from multiprocessing.shared_memory import ShareableList +from multiprocessing.queues import SimpleQueue from os import DirEntry from re import Pattern, Match from types import GenericAlias, MappingProxyType, AsyncGeneratorType @@ -59,6 +66,10 @@ def test_subscriptable(self): _AssertRaisesContext, Array, LibraryLoader, SplitResult, ParseResult, + ValueProxy, ApplyResult, + ShareableList, SimpleQueue, + Future, _WorkItem, + Morsel, ): tname = t.__name__ with self.subTest(f"Testing {tname}"):