summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2021-02-09 12:58:19 -0700
committerGitHub <noreply@github.com>2021-02-09 12:58:19 -0700
commit2bdecde364f133ce94b7f9271a6d34a8fb5cae86 (patch)
treec247176207411a7c9a148c17cb6e6315c02b8ce3
parent5c15cc3d76d171f07f9809a14a0dffd5ab37e599 (diff)
parent7df963b400f3dcf85e679e6f00af8c3c12971347 (diff)
downloadnumpy-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.py2
-rw-r--r--numpy/f2py/cb_rules.py8
-rw-r--r--numpy/f2py/tests/test_callback.py48
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):
"""