[Numpy-svn] r3289 - in trunk/numpy/f2py/lib: . parser

numpy-svn at scipy.org numpy-svn at scipy.org
Sun Oct 8 01:38:06 CDT 2006


Author: pearu
Date: 2006-10-08 01:37:50 -0500 (Sun, 08 Oct 2006)
New Revision: 3289

Removed:
   trunk/numpy/f2py/lib/generate_pyobj_tofrom_funcs.py
Modified:
   trunk/numpy/f2py/lib/parser/typedecl_statements.py
   trunk/numpy/f2py/lib/py_wrap_subprogram.py
   trunk/numpy/f2py/lib/py_wrap_type.py
   trunk/numpy/f2py/lib/test_scalar_in_out.py
   trunk/numpy/f2py/lib/wrapper_base.py
Log:
F2PY G3: added support and tests for character*(*) types.

Deleted: trunk/numpy/f2py/lib/generate_pyobj_tofrom_funcs.py
===================================================================
--- trunk/numpy/f2py/lib/generate_pyobj_tofrom_funcs.py	2006-10-07 18:05:18 UTC (rev 3288)
+++ trunk/numpy/f2py/lib/generate_pyobj_tofrom_funcs.py	2006-10-08 06:37:50 UTC (rev 3289)
@@ -1,131 +0,0 @@
-"""
-Generate
-  int pyobj_to_<ctype>(PyObject* obj, <ctype>* value)
-  PyObject* pyobj_from_<stype>(<ctype>* value)
-functions.
-"""
-__all__ = ['pyobj_to_npy_scalar','pyobj_to_f2py_string','pyobj_from_npy_scalar']
-
-from parser.api import CHAR_BIT
-
-def pyobj_from_npy_int(ctype):
-    dtype = ctype.upper()
-    cls = 'Int'+ctype[7:]
-    return '''\
-static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value) {
-  PyObject* obj = PyArrayScalar_New(%(cls)s);
-  if (obj==NULL) /* TODO: set exception */ return NULL;
-  PyArrayScalar_ASSIGN(obj,%(cls)s,*value);
-  return obj;
-}
-''' % (locals())
-
-def pyobj_from_npy_float(ctype):
-    dtype = ctype.upper()
-    cls = 'Float'+ctype[9:]
-    return '''\
-/* depends: SCALARS_IN_BITS2.cpp */
-static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value) {
-  PyObject* obj = PyArrayScalar_New(%(cls)s);
-  if (obj==NULL) /* TODO: set exception */ return NULL;
-  PyArrayScalar_ASSIGN(obj,%(cls)s,*value);
-  return obj;
-}
-''' % (locals())
-
-def pyobj_from_npy_complex(ctype):
-    dtype = ctype.upper()
-    cls = 'Complex'+ctype[11:]
-    return '''\
-/* depends: SCALARS_IN_BITS2.cpp */
-static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value) {
-  PyObject* obj = PyArrayScalar_New(%(cls)s);
-  if (obj==NULL) /* TODO: set exception */ return NULL;
-  PyArrayScalar_ASSIGN(obj,%(cls)s,*value);
-  return obj;
-}
-''' % (locals())
-
-def pyobj_from_f2py_type(ctype):
-    ctype_bits = int(ctype[10:])
-    raise NotImplementedError,`ctype`
-    return '''\
-static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value) {
-  fprintf(stderr,"In pyobj_from_%(ctype)s (%%p)\\n", value);
-}
-'''
-
-
-
-def pyobj_to_npy_int(ctype):
-    Cls = ctype[4].upper()+ctype[5:]
-    ctype_bits = int(ctype[7:])
-    CTYPE = ctype.upper()
-    return capi_code_template_scalar % (locals())
-
-def pyobj_to_npy_float(ctype):
-    Cls = ctype[4].upper()+ctype[5:]
-    ctype_bits = int(ctype[9:])
-    CTYPE = ctype.upper()
-    return capi_code_template_scalar % (locals())
-
-def pyobj_to_npy_complex(ctype):
-    ctype_bits = int(ctype[11:])
-    cfloat_bits = ctype_bits/2
-    return '''
-/* depends: pyobj_to_Py_complex.c */
-#if NPY_BITSOF_DOUBLE >= %(cfloat_bits)s
-static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
-  int return_value = 0;
-  Py_complex c;
-#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
-  fprintf(stderr,"pyobj_to_%(ctype)s(type=%%s)\\n",PyString_AS_STRING(PyObject_Repr(PyObject_Type(obj))));
-#endif
-  if (pyobj_to_Py_complex(obj,&c)) {
-    (*value).real = (npy_float%(cfloat_bits)s)c.real;
-    (*value).imag = (npy_float%(cfloat_bits)s)c.imag;
-    return_value = 1;
-  }
-#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
-  fprintf(stderr,"pyobj_to_%(ctype)s: return_value=%%d, PyErr_Occurred()=%%p\\n", return_value, PyErr_Occurred());
-#endif
-  return return_value;
-}
-#else
-#error, "NOTIMPLEMENTED pyobj_to_%(ctype)s"
-#endif
-''' % (locals())
-
-def pyobj_to_npy_scalar(ctype):
-    if ctype.startswith('npy_int'):
-        return dict(c_code=pyobj_to_npy_int(ctype))
-    elif ctype.startswith('npy_float'):
-        return dict(c_code=pyobj_to_npy_float(ctype))
-    elif ctype.startswith('npy_complex'):
-        return dict(c_code=pyobj_to_npy_complex(ctype))
-    raise NotImplementedError,`ctype`
-
-def pyobj_to_f2py_string(ctype):
-    ctype_bits = int(ctype[11:])
-    ctype_bytes = ctype_bits / CHAR_BIT
-    return dict(
-        c_code = '''
-/* depends: pyobj_to_string_len.c */
-static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
-  return pyobj_to_string_len(obj, (f2py_string*)value, %(ctype_bytes)s);
-}
-''' % (locals()),
-        typedef = ['typedef char * f2py_string;',
-                         'typedef struct { char data[%(ctype_bytes)s]; } %(ctype); ' % (locals())],
-        header = ['#include <string.h>'],
-        )
-
-def pyobj_from_npy_scalar(ctype):
-    if ctype.startswith('npy_int'):
-        return dict(c_code=pyobj_from_npy_int(ctype))
-    elif ctype.startswith('npy_float'):
-        return dict(c_code=pyobj_from_npy_float(ctype))
-    elif ctype.startswith('npy_complex'):
-        return dict(c_code=pyobj_from_npy_complex(ctype))
-    raise NotImplementedError,`ctype`
-

