From 24f5ccbc486927432fa2641a634e2d237640f24a Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Tue, 20 Jul 2021 18:44:13 +0300 Subject: [PATCH 01/16] bpo-44353: Implement typing.NewType __call__ method in C --- Lib/functools.py | 6 ++++++ Lib/typing.py | 5 ++--- .../next/Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst | 2 ++ Modules/_functoolsmodule.c | 6 ++++++ 4 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst diff --git a/Lib/functools.py b/Lib/functools.py index b1f1fe8d9a6f27d..3197e486b0379ad 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -979,3 +979,9 @@ def __get__(self, instance, owner=None): return val __class_getitem__ = classmethod(GenericAlias) + +try: + from _functools import _idfunc +except ImportError: + def _idfunc(_, x): + return x diff --git a/Lib/typing.py b/Lib/typing.py index 1aff0a1b3026d50..d1a1662931472fb 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -2375,6 +2375,8 @@ def name_by_id(user_id: UserId) -> str: num = UserId(5) + 1 # type: int """ + __call__ = functools._idfunc + def __init__(self, name, tp): self.__name__ = name self.__qualname__ = name @@ -2384,9 +2386,6 @@ def __init__(self, name, tp): def __repr__(self): return f'{self.__module__}.{self.__qualname__}' - def __call__(self, x): - return x - def __or__(self, other): return Union[self, other] diff --git a/Misc/NEWS.d/next/Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst b/Misc/NEWS.d/next/Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst new file mode 100644 index 000000000000000..ec8b1d3a438ad05 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst @@ -0,0 +1,2 @@ +Add helper ``functolls._idfunc`` to make ``typing.NewType`` ``__call__`` +method faster. Patch provided by Yurii Karabas. diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index fa1452168094b92..3cb15fa0b4dd85e 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -1423,6 +1423,11 @@ static PyType_Spec lru_cache_type_spec = { .slots = lru_cache_type_slots }; +/* helper function to make typing.NewType.__call__ method faster */ + +PyObject* _idfunc(PyObject* self, PyObject* x) { + return x; +} /* module level code ********************************************************/ @@ -1433,6 +1438,7 @@ static PyMethodDef _functools_methods[] = { {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc}, {"cmp_to_key", (PyCFunction)(void(*)(void))functools_cmp_to_key, METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc}, + {"_idfunc", _idfunc, METH_O}, {NULL, NULL} /* sentinel */ }; From cdbd36e34ef4879838875415d9022cf27ad9a289 Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Tue, 20 Jul 2021 18:52:10 +0300 Subject: [PATCH 02/16] Rename _idfunc to functools_idfunc --- Modules/_functoolsmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 3cb15fa0b4dd85e..f74c25224da658d 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -1425,7 +1425,7 @@ static PyType_Spec lru_cache_type_spec = { /* helper function to make typing.NewType.__call__ method faster */ -PyObject* _idfunc(PyObject* self, PyObject* x) { +PyObject* functools_idfunc(PyObject* self, PyObject* x) { return x; } @@ -1438,7 +1438,7 @@ static PyMethodDef _functools_methods[] = { {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc}, {"cmp_to_key", (PyCFunction)(void(*)(void))functools_cmp_to_key, METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc}, - {"_idfunc", _idfunc, METH_O}, + {"_idfunc", functools_idfunc, METH_O}, {NULL, NULL} /* sentinel */ }; From 7b94a7db19f40e197ba5a44fd74bdaf0f43b82fd Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Tue, 20 Jul 2021 18:57:39 +0300 Subject: [PATCH 03/16] Add missed Py_INCREF --- Modules/_functoolsmodule.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index f74c25224da658d..66d306a03c753e6 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -1426,6 +1426,7 @@ static PyType_Spec lru_cache_type_spec = { /* helper function to make typing.NewType.__call__ method faster */ PyObject* functools_idfunc(PyObject* self, PyObject* x) { + Py_INCREF(x); return x; } From dd2becdd00c3a00f8556709d51394dc9759f53dc Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Tue, 20 Jul 2021 19:01:08 +0300 Subject: [PATCH 04/16] Make _idfunc static --- Modules/_functoolsmodule.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 66d306a03c753e6..51c9cc1dfbd040d 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -1425,7 +1425,8 @@ static PyType_Spec lru_cache_type_spec = { /* helper function to make typing.NewType.__call__ method faster */ -PyObject* functools_idfunc(PyObject* self, PyObject* x) { +static PyObject * +functools_idfunc(PyObject* self, PyObject* x) { Py_INCREF(x); return x; } From 084e77cf8039f070f56d1fac3b579578a04718b7 Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Tue, 20 Jul 2021 19:01:53 +0300 Subject: [PATCH 05/16] Update Misc/NEWS.d/next/Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst Co-authored-by: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> --- .../next/Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst b/Misc/NEWS.d/next/Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst index ec8b1d3a438ad05..1390f244b2b748e 100644 --- a/Misc/NEWS.d/next/Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst +++ b/Misc/NEWS.d/next/Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst @@ -1,2 +1,2 @@ -Add helper ``functolls._idfunc`` to make ``typing.NewType`` ``__call__`` +Add helper ``functools._idfunc`` to make ``typing.NewType`` ``__call__`` method faster. Patch provided by Yurii Karabas. From e2ac1708b9d5081fd7bf6370dcc7c77d66e74c7f Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Tue, 20 Jul 2021 19:03:25 +0300 Subject: [PATCH 06/16] Align functools_idfunc --- Modules/_functoolsmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 51c9cc1dfbd040d..ab5e92ca2d82812 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -1440,7 +1440,7 @@ static PyMethodDef _functools_methods[] = { {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc}, {"cmp_to_key", (PyCFunction)(void(*)(void))functools_cmp_to_key, METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc}, - {"_idfunc", functools_idfunc, METH_O}, + {"_idfunc", (PyCFunction)functools_idfunc, METH_O}, {NULL, NULL} /* sentinel */ }; From d5fcf8744d206e14fc70a4a02e79abb4d2f9c85c Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Tue, 20 Jul 2021 20:38:07 +0300 Subject: [PATCH 07/16] Move _idfunc to operator module --- Lib/operator.py | 6 ++++++ Lib/typing.py | 2 +- .../Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst | 4 ++-- Modules/_functoolsmodule.c | 8 -------- Modules/_operator.c | 9 +++++++++ 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Lib/operator.py b/Lib/operator.py index 241fdbb679e7c13..4231262e3305536 100644 --- a/Lib/operator.py +++ b/Lib/operator.py @@ -411,6 +411,12 @@ def ixor(a, b): else: from _operator import __doc__ +try: + from _operator import _idfunc +except ImportError: + def _idfunc(_, x): + return x + # All of these "__func__ = func" assignments have to happen after importing # from _operator to make sure they're set to the right function __lt__ = lt diff --git a/Lib/typing.py b/Lib/typing.py index d1a1662931472fb..f846f2d28fcbce9 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -2375,7 +2375,7 @@ def name_by_id(user_id: UserId) -> str: num = UserId(5) + 1 # type: int """ - __call__ = functools._idfunc + __call__ = operator._idfunc def __init__(self, name, tp): self.__name__ = name diff --git a/Misc/NEWS.d/next/Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst b/Misc/NEWS.d/next/Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst index 1390f244b2b748e..7332770ac487e74 100644 --- a/Misc/NEWS.d/next/Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst +++ b/Misc/NEWS.d/next/Library/2021-07-20-18-34-16.bpo-44353.ATuYq4.rst @@ -1,2 +1,2 @@ -Add helper ``functools._idfunc`` to make ``typing.NewType`` ``__call__`` -method faster. Patch provided by Yurii Karabas. +Make ``NewType.__call__`` faster by implementing it in C. +Patch provided by Yurii Karabas. diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index ab5e92ca2d82812..fa1452168094b92 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -1423,13 +1423,6 @@ static PyType_Spec lru_cache_type_spec = { .slots = lru_cache_type_slots }; -/* helper function to make typing.NewType.__call__ method faster */ - -static PyObject * -functools_idfunc(PyObject* self, PyObject* x) { - Py_INCREF(x); - return x; -} /* module level code ********************************************************/ @@ -1440,7 +1433,6 @@ static PyMethodDef _functools_methods[] = { {"reduce", functools_reduce, METH_VARARGS, functools_reduce_doc}, {"cmp_to_key", (PyCFunction)(void(*)(void))functools_cmp_to_key, METH_VARARGS | METH_KEYWORDS, functools_cmp_to_key_doc}, - {"_idfunc", (PyCFunction)functools_idfunc, METH_O}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/_operator.c b/Modules/_operator.c index f051513fc793a01..6ab677e0ce96c59 100644 --- a/Modules/_operator.c +++ b/Modules/_operator.c @@ -886,6 +886,14 @@ _operator__compare_digest_impl(PyObject *module, PyObject *a, PyObject *b) return PyBool_FromLong(rc); } +/* helper function to make typing.NewType.__call__ method faster */ + +static PyObject * +functools_idfunc(PyObject* self, PyObject* x) { + Py_INCREF(x); + return x; +} + /* operator methods **********************************************************/ static struct PyMethodDef operator_methods[] = { @@ -942,6 +950,7 @@ static struct PyMethodDef operator_methods[] = { _OPERATOR_GE_METHODDEF _OPERATOR__COMPARE_DIGEST_METHODDEF _OPERATOR_LENGTH_HINT_METHODDEF + {"_idfunc", (PyCFunction)functools_idfunc, METH_O}, {NULL, NULL} /* sentinel */ }; From 3d7b70ccc37930619253cf112fa128a5eed1ce40 Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Wed, 21 Jul 2021 13:07:50 +0300 Subject: [PATCH 08/16] Remove _idfunc from functools --- Lib/functools.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Lib/functools.py b/Lib/functools.py index 3197e486b0379ad..b1f1fe8d9a6f27d 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -979,9 +979,3 @@ def __get__(self, instance, owner=None): return val __class_getitem__ = classmethod(GenericAlias) - -try: - from _functools import _idfunc -except ImportError: - def _idfunc(_, x): - return x From 5293943734de6bbb52a8a3c71cc232f80feb2091 Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Wed, 21 Jul 2021 14:33:26 +0300 Subject: [PATCH 09/16] Rename functools_idfunc to operator_idfunc --- Modules/_operator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_operator.c b/Modules/_operator.c index 6ab677e0ce96c59..470707e94912c93 100644 --- a/Modules/_operator.c +++ b/Modules/_operator.c @@ -889,7 +889,7 @@ _operator__compare_digest_impl(PyObject *module, PyObject *a, PyObject *b) /* helper function to make typing.NewType.__call__ method faster */ static PyObject * -functools_idfunc(PyObject* self, PyObject* x) { +operator_idfunc(PyObject* self, PyObject* x) { Py_INCREF(x); return x; } @@ -950,7 +950,7 @@ static struct PyMethodDef operator_methods[] = { _OPERATOR_GE_METHODDEF _OPERATOR__COMPARE_DIGEST_METHODDEF _OPERATOR_LENGTH_HINT_METHODDEF - {"_idfunc", (PyCFunction)functools_idfunc, METH_O}, + {"_idfunc", (PyCFunction)operator_idfunc, METH_O}, {NULL, NULL} /* sentinel */ }; From ceea1bce3c057e9a1ebdb25f7ba34447f63a46d3 Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Wed, 21 Jul 2021 15:10:48 +0300 Subject: [PATCH 10/16] Update Modules/_operator.c Co-authored-by: Denis Laxalde --- Modules/_operator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_operator.c b/Modules/_operator.c index 470707e94912c93..d9b8315ff4f6cde 100644 --- a/Modules/_operator.c +++ b/Modules/_operator.c @@ -889,7 +889,7 @@ _operator__compare_digest_impl(PyObject *module, PyObject *a, PyObject *b) /* helper function to make typing.NewType.__call__ method faster */ static PyObject * -operator_idfunc(PyObject* self, PyObject* x) { +_operator__idfunc(PyObject* self, PyObject* x) { Py_INCREF(x); return x; } From 1b70a792c7cf3420d9e3512a9b060ea67d60e6ea Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Wed, 21 Jul 2021 15:10:55 +0300 Subject: [PATCH 11/16] Update Modules/_operator.c Co-authored-by: Denis Laxalde --- Modules/_operator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_operator.c b/Modules/_operator.c index d9b8315ff4f6cde..8430b2adcde4911 100644 --- a/Modules/_operator.c +++ b/Modules/_operator.c @@ -950,7 +950,7 @@ static struct PyMethodDef operator_methods[] = { _OPERATOR_GE_METHODDEF _OPERATOR__COMPARE_DIGEST_METHODDEF _OPERATOR_LENGTH_HINT_METHODDEF - {"_idfunc", (PyCFunction)operator_idfunc, METH_O}, + {"_idfunc", (PyCFunction)_operator__idfunc, METH_O}, {NULL, NULL} /* sentinel */ }; From 9fc1ebf9e00ea608c33eed76db32bc92c799b8ec Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Thu, 22 Jul 2021 11:33:36 +0300 Subject: [PATCH 12/16] Move _idfunc to seperate module --- Lib/operator.py | 5 --- Lib/typing.py | 9 ++++- Modules/Setup | 1 + Modules/_operator.c | 9 ----- Modules/_typingmodule.c | 59 ++++++++++++++++++++++++++++++ Modules/clinic/_typingmodule.c.h | 12 ++++++ PC/config.c | 2 + PCbuild/pythoncore.vcxproj | 1 + PCbuild/pythoncore.vcxproj.filters | 3 ++ Python/stdlib_module_names.h | 1 + setup.py | 2 + 11 files changed, 89 insertions(+), 15 deletions(-) create mode 100644 Modules/_typingmodule.c create mode 100644 Modules/clinic/_typingmodule.c.h diff --git a/Lib/operator.py b/Lib/operator.py index 4231262e3305536..b2de1598cdeb9be 100644 --- a/Lib/operator.py +++ b/Lib/operator.py @@ -411,11 +411,6 @@ def ixor(a, b): else: from _operator import __doc__ -try: - from _operator import _idfunc -except ImportError: - def _idfunc(_, x): - return x # All of these "__func__ = func" assignments have to happen after importing # from _operator to make sure they're set to the right function diff --git a/Lib/typing.py b/Lib/typing.py index f846f2d28fcbce9..5c95a4dbd892499 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -31,6 +31,13 @@ import warnings from types import WrapperDescriptorType, MethodWrapperType, MethodDescriptorType, GenericAlias + +try: + from _typing import _idfunc +except ImportError: + def _idfunc(_, x): + return x + # Please keep __all__ alphabetized within each category. __all__ = [ # Super-special typing primitives. @@ -2375,7 +2382,7 @@ def name_by_id(user_id: UserId) -> str: num = UserId(5) + 1 # type: int """ - __call__ = operator._idfunc + __call__ = _idfunc def __init__(self, name, tp): self.__name__ = name diff --git a/Modules/Setup b/Modules/Setup index 87c6a152f86eac0..5e26472446677a2 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -184,6 +184,7 @@ _symtable symtablemodule.c #_asyncio _asynciomodule.c # Fast asyncio Future #_json -I$(srcdir)/Include/internal -DPy_BUILD_CORE_BUILTIN _json.c # _json speedups #_statistics _statisticsmodule.c # statistics accelerator +#_typing _typingmodule.c # typing accelerator #unicodedata unicodedata.c -DPy_BUILD_CORE_BUILTIN # static Unicode character database diff --git a/Modules/_operator.c b/Modules/_operator.c index 8430b2adcde4911..f051513fc793a01 100644 --- a/Modules/_operator.c +++ b/Modules/_operator.c @@ -886,14 +886,6 @@ _operator__compare_digest_impl(PyObject *module, PyObject *a, PyObject *b) return PyBool_FromLong(rc); } -/* helper function to make typing.NewType.__call__ method faster */ - -static PyObject * -_operator__idfunc(PyObject* self, PyObject* x) { - Py_INCREF(x); - return x; -} - /* operator methods **********************************************************/ static struct PyMethodDef operator_methods[] = { @@ -950,7 +942,6 @@ static struct PyMethodDef operator_methods[] = { _OPERATOR_GE_METHODDEF _OPERATOR__COMPARE_DIGEST_METHODDEF _OPERATOR_LENGTH_HINT_METHODDEF - {"_idfunc", (PyCFunction)_operator__idfunc, METH_O}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/_typingmodule.c b/Modules/_typingmodule.c new file mode 100644 index 000000000000000..8b6faa646d61878 --- /dev/null +++ b/Modules/_typingmodule.c @@ -0,0 +1,59 @@ +/* typing accelerator C extension: _typing module. */ + +#include "Python.h" +#include "clinic/_typingmodule.c.h" + +/*[clinic input] +module _typing + +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=1db35baf1c72942b]*/ + +/* helper function to make typing.NewType.__call__ method faster */ + +/*[clinic input] +_typing._idfunc -> object + + x: object + / + +[clinic start generated code]*/ + +static PyObject * +_typing__idfunc(PyObject *module, PyObject *x) +/*[clinic end generated code: output=63c38be4a6ec5f2c input=49f17284b43de451]*/ +{ + Py_INCREF(x); + return x; +} + + +static PyMethodDef typing_methods[] = { + _TYPING__IDFUNC_METHODDEF + {NULL, NULL, 0, NULL} +}; + +PyDoc_STRVAR(typing_doc, +"Accelerators for the typing module.\n"); + +static struct PyModuleDef_Slot _typingmodule_slots[] = { + {0, NULL} +}; + +static struct PyModuleDef typingmodule = { + PyModuleDef_HEAD_INIT, + "_typing", + typing_doc, + 0, + typing_methods, + _typingmodule_slots, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC +PyInit__typing(void) +{ + return PyModuleDef_Init(&typingmodule); +} diff --git a/Modules/clinic/_typingmodule.c.h b/Modules/clinic/_typingmodule.c.h new file mode 100644 index 000000000000000..ea415e67153ed86 --- /dev/null +++ b/Modules/clinic/_typingmodule.c.h @@ -0,0 +1,12 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(_typing__idfunc__doc__, +"_idfunc($module, x, /)\n" +"--\n" +"\n"); + +#define _TYPING__IDFUNC_METHODDEF \ + {"_idfunc", (PyCFunction)_typing__idfunc, METH_O, _typing__idfunc__doc__}, +/*[clinic end generated code: output=e7ea2a3cb7ab301a input=a9049054013a1b77]*/ diff --git a/PC/config.c b/PC/config.c index 87cd76d37bede8a..11743ea45a969d1 100644 --- a/PC/config.c +++ b/PC/config.c @@ -24,6 +24,7 @@ extern PyObject* PyInit__sha256(void); extern PyObject* PyInit__sha512(void); extern PyObject* PyInit__sha3(void); extern PyObject* PyInit__statistics(void); +extern PyObject* PyInit__typing(void); extern PyObject* PyInit__blake2(void); extern PyObject* PyInit_time(void); extern PyObject* PyInit__thread(void); @@ -104,6 +105,7 @@ struct _inittab _PyImport_Inittab[] = { {"_blake2", PyInit__blake2}, {"time", PyInit_time}, {"_thread", PyInit__thread}, + {"_typing", PyInit__typing}, {"_statistics", PyInit__statistics}, #ifdef WIN32 {"msvcrt", PyInit_msvcrt}, diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 66d35e0cb24d0ed..7b4d0a8297251d9 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -360,6 +360,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 22904d5093aa461..7f5bdfa4199713a 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -698,6 +698,9 @@ Modules + + Modules + Modules diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index b09b8dc7a394ae5..3c5f1768305cb0d 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -81,6 +81,7 @@ static const char* _Py_stdlib_module_names[] = { "_threading_local", "_tkinter", "_tracemalloc", +"_typing", "_uuid", "_warnings", "_weakref", diff --git a/setup.py b/setup.py index bc2ea16089569fb..97f101a2c576836 100644 --- a/setup.py +++ b/setup.py @@ -957,6 +957,8 @@ def detect_simple_extensions(self): extra_compile_args=['-DPy_BUILD_CORE_MODULE'])) # _statistics module self.add(Extension("_statistics", ["_statisticsmodule.c"])) + # _typing module + self.add(Extension("_typing", ["_typingmodule.c"])) # Modules with some UNIX dependencies -- on by default: # (If you have a really backward UNIX, select and socket may not be From aaff1cf62031363954180b8c63a8ab43dd82efed Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Thu, 22 Jul 2021 11:36:29 +0300 Subject: [PATCH 13/16] Remove newline from operator module --- Lib/operator.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/operator.py b/Lib/operator.py index b2de1598cdeb9be..241fdbb679e7c13 100644 --- a/Lib/operator.py +++ b/Lib/operator.py @@ -411,7 +411,6 @@ def ixor(a, b): else: from _operator import __doc__ - # All of these "__func__ = func" assignments have to happen after importing # from _operator to make sure they're set to the right function __lt__ = lt From 1cad8c60c2303cc12d52228c34be7f888157b4e7 Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Thu, 22 Jul 2021 11:43:26 +0300 Subject: [PATCH 14/16] Fix typos --- PCbuild/pythoncore.vcxproj | 2 +- PCbuild/pythoncore.vcxproj.filters | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 7b4d0a8297251d9..7cd3c21fbf691ca 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -360,10 +360,10 @@ - + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 7f5bdfa4199713a..4eccf4f43d1ad2a 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -698,7 +698,7 @@ Modules - + Modules From 2c51ef7f55a893995725a43a4c152014de1dc5fa Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Thu, 22 Jul 2021 19:25:17 +0300 Subject: [PATCH 15/16] Add tests to cover _typing and typing modules --- Lib/test/test_typing.py | 56 ++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 169b92b6513792e..9f04b7c0f13c433 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -33,10 +33,15 @@ import weakref import types +from test.support import import_helper from test import mod_generics_cache from test import _typed_dict_helper +py_typing = import_helper.import_fresh_module('typing', blocked=['_typing']) +c_typing = import_helper.import_fresh_module('typing', fresh=['_typing']) + + class BaseTestCase(TestCase): def assertIsSubclass(self, cls, class_or_tuple, msg=None): @@ -3673,18 +3678,36 @@ def foo(a: A) -> Optional[BaseException]: assert foo(None) is None -class NewTypeTests(BaseTestCase): +class TestModules(TestCase): + func_names = ['_idfunc'] + + def test_py_functions(self): + for fname in self.func_names: + self.assertEqual(getattr(py_typing, fname).__module__, 'typing') + + @skipUnless(c_typing, 'requires _typing') + def test_c_functions(self): + for fname in self.func_names: + self.assertEqual(getattr(c_typing, fname).__module__, '_typing') + + +class NewTypeTests: + def setUp(self): + sys.modules['typing'] = self.module + + def tearDown(self): + sys.modules['typing'] = typing def test_basic(self): - UserId = NewType('UserId', int) - UserName = NewType('UserName', str) + UserId = self.module.NewType('UserId', int) + UserName = self.module.NewType('UserName', str) self.assertIsInstance(UserId(5), int) self.assertIsInstance(UserName('Joe'), str) self.assertEqual(UserId(5) + 1, 6) def test_errors(self): - UserId = NewType('UserId', int) - UserName = NewType('UserName', str) + UserId = self.module.NewType('UserId', int) + UserName = self.module.NewType('UserName', str) with self.assertRaises(TypeError): issubclass(UserId, int) with self.assertRaises(TypeError): @@ -3692,26 +3715,35 @@ class D(UserName): pass def test_or(self): - UserId = NewType('UserId', int) + UserId = self.module.NewType('UserId', int) - self.assertEqual(UserId | int, Union[UserId, int]) - self.assertEqual(int | UserId, Union[int, UserId]) + self.assertEqual(UserId | int, self.module.Union[UserId, int]) + self.assertEqual(int | UserId, self.module.Union[int, UserId]) - self.assertEqual(get_args(UserId | int), (UserId, int)) - self.assertEqual(get_args(int | UserId), (int, UserId)) + self.assertEqual(self.module.get_args(UserId | int), (UserId, int)) + self.assertEqual(self.module.get_args(int | UserId), (int, UserId)) def test_special_attrs(self): - UserId = NewType('UserId', int) + UserId = self.module.NewType('UserId', int) self.assertEqual(UserId.__name__, 'UserId') self.assertEqual(UserId.__qualname__, 'UserId') self.assertEqual(UserId.__module__, __name__) def test_repr(self): - UserId = NewType('UserId', int) + UserId = self.module.NewType('UserId', int) self.assertEqual(repr(UserId), f'{__name__}.UserId') +class NewTypePythonTests(BaseTestCase, NewTypeTests): + module = py_typing + + +@skipUnless(c_typing, 'requires _typing') +class NewTypeCTests(BaseTestCase, NewTypeTests): + module = c_typing + + class NamedTupleTests(BaseTestCase): class NestedEmployee(NamedTuple): name: str From 6f990c0b09f684bdcfb2044516f710745e3145a0 Mon Sep 17 00:00:00 2001 From: Yurii Karabas <1998uriyyo@gmail.com> Date: Thu, 22 Jul 2021 19:29:28 +0300 Subject: [PATCH 16/16] Update test_or --- Lib/test/test_typing.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index dd3e4b230b349cd..6f1d4f6ce20e16d 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -3715,16 +3715,16 @@ class D(UserName): pass def test_or(self): - UserId = NewType('UserId', int) - UserName = NewType('UserName', str) + UserId = self.module.NewType('UserId', int) + UserName = self.module.NewType('UserName', str) for cls in (int, UserName): with self.subTest(cls=cls): - self.assertEqual(UserId | cls, Union[UserId, cls]) - self.assertEqual(cls | UserId, Union[cls, UserId]) + self.assertEqual(UserId | cls, self.module.Union[UserId, cls]) + self.assertEqual(cls | UserId, self.module.Union[cls, UserId]) - self.assertEqual(get_args(UserId | cls), (UserId, cls)) - self.assertEqual(get_args(cls | UserId), (cls, UserId)) + self.assertEqual(self.module.get_args(UserId | cls), (UserId, cls)) + self.assertEqual(self.module.get_args(cls | UserId), (cls, UserId)) def test_special_attrs(self): UserId = self.module.NewType('UserId', int)