summaryrefslogtreecommitdiff
path: root/numpy/f2py
diff options
context:
space:
mode:
authorPearu Peterson <pearu.peterson@gmail.com>2007-08-05 21:13:49 +0000
committerPearu Peterson <pearu.peterson@gmail.com>2007-08-05 21:13:49 +0000
commitc7f8d0d531e263969c80f861df1b3e41bff6683b (patch)
treeb8d3a2a9da86e0843fc22c662e10ff96d9879d8f /numpy/f2py
parent4196b728240d9225c38a6d630b5c117194c7577e (diff)
downloadnumpy-c7f8d0d531e263969c80f861df1b3e41bff6683b.tar.gz
ExtGen: impl PObject* and C int support, minor improvements.
Diffstat (limited to 'numpy/f2py')
-rw-r--r--numpy/f2py/lib/extgen/__init__.py6
-rw-r--r--numpy/f2py/lib/extgen/base.py6
-rw-r--r--numpy/f2py/lib/extgen/c_code.py1
-rw-r--r--numpy/f2py/lib/extgen/c_type.py89
-rw-r--r--numpy/f2py/lib/extgen/converters.py22
-rw-r--r--numpy/f2py/lib/extgen/doc.txt7
-rw-r--r--numpy/f2py/lib/extgen/extension_module.py2
-rw-r--r--numpy/f2py/lib/extgen/pyc_argument.py107
-rw-r--r--numpy/f2py/lib/extgen/pyc_function.py13
9 files changed, 156 insertions, 97 deletions
diff --git a/numpy/f2py/lib/extgen/__init__.py b/numpy/f2py/lib/extgen/__init__.py
index 740793c9a..8c0d8e18b 100644
--- a/numpy/f2py/lib/extgen/__init__.py
+++ b/numpy/f2py/lib/extgen/__init__.py
@@ -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 @@ from c_type import *
__all__ += c_type.__all__
import predefined_components
+import converters
+c_type.register()
diff --git a/numpy/f2py/lib/extgen/base.py b/numpy/f2py/lib/extgen/base.py
index 6efe042d0..62367b154 100644
--- a/numpy/f2py/lib/extgen/base.py
+++ b/numpy/f2py/lib/extgen/base.py
@@ -43,7 +43,7 @@ class Component(object): # XXX: rename Component to Component
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 @@ class Component(object): # XXX: rename Component to Component
"""
# self.myattr = ..
# map(self.add, components)
- return
+ return self
@property
def provides(self):
@@ -73,7 +73,7 @@ class Component(object): # XXX: rename Component to Component
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
diff --git a/numpy/f2py/lib/extgen/c_code.py b/numpy/f2py/lib/extgen/c_code.py
index 898a048f9..cbb95e760 100644
--- a/numpy/f2py/lib/extgen/c_code.py
+++ b/numpy/f2py/lib/extgen/c_code.py
@@ -14,6 +14,7 @@ class CCode(Component):
def initialize(self, *lines, **options):
self.lines = []
map(self.add, lines)
+ return self
def update_containers(self):
CCodeLines = self.get_container('CCodeLines')
diff --git a/numpy/f2py/lib/extgen/c_type.py b/numpy/f2py/lib/extgen/c_type.py
index 157d227a7..6d75105f7 100644
--- a/numpy/f2py/lib/extgen/c_type.py
+++ b/numpy/f2py/lib/extgen/c_type.py
@@ -22,20 +22,35 @@ class CTypeBase(Component):
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 @@ class CType(CTypeBase):
"""
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 @@ class CTypeAlias(CTypeBase):
if isinstance(ctype, str): ctype = CType(ctype)
self.ctype_name = ctype.name
self.add(ctype)
-
+ return self
+
class CTypeFuncAlias(CTypeBase):
"""
@@ -126,6 +146,7 @@ class CTypePtr(CTypeBase):
self.name = '%s_ptr' % (ctype)
self.ctype_name = ctype.name
self.add(ctype)
+ return self
class CTypeStruct(CTypeBase):
@@ -161,6 +182,7 @@ typedef struct {
def initialize(self, name, *components):
self.name = name
map(self.add, components)
+ return self
class CDecl(Component):
@@ -191,31 +213,40 @@ class CDecl(Component):
if isinstance(ctype, str): ctype = CType(ctype)
self.add(ctype, 'CTypeName')
map(self.add, names)
-
-
-if 0:
-
- 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)
-
- return self.declare(params)
+ 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
+
+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 register():
+ Component.register(
+ PyObjectPtr(),
+ CInt(),
+ )
def _test():
import doctest
diff --git a/numpy/f2py/lib/extgen/converters.py b/numpy/f2py/lib/extgen/converters.py
new file mode 100644
index 000000000..182c95339
--- /dev/null
+++ b/numpy/f2py/lib/extgen/converters.py
@@ -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'),
+
+ )
diff --git a/numpy/f2py/lib/extgen/doc.txt b/numpy/f2py/lib/extgen/doc.txt
index c971f22c0..73908caca 100644
--- a/numpy/f2py/lib/extgen/doc.txt
+++ b/numpy/f2py/lib/extgen/doc.txt
@@ -135,7 +135,8 @@ tasks:
`.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 @@ using `Component.get(<provides>)` method:
- `'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
diff --git a/numpy/f2py/lib/extgen/extension_module.py b/numpy/f2py/lib/extgen/extension_module.py
index 4b4b2dd29..2336bc859 100644
--- a/numpy/f2py/lib/extgen/extension_module.py
+++ b/numpy/f2py/lib/extgen/extension_module.py
@@ -145,7 +145,7 @@ capi_error:
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:
diff --git a/numpy/f2py/lib/extgen/pyc_argument.py b/numpy/f2py/lib/extgen/pyc_argument.py
index d88a4c0d3..d834e406d 100644
--- a/numpy/f2py/lib/extgen/pyc_argument.py
+++ b/numpy/f2py/lib/extgen/pyc_argument.py
@@ -4,7 +4,7 @@ from base import Component
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 @@ class PyCArgument(Component):
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 @@ class PyCArgument(Component):
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 @@ class PyCArgument(Component):
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 @@ class PyCArgument(Component):
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:
diff --git a/numpy/f2py/lib/extgen/pyc_function.py b/numpy/f2py/lib/extgen/pyc_function.py
index daa5a0b94..65e18fc5a 100644
--- a/numpy/f2py/lib/extgen/pyc_function.py
+++ b/numpy/f2py/lib/extgen/pyc_function.py
@@ -50,6 +50,8 @@ class PyCFunction(Component):
<BLANKLINE>
First line.
2nd line.
+ >>> print foo.hello(1, 2)
+ (1, None)
"""
container_options = dict(\
@@ -97,6 +99,7 @@ class PyCFunction(Component):
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 @@ class PyCFunction(Component):
)
component_container_map = dict(CCode = 'Exec',
- PyCArgument = 'Args')
+ PyCArgument = 'Args',
+ CDecl = 'Decl')
template = '''
static char %(pyc_name)s_doc[] =
@@ -135,7 +139,7 @@ static PyObject*
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 @@ static PyObject*
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 @@ static PyObject*
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 @@ static PyObject*
# 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