Modified: trunk/numpy/f2py/lib/parser/typedecl_statements.py
===================================================================
--- trunk/numpy/f2py/lib/parser/typedecl_statements.py	2006-10-07 18:05:18 UTC (rev 3288)
+++ trunk/numpy/f2py/lib/parser/typedecl_statements.py	2006-10-08 06:37:50 UTC (rev 3289)
@@ -445,7 +445,10 @@
     default_kind = 1
 
     def get_bit_size(self):
-        return CHAR_BIT * int(self.get_length()) * int(self.get_kind())
+        length = self.get_length()
+        if length=='*':
+            return 0  # model for character*(*)
+        return CHAR_BIT * int(length) * int(self.get_kind())
 
     def get_c_type(self):
         return 'f2py_string%s' % (self.get_bit_size())

Modified: trunk/numpy/f2py/lib/py_wrap_subprogram.py
===================================================================
--- trunk/numpy/f2py/lib/py_wrap_subprogram.py	2006-10-07 18:05:18 UTC (rev 3288)
+++ trunk/numpy/f2py/lib/py_wrap_subprogram.py	2006-10-08 06:37:50 UTC (rev 3289)
@@ -31,10 +31,9 @@
   volatile int f2py_success = 1;
   %(decl_list)s
   static char *capi_kwlist[] = {%(kw_clist+optkw_clist+extrakw_clist+["NULL"])s};
