8000 MAINT: Make `__class_getitem__` available to all python version and p… · numpy/numpy@eba93e9 · GitHub
[go: up one dir, main page]

Skip to content

Commit eba93e9

Browse files
author
Bas van Beek
committed
MAINT: Make __class_getitem__ available to all python version and perform basic validation of its input arguments
It will still raise on python 3.8, but now with a more explicit exception message
1 parent 0baeeb1 commit eba93e9

File tree

7 files changed

+196
-99
lines changed

7 files changed

+196
-99
lines changed

numpy/core/_add_newdocs.py

Lines changed: 66 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
1010
"""
1111

12-
import sys
1312
from numpy.core.function_base import add_newdoc
1413
from numpy.core.overrides import array_function_like_doc
1514

@@ -2799,38 +2798,37 @@
27992798
"""))
28002799

28012800

2802-
if sys.version_info > (3, 9):
2803-
add_newdoc('numpy.core.multiarray', 'ndarray', ('__class_getitem__',
2804-
"""a.__class_getitem__(item, /)
2801+
add_newdoc('numpy.core.multiarray', 'ndarray', ('__class_getitem__',
2802+
"""a.__class_getitem__(item, /)
28052803
2806-
Return a parametrized wrapper around the `~numpy.ndarray` type.
2804+
Return a parametrized wrapper around the `~numpy.ndarray` type.
28072805
2808-
.. versionadded:: 1.22
2806+
.. versionadded:: 1.22
28092807
2810-
Returns
2811-
-------
2812-
alias : types.GenericAlias
2813-
A parametrized `~numpy.ndarray` type.
2808+
Returns
2809+
-------
2810+
alias : types.GenericAlias
2811+
A parametrized `~numpy.ndarray` type.
28142812
2815-
Examples
2816-
--------
2817-
>>> from typing import Any
2818-
>>> import numpy as np
2813+
Examples
2814+
--------
2815+
>>> from typing import Any
2816+
>>> import numpy as np
28192817
2820-
>>> np.ndarray[Any, np.dtype]
2821-
numpy.ndarray[typing.Any, numpy.dtype]
2818+
>>> np.ndarray[Any, np.dtype[Any]]
2819+
numpy.ndarray[typing.Any, numpy.dtype[Any]]
28222820
2823-
Note
2824-
----
2825-
This method is only available for python 3.9 and later.
2821+
Note
2822+
----
2823+
This method is only available for python 3.9 and later.
28262824
2827-
See Also
2828-
--------
2829-
:pep:`585` : Type hinting generics in standard collections.
2830-
numpy.typing.NDArray : An ndarray alias :term:`generic <generic type>`
2831-
w.r.t. its `dtype.type <numpy.dtype.type>`.
2825+
See Also
2826+
--------
2827+
:pep:`585` : Type hinting generics in standard collections.
2828+
numpy.typing.NDArray : An ndarray alias :term:`generic <generic type>`
2829+
w.r.t. its `dtype.type <numpy.dtype.type>`.
28322830
2833-
"""))
2831+
"""))
28342832

28352833

