diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2021-02-09 12:58:19 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-09 12:58:19 -0700 |
commit | 2bdecde364f133ce94b7f9271a6d34a8fb5cae86 (patch) | |
tree | c247176207411a7c9a148c17cb6e6315c02b8ce3 | |
parent | 5c15cc3d76d171f07f9809a14a0dffd5ab37e599 (diff) | |
parent | 7df963b400f3dcf85e679e6f00af8c3c12971347 (diff) | |
download | numpy-2bdecde364f133ce94b7f9271a6d34a8fb5cae86.tar.gz |
Merge pull request #18375 from pearu/pearu/18341
BUG: fix regression in a hidden callback use case
-rw-r--r-- | numpy/distutils/command/config.py | 2 | ||||
-rw-r--r-- | numpy/f2py/cb_rules.py | 8 | ||||
-rw-r--r-- | numpy/f2py/tests/test_callback.py | 48 |
3 files changed, 57 insertions, 1 deletions
diff --git a/numpy/distutils/command/config.py b/numpy/distutils/command/config.py index 60881f4a3..8b735677a 100644 --- a/numpy/distutils/command/config.py +++ b/numpy/distutils/command/config.py @@ -92,6 +92,8 @@ class config(old_config): save_compiler = self.compiler if lang in ['f77', 'f90']: self.compiler = self.fcompiler + if self.compiler is None: + raise CompileError('%s compiler is not set' % (lang,)) try: ret = mth(*((self,)+args)) except (DistutilsExecError, CompileError) as e: diff --git a/numpy/f2py/cb_rules.py b/numpy/f2py/cb_rules.py index 60bc1ad11..62aa2fca9 100644 --- a/numpy/f2py/cb_rules.py +++ b/numpy/f2py/cb_rules.py @@ -70,7 +70,8 @@ static #name#_t *get_active_#name#(void) { /*typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);*/ #static# #rctype# #callbackname# (#optargs##args##strarglens##noargs#) { - #name#_t *cb; + #name#_t cb_local = { NULL, NULL, 0 }; + #name#_t *cb = NULL; PyTupleObject *capi_arglist = NULL; PyObject *capi_return = NULL; PyObject *capi_tmp = NULL; @@ -82,12 +83,17 @@ static #name#_t *get_active_#name#(void) { f2py_cb_start_clock(); #endif cb = get_active_#name#(); + if (cb == NULL) { + capi_longjmp_ok = 0; + cb = &cb_local; + } capi_arglist = cb->args_capi; CFUNCSMESS(\"cb:Call-back function #name# (maxnofargs=#maxnofargs#(-#nofoptargs#))\\n\"); CFUNCSMESSPY(\"cb:#name#_capi=\",cb->capi); if (cb->capi==NULL) { capi_longjmp_ok = 0; cb->capi = PyObject_GetAttrString(#modulename#_module,\"#argname#\"); + CFUNCSMESSPY(\"cb:#name#_capi=\",cb->capi); } if (cb->capi==NULL) { PyErr_SetString(#modulename#_error,\"cb: Callback #argname# not defined (as an argument or module #modulename# attribute).\\n\"); diff --git a/numpy/f2py/tests/test_callback.py b/numpy/f2py/tests/test_callback.py index 4d4f2b443..2cb429ec2 100644 --- a/numpy/f2py/tests/test_callback.py +++ b/numpy/f2py/tests/test_callback.py @@ -61,6 +61,21 @@ cf2py intent(out) a a = callback(cu, lencu) end + + subroutine hidden_callback(a, r) + external global_f +cf2py intent(callback, hide) global_f + integer a, r, global_f +cf2py intent(out) r + r = global_f(a) + end + + subroutine hidden_callback2(a, r) + external global_f + integer a, r, global_f +cf2py intent(out) r + r = global_f(a) + end """ @pytest.mark.parametrize('name', 't,t2'.split(',')) @@ -204,6 +219,39 @@ cf2py intent(out) a if errors: raise AssertionError(errors) + def test_hidden_callback(self): + try: + self.module.hidden_callback(2) + except Exception as msg: + assert_(str(msg).startswith('Callback global_f not defined')) + + try: + self.module.hidden_callback2(2) + except Exception as msg: + assert_(str(msg).startswith('cb: Callback global_f not defined')) + + self.module.global_f = lambda x: x + 1 + r = self.module.hidden_callback(2) + assert_(r == 3) + + self.module.global_f = lambda x: x + 2 + r = self.module.hidden_callback(2) + assert_(r == 4) + + del self.module.global_f + try: + self.module.hidden_callback(2) + except Exception as msg: + assert_(str(msg).startswith('Callback global_f not defined')) + + self.module.global_f = lambda x=0: x + 3 + r = self.module.hidden_callback(2) + assert_(r == 5) + + # reproducer of gh18341 + r = self.module.hidden_callback2(2) + assert_(r == 3) + class TestF77CallbackPythonTLS(TestF77Callback): """ |