diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2015-03-12 16:30:16 -0400 |
---|---|---|
committer | Charles Harris <charlesr.harris@gmail.com> | 2015-03-12 16:30:16 -0400 |
commit | 27c68a30de03fbf65bc949e014851644f436fda8 (patch) | |
tree | f0ff75af99707e42dd20c8fe493c7a30a2c7a013 /numpy/core | |
parent | a866fdd2c9481de18241a27778679013042d5349 (diff) | |
parent | 3a39a0e6ac0d85d3365c0671d8010441180a7d95 (diff) | |
download | numpy-27c68a30de03fbf65bc949e014851644f436fda8.tar.gz |
Merge pull request #5659 from jaimefrio/strict_out_check
ENH: Strict checking of ufunc keyword argument names
Diffstat (limited to 'numpy/core')
-rw-r--r-- | numpy/core/src/umath/ufunc_object.c | 25 | ||||
-rw-r--r-- | numpy/core/tests/test_ufunc.py | 23 |
2 files changed, 39 insertions, 9 deletions
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index 5e4a49553..3e52aa764 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -808,6 +808,7 @@ get_ufunc_arguments(PyUFuncObject *ufunc, int type_num; int any_flexible = 0, any_object = 0, any_flexible_userloops = 0; + int has_sig = 0; ufunc_name = ufunc->name ? ufunc->name : "<unnamed ufunc>"; @@ -945,7 +946,7 @@ get_ufunc_arguments(PyUFuncObject *ufunc, switch (str[0]) { case 'c': /* Provides a policy for allowed casting */ - if (strncmp(str, "casting", 7) == 0) { + if (strcmp(str, "casting") == 0) { if (!PyArray_CastingConverter(value, out_casting)) { goto fail; } @@ -954,7 +955,7 @@ get_ufunc_arguments(PyUFuncObject *ufunc, break; case 'd': /* Another way to specify 'sig' */ - if (strncmp(str, "dtype", 5) == 0) { + if (strcmp(str, "dtype") == 0) { /* Allow this parameter to be None */ PyArray_Descr *dtype; if (!PyArray_DescrConverter2(value, &dtype)) { @@ -976,7 +977,7 @@ get_ufunc_arguments(PyUFuncObject *ufunc, * Overrides the global parameters buffer size, * error mask, and error object */ - if (strncmp(str, "extobj", 6) == 0) { + if (strcmp(str, "extobj") == 0) { *out_extobj = value; bad_arg = 0; } @@ -987,7 +988,7 @@ get_ufunc_arguments(PyUFuncObject *ufunc, * either as a single array or None for single output * ufuncs, or as a tuple of arrays and Nones. */ - if (strncmp(str, "out", 3) == 0) { + if (strcmp(str, "out") == 0) { if (nargs > nin) { PyErr_SetString(PyExc_ValueError, "cannot specify 'out' as both a " @@ -1048,7 +1049,7 @@ get_ufunc_arguments(PyUFuncObject *ufunc, bad_arg = 0; } /* Allows the default output layout to be overridden */ - else if (strncmp(str,"order",5) == 0) { + else if (strcmp(str, "order") == 0) { if (!PyArray_OrderConverter(value, out_order)) { goto fail; } @@ -1057,7 +1058,13 @@ get_ufunc_arguments(PyUFuncObject *ufunc, break; case 's': /* Allows a specific function inner loop to be selected */ - if (strncmp(str,"sig",3) == 0) { + if (strcmp(str, "sig") == 0 || + strcmp(str, "signature") == 0) { + if (has_sig == 1) { + PyErr_SetString(PyExc_ValueError, + "cannot specify both 'sig' and 'signature'"); + goto fail; + } if (*out_typetup != NULL) { PyErr_SetString(PyExc_RuntimeError, "cannot specify both 'sig' and 'dtype'"); @@ -1066,8 +1073,9 @@ get_ufunc_arguments(PyUFuncObject *ufunc, *out_typetup = value; Py_INCREF(value); bad_arg = 0; + has_sig = 1; } - else if (strncmp(str,"subok",5) == 0) { + else if (strcmp(str, "subok") == 0) { if (!PyBool_Check(value)) { PyErr_SetString(PyExc_TypeError, "'subok' must be a boolean"); @@ -1082,8 +1090,7 @@ get_ufunc_arguments(PyUFuncObject *ufunc, * Provides a boolean array 'where=' mask if * out_wheremask is supplied. */ - if (out_wheremask != NULL && - strncmp(str,"where",5) == 0) { + if (out_wheremask != NULL && strcmp(str, "where") == 0) { PyArray_Descr *dtype; dtype = PyArray_DescrFromType(NPY_BOOL); if (dtype == NULL) { diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py index a285d5334..ab885bbf0 100644 --- a/numpy/core/tests/test_ufunc.py +++ b/numpy/core/tests/test_ufunc.py @@ -9,6 +9,29 @@ import numpy.core.operand_flag_tests as opflag_tests from numpy.compat import asbytes from numpy.core.test_rational import * + +class TestUfuncKwargs(TestCase): + def test_kwarg_exact(self): + assert_raises(TypeError, np.add, 1, 2, castingx='safe') + assert_raises(TypeError, np.add, 1, 2, dtypex=np.int) + assert_raises(TypeError, np.add, 1, 2, extobjx=[4096]) + assert_raises(TypeError, np.add, 1, 2, outx=None) + assert_raises(TypeError, np.add, 1, 2, sigx='ii->i') + assert_raises(TypeError, np.add, 1, 2, signaturex='ii->i') + assert_raises(TypeError, np.add, 1, 2, subokx=False) + assert_raises(TypeError, np.add, 1, 2, wherex=[True]) + + def test_sig_signature(self): + assert_raises(ValueError, np.add, 1, 2, sig='ii->i', + signature='ii->i') + + def test_sig_dtype(self): + assert_raises(RuntimeError, np.add, 1, 2, sig='ii->i', + dtype=np.int) + assert_raises(RuntimeError, np.add, 1, 2, signature='ii->i', + dtype=np.int) + + class TestUfunc(TestCase): def test_pickle(self): import pickle |