This is on top of #2225. The goal is to be able to skip specific tests. Many core test sets have just one test that uses subprocess or threads. Others have a few tests that are failing due to upstream problems in emscripten. I went through and switched to skipping specific tests in as many cases as I could. In modules where most or all tests use threading or subprocess, I gave up and put a comment saying something like 35/50 tests fork and I didn't want to bother to salvage the remaining ones.

In order to accommodate using patterns to skip specific tests (and also extra comments) I switched the format of `python_tests` to a yaml file. This gives us significantly more flexibility in the structure of the file and allows us to use `ruamel.yaml` to update it. We gain a lot flexibility while reducing the length of `make_test_lists.py` modestly from 108 to 78 loc.

In the future, hopefully we should be able to make fixes by deleting one skip pattern and looking into why that particular test fails.

Rework core tests. This is on top of #2225. The goal is to be able to skip specific tests. Many core test sets have just one test that uses subprocess or threads. Others have a few tests that are failing due to upstream problems in emscripten. I went through and switched to skipping specific tests in as many cases as I could. In modules where most or all tests use threading or subprocess, I gave up and put a comment saying something like 35/50 tests fork and I didn't want to bother to salvage the remaining ones.

In order to accommodate using patterns to skip specific tests (and also extra comments) I switched the format of `python_tests` to a yaml file. This gives us significantly more flexibility in the structure of the file and allows us to use `ruamel.yaml` to update it. We gain a lot flexibility while reducing the length of `make_test_lists.py` modestly from 108 to 78 loc.

In the future, hopefully we should be able to make fixes by deleting one skip pattern and looking into why that particular test fails.

Make return values to fortran subroutines be consistently int.

This is because f2py defaults to making subroutines return void, whereas
f2c makes them int. On most systems this doesn't matter, but on WASM, strict
return type checking is used which makes things fail when f2py code calls
subroutines that were generated from fortran with f2c. To fix this we make
everything, including f2c, return int from subroutines.

diff --git a/numpy/f2py/src/fortranobject.h b/numpy/f2py/src/fortranobject.h
index 5d0dcf6..d5f77b3 100644
--- a/numpy/f2py/src/fortranobject.h
+++ b/numpy/f2py/src/fortranobject.h
@@ -67,9 +67,9 @@ Author: Pearu Peterson <pearu@cens.ioc.ee>

 #define F2PY_MAX_DIMS 40

-typedef void (*f2py_set_data_func)(char*,npy_intp*);
-typedef void (*f2py_void_func)(void);
-typedef void (*f2py_init_func)(int*,npy_intp*,f2py_set_data_func,int*);
+typedef int (*f2py_set_data_func)(char*,npy_intp*);
+typedef int (*f2py_void_func)(void);
+typedef int (*f2py_init_func)(int*,npy_intp*,f2py_set_data_func,int*);

   /*typedef void* (*f2py_c_func)(void*,...);*/
 
diff --git a/numpy/f2py/common_rules.py b/numpy/f2py/common_rules.py
index 62c1ba2..5893683 100644
--- a/numpy/f2py/common_rules.py
+++ b/numpy/f2py/common_rules.py
@@ -108,7 +108,7 @@ def buildhooks(m):
         cadd('\t{NULL}\n};')
         inames1 = rmbadname(inames)
         inames1_tps = ','.join(['char *' + s for s in inames1])
-        cadd('static void f2py_setup_%s(%s) {' % (name, inames1_tps))
+        cadd('static int f2py_setup_%s(%s) {' % (name, inames1_tps))
         cadd('\tint i_f2py=0;')
         for n in inames1:
             cadd('\tf2py_%s_def[i_f2py++].data = %s;' % (name, n))
@@ -117,10 +117,10 @@ def buildhooks(m):
             F_FUNC = 'F_FUNC_US'
         else:
             F_FUNC = 'F_FUNC'
-        cadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void(*)(%s));'
+        cadd('extern int %s(f2pyinit%s,F2PYINIT%s)(int(*)(%s));'
              % (F_FUNC, lower_name, name.upper(),
                 ','.join(['char*'] * len(inames1))))
-        cadd('static void f2py_init_%s(void) {' % name)
+        cadd('static int f2py_init_%s(void) {' % name)
         cadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);'
              % (F_FUNC, lower_name, name.upper(), name))
         cadd('}\n')
diff --git a/numpy/f2py/rules.py b/numpy/f2py/rules.py
index 1b41498ea..9419aeb16 100755
--- a/numpy/f2py/rules.py
+++ b/numpy/f2py/rules.py
@@ -399,9 +399,9 @@ rout_rules = [
         'decl': '',
         '_check': ismoduleroutine
     }, {  # Subroutine
-        'functype': 'void',
-        'declfortranroutine': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'extern void #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
-                               l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): 'extern void #fortranname#(#callprotoargument#);',
+        'functype': 'int',
+        'declfortranroutine': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'extern int #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
+                               l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): 'extern int #fortranname#(#callprotoargument#);',
                                ismoduleroutine: '',
                                isdummyroutine: ''
                                },
