summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/__init__.pyi25
-rw-r--r--numpy/core/fromnumeric.py12
-rw-r--r--numpy/core/include/numpy/numpyconfig.h1
-rw-r--r--numpy/core/src/multiarray/_multiarray_tests.c.src5
-rw-r--r--numpy/core/src/multiarray/compiled_base.c2
-rw-r--r--numpy/core/src/multiarray/mapping.c3
-rw-r--r--numpy/core/src/multiarray/scalartypes.c.src14
-rw-r--r--numpy/core/tests/test_multiarray.py4
-rw-r--r--numpy/core/tests/test_scalarbuffer.py39
-rw-r--r--numpy/f2py/__version__.py9
-rw-r--r--numpy/f2py/capi_maps.py2
-rw-r--r--numpy/f2py/common_rules.py2
-rwxr-xr-xnumpy/f2py/f2py2e.py20
-rwxr-xr-xnumpy/f2py/rules.py15
-rw-r--r--numpy/lib/function_base.py6
-rw-r--r--numpy/tests/test_scripts.py4
-rw-r--r--numpy/typing/_callable.py9
-rw-r--r--numpy/typing/tests/data/pass/comparisons.py247
-rw-r--r--numpy/typing/tests/data/reveal/comparisons.py247
19 files changed, 606 insertions, 60 deletions
diff --git a/numpy/__init__.pyi b/numpy/__init__.pyi
index 2366e9b75..ad37979ed 100644
--- a/numpy/__init__.pyi
+++ b/numpy/__init__.pyi
@@ -47,6 +47,7 @@ from numpy.typing._callable import (
_FloatDivMod,
_ComplexOp,
_NumberOp,
+ _ComparisonOp,
)
from typing import (
@@ -1013,12 +1014,8 @@ class _ArrayOrScalarCommon:
def __repr__(self) -> str: ...
def __copy__(self: _ArraySelf) -> _ArraySelf: ...
def __deepcopy__(self: _ArraySelf, __memo: Optional[dict] = ...) -> _ArraySelf: ...
- def __lt__(self, other): ...
- def __le__(self, other): ...
def __eq__(self, other): ...
def __ne__(self, other): ...
- def __gt__(self, other): ...
- def __ge__(self, other): ...
def astype(
self: _ArraySelf,
dtype: DTypeLike,
@@ -1579,6 +1576,10 @@ class ndarray(_ArrayOrScalarCommon, Iterable, Sized, Container):
def __iter__(self) -> Any: ...
def __contains__(self, key) -> bool: ...
def __index__(self) -> int: ...
+ def __lt__(self, other: ArrayLike) -> Union[ndarray, bool_]: ...
+ def __le__(self, other: ArrayLike) -> Union[ndarray, bool_]: ...
+ def __gt__(self, other: ArrayLike) -> Union[ndarray, bool_]: ...
+ def __ge__(self, other: ArrayLike) -> Union[ndarray, bool_]: ...
def __matmul__(self, other: ArrayLike) -> Any: ...
# NOTE: `ndarray` does not implement `__imatmul__`
def __rmatmul__(self, other: ArrayLike) -> Any: ...
@@ -1689,6 +1690,10 @@ class number(generic, Generic[_NBit_co]): # type: ignore
__rpow__: _NumberOp
__truediv__: _NumberOp
__rtruediv__: _NumberOp
+ __lt__: _ComparisonOp[_NumberLike]
+ __le__: _ComparisonOp[_NumberLike]
+ __gt__: _ComparisonOp[_NumberLike]
+ __ge__: _ComparisonOp[_NumberLike]
class bool_(generic):
def __init__(self, __value: object = ...) -> None: ...
@@ -1727,6 +1732,10 @@ class bool_(generic):
__rmod__: _BoolMod
__divmod__: _BoolDivMod
__rdivmod__: _BoolDivMod
+ __lt__: _ComparisonOp[_NumberLike]
+ __le__: _ComparisonOp[_NumberLike]
+ __gt__: _ComparisonOp[_NumberLike]
+ __ge__: _ComparisonOp[_NumberLike]
class object_(generic):
def __init__(self, __value: object = ...) -> None: ...
@@ -1755,6 +1764,10 @@ class datetime64(generic):
@overload
def __sub__(self, other: Union[timedelta64, _IntLike, _BoolLike]) -> datetime64: ...
def __rsub__(self, other: datetime64) -> timedelta64: ...
+ __lt__: _ComparisonOp[datetime64]
+ __le__: _ComparisonOp[datetime64]
+ __gt__: _ComparisonOp[datetime64]
+ __ge__: _ComparisonOp[datetime64]
# Support for `__index__` was added in python 3.8 (bpo-20092)
if sys.version_info >= (3, 8):
@@ -1845,6 +1858,10 @@ class timedelta64(generic):
def __rmod__(self, other: timedelta64) -> timedelta64: ...
def __divmod__(self, other: timedelta64) -> Tuple[int64, timedelta64]: ...
def __rdivmod__(self, other: timedelta64) -> Tuple[int64, timedelta64]: ...
+ __lt__: _ComparisonOp[Union[timedelta64, _IntLike, _BoolLike]]
+ __le__: _ComparisonOp[Union[timedelta64, _IntLike, _BoolLike]]
+ __gt__: _ComparisonOp[Union[timedelta64, _IntLike, _BoolLike]]
+ __ge__: _ComparisonOp[Union[timedelta64, _IntLike, _BoolLike]]
class unsignedinteger(integer[_NBit_co]):
# NOTE: `uint64 + signedinteger -> float64`
diff --git a/numpy/core/fromnumeric.py b/numpy/core/fromnumeric.py
index d65e26827..efb052bc2 100644
--- a/numpy/core/fromnumeric.py
+++ b/numpy/core/fromnumeric.py
@@ -1375,7 +1375,7 @@ def resize(a, new_shape):
reshaped_array : ndarray
The new array is formed from the data in the old array, repeated
if necessary to fill out the required number of elements. The
- data are repeated in the order that they are stored in memory.
+ data are repeated iterating over the array in C-order.
See Also
--------
@@ -1392,11 +1392,11 @@ def resize(a, new_shape):
Warning: This functionality does **not** consider axes separately,
i.e. it does not apply interpolation/extrapolation.
- It fills the return array with the required number of elements, taken
- from `a` as they are laid out in memory, disregarding strides and axes.
- (This is in case the new shape is smaller. For larger, see above.)
- This functionality is therefore not suitable to resize images,
- or data where each axis represents a separate and distinct entity.
+ It fills the return array with the required number of elements, iterating
+ over `a` in C-order, disregarding axes (and cycling back from the start if
+ the new shape is larger). This functionality is therefore not suitable to
+ resize images, or data where each axis represents a separate and distinct
+ entity.
Examples
--------
diff --git a/numpy/core/include/numpy/numpyconfig.h b/numpy/core/include/numpy/numpyconfig.h
index e39303123..a1b1de0ef 100644
--- a/numpy/core/include/numpy/numpyconfig.h
+++ b/numpy/core/include/numpy/numpyconfig.h
@@ -42,5 +42,6 @@
#define NPY_1_18_API_VERSION 0x00000008
#define NPY_1_19_API_VERSION 0x00000008
#define NPY_1_20_API_VERSION 0x0000000e
+#define NPY_1_21_API_VERSION 0x0000000e
#endif
diff --git a/numpy/core/src/multiarray/_multiarray_tests.c.src b/numpy/core/src/multiarray/_multiarray_tests.c.src
index 3811e87a8..3c8caefce 100644
--- a/numpy/core/src/multiarray/_multiarray_tests.c.src
+++ b/numpy/core/src/multiarray/_multiarray_tests.c.src
@@ -677,11 +677,12 @@ create_custom_field_dtype(PyObject *NPY_UNUSED(mod), PyObject *args)
"invalid error argument to test function.");
}
if (PyArray_RegisterDataType(dtype) < 0) {
- /* Fix original type in the error_path == 2 case. */
+ /* Fix original type in the error_path == 2 case and delete it */
Py_SET_TYPE(dtype, original_type);
+ Py_DECREF(dtype);
return NULL;
}
- Py_INCREF(dtype);
+ Py_INCREF(dtype); /* hold on to the original (leaks a reference) */
return (PyObject *)dtype;
}
diff --git a/numpy/core/src/multiarray/compiled_base.c b/numpy/core/src/multiarray/compiled_base.c
index 061db2250..8ab592015 100644
--- a/numpy/core/src/multiarray/compiled_base.c
+++ b/numpy/core/src/multiarray/compiled_base.c
@@ -1420,7 +1420,7 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
{
PyObject *obj;
PyObject *str;
- #if (PY_VERSION_HEX >= 0x030700A2)
+ #if PY_VERSION_HEX >= 0x030700A2 && (!defined(PYPY_VERSION_NUM) || PYPY_VERSION_NUM > 0x07030300)
const char *docstr;
#else
char *docstr;
diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c
index cb5c3823d..d64962f87 100644
--- a/numpy/core/src/multiarray/mapping.c
+++ b/numpy/core/src/multiarray/mapping.c
@@ -3194,9 +3194,10 @@ PyArray_MapIterNew(npy_index_info *indices , int index_num, int index_type,
}
PyObject *shape2 = convert_shape_to_string(mit->nd, mit->dimensions, "");
- if (shape2 == NULL)
+ if (shape2 == NULL) {
Py_DECREF(shape1);
goto finish;
+ }
PyErr_Format(PyExc_ValueError,
"shape mismatch: value array of shape %S could not be broadcast "
diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src
index d018fccbb..e480628e7 100644
--- a/numpy/core/src/multiarray/scalartypes.c.src
+++ b/numpy/core/src/multiarray/scalartypes.c.src
@@ -2395,6 +2395,10 @@ gentype_arrtype_getbuffer(PyObject *self, Py_buffer *view, int flags)
self);
return -1;
}
+ if ((flags & PyBUF_WRITEABLE) == PyBUF_WRITEABLE) {
+ PyErr_SetString(PyExc_BufferError, "scalar buffer is readonly");
+ return -1;
+ }
PyArray_Descr *descr = PyArray_DescrFromScalar(self);
if (descr == NULL) {
return -1;
@@ -2413,6 +2417,7 @@ gentype_arrtype_getbuffer(PyObject *self, Py_buffer *view, int flags)
view->shape = NULL;
view->strides = NULL;
view->suboffsets = NULL;
+ view->readonly = 1; /* assume general (user) scalars are readonly. */
Py_INCREF(self);
view->obj = self;
view->buf = scalar_value(self, descr);
@@ -2444,6 +2449,7 @@ static int
@name@_getbuffer(PyObject *self, Py_buffer *view, int flags)
{
if ((flags & PyBUF_WRITEABLE) == PyBUF_WRITEABLE) {
+ PyErr_SetString(PyExc_BufferError, "scalar buffer is readonly");
return -1;
}
Py@Name@ScalarObject *scalar = (Py@Name@ScalarObject *)self;
@@ -2456,6 +2462,7 @@ static int
view->shape = NULL;
view->strides = NULL;
view->suboffsets = NULL;
+ view->readonly = 1;
Py_INCREF(self);
view->obj = self;
view->buf = &(scalar->obval);
@@ -2482,6 +2489,7 @@ static int
unicode_getbuffer(PyObject *self, Py_buffer *view, int flags)
{
if ((flags & PyBUF_WRITEABLE) == PyBUF_WRITEABLE) {
+ PyErr_SetString(PyExc_BufferError, "scalar buffer is readonly");
return -1;
}
PyUnicodeScalarObject *scalar = (PyUnicodeScalarObject *)self;
@@ -2493,6 +2501,7 @@ unicode_getbuffer(PyObject *self, Py_buffer *view, int flags)
view->shape = NULL;
view->strides = NULL;
view->suboffsets = NULL;
+ view->readonly = 1;
Py_INCREF(self);
view->obj = self;
@@ -2522,7 +2531,7 @@ unicode_getbuffer(PyObject *self, Py_buffer *view, int flags)
view->format = scalar->buffer_fmt;
}
else {
- scalar->buffer_fmt = PyObject_Malloc(22);
+ scalar->buffer_fmt = PyMem_Malloc(22);
if (scalar->buffer_fmt == NULL) {
Py_SETREF(view->obj, NULL);
return -1;
@@ -2549,6 +2558,7 @@ static int
@name@_getbuffer(PyObject *self, Py_buffer *view, int flags)
{
if ((flags & PyBUF_WRITEABLE) == PyBUF_WRITEABLE) {
+ PyErr_SetString(PyExc_BufferError, "scalar buffer is readonly");
return -1;
}
Py@Name@ScalarObject *scalar = (Py@Name@ScalarObject *)self;
@@ -2560,6 +2570,7 @@ static int
view->shape = &length;
view->strides = NULL;
view->suboffsets = NULL;
+ view->readonly = 1;
Py_INCREF(self);
view->obj = self;
@@ -2651,6 +2662,7 @@ unicode_arrtype_dealloc(PyObject *v)
{
/* note: may be null if it was never requested */
PyMem_Free(PyArrayScalar_VAL(v, Unicode));
+ PyMem_Free(((PyUnicodeScalarObject *)v)->buffer_fmt);
/* delegate to the base class */
PyUnicode_Type.tp_dealloc(v);
}
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index 12306cbb8..bd8c51ab7 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -7350,9 +7350,9 @@ class TestNewBufferProtocol:
def test_export_and_pickle_user_dtype(self, obj, error):
# User dtypes should export successfully when FORMAT was not requested.
with pytest.raises(error):
- _multiarray_tests.get_buffer_info(obj, ("STRIDED", "FORMAT"))
+ _multiarray_tests.get_buffer_info(obj, ("STRIDED_RO", "FORMAT"))
- _multiarray_tests.get_buffer_info(obj, ("STRIDED",))
+ _multiarray_tests.get_buffer_info(obj, ("STRIDED_RO",))
# This is currently also necessary to implement pickling:
pickle_obj = pickle.dumps(obj)
diff --git a/numpy/core/tests/test_scalarbuffer.py b/numpy/core/tests/test_scalarbuffer.py
index 574c56864..851cd3081 100644
--- a/numpy/core/tests/test_scalarbuffer.py
+++ b/numpy/core/tests/test_scalarbuffer.py
@@ -3,6 +3,7 @@ Test scalar buffer interface adheres to PEP 3118
"""
import numpy as np
from numpy.core._rational_tests import rational
+from numpy.core._multiarray_tests import get_buffer_info
import pytest
from numpy.testing import assert_, assert_equal, assert_raises
@@ -52,10 +53,20 @@ class TestScalarPEP3118:
assert_equal(mv_x.suboffsets, ())
@pytest.mark.parametrize('scalar, code', scalars_and_codes, ids=codes_only)
- def test_scalar_known_code(self, scalar, code):
+ def test_scalar_code_and_properties(self, scalar, code):
x = scalar()
+ expected = dict(strides=(), itemsize=x.dtype.itemsize, ndim=0,
+ shape=(), format=code, readonly=True)
+
mv_x = memoryview(x)
- assert_equal(mv_x.format, code)
+ print(mv_x.readonly, self._as_dict(mv_x))
+ assert self._as_dict(mv_x) == expected
+
+ @pytest.mark.parametrize('scalar', scalars_only, ids=codes_only)
+ def test_scalar_buffers_readonly(self, scalar):
+ x = scalar()
+ with pytest.raises(BufferError, match="scalar buffer is readonly"):
+ get_buffer_info(x, ["WRITABLE"])
def test_void_scalar_structured_data(self):
dt = np.dtype([('name', np.unicode_, 16), ('grades', np.float64, (2,))])
@@ -77,9 +88,14 @@ class TestScalarPEP3118:
assert_equal(mv_x.itemsize, mv_a.itemsize)
assert_equal(mv_x.format, mv_a.format)
+ # Check that we do not allow writeable buffer export (technically
+ # we could allow it sometimes here...)
+ with pytest.raises(BufferError, match="scalar buffer is readonly"):
+ get_buffer_info(x, ["WRITABLE"])
+
def _as_dict(self, m):
return dict(strides=m.strides, shape=m.shape, itemsize=m.itemsize,
- ndim=m.ndim, format=m.format)
+ ndim=m.ndim, format=m.format, readonly=m.readonly)
def test_datetime_memoryview(self):
# gh-11656
@@ -88,7 +104,7 @@ class TestScalarPEP3118:
dt1 = np.datetime64('2016-01-01')
dt2 = np.datetime64('2017-01-01')
expected = dict(strides=(1,), itemsize=1, ndim=1, shape=(8,),
- format='B')
+ format='B', readonly=True)
v = memoryview(dt1)
assert self._as_dict(v) == expected
@@ -100,6 +116,10 @@ class TestScalarPEP3118:
# Fails to create a PEP 3118 valid buffer
assert_raises((ValueError, BufferError), memoryview, a[0])
+ # Check that we do not allow writeable buffer export
+ with pytest.raises(BufferError, match="scalar buffer is readonly"):
+ get_buffer_info(dt1, ["WRITABLE"])
+
@pytest.mark.parametrize('s', [
pytest.param("\x32\x32", id="ascii"),
pytest.param("\uFE0F\uFE0F", id="basic multilingual"),
@@ -109,7 +129,8 @@ class TestScalarPEP3118:
s = np.str_(s) # only our subclass implements the buffer protocol
# all the same, characters always encode as ucs4
- expected = dict(strides=(), itemsize=8, ndim=0, shape=(), format='2w')
+ expected = dict(strides=(), itemsize=8, ndim=0, shape=(), format='2w',
+ readonly=True)
v = memoryview(s)
assert self._as_dict(v) == expected
@@ -119,7 +140,15 @@ class TestScalarPEP3118:
assert_equal(code_points, [ord(c) for c in s])
+ # Check that we do not allow writeable buffer export
+ with pytest.raises(BufferError, match="scalar buffer is readonly"):
+ get_buffer_info(s, ["WRITABLE"])
+
def test_user_scalar_fails_buffer(self):
r = rational(1)
with assert_raises(TypeError):
memoryview(r)
+
+ # Check that we do not allow writeable buffer export
+ with pytest.raises(BufferError, match="scalar buffer is readonly"):
+ get_buffer_info(r, ["WRITABLE"]) \ No newline at end of file
diff --git a/numpy/f2py/__version__.py b/numpy/f2py/__version__.py
index 104c2e1a8..e20d7c1db 100644
--- a/numpy/f2py/__version__.py
+++ b/numpy/f2py/__version__.py
@@ -1,8 +1 @@
-major = 2
-
-try:
- from __svn_version__ import version
- version_info = (major, version)
- version = '%s_%s' % version_info
-except (ImportError, ValueError):
- version = str(major)
+from numpy.version import version
diff --git a/numpy/f2py/capi_maps.py b/numpy/f2py/capi_maps.py
index fabbfc4c2..472ddde43 100644
--- a/numpy/f2py/capi_maps.py
+++ b/numpy/f2py/capi_maps.py
@@ -11,8 +11,6 @@ $Date: 2005/05/06 10:57:33 $
Pearu Peterson
"""
-__version__ = "$Revision: 1.60 $"[10:-1]
-
from . import __version__
f2py_version = __version__.version
diff --git a/numpy/f2py/common_rules.py b/numpy/f2py/common_rules.py
index 90483e55b..937d8bc72 100644
--- a/numpy/f2py/common_rules.py
+++ b/numpy/f2py/common_rules.py
@@ -13,8 +13,6 @@ $Date: 2005/05/06 10:57:33 $
Pearu Peterson
"""
-__version__ = "$Revision: 1.19 $"[10:-1]
-
from . import __version__
f2py_version = __version__.version
diff --git a/numpy/f2py/f2py2e.py b/numpy/f2py/f2py2e.py
index be2c345d1..b45d985aa 100755
--- a/numpy/f2py/f2py2e.py
+++ b/numpy/f2py/f2py2e.py
@@ -29,18 +29,14 @@ from . import __version__
from . import capi_maps
f2py_version = __version__.version
+numpy_version = __version__.version
errmess = sys.stderr.write
# outmess=sys.stdout.write
show = pprint.pprint
outmess = auxfuncs.outmess
-try:
- from numpy import __version__ as numpy_version
-except ImportError:
- numpy_version = 'N/A'
-
-__usage__ = """\
-Usage:
+__usage__ =\
+f"""Usage:
1) To construct extension module sources:
@@ -97,8 +93,8 @@ Options:
--[no-]latex-doc Create (or not) <modulename>module.tex.
Default is --no-latex-doc.
--short-latex Create 'incomplete' LaTeX document (without commands
- \\documentclass, \\tableofcontents, and \\begin{document},
- \\end{document}).
+ \\documentclass, \\tableofcontents, and \\begin{{document}},
+ \\end{{document}}).
--[no-]rest-doc Create (or not) <modulename>module.rst.
Default is --no-rest-doc.
@@ -167,12 +163,12 @@ Extra options (only effective with -c):
array. Integer <int> sets the threshold for array sizes when
a message should be shown.
-Version: %s
-numpy Version: %s
+Version: {f2py_version}
+numpy Version: {numpy_version}
Requires: Python 3.5 or higher.
License: NumPy license (see LICENSE.txt in the NumPy source code)
Copyright 1999 - 2011 Pearu Peterson all rights reserved.
-http://cens.ioc.ee/projects/f2py2e/""" % (f2py_version, numpy_version)
+http://cens.ioc.ee/projects/f2py2e/"""
def scaninputline(inputline):
diff --git a/numpy/f2py/rules.py b/numpy/f2py/rules.py
index a14f60194..f1490527e 100755
--- a/numpy/f2py/rules.py
+++ b/numpy/f2py/rules.py
@@ -50,18 +50,15 @@ $Date: 2005/08/30 08:58:42 $
Pearu Peterson
"""
-__version__ = "$Revision: 1.129 $"[10:-1]
-
-from . import __version__
-f2py_version = __version__.version
-
-from .. import version as _numpy_version
-numpy_version = _numpy_version.version
-
import os
import time
import copy
+# __version__.version is now the same as the NumPy version
+from . import __version__
+f2py_version = __version__.version
+numpy_version = __version__.version
+
from .auxfuncs import (
applyrules, debugcapi, dictappend, errmess, gentitle, getargs2,
hascallstatement, hasexternals, hasinitvalue, hasnote, hasresultnote,
@@ -202,7 +199,7 @@ PyMODINIT_FUNC PyInit_#modulename#(void) {
\tif (PyErr_Occurred())
\t\t{PyErr_SetString(PyExc_ImportError, \"can't initialize module #modulename# (failed to import numpy)\"); return m;}
\td = PyModule_GetDict(m);
-\ts = PyUnicode_FromString(\"$R""" + """evision: $\");
+\ts = PyUnicode_FromString(\"#f2py_version#\");
\tPyDict_SetItemString(d, \"__version__\", s);
\tPy_DECREF(s);
\ts = PyUnicode_FromString(
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
index 984f3086e..696fe617b 100644
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -1290,7 +1290,7 @@ def _interp_dispatcher(x, xp, fp, left=None, right=None, period=None):
@array_function_dispatch(_interp_dispatcher)
def interp(x, xp, fp, left=None, right=None, period=None):
"""
- One-dimensional linear interpolation.
+ One-dimensional linear interpolation for monotonically increasing sample points.
Returns the one-dimensional piecewise linear interpolant to a function
with given discrete data points (`xp`, `fp`), evaluated at `x`.
@@ -1337,8 +1337,8 @@ def interp(x, xp, fp, left=None, right=None, period=None):
--------
scipy.interpolate
- Notes
- -----
+ Warnings
+ --------
The x-coordinate sequence is expected to be increasing, but this is not
explicitly enforced. However, if the sequence `xp` is non-increasing,
interpolation results are meaningless.
diff --git a/numpy/tests/test_scripts.py b/numpy/tests/test_scripts.py
index a0f2ba70a..e67a82947 100644
--- a/numpy/tests/test_scripts.py
+++ b/numpy/tests/test_scripts.py
@@ -38,9 +38,9 @@ def find_f2py_commands():
def test_f2py(f2py_cmd):
# test that we can run f2py script
stdout = subprocess.check_output([f2py_cmd, '-v'])
- assert_equal(stdout.strip(), b'2')
+ assert_equal(stdout.strip(), np.__version__.encode('ascii'))
def test_pep338():
stdout = subprocess.check_output([sys.executable, '-mnumpy.f2py', '-v'])
- assert_equal(stdout.strip(), b'2')
+ assert_equal(stdout.strip(), np.__version__.encode('ascii'))
diff --git a/numpy/typing/_callable.py b/numpy/typing/_callable.py
index 91b7a4ec2..c703df28a 100644
--- a/numpy/typing/_callable.py
+++ b/numpy/typing/_callable.py
@@ -20,6 +20,7 @@ from typing import (
)
from numpy import (
+ ndarray,
generic,
bool_,
timedelta64,
@@ -41,6 +42,7 @@ from ._scalars import (
_NumberLike,
)
from . import NBitBase
+from ._array_like import ArrayLike
if sys.version_info >= (3, 8):
from typing import Protocol
@@ -312,6 +314,12 @@ if TYPE_CHECKING or HAVE_PROTOCOL:
class _NumberOp(Protocol):
def __call__(self, __other: _NumberLike) -> number: ...
+ class _ComparisonOp(Protocol[_T]):
+ @overload
+ def __call__(self, __other: _T) -> bool_: ...
+ @overload
+ def __call__(self, __other: ArrayLike) -> Union[ndarray, bool_]: ...
+
else:
_BoolOp = Any
_BoolBitOp = Any
@@ -334,3 +342,4 @@ else:
_FloatDivMod = Any
_ComplexOp = Any
_NumberOp = Any
+ _ComparisonOp = Any
diff --git a/numpy/typing/tests/data/pass/comparisons.py b/numpy/typing/tests/data/pass/comparisons.py
new file mode 100644
index 000000000..b298117a6
--- /dev/null
+++ b/numpy/typing/tests/data/pass/comparisons.py
@@ -0,0 +1,247 @@
+import numpy as np
+
+c16 = np.complex128()
+f8 = np.float64()
+i8 = np.int64()
+u8 = np.uint64()
+
+c8 = np.complex64()
+f4 = np.float32()
+i4 = np.int32()
+u4 = np.uint32()
+
+dt = np.datetime64(0, "D")
+td = np.timedelta64(0, "D")
+
+b_ = np.bool_()
+
+b = bool()
+c = complex()
+f = float()
+i = int()
+
+AR = np.array([0], dtype=np.int64)
+AR.setflags(write=False)
+
+SEQ = (0, 1, 2, 3, 4)
+
+# Time structures
+
+dt > dt
+
+td > td
+td > i
+td > i4
+td > i8
+td > AR
+td > SEQ
+
+# boolean
+
+b_ > b
+b_ > b_
+b_ > i
+b_ > i8
+b_ > i4
+b_ > u8
+b_ > u4
+b_ > f
+b_ > f8
+b_ > f4
+b_ > c
+b_ > c16
+b_ > c8
+b_ > AR
+b_ > SEQ
+
+# Complex
+
+c16 > c16
+c16 > f8
+c16 > i8
+c16 > c8
+c16 > f4
+c16 > i4
+c16 > b_
+c16 > b
+c16 > c
+c16 > f
+c16 > i
+c16 > AR
+c16 > SEQ
+
+c16 > c16
+f8 > c16
+i8 > c16
+c8 > c16
+f4 > c16
+i4 > c16
+b_ > c16
+b > c16
+c > c16
+f > c16
+i > c16
+AR > c16
+SEQ > c16
+
+c8 > c16
+c8 > f8
+c8 > i8
+c8 > c8
+c8 > f4
+c8 > i4
+c8 > b_
+c8 > b
+c8 > c
+c8 > f
+c8 > i
+c8 > AR
+c8 > SEQ
+
+c16 > c8
+f8 > c8
+i8 > c8
+c8 > c8
+f4 > c8
+i4 > c8
+b_ > c8
+b > c8
+c > c8
+f > c8
+i > c8
+AR > c8
+SEQ > c8
+
+# Float
+
+f8 > f8
+f8 > i8
+f8 > f4
+f8 > i4
+f8 > b_
+f8 > b
+f8 > c
+f8 > f
+f8 > i
+f8 > AR
+f8 > SEQ
+
+f8 > f8
+i8 > f8
+f4 > f8
+i4 > f8
+b_ > f8
+b > f8
+c > f8
+f > f8
+i > f8
+AR > f8
+SEQ > f8
+
+f4 > f8
+f4 > i8
+f4 > f4
+f4 > i4
+f4 > b_
+f4 > b
+f4 > c
+f4 > f
+f4 > i
+f4 > AR
+f4 > SEQ
+
+f8 > f4
+i8 > f4
+f4 > f4
+i4 > f4
+b_ > f4
+b > f4
+c > f4
+f > f4
+i > f4
+AR > f4
+SEQ > f4
+
+# Int
+
+i8 > i8
+i8 > u8
+i8 > i4
+i8 > u4
+i8 > b_
+i8 > b
+i8 > c
+i8 > f
+i8 > i
+i8 > AR
+i8 > SEQ
+
+u8 > u8
+u8 > i4
+u8 > u4
+u8 > b_
+u8 > b
+u8 > c
+u8 > f
+u8 > i
+u8 > AR
+u8 > SEQ
+
+i8 > i8
+u8 > i8
+i4 > i8
+u4 > i8
+b_ > i8
+b > i8
+c > i8
+f > i8
+i > i8
+AR > i8
+SEQ > i8
+
+u8 > u8
+i4 > u8
+u4 > u8
+b_ > u8
+b > u8
+c > u8
+f > u8
+i > u8
+AR > u8
+SEQ > u8
+
+i4 > i8
+i4 > i4
+i4 > i
+i4 > b_
+i4 > b
+i4 > AR
+i4 > SEQ
+
+u4 > i8
+u4 > i4
+u4 > u8
+u4 > u4
+u4 > i
+u4 > b_
+u4 > b
+u4 > AR
+u4 > SEQ
+
+i8 > i4
+i4 > i4
+i > i4
+b_ > i4
+b > i4
+AR > i4
+SEQ > i4
+
+i8 > u4
+i4 > u4
+u8 > u4
+u4 > u4
+b_ > u4
+b > u4
+i > u4
+AR > u4
+SEQ > u4
diff --git a/numpy/typing/tests/data/reveal/comparisons.py b/numpy/typing/tests/data/reveal/comparisons.py
new file mode 100644
index 000000000..82d1fa6de
--- /dev/null
+++ b/numpy/typing/tests/data/reveal/comparisons.py
@@ -0,0 +1,247 @@
+import numpy as np
+
+c16 = np.complex128()
+f8 = np.float64()
+i8 = np.int64()
+u8 = np.uint64()
+
+c8 = np.complex64()
+f4 = np.float32()
+i4 = np.int32()
+u4 = np.uint32()
+
+dt = np.datetime64(0, "D")
+td = np.timedelta64(0, "D")
+
+b_ = np.bool_()
+
+b = bool()
+c = complex()
+f = float()
+i = int()
+
+AR = np.array([0], dtype=np.int64)
+AR.setflags(write=False)
+
+SEQ = (0, 1, 2, 3, 4)
+
+# Time structures
+
+reveal_type(dt > dt) # E: numpy.bool_
+
+reveal_type(td > td) # E: numpy.bool_
+reveal_type(td > i) # E: numpy.bool_
+reveal_type(td > i4) # E: numpy.bool_
+reveal_type(td > i8) # E: numpy.bool_
+reveal_type(td > AR) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(td > SEQ) # E: Union[numpy.ndarray, numpy.bool_]
+
+# boolean
+
+reveal_type(b_ > b) # E: numpy.bool_
+reveal_type(b_ > b_) # E: numpy.bool_
+reveal_type(b_ > i) # E: numpy.bool_
+reveal_type(b_ > i8) # E: numpy.bool_
+reveal_type(b_ > i4) # E: numpy.bool_
+reveal_type(b_ > u8) # E: numpy.bool_
+reveal_type(b_ > u4) # E: numpy.bool_
+reveal_type(b_ > f) # E: numpy.bool_
+reveal_type(b_ > f8) # E: numpy.bool_
+reveal_type(b_ > f4) # E: numpy.bool_
+reveal_type(b_ > c) # E: numpy.bool_
+reveal_type(b_ > c16) # E: numpy.bool_
+reveal_type(b_ > c8) # E: numpy.bool_
+reveal_type(b_ > AR) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(b_ > SEQ) # E: Union[numpy.ndarray, numpy.bool_]
+
+# Complex
+
+reveal_type(c16 > c16) # E: numpy.bool_
+reveal_type(c16 > f8) # E: numpy.bool_
+reveal_type(c16 > i8) # E: numpy.bool_
+reveal_type(c16 > c8) # E: numpy.bool_
+reveal_type(c16 > f4) # E: numpy.bool_
+reveal_type(c16 > i4) # E: numpy.bool_
+reveal_type(c16 > b_) # E: numpy.bool_
+reveal_type(c16 > b) # E: numpy.bool_
+reveal_type(c16 > c) # E: numpy.bool_
+reveal_type(c16 > f) # E: numpy.bool_
+reveal_type(c16 > i) # E: numpy.bool_
+reveal_type(c16 > AR) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(c16 > SEQ) # E: Union[numpy.ndarray, numpy.bool_]
+
+reveal_type(c16 > c16) # E: numpy.bool_
+reveal_type(f8 > c16) # E: numpy.bool_
+reveal_type(i8 > c16) # E: numpy.bool_
+reveal_type(c8 > c16) # E: numpy.bool_
+reveal_type(f4 > c16) # E: numpy.bool_
+reveal_type(i4 > c16) # E: numpy.bool_
+reveal_type(b_ > c16) # E: numpy.bool_
+reveal_type(b > c16) # E: numpy.bool_
+reveal_type(c > c16) # E: numpy.bool_
+reveal_type(f > c16) # E: numpy.bool_
+reveal_type(i > c16) # E: numpy.bool_
+reveal_type(AR > c16) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(SEQ > c16) # E: Union[numpy.ndarray, numpy.bool_]
+
+reveal_type(c8 > c16) # E: numpy.bool_
+reveal_type(c8 > f8) # E: numpy.bool_
+reveal_type(c8 > i8) # E: numpy.bool_
+reveal_type(c8 > c8) # E: numpy.bool_
+reveal_type(c8 > f4) # E: numpy.bool_
+reveal_type(c8 > i4) # E: numpy.bool_
+reveal_type(c8 > b_) # E: numpy.bool_
+reveal_type(c8 > b) # E: numpy.bool_
+reveal_type(c8 > c) # E: numpy.bool_
+reveal_type(c8 > f) # E: numpy.bool_
+reveal_type(c8 > i) # E: numpy.bool_
+reveal_type(c8 > AR) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(c8 > SEQ) # E: Union[numpy.ndarray, numpy.bool_]
+
+reveal_type(c16 > c8) # E: numpy.bool_
+reveal_type(f8 > c8) # E: numpy.bool_
+reveal_type(i8 > c8) # E: numpy.bool_
+reveal_type(c8 > c8) # E: numpy.bool_
+reveal_type(f4 > c8) # E: numpy.bool_
+reveal_type(i4 > c8) # E: numpy.bool_
+reveal_type(b_ > c8) # E: numpy.bool_
+reveal_type(b > c8) # E: numpy.bool_
+reveal_type(c > c8) # E: numpy.bool_
+reveal_type(f > c8) # E: numpy.bool_
+reveal_type(i > c8) # E: numpy.bool_
+reveal_type(AR > c8) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(SEQ > c8) # E: Union[numpy.ndarray, numpy.bool_]
+
+# Float
+
+reveal_type(f8 > f8) # E: numpy.bool_
+reveal_type(f8 > i8) # E: numpy.bool_
+reveal_type(f8 > f4) # E: numpy.bool_
+reveal_type(f8 > i4) # E: numpy.bool_
+reveal_type(f8 > b_) # E: numpy.bool_
+reveal_type(f8 > b) # E: numpy.bool_
+reveal_type(f8 > c) # E: numpy.bool_
+reveal_type(f8 > f) # E: numpy.bool_
+reveal_type(f8 > i) # E: numpy.bool_
+reveal_type(f8 > AR) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(f8 > SEQ) # E: Union[numpy.ndarray, numpy.bool_]
+
+reveal_type(f8 > f8) # E: numpy.bool_
+reveal_type(i8 > f8) # E: numpy.bool_
+reveal_type(f4 > f8) # E: numpy.bool_
+reveal_type(i4 > f8) # E: numpy.bool_
+reveal_type(b_ > f8) # E: numpy.bool_
+reveal_type(b > f8) # E: numpy.bool_
+reveal_type(c > f8) # E: numpy.bool_
+reveal_type(f > f8) # E: numpy.bool_
+reveal_type(i > f8) # E: numpy.bool_
+reveal_type(AR > f8) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(SEQ > f8) # E: Union[numpy.ndarray, numpy.bool_]
+
+reveal_type(f4 > f8) # E: numpy.bool_
+reveal_type(f4 > i8) # E: numpy.bool_
+reveal_type(f4 > f4) # E: numpy.bool_
+reveal_type(f4 > i4) # E: numpy.bool_
+reveal_type(f4 > b_) # E: numpy.bool_
+reveal_type(f4 > b) # E: numpy.bool_
+reveal_type(f4 > c) # E: numpy.bool_
+reveal_type(f4 > f) # E: numpy.bool_
+reveal_type(f4 > i) # E: numpy.bool_
+reveal_type(f4 > AR) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(f4 > SEQ) # E: Union[numpy.ndarray, numpy.bool_]
+
+reveal_type(f8 > f4) # E: numpy.bool_
+reveal_type(i8 > f4) # E: numpy.bool_
+reveal_type(f4 > f4) # E: numpy.bool_
+reveal_type(i4 > f4) # E: numpy.bool_
+reveal_type(b_ > f4) # E: numpy.bool_
+reveal_type(b > f4) # E: numpy.bool_
+reveal_type(c > f4) # E: numpy.bool_
+reveal_type(f > f4) # E: numpy.bool_
+reveal_type(i > f4) # E: numpy.bool_
+reveal_type(AR > f4) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(SEQ > f4) # E: Union[numpy.ndarray, numpy.bool_]
+
+# Int
+
+reveal_type(i8 > i8) # E: numpy.bool_
+reveal_type(i8 > u8) # E: numpy.bool_
+reveal_type(i8 > i4) # E: numpy.bool_
+reveal_type(i8 > u4) # E: numpy.bool_
+reveal_type(i8 > b_) # E: numpy.bool_
+reveal_type(i8 > b) # E: numpy.bool_
+reveal_type(i8 > c) # E: numpy.bool_
+reveal_type(i8 > f) # E: numpy.bool_
+reveal_type(i8 > i) # E: numpy.bool_
+reveal_type(i8 > AR) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(i8 > SEQ) # E: Union[numpy.ndarray, numpy.bool_]
+
+reveal_type(u8 > u8) # E: numpy.bool_
+reveal_type(u8 > i4) # E: numpy.bool_
+reveal_type(u8 > u4) # E: numpy.bool_
+reveal_type(u8 > b_) # E: numpy.bool_
+reveal_type(u8 > b) # E: numpy.bool_
+reveal_type(u8 > c) # E: numpy.bool_
+reveal_type(u8 > f) # E: numpy.bool_
+reveal_type(u8 > i) # E: numpy.bool_
+reveal_type(u8 > AR) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(u8 > SEQ) # E: Union[numpy.ndarray, numpy.bool_]
+
+reveal_type(i8 > i8) # E: numpy.bool_
+reveal_type(u8 > i8) # E: numpy.bool_
+reveal_type(i4 > i8) # E: numpy.bool_
+reveal_type(u4 > i8) # E: numpy.bool_
+reveal_type(b_ > i8) # E: numpy.bool_
+reveal_type(b > i8) # E: numpy.bool_
+reveal_type(c > i8) # E: numpy.bool_
+reveal_type(f > i8) # E: numpy.bool_
+reveal_type(i > i8) # E: numpy.bool_
+reveal_type(AR > i8) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(SEQ > i8) # E: Union[numpy.ndarray, numpy.bool_]
+
+reveal_type(u8 > u8) # E: numpy.bool_
+reveal_type(i4 > u8) # E: numpy.bool_
+reveal_type(u4 > u8) # E: numpy.bool_
+reveal_type(b_ > u8) # E: numpy.bool_
+reveal_type(b > u8) # E: numpy.bool_
+reveal_type(c > u8) # E: numpy.bool_
+reveal_type(f > u8) # E: numpy.bool_
+reveal_type(i > u8) # E: numpy.bool_
+reveal_type(AR > u8) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(SEQ > u8) # E: Union[numpy.ndarray, numpy.bool_]
+
+reveal_type(i4 > i8) # E: numpy.bool_
+reveal_type(i4 > i4) # E: numpy.bool_
+reveal_type(i4 > i) # E: numpy.bool_
+reveal_type(i4 > b_) # E: numpy.bool_
+reveal_type(i4 > b) # E: numpy.bool_
+reveal_type(i4 > AR) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(i4 > SEQ) # E: Union[numpy.ndarray, numpy.bool_]
+
+reveal_type(u4 > i8) # E: numpy.bool_
+reveal_type(u4 > i4) # E: numpy.bool_
+reveal_type(u4 > u8) # E: numpy.bool_
+reveal_type(u4 > u4) # E: numpy.bool_
+reveal_type(u4 > i) # E: numpy.bool_
+reveal_type(u4 > b_) # E: numpy.bool_
+reveal_type(u4 > b) # E: numpy.bool_
+reveal_type(u4 > AR) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(u4 > SEQ) # E: Union[numpy.ndarray, numpy.bool_]
+
+reveal_type(i8 > i4) # E: numpy.bool_
+reveal_type(i4 > i4) # E: numpy.bool_
+reveal_type(i > i4) # E: numpy.bool_
+reveal_type(b_ > i4) # E: numpy.bool_
+reveal_type(b > i4) # E: numpy.bool_
+reveal_type(AR > i4) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(SEQ > i4) # E: Union[numpy.ndarray, numpy.bool_]
+
+reveal_type(i8 > u4) # E: numpy.bool_
+reveal_type(i4 > u4) # E: numpy.bool_
+reveal_type(u8 > u4) # E: numpy.bool_
+reveal_type(u4 > u4) # E: numpy.bool_
+reveal_type(b_ > u4) # E: numpy.bool_
+reveal_type(b > u4) # E: numpy.bool_
+reveal_type(i > u4) # E: numpy.bool_
+reveal_type(AR > u4) # E: Union[numpy.ndarray, numpy.bool_]
+reveal_type(SEQ > u4) # E: Union[numpy.ndarray, numpy.bool_]