[Numpy-svn] r3947 - trunk/numpy/f2py/lib/extgen

numpy-svn@scip... numpy-svn@scip...
Sun Aug 5 16:14:00 CDT 2007


Author: pearu
Date: 2007-08-05 16:13:49 -0500 (Sun, 05 Aug 2007)
New Revision: 3947

Added:
   trunk/numpy/f2py/lib/extgen/converters.py
Modified:
   trunk/numpy/f2py/lib/extgen/__init__.py
   trunk/numpy/f2py/lib/extgen/base.py
   trunk/numpy/f2py/lib/extgen/c_code.py
   trunk/numpy/f2py/lib/extgen/c_type.py
   trunk/numpy/f2py/lib/extgen/doc.txt
   trunk/numpy/f2py/lib/extgen/extension_module.py
   trunk/numpy/f2py/lib/extgen/pyc_argument.py
   trunk/numpy/f2py/lib/extgen/pyc_function.py
Log:
ExtGen: impl PObject* and C int support, minor improvements.

Modified: trunk/numpy/f2py/lib/extgen/__init__.py
===================================================================
--- trunk/numpy/f2py/lib/extgen/__init__.py	2007-08-05 15:23:30 UTC (rev 3946)
+++ trunk/numpy/f2py/lib/extgen/__init__.py	2007-08-05 21:13:49 UTC (rev 3947)
@@ -2,10 +2,10 @@
 Python Extensions Generator
 """
 
-__all__ = ['ExtensionModule', 'PyCFunction', 'PyCArgument',
+__all__ = ['Component', 'ExtensionModule', 'PyCFunction', 'PyCArgument',
            'CCode']
 
-import base
+from base import Component
 from extension_module import ExtensionModule
 from pyc_function import PyCFunction
 from pyc_argument import PyCArgument
@@ -16,3 +16,5 @@
 __all__ += c_type.__all__
 
 import predefined_components
+import converters
+c_type.register()

Modified: trunk/numpy/f2py/lib/extgen/base.py
===================================================================
--- trunk/numpy/f2py/lib/extgen/base.py	2007-08-05 15:23:30 UTC (rev 3946)
+++ trunk/numpy/f2py/lib/extgen/base.py	2007-08-05 21:13:49 UTC (rev 3947)
@@ -43,7 +43,7 @@
         obj.parent = None
         obj.containers = {} # holds containers for named string lists
         obj.components = [] # holds pairs (<Component subclass instance>, <container name or None>)
-        obj.initialize(*args, **kws)    # initialize from constructor arguments
+        obj = obj.initialize(*args, **kws)    # initialize from constructor arguments
         return obj
 
     def initialize(self, *components, **options):
@@ -52,7 +52,7 @@
         """
         # self.myattr = ..
         # map(self.add, components)
-        return
+        return self
 
     @property
     def provides(self):
@@ -73,7 +73,7 @@
         print >> sys.stderr, message
 
     def __repr__(self):
-        return '%s%s' % (self.__class__.__name__, `self.containers`)
+        return '%s(%s)' % (self.__class__.__name__, `self.containers`)
 
     def __getattr__(self, attr):
         if attr.startswith('container_'): # convenience feature

Modified: trunk/numpy/f2py/lib/extgen/c_code.py
===================================================================
--- trunk/numpy/f2py/lib/extgen/c_code.py	2007-08-05 15:23:30 UTC (rev 3946)
+++ trunk/numpy/f2py/lib/extgen/c_code.py	2007-08-05 21:13:49 UTC (rev 3947)
@@ -14,6 +14,7 @@
     def initialize(self, *lines, **options):
         self.lines = []
         map(self.add, lines)
+        return self
 
     def update_containers(self):
         CCodeLines = self.get_container('CCodeLines')

Modified: trunk/numpy/f2py/lib/extgen/c_type.py
===================================================================
--- trunk/numpy/f2py/lib/extgen/c_type.py	2007-08-05 15:23:30 UTC (rev 3946)
+++ trunk/numpy/f2py/lib/extgen/c_type.py	2007-08-05 21:13:49 UTC (rev 3947)
@@ -22,20 +22,35 @@
     def initialize(self, name, *components):
         self.name = name
         map(self.add, components)