diff --git a/numpy/f2py/src/fortranobject.c b/numpy/f2py/src/fortranobject.c
index b55385b50..232a7f90d 100644
--- a/numpy/f2py/src/fortranobject.c
+++ b/numpy/f2py/src/fortranobject.c
@@ -308,6 +308,11 @@ fortran_getattr(PyFortranObject *fp, char *name) {
         return s;
     }
     if ((strcmp(name,"_cpointer")==0) && (fp->len==1)) {
+        if(fp->defs[0].data==NULL)
+        {
+            PyErr_Format(PyExc_AttributeError,"missing function pointer %s",fp->defs[0].name);
+
+        }
         PyObject *cobj = F2PyCapsule_FromVoidPtr((void *)(fp->defs[0].data),NULL);
         if (PyDict_SetItemString(fp->dict, name, cobj))
             return NULL;
@@ -382,7 +387,7 @@ fortran_setattr(PyFortranObject *fp, char *name, PyObject *v) {
     if (v == NULL) {
         int rv = PyDict_DelItemString(fp->dict, name);
         if (rv < 0)
-            PyErr_SetString(PyExc_AttributeError,"delete non-existing fortran attribute");
+            PyErr_Format(PyExc_AttributeError,"delete non-existing fortran attribute %s",name);
         return rv;
     }
     else
diff --git a/numpy/linalg/lapack_lite/f2c.c b/numpy/linalg/lapack_lite/f2c.c
index 1114bef3b..905beaa0d 100644
--- a/numpy/linalg/lapack_lite/f2c.c
+++ b/numpy/linalg/lapack_lite/f2c.c
@@ -14,9 +14,9 @@
 #include "f2c.h"
 
 
-extern void s_wsfe(cilist *f) {;}
-extern void e_wsfe(void) {;}
-extern void do_fio(integer *c, char *s, ftnlen l) {;}
+extern int s_wsfe(cilist *f) {return 0;}
+extern int e_wsfe(void) {return 0;}
+extern int do_fio(integer *c, char *s, ftnlen l) {return 0;}
 
 /* You'll want this if you redo the f2c_*.c files with the -C option
  * to f2c for checking array subscripts. (It's not suggested you do that
@@ -377,7 +377,7 @@ p->i = p1.i;
 
 #endif /* NO_OVERWRITE */
 
- VOID
+ int
 #ifdef KR_headers
 s_cat(lp, rpp, rnp, np, ll) char *lp, *rpp[]; ftnlen rnp[], *np, ll;
 #else
@@ -487,7 +487,7 @@ return(0);
 #ifdef KR_headers
 VOID s_copy(a, b, la, lb) register char *a, *b; ftnlen la, lb;
 #else
-void s_copy(register char *a, register char *b, ftnlen la, ftnlen lb)
+int s_copy(register char *a, register char *b, ftnlen la, ftnlen lb)
 #endif
 {
 	register char *aend, *bend;
@@ -524,6 +524,7 @@ void s_copy(register char *a, register char *b, ftnlen la, ftnlen lb)
 		while(a < aend)
 			*a++ = ' ';
 		}
+        return 0;
 	}
 
 
diff --git a/numpy/linalg/lapack_lite/f2c.h b/numpy/linalg/lapack_lite/f2c.h
index 80f1a12b1..25204797b 100644
--- a/numpy/linalg/lapack_lite/f2c.h
+++ b/numpy/linalg/lapack_lite/f2c.h
@@ -259,7 +259,7 @@ extern double d_tan(double *);
 extern double d_tanh(double *);
 extern double derf_(double *);
 extern double derfc_(double *);
-extern void do_fio(ftnint *, char *, ftnlen);
+extern int do_fio(ftnint *, char *, ftnlen);
 extern integer do_lio(ftnint *, ftnint *, char *, ftnlen);
 extern integer do_uio(ftnint *, char *, ftnlen);
 extern integer e_rdfe(void);
@@ -271,7 +271,7 @@ extern integer e_rsli(void);
 extern integer e_rsue(void);
 extern integer e_wdfe(void);
 extern integer e_wdue(void);
-extern void e_wsfe(void);
+extern int e_wsfe(void);
 extern integer e_wsfi(void);
 extern integer e_wsle(void);
 extern integer e_wsli(void);
@@ -346,9 +346,9 @@ extern double r_sinh(float *);
 extern double r_sqrt(float *);
 extern double r_tan(float *);
 extern double r_tanh(float *);
-extern void s_cat(char *, char **, integer *, integer *, ftnlen);
+extern int s_cat(char *, char **, integer *, integer *, ftnlen);
 extern integer s_cmp(char *, char *, ftnlen, ftnlen);
-extern void s_copy(char *, char *, ftnlen, ftnlen);
+extern int s_copy(char *, char *, ftnlen, ftnlen);
 extern int s_paus(char *, ftnlen);
 extern integer s_rdfe(cilist *);
 extern integer s_rdue(cilist *);
@@ -363,7 +363,7 @@ extern integer s_rsue(cilist *);
 extern int s_stop(char *, ftnlen);
 extern integer s_wdfe(cilist *);
 extern integer s_wdue(cilist *);
-extern void s_wsfe(	cilist *);
+extern int s_wsfe(	cilist *);
 extern integer s_wsfi(icilist *);
 extern integer s_wsle(cilist *);
 extern integer s_wsli(icilist *);

Make return values to fortran subroutines be consistently int.

This is because f2py defaults to making subroutines return void, whereas
f2c makes them int. On most systems this doesn't matter, but on WASM, strict
return type checking is used which makes things fail when f2py code calls
subroutines that were generated from fortran with f2c. To fix this we make
everything, including f2c, return int from subroutines.

diff --git a/numpy/f2py/src/fortranobject.h b/numpy/f2py/src/fortranobject.h
index 5d0dcf6..d5f77b3 100644
--- a/numpy/f2py/src/fortranobject.h
+++ b/numpy/f2py/src/fortranobject.h
@@ -67,9 +67,9 @@ Author: Pearu Peterson <pearu@cens.ioc.ee>

 #define F2PY_MAX_DIMS 40

-typedef void (*f2py_set_data_func)(char*,npy_intp*);
-typedef void (*f2py_void_func)(void);
-typedef void (*f2py_init_func)(int*,npy_intp*,f2py_set_data_func,int*);
+typedef int (*f2py_set_data_func)(char*,npy_intp*);
+typedef int (*f2py_void_func)(void);
+typedef int (*f2py_init_func)(int*,npy_intp*,f2py_set_data_func,int*);

   /*typedef void* (*f2py_c_func)(void*,...);*/
 
diff --git a/numpy/f2py/common_rules.py b/numpy/f2py/common_rules.py
index 62c1ba2..5893683 100644
--- a/numpy/f2py/common_rules.py
+++ b/numpy/f2py/common_rules.py
@@ -108,7 +108,7 @@ def buildhooks(m):
         cadd('\t{NULL}\n};')
         inames1 = rmbadname(inames)
         inames1_tps = ','.join(['char *' + s for s in inames1])
-        cadd('static void f2py_setup_%s(%s) {' % (name, inames1_tps))
+        cadd('static int f2py_setup_%s(%s) {' % (name, inames1_tps))
         cadd('\tint i_f2py=0;')
         for n in inames1:
             cadd('\tf2py_%s_def[i_f2py++].data = %s;' % (name, n))
@@ -117,10 +117,10 @@ def buildhooks(m):
             F_FUNC = 'F_FUNC_US'
         else:
             F_FUNC = 'F_FUNC'
-        cadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void(*)(%s));'
+        cadd('extern int %s(f2pyinit%s,F2PYINIT%s)(int(*)(%s));'
              % (F_FUNC, lower_name, name.upper(),
                 ','.join(['char*'] * len(inames1))))