28362834
add_newdoc('numpy.core.multiarray', 'ndarray', ('__deepcopy__',
9E88
@@ -6079,36 +6077,35 @@
60796077
60806078
"""))
60816079

6082-
if sys.version_info >= (3, 9):
6083-
add_newdoc('numpy.core.multiarray', 'dtype', ('__class_getitem__',
6084-
"""
6085-
__class_getitem__(item, /)
6080+
add_newdoc('numpy.core.multiarray', 'dtype', ('__class_getitem__',
6081+
"""
6082+
__class_getitem__(item, /)
60866083
6087-
Return a parametrized wrapper around the `~numpy.dtype` type.
6084+
Return a parametrized wrapper around the `~numpy.dtype` type.
60886085
6089-
.. versionadded:: 1.22
6086+
.. versionadded:: 1.22
60906087
6091-
Returns
6092-
-------
6093-
alias : types.GenericAlias
6094-
A parametrized `~numpy.dtype` type.
6088+
Returns
6089+
-------
6090+
alias : types.GenericAlias
6091+
A parametrized `~numpy.dtype` type.
60956092
6096-
Examples
6097-
--------
6098-
>>> import numpy as np
6093+
Examples
6094+
--------
6095+
>>> import numpy as np
60996096
6100-
>>> np.dtype[np.int64]
6101-
numpy.dtype[numpy.int64]
6097+
>>> np.dtype[np.int64]
6098+
numpy.dtype[numpy.int64]
61026099
6103-
Note
6104-
----
6105-
This method is only available for python 3.9 and later.
6100+
Note
6101+
----
6102+
This method is only available for python 3.9 and later.
61066103
6107-
See Also
6108-
--------
6109-
:pep:`585` : Type hinting generics in standard collections.
6104+
See Also
6105+
--------
6106+
:pep:`585` : Type hinting generics in standard collections.
61106107
6111-
"""))
6108+
"""))
61126109

61136110
##############################################################################
61146111
#
@@ -6530,37 +6527,36 @@ def refer_to_array_attribute(attr, method=True):
65306527
add_newdoc('numpy.core.numerictypes', 'generic',
65316528
refer_to_array_attribute('view'))
65326529

6533-
if sys.version_info >= (3, 9):
6534-
add_newdoc('numpy.core.numerictypes', 'number', ('__class_getitem__',
6535-
"""
6536-
__class_getitem__(item, /)
6530+
add_newdoc('numpy.core.numerictypes', 'number', ('__class_getitem__',
6531+
"""
6532+
__class_getitem__(item, /)
65376533
6538-
Return a parametrized wrapper around the `~numpy.number` type.
6534+
Return a parametrized wrapper around the `~numpy.number` type.
65396535
6540-
.. versionadded:: 1.22
6536+
.. versionadded:: 1.22
65416537
6542-
Returns
6543-
-------
6544-
alias : types.GenericAlias
6545-
A parametrized `~numpy.number` type.
6538+
Returns
6539+
-------
6540+
alias : types.GenericAlias
6541+
A parametrized `~numpy.number` type.
65466542
6547-
Examples
6548-
--------
6549-
>>> from typing import Any
6550-
>>> import numpy as np
6543+
Examples
6544+
--------
6545+
>>> from typing import Any
6546+
>>> import numpy as np
65516547
6552-
>>> np.signedinteger[Any]
6553-
numpy.signedinteger[typing.Any]
6548+
>>> np.signedinteger[Any]
6549+
numpy.signedinteger[typing.Any]
65546550
6555-
Note
6556-
----
6557-
This method is only available for python 3.9 and later.
6551+
Note
6552+
----
6553+
This method is only available for python 3.9 and later.
65586554
6559-
See Also
6560-
--------
6561-
:pep:`585` : Type hinting generics in standard collections.
6555+
See Also
6556+
--------
6557+
:pep:`585` : Type hinting generics in standard collections.
65626558
6563-
"""))
6559+
"""))
65646560

65656561
##############################################################################
65666562
#

numpy/core/src/multiarray/descriptor.c

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3101,6 +3101,30 @@ arraydescr_newbyteorder(PyArray_Descr *self, PyObject *args)
31013101
return (PyObject *)PyArray_DescrNewByteorder(self, endian);
31023102
}
31033103

3104+
static PyObject *
3105+
arraydescr_class_getitem(PyObject *cls, PyObject *args)
3106+
{
3107+
PyObject *generic_alias;
3108+
3109+
#ifdef Py_GENERICALIASOBJECT_H
3110+
Py_ssize_t args_len;
3111+
3112+
args_len = PyTuple_Check(args) ? PyTuple_Size(args) : 1;
3113+
if (args_len != 1) {
3114+
return PyErr_Format(PyExc_TypeError,
3115+
"Too %s arguments for %s",
3116+
args_len > 1 ? "many" : "few",
3117+
((PyTypeObject *)cls)->tp_name);
3118+
}
3119+
generic_alias = Py_GenericAlias(cls, args);
3120+
#else
3121+
PyErr_SetString(PyExc_TypeError,
3122+
"Type subscription requires python >= 3.9");
3123+
generic_alias = NULL;
3124+
#endif
3125+
return generic_alias;
3126+
}
3127+
31043128
static PyMethodDef arraydescr_methods[] = {
31053129
/* for pickling */
31063130
{"__reduce__",
@@ -3112,13 +3136,10 @@ static PyMethodDef arraydescr_methods[] = {
31123136
{"newbyteorder",
31133137
(PyCFunction)arraydescr_newbyteorder,
31143138
METH_VARARGS, NULL},
3115-
31163139
/* for typing; requires python >= 3.9 */
3117-
#ifdef Py_GENERICALIASOBJECT_H
31183140
{"__class_getitem__",
3119-
(PyCFunction)Py_GenericAlias,
3141+
(PyCFunction)arraydescr_class_getitem,
31203142
METH_CLASS | METH_O, NULL},
3121-
#endif
31223143
{NULL, NULL, 0, NULL} /* sentinel */
31233144
};
31243145

numpy/core/src/multiarray/methods.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2699,6 +2699,30 @@ array_complex(PyArrayObject *self, PyObject *NPY_UNUSED(args))
26992699
return c;
27002700
}
27012701

2702+
static PyObject *
2703+
array_class_getitem(PyObject *cls, PyObject *args)
2704+
{
2705+
PyObject *generic_alias;
2706+
2707+
#ifdef Py_GENERICALIASOBJECT_H
2708+
Py_ssize_t args_len;
2709+
2710+
args_len = PyTuple_Check(args) ? PyTuple_Size(args) : 1;
2711+
if (args_len != 2) {
2712+
return PyErr_Format(PyExc_TypeError,
2713+
"Too %s arguments for %s",
2714+
args_len > 2 ? "many" : "few",
2715+
((PyTypeObject *)cls)->tp_name);
2716+
}
2717+
generic_alias = Py_GenericAlias(cls, args);
2718+
#else
2719+
PyErr_SetString(PyExc_TypeError,
2720+
"Type subscription requires python >= 3.9");
2721+
generic_alias = NULL;
2722+
#endif
2723+
return generic_alias;
2724+
}
2725+
27022726
NPY_NO_EXPORT PyMethodDef array_methods[] = {
27032727

27042728
/* for subtypes */
@@ -2757,11 +2781,9 @@ NPY_NO_EXPORT PyMethodDef array_methods[] = {
27572781
METH_VARARGS, NULL},
27582782

27592783
/* for typing; requires python >= 3.9 */
2760-
#ifdef Py_GENERICALIASOBJECT_H
27612784
{"__class_getitem__",
2762-
(PyCFunction)Py_GenericAlias,
2785+
(PyCFunction)array_class_getitem,
27632786
METH_CLASS | METH_O, NULL},
2764-
#endif
27652787

27662788
/* Original and Extended methods added 2005 */
27672789
{"all",

numpy/core/src/multiarray/scalartypes.c.src

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,20 +1805,48 @@ gentype_setflags(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args),
18051805
Py_RETURN_NONE;
18061806
}
18071807

1808+
static PyObject *
1809+
numbertype_class_getitem_abc(PyObject *cls, PyObject *args)
1810+
{
1811+
PyObject *generic_alias;
1812+
1813+
#ifdef Py_GENERICALIASOBJECT_H
1814+
Py_ssize_t args_len;
1815+
1816+
args_len = PyTuple_Check(args) ? PyTuple_Size(args) : 1;
1817+
if (args_len != 1) {
1818+
return PyErr_Format(PyExc_TypeError,
1819+
"Too %s arguments for %s",
1820+
args_len > 1 ? "many" : "few",
1821+
((PyTypeObject *)cls)->tp_name);
1822+
}
1823+
generic_alias = Py_GenericAlias(cls, args);
1824+
#else
1825+
PyErr_SetString(PyExc_TypeError,
1826+
"Type subscription requires python >= 3.9");
1827+
generic_alias = NULL;
1828+
#endif
1829+
return generic_alias;
1830+
}
1831+
18081832
/*
18091833
* Use for concrete np.number subclasses, making them act as if they
18101834
* were subtyped from e.g. np.signedinteger[object], thus lacking any
18111835
* free subscription parameters. Requires python >= 3.9.
18121836
*/
1813-
#ifdef Py_GENERICALIASOBJECT_H
18141837
static PyObject *
18151838
numbertype_class_getitem(PyObject *cls, PyObject *args)
18161839
{
1817-
return PyErr_Format(PyExc_TypeError,
1818-
"There are no type variables left in %s",
1819-
((PyTypeObject *)cls)->tp_name);
1820-
}
1840+
#ifdef Py_GENERICALIASOBJECT_H
1841+
PyErr_Format(PyExc_TypeError,
1842+
"There are no type variables left in %s",
1843+
((PyTypeObject *)cls)->tp_name);
1844+
#else
1845+
PyErr_SetString(PyExc_TypeError,
1846+
"Type subscription requires python >= 3.9");
18211847
#endif
1848+
return NULL;
1849+
}
18221850

18231851
/*
18241852
* casting complex numbers (that don't inherit from Python complex)
@@ -2205,11 +2233,9 @@ static PyGetSetDef inttype_getsets[] = {
22052233

22062234
static PyMethodDef numbertype_methods[] = {
22072235
/* for typing; requires python >= 3.9 */
2208-
#ifdef Py_GENERICALIASOBJECT_H
22092236
{"__class_getitem__",
2210-
(PyCFunction)Py_GenericAlias,
2237+
(PyCFunction)numbertype_class_getitem_abc,
22112238
METH_CLASS | METH_O, NULL},
2212-
#endif
22132239
{NULL, NULL, 0, NULL} /* sentinel */
22142240
};
22152241

@@ -2221,11 +2247,9 @@ static PyMethodDef @name@type_methods[] = {
22212247
(PyCFunction)@name@_complex,
22222248
METH_VARARGS | METH_KEYWORDS, NULL},
22232249
/* for typing; requires python >= 3.9 */
2224-
#ifdef Py_GENERICALIASOBJECT_H
22252250
{"__class_getitem__",
22262251
(PyCFunction)numbertype_class_getitem,
22272252
METH_CLASS | METH_O, NULL},
2228-
#endif
22292253
{NULL, NULL, 0, NULL}
22302254
};
22312255
/**end repeat**/
@@ -2264,11 +2288,9 @@ static PyMethodDef @name@type_methods[] = {
22642288
(PyCFunction)@name@_is_integer,
22652289
METH_NOARGS, NULL},
22662290
/* for typing; requires python >= 3.9 */
2267-
#ifdef Py_GENERICALIASOBJECT_H
22682291
{"__class_getitem__",
22692292
(PyCFunction)numbertype_class_getitem,
22702293
METH_CLASS | METH_O, NULL},
2271-
#endif
22722294
{NULL, NULL, 0, NULL}
22732295
};
22742296
/**end repeat**/
@@ -2279,11 +2301,9 @@ static PyMethodDef @name@type_methods[] = {
22792301
*/
22802302
static PyMethodDef @name@type_methods[] = {
22812303
/* for typing; requires python >= 3.9 */
2282-
#ifdef Py_GENERICALIASOBJECT_H
22832304
{"__class_getitem__",
22842305
(PyCFunction)numbertype_class_getitem,
22852306
METH_CLASS | METH_O, NULL},
2286-
#endif
22872307
{NULL, NULL, 0, NULL}
22882308
};
22892309
/**end repeat**/

0 commit comments

Comments
 (0)
0