-
+        return self
+    
     def update_containers(self):
         self.container_TypeDef += self.evaluate(self.template_typedef)
 
     def __str__(self):
         return self.name
 
+    def get_pyret_fmt(self, input_intent_hide = True):
+        if input_intent_hide: return 'O'
+        return 'N'
+
+    def get_pyret_arg(self, cname):
+        return cname
+
+    def get_pyarg_fmt(self):
+        return 'O'
+
+    def get_pyarg_arg(self, cname):
+        return '&%s' % (cname)
+
 class _CatchTypeDef(Component): # for doctest
     template = '%(TypeDef)s'
     default_container_label = '<IGNORE>'
     container_options = dict(TypeDef=dict(default=''))
     def initialize(self, ctype):
         self.add(ctype)
-
+        return self
+    
 class CType(CTypeBase):
 
     """ CType(<name>)
@@ -50,8 +65,12 @@
     """
 
     def initialize(self, name):
+        try:
+            return Component.get(name)
+        except KeyError:
+            pass
         self.name = name
-
+        return self
     def update_containers(self):
         pass
 
@@ -73,7 +92,8 @@
         if isinstance(ctype, str): ctype = CType(ctype)
         self.ctype_name = ctype.name
         self.add(ctype)
-
+        return self
+    
 class CTypeFuncAlias(CTypeBase):
 
     """
@@ -126,6 +146,7 @@
         self.name = '%s_ptr' % (ctype)
         self.ctype_name = ctype.name
         self.add(ctype)
+        return self
 
 class CTypeStruct(CTypeBase):
 
@@ -161,6 +182,7 @@
     def initialize(self, name, *components):
         self.name = name
         map(self.add, components)
+        return self
 
 class CDecl(Component):
 
@@ -191,32 +213,41 @@
         if isinstance(ctype, str): ctype = CType(ctype)
         self.add(ctype, 'CTypeName')
         map(self.add, names)
+        return self
 
+class PyObjectPtr(CType):
+    name = provides = 'PyObject*'
+    def initialize(self): return self
+    def set_pyarg_decl(self, arg):
+        if arg.input_intent=='hide':
+            arg += CDecl(self, '%s = Py_None' % (arg.pycvar))
+        else:
+            arg += CDecl(self, '%s = NULL' % (arg.pycvar))
+    def get_pyarg_fmt(self, arg): return 'O'
+    def get_pyarg_obj(self, arg): return '&' + arg.pycvar
+    def get_pyret_fmt(self, arg):
+        if arg.input_intent=='hide':
+            return 'O'
+        return 'N'
+    def get_pyret_obj(self, arg): return arg.pycvar
 
-if 0:
+class CInt(CType):
+    name = provides = 'int'
+    def initialize(self): return self
+    def set_pyarg_decl(self, arg):
+        #arg += CDecl(Component.get('PyObject*'), '%s = NULL' % (arg.pycvar))
+        arg += CDecl(self, '%s = 0' % (arg.cvar))
+    def get_pyarg_fmt(self, arg): return 'i'
+    def get_pyarg_obj(self, arg): return '&' + arg.cvar
+    def get_pyret_fmt(self, arg): return 'i'
+    def get_pyret_obj(self, arg): return arg.cvar
 
-    def local_generate(self, params=None):
-        container = self.get_container('CAPICode')
-        code = '''\
-static int pyobj_to_int(PyObject *obj, int* value) {
-  int status = 1;
-  if (PyInt_Check(obj)) {
-    *value = PyInt_AS_LONG(obj);
-    status = 0;
-  }
-  return status;
-}
-'''
-        container.add('pyobj_to_int', code)
-        code = '''\
-static PyObject* pyobj_from_int(int* value) {
-  return PyInt_FromLong(*value);
-}
-'''
-        container.add('pyobj_from_int', code)
+def register():
+    Component.register(
+        PyObjectPtr(),
+        CInt(),
+        )
 
-        return self.declare(params)
-
 def _test():
     import doctest
     doctest.testmod()

Added: trunk/numpy/f2py/lib/extgen/converters.py
===================================================================
--- trunk/numpy/f2py/lib/extgen/converters.py	2007-08-05 15:23:30 UTC (rev 3946)
+++ trunk/numpy/f2py/lib/extgen/converters.py	2007-08-05 21:13:49 UTC (rev 3947)
@@ -0,0 +1,22 @@
+
+from base import Component
+from c_code import CCode
+
+Component.register(
+    CCode('''
+static int pyobj_to_int(PyObject *obj, int* value) {
+  int status = 1;
+  if (PyInt_Check(obj)) {
+    *value = PyInt_AS_LONG(obj);
+    status = 0;
+  }
+  return status;
+}
+''', provides='pyobj_to_int'),
+    CCode('''\
+static PyObject* pyobj_from_int(int* value) {
+  return PyInt_FromLong(*value);
+}
+''', provides='pyobj_from_int'),
+
+    )

Modified: trunk/numpy/f2py/lib/extgen/doc.txt
===================================================================
--- trunk/numpy/f2py/lib/extgen/doc.txt	2007-08-05 15:23:30 UTC (rev 3946)
+++ trunk/numpy/f2py/lib/extgen/doc.txt	2007-08-05 21:13:49 UTC (rev 3947)
@@ -135,7 +135,8 @@
   `.default_component_class_name`, `.template` attributes.
 
 - In `.initialize()` method one can process constructor options,
-  set new attributes and add predefined components.
+  set new attributes and add predefined components. It must
+  return a `Component` instance.
 
 - In `.init_containers()` and `.update_containers()` methods
   one may retrive containers from parents via `.get_container(<name>)`
@@ -298,3 +299,7 @@
 
 - `'import_array'` - code for importing numpy package to extension
   module.
+
+- `'int'` - C `int` type support
+
+- `'PyObject*'` - `PyObject*` type support
\ No newline at end of file

Modified: trunk/numpy/f2py/lib/extgen/extension_module.py
===================================================================
--- trunk/numpy/f2py/lib/extgen/extension_module.py	2007-08-05 15:23:30 UTC (rev 3946)
+++ trunk/numpy/f2py/lib/extgen/extension_module.py	2007-08-05 21:13:49 UTC (rev 3947)
@@ -145,7 +145,7 @@
             self.add(Component.get('arrayobject.h'), 'Header')
             self.add(Component.get('import_array'), 'ModuleInit')
         map(self.add, components)
-        return
+        return self
 
     def update_containers(self):
         if self.title is not None:

Modified: trunk/numpy/f2py/lib/extgen/pyc_argument.py
===================================================================
--- trunk/numpy/f2py/lib/extgen/pyc_argument.py	2007-08-05 15:23:30 UTC (rev 3946)
+++ trunk/numpy/f2py/lib/extgen/pyc_argument.py	2007-08-05 21:13:49 UTC (rev 3947)
@@ -4,7 +4,7 @@
 class PyCArgument(Component):
 
     """