-        cadd('static void f2py_init_%s(void) {' % name)
+        cadd('static int f2py_init_%s(void) {' % name)
         cadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);'
              % (F_FUNC, lower_name, name.upper(), name))
         cadd('}\n')
diff --git a/numpy/f2py/rules.py b/numpy/f2py/rules.py
index 1b41498ea..9419aeb16 100755
--- a/numpy/f2py/rules.py
+++ b/numpy/f2py/rules.py
@@ -399,9 +399,9 @@ rout_rules = [
         'decl': '',
         '_check': ismoduleroutine
     }, {  # Subroutine
-        'functype': 'void',
-        'declfortranroutine': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'extern void #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
-                               l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): 'extern void #fortranname#(#callprotoargument#);',
+        'functype': 'int',
+        'declfortranroutine': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'extern int #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
+                               l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): 'extern int #fortranname#(#callprotoargument#);',
                                ismoduleroutine: '',
                                isdummyroutine: ''
                                },
diff --git a/numpy/f2py/src/fortranobject.c b/numpy/f2py/src/fortranobject.c
index b55385b50..232a7f90d 100644
--- a/numpy/f2py/src/fortranobject.c
+++ b/numpy/f2py/src/fortranobject.c
@@ -308,6 +308,11 @@ fortran_getattr(PyFortranObject *fp, char *name) {
         return s;
     }
     if ((strcmp(name,"_cpointer")==0) && (fp->len==1)) {
+        if(fp->defs[0].data==NULL)
+        {
+            PyErr_Format(PyExc_AttributeError,"missing function pointer %s",fp->defs[0].name);
+
+        }
         PyObject *cobj = F2PyCapsule_FromVoidPtr((void *)(fp->defs[0].data),NULL);
         if (PyDict_SetItemString(fp->dict, name, cobj))
             return NULL;
@@ -382,7 +387,7 @@ fortran_setattr(PyFortranObject *fp, char *name, PyObject *v) {
     if (v == NULL) {
         int rv = PyDict_DelItemString(fp->dict, name);
         if (rv < 0)
-            PyErr_SetString(PyExc_AttributeError,"delete non-existing fortran attribute");
+            PyErr_Format(PyExc_AttributeError,"delete non-existing fortran attribute %s",name);
         return rv;
     }
     else
diff --git a/numpy/linalg/lapack_lite/f2c.c b/numpy/linalg/lapack_lite/f2c.c
index 1114bef3b..905beaa0d 100644
--- a/numpy/linalg/lapack_lite/f2c.c
+++ b/numpy/linalg/lapack_lite/f2c.c
@@ -14,9 +14,9 @@
 #include "f2c.h"
 
 
-extern void s_wsfe(cilist *f) {;}
-extern void e_wsfe(void) {;}
-extern void do_fio(integer *c, char *s, ftnlen l) {;}
+extern int s_wsfe(cilist *f) {return 0;}
+extern int e_wsfe(void) {return 0;}
+extern int do_fio(integer *c, char *s, ftnlen l) {return 0;}
 
 /* You'll want this if you redo the f2c_*.c files with the -C option
  * to f2c for checking array subscripts. (It's not suggested you do that
@@ -377,7 +377,7 @@ p->i = p1.i;
 
 #endif /* NO_OVERWRITE */
 
- VOID
+ int
 #ifdef KR_headers
 s_cat(lp, rpp, rnp, np, ll) char *lp, *rpp[]; ftnlen rnp[], *np, ll;
 #else
@@ -487,7 +487,7 @@ return(0);
 #ifdef KR_headers
 VOID s_copy(a, b, la, lb) register char *a, *b; ftnlen la, lb;
 #else
-void s_copy(register char *a, register char *b, ftnlen la, ftnlen lb)
+int s_copy(register char *a, register char *b, ftnlen la, ftnlen lb)
 #endif
 {
 	register char *aend, *bend;
@@ -524,6 +524,7 @@ void s_copy(register char *a, register char *b, ftnlen la, ftnlen lb)
 		while(a < aend)
 			*a++ = ' ';
 		}
+        return 0;
 	}
 
 
diff --git a/numpy/linalg/lapack_lite/f2c.h b/numpy/linalg/lapack_lite/f2c.h
index 80f1a12b1..25204797b 100644
--- a/numpy/linalg/lapack_lite/f2c.h
+++ b/numpy/linalg/lapack_lite/f2c.h
@@ -259,7 +259,7 @@ extern double d_tan(double *);
 extern double d_tanh(double *);
 extern double derf_(double *);
 extern double derfc_(double *);
-extern void do_fio(ftnint *, char *, ftnlen);
+extern int do_fio(ftnint *, char *, ftnlen);
 extern integer do_lio(ftnint *, ftnint *, char *, ftnlen);
 extern integer do_uio(ftnint *, char *, ftnlen);
 extern integer e_rdfe(void);
@@ -271,7 +271,7 @@ extern integer e_rsli(void);
 extern integer e_rsue(void);
 extern integer e_wdfe(void);
 extern integer e_wdue(void);
-extern void e_wsfe(void);
+extern int e_wsfe(void);
 extern integer e_wsfi(void);
 extern integer e_wsle(void);
 extern integer e_wsli(void);
@@ -346,9 +346,9 @@ extern double r_sinh(float *);
 extern double r_sqrt(float *);
 extern double r_tan(float *);
 extern double r_tanh(float *);
-extern void s_cat(char *, char **, integer *, integer *, ftnlen);
+extern int s_cat(char *, char **, integer *, integer *, ftnlen);
 extern integer s_cmp(char *, char *, ftnlen, ftnlen);
-extern void s_copy(char *, char *, ftnlen, ftnlen);
+extern int s_copy(char *, char *, ftnlen, ftnlen);
 extern int s_paus(char *, ftnlen);
 extern integer s_rdfe(cilist *);
 extern integer s_rdue(cilist *);
@@ -363,7 +363,7 @@ extern integer s_rsue(cilist *);
 extern int s_stop(char *, ftnlen);
 extern integer s_wdfe(cilist *);
 extern integer s_wdue(cilist *);
-extern void s_wsfe(	cilist *);
+extern int s_wsfe(	cilist *);
 extern integer s_wsfi(icilist *);
 extern integer s_wsle(cilist *);
 extern integer s_wsli(icilist *);
