diff options
author | Pearu Peterson <pearu.peterson@gmail.com> | 2007-08-05 21:13:49 +0000 |
---|---|---|
committer | Pearu Peterson <pearu.peterson@gmail.com> | 2007-08-05 21:13:49 +0000 |
commit | c7f8d0d531e263969c80f861df1b3e41bff6683b (patch) | |
tree | b8d3a2a9da86e0843fc22c662e10ff96d9879d8f /numpy/f2py | |
parent | 4196b728240d9225c38a6d630b5c117194c7577e (diff) | |
download | numpy-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__.py | 6 | ||||
-rw-r--r-- | numpy/f2py/lib/extgen/base.py | 6 | ||||
-rw-r--r-- | numpy/f2py/lib/extgen/c_code.py | 1 | ||||
-rw-r--r-- | numpy/f2py/lib/extgen/c_type.py | 89 | ||||
-rw-r--r-- | numpy/f2py/lib/extgen/converters.py | 22 | ||||
-rw-r--r-- | numpy/f2py/lib/extgen/doc.txt | 7 | ||||
-rw-r--r-- | numpy/f2py/lib/extgen/extension_module.py | 2 | ||||
-rw-r--r-- | numpy/f2py/lib/extgen/pyc_argument.py | 107 | ||||
-rw-r--r-- | numpy/f2py/lib/extgen/pyc_function.py | 13 |
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 |