-    PyCArgument(<name>, *components, provides=..,
+    PyCArgument(<name>, ctype, *components, provides=..,
                 input_intent = 'required' | 'optional' | 'extra' | 'hide',
                 output_intent = 'hide' | 'return',
                 input_title = None,
@@ -17,7 +17,9 @@
 
     template = '%(name)s'
 
-    def initialize(self, name, *components, **options):
+    component_container_map = dict(CDecl = 'Decl')
+
+    def initialize(self, name, ctype=None, *components, **options):
         self.name = name
         self._provides = options.pop('provides',
                                      '%s_%s' % (self.__class__.__name__, name))
@@ -31,23 +33,20 @@
         if options: self.warning('%s unused options: %s\n' % (self.__class__.__name__, options))
         
         map(self.add, components)
+        self.cvar = name
+        self.pycvar = name + '_pyc'
 
-    def get_ctype(self):
-        for component, container_label in self.components:
-            if isinstance(component, Component.CTypeBase):
-                return component
-        return
-
-    def init_containers(self):
-        ctype = self.get_ctype()
         if ctype is None:
-            self.cname = self.name
-        else:
-            self.cname = self.provides
+            ctype = Component.get('PyObject*')
+        self.ctype = ctype
+        ctype.set_pyarg_decl(self)
+        #self.add(ctype)
 
+        return self
+            
     def update_containers(self):
         evaluate = self.evaluate
-        ctype = self.get_ctype()
+        ctype = self.ctype
 
         # get containers
         ReqArgs = self.container_ReqArgs
@@ -59,8 +58,6 @@
         OptArgsDoc = self.container_OptArgsDoc
         ExtArgsDoc = self.container_ExtArgsDoc
 
-        Decl = self.container_Decl
-
         ReqKWList = self.container_ReqKWList
         OptKWList = self.container_OptKWList
         ExtKWList = self.container_ExtKWList
@@ -78,58 +75,50 @@
         RetObj = self.container_RetObj
 
         # update PyCFunction containers
-        Decl.add('PyObject* %s = NULL;' % (self.cname))
-        if ctype is not None:
-            Decl.add(ctype.declare(self.name))
-        
-        if ctype is None:
-            input_doc_title = '%s - %s' % (self.name, self.input_title)
-            output_doc_title = '%s - %s' % (self.name, self.output_title)
-            if self.input_description is not None:
-                input_doc_descr = '  %s' % (self.input_description.replace('\n','\\n'))
-            else:
-                input_doc_descr = None
-            if self.output_description is not None:
-                output_doc_descr = '  %s' % (self.output_description.replace('\n','\\n'))
-            else:
-                output_doc_descr = None
-            iopt = (self.name, '"%s"' % (self.name), 'O', '&%s' % (self.cname), input_doc_title, input_doc_descr)
-            ropt = (self.name, 'N', self.cname, output_doc_title, output_doc_descr)
+
+        input_doc_title = '%s - %s' % (self.name, self.input_title)
+        output_doc_title = '%s - %s' % (self.name, self.output_title)
+        if self.input_description is not None:
+            input_doc_descr = '  %s' % (self.input_description)
         else:
-            raise NotImplementedError('ctype=%r' % (ctype))
-            
+            input_doc_descr = None
+        if self.output_description is not None:
+            output_doc_descr = '  %s' % (self.output_description)
+        else:
+            output_doc_descr = None
+
         if self.input_intent=='required':
-            ReqArgs.add(iopt[0])
-            ReqKWList.add(iopt[1])
-            ReqPyArgFmt.add(iopt[2])
-            ReqPyArgObj.add(iopt[3])
-            ReqArgsDoc.add(iopt[4])
-            ReqArgsDoc.add(iopt[5])
+            ReqArgs += self.name
+            ReqKWList += '"' + self.name + '"'
+            ReqPyArgFmt += ctype.get_pyarg_fmt(self)
+            ReqPyArgObj += ctype.get_pyarg_obj(self)
+            ReqArgsDoc += input_doc_title
+            ReqArgsDoc += input_doc_descr
         elif self.input_intent=='optional':
-            OptArgs.add(iopt[0])
-            OptKWList.add(iopt[1])
-            OptPyArgFmt.add(iopt[2])
-            OptPyArgObj.add(iopt[3])
-            OptArgsDoc.add(iopt[4])
-            OptArgsDoc.add(iopt[5])
+            OptArgs += self.name
+            OptKWList += '"' + self.name + '"'
+            OptPyArgFmt += ctype.get_pyarg_fmt(self)
+            OptPyArgObj += ctype.get_pyarg_obj(self)
+            OptArgsDoc += input_doc_title
+            OptArgsDoc += input_doc_descr
         elif self.input_intent=='extra':
-            ExtArgs.add(iopt[0])
-            ExtKWList.add(iopt[1])
-            ExtPyArgFmt.add(iopt[2])
-            ExtPyArgObj.add(iopt[3])
-            ExtArgsDoc.add(iopt[4])
-            ExtArgsDoc.add(iopt[5])
+            ExtArgs += self.name
+            ExtKWList += '"' + self.name + '"'
+            ExtPyArgFmt += ctype.get_pyarg_fmt(self)
+            ExtPyArgObj += ctype.get_pyarg_obj(self)
+            ExtArgsDoc += input_doc_title
+            ExtArgsDoc += input_doc_descr
         elif self.input_intent=='hide':
-            ropt = (self.name, 'O', self.cname, output_doc_title, output_doc_descr)
+            pass
         else:
             raise NotImplementedError('input_intent=%r' % (self.input_intent))
             
         if self.output_intent=='return':
-            RetArgs.add(ropt[0])
-            RetFmt.add(ropt[1])
-            RetObj.add(ropt[2])
-            RetDoc.add(ropt[3])
-            RetDoc.add(ropt[4])
+            RetArgs += self.name
+            RetFmt += ctype.get_pyret_fmt(self)
+            RetObj += ctype.get_pyret_obj(self)
+            RetDoc += output_doc_title
+            RetDoc += output_doc_descr
         elif self.output_intent=='hide':
             pass
         else:

Modified: trunk/numpy/f2py/lib/extgen/pyc_function.py
===================================================================
--- trunk/numpy/f2py/lib/extgen/pyc_function.py	2007-08-05 15:23:30 UTC (rev 3946)
+++ trunk/numpy/f2py/lib/extgen/pyc_function.py	2007-08-05 21:13:49 UTC (rev 3947)
@@ -50,6 +50,8 @@
     <BLANKLINE>
       First line.
       2nd line.
+    >>> print foo.hello(1, 2)
+    (1, None)
     """
 
     container_options = dict(\
@@ -97,6 +99,7 @@
         ReqPyArgFmt = dict(separator=''),
         OptPyArgFmt = dict(separator=''),
         ExtPyArgFmt = dict(separator=''),
+        OptExtPyArgFmt = dict(separator='', prefix='|', skip_prefix_when_empty=True),
         
         ReqPyArgObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True),
         OptPyArgObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True),
@@ -115,7 +118,8 @@
         )
 
     component_container_map = dict(CCode = 'Exec',
-                                   PyCArgument = 'Args')
+                                   PyCArgument = 'Args',
+                                   CDecl = 'Decl')
 
     template = '''
 static char %(pyc_name)s_doc[] =
@@ -135,7 +139,7 @@
   volatile int capi_success = 1;
   %(Decl)s
   static char *capi_kwlist[] = {%(ReqKWList)s%(OptKWList)s%(ExtKWList)sNULL};
-  if (PyArg_ParseTupleAndKeywords(pyc_args, pyc_keywds,"%(ReqPyArgFmt)s%(OptPyArgFmt)s%(ExtPyArgFmt)s",
+  if (PyArg_ParseTupleAndKeywords(pyc_args, pyc_keywds,"%(ReqPyArgFmt)s%(OptExtPyArgFmt)s",
                                   capi_kwlist%(ReqPyArgObj)s%(OptPyArgObj)s%(ExtPyArgObj)s)) {
     %(FromPyObj)s
     %(Exec)s
@@ -163,6 +167,7 @@
         if options: self.warning('%s unused options: %s\n' % (self.__class__.__name__, options))
         
         map(self.add, components)
+        return self
 
     def init_containers(self):
         return
@@ -177,6 +182,9 @@
         OptArgs = self.container_OptArgs
         ExtArgs = self.container_ExtArgs
         OptExtArgs = self.container_OptExtArgs
+        OptPyArgFmt = self.container_OptPyArgFmt
+        ExtPyArgFmt = self.container_ExtPyArgFmt
+        OptExtPyArgFmt = self.container_OptExtPyArgFmt
         ModuleMethod = self.container_ModuleMethod
         ModuleFuncDoc = self.container_ModuleFuncDoc
 
@@ -186,6 +194,7 @@
 
         # update local containers:
         OptExtArgs += OptArgs + ExtArgs
+        OptExtPyArgFmt += OptPyArgFmt + ExtPyArgFmt
         ModuleFuncDoc += evaluate('%(name)s(%(ReqArgs)s%(OptExtArgs)s) -> %(RetArgs)s')
         if self.title is not None:
             FuncTitle += self.title



More information about the Numpy-svn mailing list