-  if (!PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,
-                                   "%(pyarg_format_elist)s",
-                                   %(["capi_kwlist"]+pyarg_obj_clist)s))
-     return NULL;
+  if (PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,
+                                  "%(pyarg_format_elist)s",
+                                   %(["capi_kwlist"]+pyarg_obj_clist)s)) {
   %(frompyobj_list)s
   %(call_list)s
   f2py_success = !PyErr_Occurred();
@@ -46,6 +45,7 @@
   }
   %(clean_call_list)s
   %(clean_frompyobj_list)s
+  }
   return capi_buildvalue;
 }
 '''
@@ -79,17 +79,28 @@
         self.clean_frompyobj_list = []
 
         args_f = []
+        extra_args_f = []
         for argname in block.args:
             var = block.a.variables[argname]
             typedecl = var.get_typedecl()
             PythonCAPIType(parent, typedecl)
             ctype = typedecl.get_c_type()
-            self.decl_list.append('%s %s;' % (ctype, argname))
+            if ctype=='f2py_string0':
+                self.decl_list.append('%s %s = {NULL,0};' % (ctype, argname))
+            else:
+                self.decl_list.append('%s %s;' % (ctype, argname))
             self.kw_list.append('"%s"' % (argname))
             self.pyarg_format_list.append('O&')
             self.pyarg_obj_list.append('\npyobj_to_%s, &%s' % (ctype, argname))
             if 1: # is_scalar
-                args_f.append('&'+argname)
+                if ctype=='f2py_string0':
+                    args_f.append('%s.data' % argname)
+                    extra_args_f.append('%s.len' % argname)
+                    self.clean_frompyobj_list.append(\
+                        'if (%s.len) free(%s.data);' % (argname,argname))
+                else:
+                    args_f.append('&'+argname)
+                
             else:
                 args_f.append(argname)
             if var.is_intent_out(): # and is_scalar
@@ -97,7 +108,7 @@
                 self.return_obj_list.append('\npyobj_from_%s, &%s' % (ctype, argname))
 
         WrapperCPPMacro(parent, 'F_FUNC')
-        self.call_list.append('%s_f(%s);' % (name,', '.join(args_f)))
+        self.call_list.append('%s_f(%s);' % (name,', '.join(args_f+extra_args_f)))
 
         self.clean_pyobjfrom_list.reverse()
         self.clean_call_list.reverse()

Modified: trunk/numpy/f2py/lib/py_wrap_type.py
===================================================================
--- trunk/numpy/f2py/lib/py_wrap_type.py	2006-10-07 18:05:18 UTC (rev 3288)
+++ trunk/numpy/f2py/lib/py_wrap_type.py	2006-10-08 06:37:50 UTC (rev 3289)
@@ -238,6 +238,52 @@
 #endif
   return return_value;
 }
+'''
+    capi_code_template_string0_scalar = '''
+static PyObject* pyobj_from_%(ctype)s(%(ctype)s* value) {
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+  fprintf(stderr,"pyobj_from_%(ctype)s(value->len=%%d, value->data=\'%%s\')\\n",value->len, value->data);
+#endif
+  PyArray_Descr* descr = PyArray_DescrNewFromType(NPY_STRING);
+  descr->elsize = value->len;
+  PyObject* obj = PyArray_Scalar(value->data, descr, NULL);
+  if (obj==NULL) /* TODO: set exception */ return NULL;
+  return obj;
+}
+
+static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
+  int return_value = 0;
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+  fprintf(stderr,"pyobj_to_%(ctype)s(type=%%s)\\n",PyString_AS_STRING(PyObject_Repr(PyObject_Type(obj))));
+#endif
+  if (PyString_Check(obj)) {
+    value->len = PyString_GET_SIZE(obj);
+    value->data = malloc(value->len*sizeof(char));
+    return_value = !! strncpy(value->data,PyString_AS_STRING(obj),value->len);
+  } else {
+    return_value = pyobj_to_%(ctype)s(PyObject_Str(obj), value);
+  }
+  if (!return_value && !PyErr_Occurred()) {
+    PyObject* r = PyString_FromString("Failed to convert ");
+    PyString_ConcatAndDel(&r, PyObject_Repr(PyObject_Type(obj)));
+    PyString_ConcatAndDel(&r, PyString_FromString(" to C %(ctype)s"));
+    PyErr_SetObject(PyExc_TypeError,r);
+  }
+#if defined(F2PY_DEBUG_PYOBJ_TOFROM)
+  if (PyErr_Occurred()) {
+    if (return_value)
+      fprintf(stderr,"pyobj_to_%(ctype)s:INCONSISTENCY with return_value=%%d and PyErr_Occurred()=%%p\\n",return_value, PyErr_Occurred());
+    else
+      fprintf(stderr,"pyobj_to_%(ctype)s: PyErr_Occurred()=%%p\\n", PyErr_Occurred());
+  } else {
+    if (return_value)
+      fprintf(stderr,"pyobj_to_%(ctype)s: value->len=%%d, value->data=\'%%s\'\\n", value->len, value->data);
+    else
+      fprintf(stderr,"pyobj_to_%(ctype)s:INCONSISTENCY with return_value=%%d and PyErr_Occurred()=%%p\\n",return_value, PyErr_Occurred());
+  }
+#endif
+  return return_value;
+}
 ''' 
     _defined = []
     def __init__(self, parent, typedecl):
