diff options
Diffstat (limited to 'numpy/f2py')
-rw-r--r-- | numpy/f2py/__init__.py | 1 | ||||
-rw-r--r-- | numpy/f2py/capi_maps.py | 28 | ||||
-rw-r--r-- | numpy/f2py/cfuncs.py | 25 | ||||
-rw-r--r-- | numpy/f2py/common_rules.py | 5 | ||||
-rwxr-xr-x | numpy/f2py/f2py2e.py | 15 | ||||
-rw-r--r-- | numpy/f2py/info.py | 6 | ||||
-rwxr-xr-x | numpy/f2py/rules.py | 37 | ||||
-rw-r--r-- | numpy/f2py/setup.py | 2 | ||||
-rw-r--r-- | numpy/f2py/src/fortranobject.c | 37 | ||||
-rw-r--r-- | numpy/f2py/src/test/foomodule.c | 18 | ||||
-rw-r--r-- | numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c | 139 | ||||
-rw-r--r-- | numpy/f2py/tests/test_assumed_shape.py | 22 | ||||
-rw-r--r-- | numpy/f2py/tests/test_compile_function.py | 4 | ||||
-rw-r--r-- | numpy/f2py/tests/util.py | 37 |
14 files changed, 251 insertions, 125 deletions
diff --git a/numpy/f2py/__init__.py b/numpy/f2py/__init__.py index d146739bb..42e3632fd 100644 --- a/numpy/f2py/__init__.py +++ b/numpy/f2py/__init__.py @@ -109,6 +109,7 @@ def compile(source, output = '' else: status = 0 + output = output.decode() if verbose: print(output) finally: diff --git a/numpy/f2py/capi_maps.py b/numpy/f2py/capi_maps.py index c41dd77c6..ce79f680f 100644 --- a/numpy/f2py/capi_maps.py +++ b/numpy/f2py/capi_maps.py @@ -179,17 +179,29 @@ f2cmap_all = {'real': {'': 'float', '4': 'float', '8': 'double', 'character': {'': 'string'} } -if os.path.isfile('.f2py_f2cmap'): +f2cmap_default = copy.deepcopy(f2cmap_all) + + +def load_f2cmap_file(f2cmap_file): + global f2cmap_all + + f2cmap_all = copy.deepcopy(f2cmap_default) + + if f2cmap_file is None: + # Default value + f2cmap_file = '.f2py_f2cmap' + if not os.path.isfile(f2cmap_file): + return + # User defined additions to f2cmap_all. - # .f2py_f2cmap must contain a dictionary of dictionaries, only. For + # f2cmap_file must contain a dictionary of dictionaries, only. For # example, {'real':{'low':'float'}} means that Fortran 'real(low)' is # interpreted as C 'float'. This feature is useful for F90/95 users if # they use PARAMETERSs in type specifications. try: - outmess('Reading .f2py_f2cmap ...\n') - f = open('.f2py_f2cmap', 'r') - d = eval(f.read(), {}, {}) - f.close() + outmess('Reading f2cmap from {!r} ...\n'.format(f2cmap_file)) + with open(f2cmap_file, 'r') as f: + d = eval(f.read(), {}, {}) for k, d1 in list(d.items()): for k1 in list(d1.keys()): d1[k1.lower()] = d1[k1] @@ -208,10 +220,10 @@ if os.path.isfile('.f2py_f2cmap'): else: errmess("\tIgnoring map {'%s':{'%s':'%s'}}: '%s' must be in %s\n" % ( k, k1, d[k][k1], d[k][k1], list(c2py_map.keys()))) - outmess('Successfully applied user defined changes from .f2py_f2cmap\n') + outmess('Successfully applied user defined f2cmap changes\n') except Exception as msg: errmess( - 'Failed to apply user defined changes from .f2py_f2cmap: %s. Skipping.\n' % (msg)) + 'Failed to apply user defined f2cmap changes: %s. Skipping.\n' % (msg)) cformat_map = {'double': '%g', 'float': '%g', diff --git a/numpy/f2py/cfuncs.py b/numpy/f2py/cfuncs.py index d59b6301c..ccb7b3a32 100644 --- a/numpy/f2py/cfuncs.py +++ b/numpy/f2py/cfuncs.py @@ -542,7 +542,7 @@ cppmacros[ 'ARRSIZE'] = '#define ARRSIZE(dims,rank) (_PyArray_multiply_list(dims,rank))' cppmacros['OLDPYNUM'] = """\ #ifdef OLDPYNUM -#error You need to install Numeric Python version 13 or higher. Get it from http:/sourceforge.net/project/?group_id=1369 +#error You need to install NumPy version 13 or higher. See https://scipy.org/install.html #endif """ ################# C functions ############### @@ -1049,8 +1049,10 @@ static int create_cb_arglist(PyObject* fun,PyTupleObject* xa,const int maxnofarg CFUNCSMESS(\"create_cb_arglist\\n\"); tot=opt=ext=siz=0; /* Get the total number of arguments */ - if (PyFunction_Check(fun)) + if (PyFunction_Check(fun)) { tmp_fun = fun; + Py_INCREF(tmp_fun); + } else { di = 1; if (PyObject_HasAttrString(fun,\"im_func\")) { @@ -1062,6 +1064,7 @@ static int create_cb_arglist(PyObject* fun,PyTupleObject* xa,const int maxnofarg tmp_fun = PyObject_GetAttrString(tmp,\"im_func\"); else { tmp_fun = fun; /* built-in function */ + Py_INCREF(tmp_fun); tot = maxnofargs; if (xa != NULL) tot += PyTuple_Size((PyObject *)xa); @@ -1073,6 +1076,7 @@ static int create_cb_arglist(PyObject* fun,PyTupleObject* xa,const int maxnofarg if (xa != NULL) tot += PyTuple_Size((PyObject *)xa); tmp_fun = fun; + Py_INCREF(tmp_fun); } else if (F2PyCapsule_Check(fun)) { tot = maxnofargs; @@ -1083,6 +1087,7 @@ static int create_cb_arglist(PyObject* fun,PyTupleObject* xa,const int maxnofarg goto capi_fail; } tmp_fun = fun; + Py_INCREF(tmp_fun); } } if (tmp_fun==NULL) { @@ -1091,13 +1096,19 @@ goto capi_fail; } #if PY_VERSION_HEX >= 0x03000000 if (PyObject_HasAttrString(tmp_fun,\"__code__\")) { - if (PyObject_HasAttrString(tmp = PyObject_GetAttrString(tmp_fun,\"__code__\"),\"co_argcount\")) + if (PyObject_HasAttrString(tmp = PyObject_GetAttrString(tmp_fun,\"__code__\"),\"co_argcount\")) { #else if (PyObject_HasAttrString(tmp_fun,\"func_code\")) { - if (PyObject_HasAttrString(tmp = PyObject_GetAttrString(tmp_fun,\"func_code\"),\"co_argcount\")) + if (PyObject_HasAttrString(tmp = PyObject_GetAttrString(tmp_fun,\"func_code\"),\"co_argcount\")) { #endif - tot = PyInt_AsLong(PyObject_GetAttrString(tmp,\"co_argcount\")) - di; - Py_XDECREF(tmp); + PyObject *tmp_argcount = PyObject_GetAttrString(tmp,\"co_argcount\"); + Py_DECREF(tmp); + if (tmp_argcount == NULL) { + goto capi_fail; + } + tot = PyInt_AsLong(tmp_argcount) - di; + Py_DECREF(tmp_argcount); + } } /* Get the number of optional arguments */ #if PY_VERSION_HEX >= 0x03000000 @@ -1136,10 +1147,12 @@ goto capi_fail; PyTuple_SET_ITEM(*args,i,tmp); } CFUNCSMESS(\"create_cb_arglist-end\\n\"); + Py_DECREF(tmp_fun); return 1; capi_fail: if ((PyErr_Occurred())==NULL) PyErr_SetString(#modulename#_error,errmess); + Py_XDECREF(tmp_fun); return 0; } """ diff --git a/numpy/f2py/common_rules.py b/numpy/f2py/common_rules.py index 62c1ba207..f61d8810a 100644 --- a/numpy/f2py/common_rules.py +++ b/numpy/f2py/common_rules.py @@ -124,8 +124,9 @@ def buildhooks(m): cadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);' % (F_FUNC, lower_name, name.upper(), name)) cadd('}\n') - iadd('\tF2PyDict_SetItemString(d, \"%s\", PyFortranObject_New(f2py_%s_def,f2py_init_%s));' % ( - name, name, name)) + iadd('\ttmp = PyFortranObject_New(f2py_%s_def,f2py_init_%s);' % (name, name)) + iadd('\tF2PyDict_SetItemString(d, \"%s\", tmp);' % name) + iadd('\tPy_DECREF(tmp);') tname = name.replace('_', '\\_') dadd('\\subsection{Common block \\texttt{%s}}\n' % (tname)) dadd('\\begin{description}') diff --git a/numpy/f2py/f2py2e.py b/numpy/f2py/f2py2e.py index 110337f92..d03eff9e3 100755 --- a/numpy/f2py/f2py2e.py +++ b/numpy/f2py/f2py2e.py @@ -28,6 +28,7 @@ from . import auxfuncs from . import cfuncs from . import f90mod_rules from . import __version__ +from . import capi_maps f2py_version = __version__.version errmess = sys.stderr.write @@ -118,6 +119,9 @@ Options: --link-<resource> switch below. [..] is optional list of resources names. E.g. try 'f2py --help-link lapack_opt'. + --f2cmap <filename> Load Fortran-to-Python KIND specification from the given + file. Default: .f2py_f2cmap in current directory. + --quiet Run quietly. --verbose Run with extra verbosity. -v Print f2py version ID and exit. @@ -175,7 +179,7 @@ http://cens.ioc.ee/projects/f2py2e/""" % (f2py_version, numpy_version) def scaninputline(inputline): files, skipfuncs, onlyfuncs, debug = [], [], [], [] - f, f2, f3, f5, f6, f7, f8, f9 = 1, 0, 0, 0, 0, 0, 0, 0 + f, f2, f3, f5, f6, f7, f8, f9, f10 = 1, 0, 0, 0, 0, 0, 0, 0, 0 verbose = 1 dolc = -1 dolatexdoc = 0 @@ -226,6 +230,8 @@ def scaninputline(inputline): f8 = 1 elif l == '--f2py-wrapper-output': f9 = 1 + elif l == '--f2cmap': + f10 = 1 elif l == '--overwrite-signature': options['h-overwrite'] = 1 elif l == '-h': @@ -267,6 +273,9 @@ def scaninputline(inputline): elif f9: f9 = 0 options["f2py_wrapper_output"] = l + elif f10: + f10 = 0 + options["f2cmap_file"] = l elif f == 1: try: with open(l): @@ -312,6 +321,7 @@ def scaninputline(inputline): options['wrapfuncs'] = wrapfuncs options['buildpath'] = buildpath options['include_paths'] = include_paths + options.setdefault('f2cmap_file', None) return files, options @@ -422,6 +432,7 @@ def run_main(comline_list): fobjcsrc = os.path.join(f2pydir, 'src', 'fortranobject.c') files, options = scaninputline(comline_list) auxfuncs.options = options + capi_maps.load_f2cmap_file(options['f2cmap_file']) postlist = callcrackfortran(files, options) isusedby = {} for i in range(len(postlist)): @@ -574,7 +585,7 @@ def run_compile(): modulename = 'untitled' sources = sys.argv[1:] - for optname in ['--include_paths', '--include-paths']: + for optname in ['--include_paths', '--include-paths', '--f2cmap']: if optname in sys.argv: i = sys.argv.index(optname) f2py_flags.extend(sys.argv[i:i + 2]) diff --git a/numpy/f2py/info.py b/numpy/f2py/info.py deleted file mode 100644 index c895c5de2..000000000 --- a/numpy/f2py/info.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Fortran to Python Interface Generator. - -""" -from __future__ import division, absolute_import, print_function - -postpone_import = True diff --git a/numpy/f2py/rules.py b/numpy/f2py/rules.py index 1b41498ea..f2f713bde 100755 --- a/numpy/f2py/rules.py +++ b/numpy/f2py/rules.py @@ -215,6 +215,7 @@ PyMODINIT_FUNC init#modulename#(void) { \td = PyModule_GetDict(m); \ts = PyString_FromString(\"$R""" + """evision: $\"); \tPyDict_SetItemString(d, \"__version__\", s); +\tPy_DECREF(s); #if PY_VERSION_HEX >= 0x03000000 \ts = PyUnicode_FromString( #else @@ -222,8 +223,14 @@ PyMODINIT_FUNC init#modulename#(void) { #endif \t\t\"This module '#modulename#' is auto-generated with f2py (version:#f2py_version#).\\nFunctions:\\n\"\n#docs#\".\"); \tPyDict_SetItemString(d, \"__doc__\", s); -\t#modulename#_error = PyErr_NewException (\"#modulename#.error\", NULL, NULL); \tPy_DECREF(s); +\t#modulename#_error = PyErr_NewException (\"#modulename#.error\", NULL, NULL); +\t/* +\t * Store the error object inside the dict, so that it could get deallocated. +\t * (in practice, this is a module, so it likely will not and cannot.) +\t */ +\tPyDict_SetItemString(d, \"_#modulename#_error\", #modulename#_error); +\tPy_DECREF(#modulename#_error); \tfor(i=0;f2py_routine_defs[i].name!=NULL;i++) { \t\ttmp = PyFortranObject_NewAsAttr(&f2py_routine_defs[i]); \t\tPyDict_SetItemString(d, f2py_routine_defs[i].name, tmp); @@ -238,7 +245,6 @@ PyMODINIT_FUNC init#modulename#(void) { \tif (! PyErr_Occurred()) \t\ton_exit(f2py_report_on_exit,(void*)\"#modulename#\"); #endif - \treturn RETVAL; } #ifdef __cplusplus @@ -439,12 +445,16 @@ rout_rules = [ { extern #ctype# #F_FUNC#(#name_lower#,#NAME#)(void); PyObject* o = PyDict_GetItemString(d,"#name#"); - PyObject_SetAttrString(o,"_cpointer", F2PyCapsule_FromVoidPtr((void*)#F_FUNC#(#name_lower#,#NAME#),NULL)); + tmp = F2PyCapsule_FromVoidPtr((void*)#F_FUNC#(#name_lower#,#NAME#),NULL); + PyObject_SetAttrString(o,"_cpointer", tmp); + Py_DECREF(tmp); #if PY_VERSION_HEX >= 0x03000000 - PyObject_SetAttrString(o,"__name__", PyUnicode_FromString("#name#")); + s = PyUnicode_FromString("#name#"); #else - PyObject_SetAttrString(o,"__name__", PyString_FromString("#name#")); + s = PyString_FromString("#name#"); #endif + PyObject_SetAttrString(o,"__name__", s); + Py_DECREF(s); } '''}, 'need': {l_not(l_or(ismoduleroutine, isdummyroutine)): ['F_WRAPPEDFUNC', 'F_FUNC']}, @@ -477,12 +487,16 @@ rout_rules = [ { extern void #F_FUNC#(#name_lower#,#NAME#)(void); PyObject* o = PyDict_GetItemString(d,"#name#"); - PyObject_SetAttrString(o,"_cpointer", F2PyCapsule_FromVoidPtr((void*)#F_FUNC#(#name_lower#,#NAME#),NULL)); + tmp = F2PyCapsule_FromVoidPtr((void*)#F_FUNC#(#name_lower#,#NAME#),NULL); + PyObject_SetAttrString(o,"_cpointer", tmp); + Py_DECREF(tmp); #if PY_VERSION_HEX >= 0x03000000 - PyObject_SetAttrString(o,"__name__", PyUnicode_FromString("#name#")); + s = PyUnicode_FromString("#name#"); #else - PyObject_SetAttrString(o,"__name__", PyString_FromString("#name#")); + s = PyString_FromString("#name#"); #endif + PyObject_SetAttrString(o,"__name__", s); + Py_DECREF(s); } '''}, 'need': {l_not(l_or(ismoduleroutine, isdummyroutine)): ['F_WRAPPEDFUNC', 'F_FUNC']}, @@ -794,10 +808,13 @@ if (#varname#_capi==Py_None) { if (#varname#_xa_capi==NULL) { if (PyObject_HasAttrString(#modulename#_module,\"#varname#_extra_args\")) { PyObject* capi_tmp = PyObject_GetAttrString(#modulename#_module,\"#varname#_extra_args\"); - if (capi_tmp) + if (capi_tmp) { #varname#_xa_capi = (PyTupleObject *)PySequence_Tuple(capi_tmp); - else + Py_DECREF(capi_tmp); + } + else { #varname#_xa_capi = (PyTupleObject *)Py_BuildValue(\"()\"); + } if (#varname#_xa_capi==NULL) { PyErr_SetString(#modulename#_error,\"Failed to convert #modulename#.#varname#_extra_args to tuple.\\n\"); return NULL; diff --git a/numpy/f2py/setup.py b/numpy/f2py/setup.py index c0c50ce54..a8c1401aa 100644 --- a/numpy/f2py/setup.py +++ b/numpy/f2py/setup.py @@ -3,7 +3,7 @@ setup.py for installing F2PY Usage: - python setup.py install + pip install . Copyright 2001-2005 Pearu Peterson all rights reserved, Pearu Peterson <pearu@cens.ioc.ee> diff --git a/numpy/f2py/src/fortranobject.c b/numpy/f2py/src/fortranobject.c index b55385b50..8aa55555d 100644 --- a/numpy/f2py/src/fortranobject.c +++ b/numpy/f2py/src/fortranobject.c @@ -39,19 +39,33 @@ PyFortranObject_New(FortranDataDef* defs, f2py_void_func init) { int i; PyFortranObject *fp = NULL; PyObject *v = NULL; - if (init!=NULL) /* Initialize F90 module objects */ + if (init!=NULL) { /* Initialize F90 module objects */ (*(init))(); - if ((fp = PyObject_New(PyFortranObject, &PyFortran_Type))==NULL) return NULL; - if ((fp->dict = PyDict_New())==NULL) return NULL; + } + fp = PyObject_New(PyFortranObject, &PyFortran_Type); + if (fp == NULL) { + return NULL; + } + if ((fp->dict = PyDict_New()) == NULL) { + Py_DECREF(fp); + return NULL; + } fp->len = 0; - while (defs[fp->len].name != NULL) fp->len++; - if (fp->len == 0) goto fail; + while (defs[fp->len].name != NULL) { + fp->len++; + } + if (fp->len == 0) { + goto fail; + } fp->defs = defs; - for (i=0;i<fp->len;i++) + for (i=0;i<fp->len;i++) { if (fp->defs[i].rank == -1) { /* Is Fortran routine */ v = PyFortranObject_NewAsAttr(&(fp->defs[i])); - if (v==NULL) return NULL; + if (v==NULL) { + goto fail; + } PyDict_SetItemString(fp->dict,fp->defs[i].name,v); + Py_XDECREF(v); } else if ((fp->defs[i].data)!=NULL) { /* Is Fortran variable or array (not allocatable) */ if (fp->defs[i].type == NPY_STRING) { @@ -65,13 +79,16 @@ PyFortranObject_New(FortranDataDef* defs, f2py_void_func init) { fp->defs[i].type, NULL, fp->defs[i].data, 0, NPY_ARRAY_FARRAY, NULL); } - if (v==NULL) return NULL; + if (v==NULL) { + goto fail; + } PyDict_SetItemString(fp->dict,fp->defs[i].name,v); + Py_XDECREF(v); } - Py_XDECREF(v); + } return (PyObject *)fp; fail: - Py_XDECREF(v); + Py_XDECREF(fp); return NULL; } diff --git a/numpy/f2py/src/test/foomodule.c b/numpy/f2py/src/test/foomodule.c index 733fab0be..caf3590d4 100644 --- a/numpy/f2py/src/test/foomodule.c +++ b/numpy/f2py/src/test/foomodule.c @@ -115,7 +115,7 @@ static PyMethodDef foo_module_methods[] = { void initfoo() { int i; - PyObject *m, *d, *s; + PyObject *m, *d, *s, *tmp; import_array(); m = Py_InitModule("foo", foo_module_methods); @@ -125,11 +125,17 @@ void initfoo() { PyDict_SetItemString(d, "__doc__", s); /* Fortran objects: */ - PyDict_SetItemString(d, "mod", PyFortranObject_New(f2py_mod_def,f2py_init_mod)); - PyDict_SetItemString(d, "foodata", PyFortranObject_New(f2py_foodata_def,f2py_init_foodata)); - for(i=0;f2py_routines_def[i].name!=NULL;i++) - PyDict_SetItemString(d, f2py_routines_def[i].name, - PyFortranObject_NewAsAttr(&f2py_routines_def[i])); + tmp = PyFortranObject_New(f2py_mod_def,f2py_init_mod); + PyDict_SetItemString(d, "mod", tmp); + Py_DECREF(tmp); + tmp = PyFortranObject_New(f2py_foodata_def,f2py_init_foodata); + PyDict_SetItemString(d, "foodata", tmp); + Py_DECREF(tmp); + for(i=0;f2py_routines_def[i].name!=NULL;i++) { + tmp = PyFortranObject_NewAsAttr(&f2py_routines_def[i]); + PyDict_SetItemString(d, f2py_routines_def[i].name, tmp); + Py_DECREF(tmp); + } Py_DECREF(s); diff --git a/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c b/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c index 7f46303b0..978db4e69 100644 --- a/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c +++ b/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c @@ -49,9 +49,18 @@ static PyObject *f2py_rout_wrap_call(PyObject *capi_self, return NULL; rank = PySequence_Length(dims_capi); dims = malloc(rank*sizeof(npy_intp)); - for (i=0;i<rank;++i) - dims[i] = (npy_intp)PyInt_AsLong(PySequence_GetItem(dims_capi,i)); - + for (i=0;i<rank;++i) { + PyObject *tmp; + tmp = PySequence_GetItem(dims_capi, i); + if (tmp == NULL) { + goto fail; + } + dims[i] = (npy_intp)PyInt_AsLong(tmp); + Py_DECREF(tmp); + if (dims[i] == -1 && PyErr_Occurred()) { + goto fail; + } + } capi_arr_tmp = array_from_pyobj(type_num,dims,rank,intent|F2PY_INTENT_OUT,arr_capi); if (capi_arr_tmp == NULL) { free(dims); @@ -60,6 +69,10 @@ static PyObject *f2py_rout_wrap_call(PyObject *capi_self, capi_buildvalue = Py_BuildValue("N",capi_arr_tmp); free(dims); return capi_buildvalue; + +fail: + free(dims); + return NULL; } static char doc_f2py_rout_wrap_attrs[] = "\ @@ -97,7 +110,7 @@ static PyObject *f2py_rout_wrap_attrs(PyObject *capi_self, PyTuple_SetItem(dimensions,i,PyInt_FromLong(PyArray_DIM(arr,i))); PyTuple_SetItem(strides,i,PyInt_FromLong(PyArray_STRIDE(arr,i))); } - return Py_BuildValue("siOOO(cciii)ii",s,PyArray_NDIM(arr), + return Py_BuildValue("siNNO(cciii)ii",s,PyArray_NDIM(arr), dimensions,strides, (PyArray_BASE(arr)==NULL?Py_None:PyArray_BASE(arr)), PyArray_DESCR(arr)->kind, @@ -154,61 +167,69 @@ PyMODINIT_FUNC inittest_array_from_pyobj_ext(void) { PyDict_SetItemString(d, "__doc__", s); wrap_error = PyErr_NewException ("wrap.error", NULL, NULL); Py_DECREF(s); - PyDict_SetItemString(d, "F2PY_INTENT_IN", PyInt_FromLong(F2PY_INTENT_IN)); - PyDict_SetItemString(d, "F2PY_INTENT_INOUT", PyInt_FromLong(F2PY_INTENT_INOUT)); - PyDict_SetItemString(d, "F2PY_INTENT_OUT", PyInt_FromLong(F2PY_INTENT_OUT)); - PyDict_SetItemString(d, "F2PY_INTENT_HIDE", PyInt_FromLong(F2PY_INTENT_HIDE)); - PyDict_SetItemString(d, "F2PY_INTENT_CACHE", PyInt_FromLong(F2PY_INTENT_CACHE)); - PyDict_SetItemString(d, "F2PY_INTENT_COPY", PyInt_FromLong(F2PY_INTENT_COPY)); - PyDict_SetItemString(d, "F2PY_INTENT_C", PyInt_FromLong(F2PY_INTENT_C)); - PyDict_SetItemString(d, "F2PY_OPTIONAL", PyInt_FromLong(F2PY_OPTIONAL)); - PyDict_SetItemString(d, "F2PY_INTENT_INPLACE", PyInt_FromLong(F2PY_INTENT_INPLACE)); - PyDict_SetItemString(d, "NPY_BOOL", PyInt_FromLong(NPY_BOOL)); - PyDict_SetItemString(d, "NPY_BYTE", PyInt_FromLong(NPY_BYTE)); - PyDict_SetItemString(d, "NPY_UBYTE", PyInt_FromLong(NPY_UBYTE)); - PyDict_SetItemString(d, "NPY_SHORT", PyInt_FromLong(NPY_SHORT)); - PyDict_SetItemString(d, "NPY_USHORT", PyInt_FromLong(NPY_USHORT)); - PyDict_SetItemString(d, "NPY_INT", PyInt_FromLong(NPY_INT)); - PyDict_SetItemString(d, "NPY_UINT", PyInt_FromLong(NPY_UINT)); - PyDict_SetItemString(d, "NPY_INTP", PyInt_FromLong(NPY_INTP)); - PyDict_SetItemString(d, "NPY_UINTP", PyInt_FromLong(NPY_UINTP)); - PyDict_SetItemString(d, "NPY_LONG", PyInt_FromLong(NPY_LONG)); - PyDict_SetItemString(d, "NPY_ULONG", PyInt_FromLong(NPY_ULONG)); - PyDict_SetItemString(d, "NPY_LONGLONG", PyInt_FromLong(NPY_LONGLONG)); - PyDict_SetItemString(d, "NPY_ULONGLONG", PyInt_FromLong(NPY_ULONGLONG)); - PyDict_SetItemString(d, "NPY_FLOAT", PyInt_FromLong(NPY_FLOAT)); - PyDict_SetItemString(d, "NPY_DOUBLE", PyInt_FromLong(NPY_DOUBLE)); - PyDict_SetItemString(d, "NPY_LONGDOUBLE", PyInt_FromLong(NPY_LONGDOUBLE)); - PyDict_SetItemString(d, "NPY_CFLOAT", PyInt_FromLong(NPY_CFLOAT)); - PyDict_SetItemString(d, "NPY_CDOUBLE", PyInt_FromLong(NPY_CDOUBLE)); - PyDict_SetItemString(d, "NPY_CLONGDOUBLE", PyInt_FromLong(NPY_CLONGDOUBLE)); - PyDict_SetItemString(d, "NPY_OBJECT", PyInt_FromLong(NPY_OBJECT)); - PyDict_SetItemString(d, "NPY_STRING", PyInt_FromLong(NPY_STRING)); - PyDict_SetItemString(d, "NPY_UNICODE", PyInt_FromLong(NPY_UNICODE)); - PyDict_SetItemString(d, "NPY_VOID", PyInt_FromLong(NPY_VOID)); - PyDict_SetItemString(d, "NPY_NTYPES", PyInt_FromLong(NPY_NTYPES)); - PyDict_SetItemString(d, "NPY_NOTYPE", PyInt_FromLong(NPY_NOTYPE)); - PyDict_SetItemString(d, "NPY_USERDEF", PyInt_FromLong(NPY_USERDEF)); - - PyDict_SetItemString(d, "CONTIGUOUS", PyInt_FromLong(NPY_ARRAY_C_CONTIGUOUS)); - PyDict_SetItemString(d, "FORTRAN", PyInt_FromLong(NPY_ARRAY_F_CONTIGUOUS)); - PyDict_SetItemString(d, "OWNDATA", PyInt_FromLong(NPY_ARRAY_OWNDATA)); - PyDict_SetItemString(d, "FORCECAST", PyInt_FromLong(NPY_ARRAY_FORCECAST)); - PyDict_SetItemString(d, "ENSURECOPY", PyInt_FromLong(NPY_ARRAY_ENSURECOPY)); - PyDict_SetItemString(d, "ENSUREARRAY", PyInt_FromLong(NPY_ARRAY_ENSUREARRAY)); - PyDict_SetItemString(d, "ALIGNED", PyInt_FromLong(NPY_ARRAY_ALIGNED)); - PyDict_SetItemString(d, "WRITEABLE", PyInt_FromLong(NPY_ARRAY_WRITEABLE)); - PyDict_SetItemString(d, "UPDATEIFCOPY", PyInt_FromLong(NPY_ARRAY_UPDATEIFCOPY)); - PyDict_SetItemString(d, "WRITEBACKIFCOPY", PyInt_FromLong(NPY_ARRAY_WRITEBACKIFCOPY)); - - PyDict_SetItemString(d, "BEHAVED", PyInt_FromLong(NPY_ARRAY_BEHAVED)); - PyDict_SetItemString(d, "BEHAVED_NS", PyInt_FromLong(NPY_ARRAY_BEHAVED_NS)); - PyDict_SetItemString(d, "CARRAY", PyInt_FromLong(NPY_ARRAY_CARRAY)); - PyDict_SetItemString(d, "FARRAY", PyInt_FromLong(NPY_ARRAY_FARRAY)); - PyDict_SetItemString(d, "CARRAY_RO", PyInt_FromLong(NPY_ARRAY_CARRAY_RO)); - PyDict_SetItemString(d, "FARRAY_RO", PyInt_FromLong(NPY_ARRAY_FARRAY_RO)); - PyDict_SetItemString(d, "DEFAULT", PyInt_FromLong(NPY_ARRAY_DEFAULT)); - PyDict_SetItemString(d, "UPDATE_ALL", PyInt_FromLong(NPY_ARRAY_UPDATE_ALL)); + +#define ADDCONST(NAME, CONST) \ + s = PyInt_FromLong(CONST); \ + PyDict_SetItemString(d, NAME, s); \ + Py_DECREF(s) + + ADDCONST("F2PY_INTENT_IN", F2PY_INTENT_IN); + ADDCONST("F2PY_INTENT_INOUT", F2PY_INTENT_INOUT); + ADDCONST("F2PY_INTENT_OUT", F2PY_INTENT_OUT); + ADDCONST("F2PY_INTENT_HIDE", F2PY_INTENT_HIDE); + ADDCONST("F2PY_INTENT_CACHE", F2PY_INTENT_CACHE); + ADDCONST("F2PY_INTENT_COPY", F2PY_INTENT_COPY); + ADDCONST("F2PY_INTENT_C", F2PY_INTENT_C); + ADDCONST("F2PY_OPTIONAL", F2PY_OPTIONAL); + ADDCONST("F2PY_INTENT_INPLACE", F2PY_INTENT_INPLACE); + ADDCONST("NPY_BOOL", NPY_BOOL); + ADDCONST("NPY_BYTE", NPY_BYTE); + ADDCONST("NPY_UBYTE", NPY_UBYTE); + ADDCONST("NPY_SHORT", NPY_SHORT); + ADDCONST("NPY_USHORT", NPY_USHORT); + ADDCONST("NPY_INT", NPY_INT); + ADDCONST("NPY_UINT", NPY_UINT); + ADDCONST("NPY_INTP", NPY_INTP); + ADDCONST("NPY_UINTP", NPY_UINTP); + ADDCONST("NPY_LONG", NPY_LONG); + ADDCONST("NPY_ULONG", NPY_ULONG); + ADDCONST("NPY_LONGLONG", NPY_LONGLONG); + ADDCONST("NPY_ULONGLONG", NPY_ULONGLONG); + ADDCONST("NPY_FLOAT", NPY_FLOAT); + ADDCONST("NPY_DOUBLE", NPY_DOUBLE); + ADDCONST("NPY_LONGDOUBLE", NPY_LONGDOUBLE); + ADDCONST("NPY_CFLOAT", NPY_CFLOAT); + ADDCONST("NPY_CDOUBLE", NPY_CDOUBLE); + ADDCONST("NPY_CLONGDOUBLE", NPY_CLONGDOUBLE); + ADDCONST("NPY_OBJECT", NPY_OBJECT); + ADDCONST("NPY_STRING", NPY_STRING); + ADDCONST("NPY_UNICODE", NPY_UNICODE); + ADDCONST("NPY_VOID", NPY_VOID); + ADDCONST("NPY_NTYPES", NPY_NTYPES); + ADDCONST("NPY_NOTYPE", NPY_NOTYPE); + ADDCONST("NPY_USERDEF", NPY_USERDEF); + + ADDCONST("CONTIGUOUS", NPY_ARRAY_C_CONTIGUOUS); + ADDCONST("FORTRAN", NPY_ARRAY_F_CONTIGUOUS); + ADDCONST("OWNDATA", NPY_ARRAY_OWNDATA); + ADDCONST("FORCECAST", NPY_ARRAY_FORCECAST); + ADDCONST("ENSURECOPY", NPY_ARRAY_ENSURECOPY); + ADDCONST("ENSUREARRAY", NPY_ARRAY_ENSUREARRAY); + ADDCONST("ALIGNED", NPY_ARRAY_ALIGNED); + ADDCONST("WRITEABLE", NPY_ARRAY_WRITEABLE); + ADDCONST("UPDATEIFCOPY", NPY_ARRAY_UPDATEIFCOPY); + ADDCONST("WRITEBACKIFCOPY", NPY_ARRAY_WRITEBACKIFCOPY); + + ADDCONST("BEHAVED", NPY_ARRAY_BEHAVED); + ADDCONST("BEHAVED_NS", NPY_ARRAY_BEHAVED_NS); + ADDCONST("CARRAY", NPY_ARRAY_CARRAY); + ADDCONST("FARRAY", NPY_ARRAY_FARRAY); + ADDCONST("CARRAY_RO", NPY_ARRAY_CARRAY_RO); + ADDCONST("FARRAY_RO", NPY_ARRAY_FARRAY_RO); + ADDCONST("DEFAULT", NPY_ARRAY_DEFAULT); + ADDCONST("UPDATE_ALL", NPY_ARRAY_UPDATE_ALL); + +#undef ADDCONST( if (PyErr_Occurred()) Py_FatalError("can't initialize module wrap"); diff --git a/numpy/f2py/tests/test_assumed_shape.py b/numpy/f2py/tests/test_assumed_shape.py index 460afd68d..e5695a61c 100644 --- a/numpy/f2py/tests/test_assumed_shape.py +++ b/numpy/f2py/tests/test_assumed_shape.py @@ -2,6 +2,7 @@ from __future__ import division, absolute_import, print_function import os import pytest +import tempfile from numpy.testing import assert_ from . import util @@ -16,6 +17,7 @@ class TestAssumedShapeSumExample(util.F2PyTest): _path('src', 'assumed_shape', 'foo_use.f90'), _path('src', 'assumed_shape', 'precision.f90'), _path('src', 'assumed_shape', 'foo_mod.f90'), + _path('src', 'assumed_shape', '.f2py_f2cmap'), ] @pytest.mark.slow @@ -31,3 +33,23 @@ class TestAssumedShapeSumExample(util.F2PyTest): assert_(r == 3, repr(r)) r = self.module.mod.fsum([1, 2]) assert_(r == 3, repr(r)) + + +class TestF2cmapOption(TestAssumedShapeSumExample): + def setup(self): + # Use a custom file name for .f2py_f2cmap + self.sources = list(self.sources) + f2cmap_src = self.sources.pop(-1) + + self.f2cmap_file = tempfile.NamedTemporaryFile(delete=False) + with open(f2cmap_src, 'rb') as f: + self.f2cmap_file.write(f.read()) + self.f2cmap_file.close() + + self.sources.append(self.f2cmap_file.name) + self.options = ["--f2cmap", self.f2cmap_file.name] + + super(TestF2cmapOption, self).setup() + + def teardown(self): + os.unlink(self.f2cmap_file.name) diff --git a/numpy/f2py/tests/test_compile_function.py b/numpy/f2py/tests/test_compile_function.py index 36abf05f9..40ea7997f 100644 --- a/numpy/f2py/tests/test_compile_function.py +++ b/numpy/f2py/tests/test_compile_function.py @@ -29,6 +29,7 @@ def setup_module(): @pytest.mark.parametrize( "extra_args", [['--noopt', '--debug'], '--noopt --debug', ''] ) +@pytest.mark.leaks_references(reason="Imported module seems never deleted.") def test_f2py_init_compile(extra_args): # flush through the f2py __init__ compile() function code path as a # crude test for input handling following migration from @@ -81,6 +82,9 @@ def test_f2py_init_compile(extra_args): return_check = import_module(modname) calc_result = return_check.foo() assert_equal(calc_result, 15) + # Removal from sys.modules, is not as such necessary. Even with + # removal, the module (dict) stays alive. + del sys.modules[modname] def test_f2py_init_compile_failure(): diff --git a/numpy/f2py/tests/util.py b/numpy/f2py/tests/util.py index d20dc5908..bf005df88 100644 --- a/numpy/f2py/tests/util.py +++ b/numpy/f2py/tests/util.py @@ -31,6 +31,7 @@ except ImportError: # _module_dir = None +_module_num = 5403 def _cleanup(): @@ -59,13 +60,14 @@ def get_module_dir(): def get_temp_module_name(): # Assume single-threaded, and the module dir usable only by this thread + global _module_num d = get_module_dir() - for j in range(5403, 9999999): - name = "_test_ext_module_%d" % j - fn = os.path.join(d, name) - if name not in sys.modules and not os.path.isfile(fn + '.py'): - return name - raise RuntimeError("Failed to create a temporary module name") + name = "_test_ext_module_%d" % _module_num + _module_num += 1 + if name in sys.modules: + # this should not be possible, but check anyway + raise RuntimeError("Temporary module name already in use.") + return name def _memoize(func): @@ -105,6 +107,7 @@ def build_module(source_files, options=[], skip=[], only=[], module_name=None): # Copy files dst_sources = [] + f2py_sources = [] for fn in source_files: if not os.path.isfile(fn): raise RuntimeError("%s is not a file" % fn) @@ -112,16 +115,14 @@ def build_module(source_files, options=[], skip=[], only=[], module_name=None): shutil.copyfile(fn, dst) dst_sources.append(dst) - fn = os.path.join(os.path.dirname(fn), '.f2py_f2cmap') - if os.path.isfile(fn): - dst = os.path.join(d, os.path.basename(fn)) - if not os.path.isfile(dst): - shutil.copyfile(fn, dst) + base, ext = os.path.splitext(dst) + if ext in ('.f90', '.f', '.c', '.pyf'): + f2py_sources.append(dst) # Prepare options if module_name is None: module_name = get_temp_module_name() - f2py_opts = ['-c', '-m', module_name] + options + dst_sources + f2py_opts = ['-c', '-m', module_name] + options + f2py_sources if skip: f2py_opts += ['skip:'] + skip if only: @@ -203,14 +204,20 @@ def _get_compiler_status(): """) code = code % dict(syspath=repr(sys.path)) - with temppath(suffix='.py') as script: + tmpdir = tempfile.mkdtemp() + try: + script = os.path.join(tmpdir, 'setup.py') + with open(script, 'w') as f: f.write(code) - cmd = [sys.executable, script, 'config'] + cmd = [sys.executable, 'setup.py', 'config'] p = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + stderr=subprocess.STDOUT, + cwd=tmpdir) out, err = p.communicate() + finally: + shutil.rmtree(tmpdir) m = re.search(br'COMPILERS:(\d+),(\d+),(\d+)', out) if m: |