@@ -270,12 +316,21 @@
                 self.capi_code_template = self.capi_code_template_logical_scalar
                 parent.apply_templates(self)
                 return
+            if ctype == 'f2py_string0':
+                self.header_template = '''
+#include <string.h>
+typedef struct { char* data; size_t len; } %(ctype)s;
+'''
+                self.capi_code_template = self.capi_code_template_string0_scalar
+                parent.apply_templates(self)
+                return
+                raise NotImplementedError,`name,ctype`
             if ctype.startswith('f2py_string'):
                 self.bits = bits = int(ctype[11:])
                 self.bytes = bits/CHAR_BIT
                 self.header_template = '''
 #include <string.h>
-typedef struct { char data[%(bytes)s] } %(ctype)s;
+typedef struct { char data[%(bytes)s]; } %(ctype)s;
 '''
                 self.capi_code_template = self.capi_code_template_string_scalar
                 parent.apply_templates(self)

Modified: trunk/numpy/f2py/lib/test_scalar_in_out.py
===================================================================
--- trunk/numpy/f2py/lib/test_scalar_in_out.py	2006-10-07 18:05:18 UTC (rev 3288)
+++ trunk/numpy/f2py/lib/test_scalar_in_out.py	2006-10-08 06:37:50 UTC (rev 3289)
@@ -1,5 +1,8 @@
 #!/usr/bin/env python
+"""
 
+"""
+
 import os
 import sys
 from numpy.testing import *
@@ -100,6 +103,13 @@
 !f2py intent(in,out) a
       a(1:2) = "12"
       end
+      subroutine foostringstar(a)
+      character*(*) a
+!f2py intent(in,out) a
+      if (len(a).gt.0) then
+        a(1:1) = "1"
+      endif
+      end
 '''
 
 # tester note: set rebuild=True when changing fortan_code and for SVN
@@ -518,6 +528,15 @@
         r = func([1])
         assert isinstance(r,string0),`type(r)`
         assert_equal(r,'12]  ')
+
+    def check_foo_string0(self, level=1):
+        i = string0('abcde')
+        e = string0('12cde')
+        func = m.foostringstar
+        r = func('abcde')
+        assert_equal(r,'1bcde')
+        r = func('')
+        assert_equal(r,'')
         
 if __name__ == "__main__":
     NumpyTest().run()

Modified: trunk/numpy/f2py/lib/wrapper_base.py
===================================================================
--- trunk/numpy/f2py/lib/wrapper_base.py	2006-10-07 18:05:18 UTC (rev 3288)
+++ trunk/numpy/f2py/lib/wrapper_base.py	2006-10-08 06:37:50 UTC (rev 3289)
@@ -109,7 +109,9 @@
     def apply_templates(self, child):
         for n in self.list_names:
             l = getattr(self,n + '_list')
-            l.append(child.apply_attributes(getattr(child, n+'_template','')))
+            c = child.apply_attributes(getattr(child, n+'_template',''))
+            if c:
+                l.append(c)
         return
 
 class WrapperCPPMacro(WrapperBase):



More information about the Numpy-svn mailing list