summaryrefslogtreecommitdiff
path: root/numpy/f2py/lib/extgen/py_support.py
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/f2py/lib/extgen/py_support.py')
-rw-r--r--numpy/f2py/lib/extgen/py_support.py833
1 files changed, 833 insertions, 0 deletions
diff --git a/numpy/f2py/lib/extgen/py_support.py b/numpy/f2py/lib/extgen/py_support.py
new file mode 100644
index 000000000..8fc2bac31
--- /dev/null
+++ b/numpy/f2py/lib/extgen/py_support.py
@@ -0,0 +1,833 @@
+
+__all__ = ['PySource', 'PyCFunction', 'PyCModule', 'PyCTypeSpec', 'PyCArgument', 'PyCReturn']
+
+import os
+import sys
+from base import Component
+from utils import *
+from c_support import *
+
+class PySource(FileSource):
+
+ template_py_header = '''\
+#!/usr/bin/env python
+# This file %(path)r is generated using ExtGen tool
+# from NumPy version %(numpy_version)s.
+# ExtGen is developed by Pearu Peterson <pearu.peterson@gmail.com>.
+# For more information see http://www.scipy.org/ExtGen/ .'''
+
+ container_options = dict(
+ Content = dict(default='',
+ prefix = template_py_header + '\n',
+ suffix = '\n',
+ use_indent=True)
+ )
+
+ pass
+
+class PyCModule(CSource):
+
+ """
+ >>> m = PyCModule('PyCModule_test', title='This is first line.\\nSecond line.', description='This is a module.\\nYes, it is.')
+ >>> mod = m.build()
+ >>> print mod.__doc__ #doctest: +ELLIPSIS
+ This module 'PyCModule_test' is generated with ExtGen from NumPy version ...
+ <BLANKLINE>
+ This is first line.
+ Second line.
+ <BLANKLINE>
+ This is a module.
+ Yes, it is.
+ """
+
+ template = CSource.template_c_header + '''
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+#include "Python.h"
+%(CHeader)s
+%(CTypeDef)s
+%(CProto)s
+%(CDefinition)s
+%(CAPIDefinition)s
+%(CDeclaration)s
+%(PyCModuleCDeclaration)s
+%(CMainProgram)s
+#ifdef __cplusplus
+}
+#endif
+'''
+
+ container_options = CSource.container_options.copy()
+ container_options.update(CAPIDefinition=container_options['CDefinition'],
+ PyCModuleCDeclaration=dict(default='<KILLLINE>',
+ ignore_empty_content=True),
+ )
+
+ component_container_map = dict(
+ PyCModuleInitFunction = 'CMainProgram',
+ PyCModuleCDeclaration = 'PyCModuleCDeclaration',
+ PyCFunction = 'CAPIDefinition',
+ )
+
+ def initialize(self, pyname, *components, **options):
+ self.pyname = pyname
+ self.title = options.pop('title', None)
+ self.description = options.pop('description', None)
+
+ self = CSource.initialize(self, '%smodule.c' % (pyname), **options)
+
+ self.cdecl = PyCModuleCDeclaration(pyname)
+ self += self.cdecl
+
+ self.main = PyCModuleInitFunction(pyname)
+ self += self.main
+ map(self.add, components)
+ return self
+
+ def update_parent(self, parent):
+ if isinstance(parent, Component.SetupPy):
+ self.update_SetupPy(parent)
+
+ def update_SetupPy(self, parent):
+ parent.setup_py += self.evaluate(' config.add_extension(%(pyname)r, sources = ["%(extmodulesrc)s"])',
+ extmodulesrc = self.path)
+ parent.init_py += 'import %s' % (self.pyname)
+
+ def build(self, build_dir=None, clean_at_exit=None):
+ """ build(build_dir=None, clean_at_exit=None)
+
+ A convenience function to build, import, an return
+ an extension module object.
+ """
+ if build_dir is None:
+ import tempfile
+ import time
+ packagename = 'extgen_' + str(hex(int(time.time()*10000000)))[2:]
+ build_dir = os.path.join(tempfile.gettempdir(), packagename)
+ clean_at_exit = True
+ if clean_at_exit:
+ import atexit
+ import shutil
+ atexit.register(lambda d=build_dir: shutil.rmtree(d))
+ self.info('directory %r will be removed at exit from python.' % (build_dir))
+
+ setup = Component.SetupPy(build_dir)
+ setup += self
+ s,o = setup.execute('build_ext','--inplace')
+ if s:
+ self.info('return status=%s' % (s))
+ self.info(o)
+ raise RuntimeError('failed to build extension module %r' % (self.pyname))
+ sys.path.insert(0, os.path.dirname(build_dir))
+ packagename = os.path.basename(build_dir)
+ try:
+ p = __import__(packagename)
+ #exec 'import %s as p' % (packagename)
+ m = getattr(p, self.pyname)
+ except:
+ self.info(sys.path)
+ del sys.path[0]
+ raise
+ else:
+ del sys.path[0]
+ return m
+
+class PyCModuleCDeclaration(Component):
+
+ template = '''\
+static PyObject* extgen_module;
+static
+PyMethodDef extgen_module_methods[] = {
+ %(PyMethodDef)s
+ {NULL,NULL,0,NULL}
+};
+static
+char extgen_module_doc[] =
+"This module %(pyname)r is generated with ExtGen from NumPy version %(numpy_version)s."
+%(Title)s
+%(Description)s
+%(FunctionSignature)s
+;'''
+ container_options = dict(
+ PyMethodDef = dict(suffix=',', skip_suffix_when_empty=True,separator=',\n',
+ default='<KILLLINE>', use_indent=True, ignore_empty_content=True),
+ FunctionSignature = dict(prefix='"\\n\\n:Functions:\\n"\n" ', skip_prefix_when_empty=True, use_indent=True,
+ ignore_empty_content=True, default='<KILLLINE>',
+ separator = '"\n" ', suffix='"', skip_suffix_when_empty=True,
+ ),
+ Title = dict(default='<KILLLINE>',prefix='"\\n\\n',suffix='"',separator='\\n"\n"',
+ skip_prefix_when_empty=True, skip_suffix_when_empty=True,
+ use_firstline_indent=True, replace_map={'\n':'\\n'}),
+ Description = dict(default='<KILLLINE>',prefix='"\\n\\n"\n"',
+ suffix='"',separator='\\n"\n"',
+ skip_prefix_when_empty=True, skip_suffix_when_empty=True,
+ use_firstline_indent=True, replace_map={'\n':'\\n'}),
+ )
+
+ default_component_class_name = 'Line'
+
+ def initialize(self, pyname):
+ self.pyname = pyname
+ return self
+
+ def update_parent(self, parent):
+ if isinstance(parent, PyCModule):
+ self.update_PyCModule(parent)
+
+ def update_PyCModule(self, parent):
+ if parent.title:
+ self.add(parent.title, 'Title')
+ if parent.description:
+ self.add(parent.description, 'Description')
+
+
+class PyCModuleInitFunction(CFunction):
+
+ """
+ >>> f = PyCModuleInitFunction('test_PyCModuleInitFunction')
+ >>> print f.generate()
+ PyMODINIT_FUNC
+ inittest_PyCModuleInitFunction(void) {
+ PyObject* extgen_module_dict = NULL;
+ PyObject* extgen_str_obj = NULL;
+ extgen_module = Py_InitModule(\"test_PyCModuleInitFunction\", extgen_module_methods);
+ if ((extgen_module_dict = PyModule_GetDict(extgen_module))==NULL) goto capi_error;
+ if ((extgen_str_obj = PyString_FromString(extgen_module_doc))==NULL) goto capi_error;
+ PyDict_SetItemString(extgen_module_dict, \"__doc__\", extgen_str_obj);
+ Py_DECREF(extgen_str_obj);
+ if ((extgen_str_obj = PyString_FromString(\"restructuredtext\"))==NULL) goto capi_error;
+ PyDict_SetItemString(extgen_module_dict, \"__docformat__\", extgen_str_obj);
+ Py_DECREF(extgen_str_obj);
+ return;
+ capi_error:
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_RuntimeError, \"failed to initialize 'test_PyCModuleInitFunction' module.\");
+ }
+ return;
+ }
+ """
+
+ template = '''\
+%(CSpecifier)s
+%(CTypeSpec)s
+%(name)s(void) {
+ PyObject* extgen_module_dict = NULL;
+ PyObject* extgen_str_obj = NULL;
+ %(CDeclaration)s
+ extgen_module = Py_InitModule("%(pyname)s", extgen_module_methods);
+ if ((extgen_module_dict = PyModule_GetDict(extgen_module))==NULL) goto capi_error;
+ if ((extgen_str_obj = PyString_FromString(extgen_module_doc))==NULL) goto capi_error;
+ PyDict_SetItemString(extgen_module_dict, "__doc__", extgen_str_obj);
+ Py_DECREF(extgen_str_obj);
+ if ((extgen_str_obj = PyString_FromString("restructuredtext"))==NULL) goto capi_error;
+ PyDict_SetItemString(extgen_module_dict, "__docformat__", extgen_str_obj);
+ Py_DECREF(extgen_str_obj);
+ %(CBody)s
+ return;
+capi_error:
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_RuntimeError, "failed to initialize %(pyname)r module.");
+ }
+ return;
+}'''
+
+ def initialize(self, pyname, *components, **options):
+ self.pyname = pyname
+ self.title = options.pop('title', None)
+ self.description = options.pop('description', None)
+ self = CFunction.initialize(self, 'init'+pyname, 'PyMODINIT_FUNC', *components, **options)
+ return self
+
+#helper classes for PyCFunction
+class KWListBase(Word): parent_container_options = dict(separator=', ', suffix=', ', skip_suffix_when_empty=True)
+class ReqKWList(KWListBase): pass
+class OptKWList(KWListBase): pass
+class ExtKWList(KWListBase): pass
+class ArgBase(Word): parent_container_options = dict(separator=', ')
+class ReqArg(ArgBase): pass
+class OptArg(ArgBase): pass
+class ExtArg(ArgBase): pass
+class RetArg(ArgBase):
+ parent_container_options = dict(separator=', ', prefix='(', suffix=')', default = 'None',
+ skip_prefix_when_empty=True, skip_suffix_when_empty=True,
+ skip_prefix_suffix_when_single=True)
+class OptExtArg(ArgBase):
+ parent_container_options = dict(separator=', ', prefix=' [, ', skip_prefix_when_empty=True,
+ suffix=']', skip_suffix_when_empty=True)
+class ArgDocBase(Word):
+ parent_container_options = dict(default='<KILLLINE>', prefix='"\\n\\nArguments:\\n"\n" ',
+ separator='\\n"\n" ', suffix='"',
+ skip_prefix_when_empty=True, skip_suffix_when_empty=True,
+ use_firstline_indent=True, replace_map={'\n':'\\n'})
+class ReqArgDoc(ArgDocBase):
+ parent_container_options = ArgDocBase.parent_container_options.copy()
+ parent_container_options.update(prefix='"\\n\\n:Parameters:\\n"\n" ')
+class OptArgDoc(ArgDocBase):
+ parent_container_options = ArgDocBase.parent_container_options.copy()
+ parent_container_options.update(prefix='"\\n\\n:Optional parameters:\\n"\n" ')
+class ExtArgDoc(ArgDocBase):
+ parent_container_options = ArgDocBase.parent_container_options.copy()
+ parent_container_options.update(prefix='"\\n\\n:Extra parameters:\\n"\n" ')
+class RetArgDoc(ArgDocBase):
+ parent_container_options = ArgDocBase.parent_container_options.copy()
+ parent_container_options.update(prefix='"\\n\\n:Returns:\\n"\n" ',
+ default='"\\n\\n:Returns:\\n None"')
+class ArgFmtBase(Word): parent_container_options = dict(separator='')
+class ReqArgFmt(ArgFmtBase): pass
+class OptArgFmt(ArgFmtBase): pass
+class ExtArgFmt(ArgFmtBase): pass
+class RetArgFmt(ArgFmtBase): pass
+class OptExtArgFmt(ArgFmtBase):
+ parent_container_options = dict(separator='', prefix='|', skip_prefix_when_empty=True)
+class ArgObjBase(Word): parent_container_options = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True)
+class ReqArgObj(ArgObjBase): pass
+class OptArgObj(ArgObjBase): pass
+class ExtArgObj(ArgObjBase): pass
+class RetArgObj(ArgObjBase): pass
+
+class FunctionSignature(Component):
+ template = '%(name)s(%(ReqArg)s%(OptExtArg)s) -> %(RetArg)s'
+ parent_container_options = dict()
+ container_options = dict(
+ ReqArg = ReqArg.parent_container_options,
+ OptArg = OptArg.parent_container_options,
+ ExtArg = ExtArg.parent_container_options,
+ RetArg = RetArg.parent_container_options,
+ OptExtArg = OptExtArg.parent_container_options,
+ )
+ def initialize(self, name, *components, **options):
+ self.name = name
+ map(self.add, components)
+ return self
+ def update_containers(self):
+ self.container_OptExtArg += self.container_OptArg + self.container_ExtArg
+
+class PyCFunction(CFunction):
+
+ """
+ >>> from __init__ import *
+ >>> f = PyCFunction('foo')
+ >>> print f.generate()
+ static
+ char pyc_function_foo_doc[] =
+ \" foo() -> None\"
+ \"\\n\\n:Returns:\\n None\"
+ ;
+ static
+ PyObject*
+ pyc_function_foo(PyObject *pyc_self, PyObject *pyc_args, PyObject *pyc_keywds) {
+ PyObject * volatile pyc_buildvalue = NULL;
+ volatile int capi_success = 1;
+ static char *capi_kwlist[] = {NULL};
+ if (PyArg_ParseTupleAndKeywords(pyc_args, pyc_keywds,"",
+ capi_kwlist)) {
+ capi_success = !PyErr_Occurred();
+ if (capi_success) {
+ pyc_buildvalue = Py_BuildValue("");
+ }
+ }
+ return pyc_buildvalue;
+ }
+ >>> f = PyCFunction('foo', title=' Function title.\\nSecond line.', description=' This is a function.\\n2nd line.')
+ >>> e = PyCModule('PyCFunction_test', f)
+ >>> mod = e.build()
+ >>> print mod.foo.__doc__
+ foo() -> None
+ <BLANKLINE>
+ Function title.
+ Second line.
+ <BLANKLINE>
+ This is a function.
+ 2nd line.
+ <BLANKLINE>
+ :Returns:
+ None
+ """
+
+ template = '''\
+static
+char %(name)s_doc[] =
+" %(FunctionSignature)s"
+%(Title)s
+%(Description)s
+%(ReqArgDoc)s
+%(RetArgDoc)s
+%(OptArgDoc)s
+%(ExtArgDoc)s
+;
+static
+PyObject*
+%(name)s(PyObject *pyc_self, PyObject *pyc_args, PyObject *pyc_keywds) {
+ PyObject * volatile pyc_buildvalue = NULL;
+ volatile int capi_success = 1;
+ %(CDeclaration)s
+ static char *capi_kwlist[] = {%(ReqKWList)s%(OptKWList)s%(ExtKWList)sNULL};
+ if (PyArg_ParseTupleAndKeywords(pyc_args, pyc_keywds,"%(ReqArgFmt)s%(OptExtArgFmt)s",
+ capi_kwlist%(ReqArgObj)s%(OptArgObj)s%(ExtArgObj)s)) {
+ %(FromPyObj)s
+ %(CBody)s
+ capi_success = !PyErr_Occurred();
+ if (capi_success) {
+ %(PyObjFrom)s
+ pyc_buildvalue = Py_BuildValue("%(RetArgFmt)s"%(RetArgObj)s);
+ %(CleanPyObjFrom)s
+ }
+ %(CleanCBody)s
+ %(CleanFromPyObj)s
+ }
+ return pyc_buildvalue;
+}'''
+
+ container_options = CFunction.container_options.copy()
+
+ container_options.update(\
+
+ TMP = dict(),
+
+ ReqArg = ReqArg.parent_container_options,
+ OptArg = OptArg.parent_container_options,
+ ExtArg = ExtArg.parent_container_options,
+ RetArg = RetArg.parent_container_options,
+
+ FunctionSignature = FunctionSignature.parent_container_options,
+
+ OptExtArg = OptExtArg.parent_container_options,
+
+ Title = dict(default='<KILLLINE>',prefix='"\\n\\n',suffix='"',separator='\\n"\n"',
+ skip_prefix_when_empty=True, skip_suffix_when_empty=True,
+ use_firstline_indent=True, replace_map={'\n':'\\n'}),
+ Description = dict(default='<KILLLINE>',prefix='"\\n\\n"\n"',
+ suffix='"',separator='\\n"\n"',
+ skip_prefix_when_empty=True, skip_suffix_when_empty=True,
+ use_firstline_indent=True, replace_map={'\n':'\\n'}),
+
+ ReqArgDoc = ReqArgDoc.parent_container_options,
+ OptArgDoc = OptArgDoc.parent_container_options,
+ ExtArgDoc = ExtArgDoc.parent_container_options,
+ RetArgDoc = RetArgDoc.parent_container_options,
+
+ ReqKWList = ReqKWList.parent_container_options,
+ OptKWList = OptKWList.parent_container_options,
+ ExtKWList = ExtKWList.parent_container_options,
+
+ ReqArgFmt = ReqArgFmt.parent_container_options,
+ OptArgFmt = OptArgFmt.parent_container_options,
+ ExtArgFmt = ExtArgFmt.parent_container_options,
+ OptExtArgFmt = OptExtArgFmt.ExtArgFmt.parent_container_options,
+ RetArgFmt = ExtArgFmt.parent_container_options,
+
+ ReqArgObj = ReqArgObj.parent_container_options,
+ OptArgObj = OptArgObj.parent_container_options,
+ ExtArgObj = ExtArgObj.parent_container_options,
+ RetArgObj = RetArgObj.parent_container_options,
+
+ FromPyObj = CCode.parent_container_options,
+ PyObjFrom = CCode.parent_container_options,
+
+ CleanPyObjFrom = dict(default='<KILLLINE>', reverse=True, use_indent=True, ignore_empty_content=True),
+ CleanCBody = dict(default='<KILLLINE>', reverse=True, use_indent=True, ignore_empty_content=True),
+ CleanFromPyObj = dict(default='<KILLLINE>', reverse=True, use_indent=True, ignore_empty_content=True),
+
+ )
+
+ default_component_class_name = 'CCode'
+
+ component_container_map = CFunction.component_container_map.copy()
+ component_container_map.update(
+ PyCArgument = 'TMP',
+ CCode = 'CBody',
+ )
+
+ def initialize(self, pyname, *components, **options):
+ self.pyname = pyname
+ self.title = options.pop('title', None)
+ self.description = options.pop('description', None)
+ self = CFunction.initialize(self, 'pyc_function_'+pyname, 'PyObject*', **options)
+ self.signature = FunctionSignature(pyname)
+ self += self.signature
+ if self.title:
+ self.add(self.title, 'Title')
+ if self.description:
+ self.add(self.description, 'Description')
+ map(self.add, components)
+ return self
+
+ def __repr__(self):
+ return '%s(%s)' % (self.__class__.__name__, ', '.join(map(repr,[self.pyname]+[c for (c,l) in self.components])))
+
+ def update_parent(self, parent):
+ if isinstance(parent, PyCModule):
+ self.update_PyCModule(parent)
+
+ def update_PyCModule(self, parent):
+ t = ' {"%(pyname)s", (PyCFunction)%(name)s, METH_VARARGS | METH_KEYWORDS, %(name)s_doc}'
+ parent.cdecl.add(self.evaluate(t),'PyMethodDef')
+ parent.cdecl.add(self.signature,'FunctionSignature')
+
+ def update_containers(self):
+ self.container_OptExtArg += self.container_OptArg + self.container_ExtArg
+ self.container_OptExtArgFmt += self.container_OptArgFmt + self.container_ExtArgFmt
+
+
+class PyCArgument(Component):
+
+ """
+ >>> from __init__ import *
+ >>> a = PyCArgument('a')
+ >>> print a
+ PyCArgument('a', PyCTypeSpec('object'))
+ >>> print a.generate()
+ a
+ >>> f = PyCFunction('foo')
+ >>> f += a
+ >>> f += PyCArgument('b')
+ >>> m = PyCModule('PyCArgument_test')
+ >>> m += f
+ >>> #print m.generate()
+ >>> mod = m.build()
+ >>> print mod.__doc__ #doctest: +ELLIPSIS
+ This module 'PyCArgument_test' is generated with ExtGen from NumPy version ...
+ <BLANKLINE>
+ :Functions:
+ foo(a, b) -> None
+
+ """
+
+ container_options = dict(
+ TMP = dict()
+ )
+
+ component_container_map = dict(
+ PyCTypeSpec = 'TMP'
+ )
+
+ template = '%(name)s'
+
+ def initialize(self, name, ctype = object, *components, **options):
+ self.input_intent = options.pop('input_intent','required') # 'optional', 'extra', 'hide'
+ self.output_intent = options.pop('output_intent','hide') # 'return'
+ self.input_title = options.pop('input_title', None)
+ self.output_title = options.pop('output_title', None)
+ self.input_description = options.pop('input_description', None)
+ self.output_description = options.pop('output_description', None)
+ self.depends = options.pop('depends', [])
+ title = options.pop('title', None)
+ description = options.pop('description', None)
+ if title is not None:
+ if self.input_intent!='hide':
+ if self.input_title is None:
+ self.input_title = title
+ elif self.output_intent!='hide':
+ if self.output_title is None:
+ self.output_title = title
+ if description is not None:
+ if self.input_intent!='hide':
+ if self.input_description is None:
+ self.input_description = description
+ elif self.output_intent!='hide':
+ if self.output_description is None:
+ self.output_description = description
+ if options: self.warning('%s unused options: %s\n' % (self.__class__.__name__, options))
+
+ self.name = name
+ self.ctype = ctype = PyCTypeSpec(ctype)
+ self += ctype
+
+ self.cvar = name
+ self.pycvar = None
+ self.retpycvar = None
+
+ retfmt = ctype.get_pyret_fmt(self)
+ if isinstance(ctype, PyCTypeSpec):
+ if retfmt and retfmt in 'SON':
+ if self.output_intent == 'return':
+ if self.input_intent=='hide':
+ self.retpycvar = name
+ else:
+ self.pycvar = name
+ self.retpycvar = name + '_return'
+ elif self.input_intent!='hide':
+ self.pycvar = name
+ else:
+ self.pycvar = name
+ self.retpycvar = name
+ else:
+ self.pycvar = name + '_pyc'
+ self.retpycvar = name + '_pyc_r'
+
+ ctype.set_titles(self)
+
+ map(self.add, components)
+ return self
+
+ def __repr__(self):
+ return '%s(%s)' % (self.__class__.__name__, ', '.join(map(repr,[self.name]+[c for (c,l) in self.components])))
+
+ def update_parent(self, parent):
+ if isinstance(parent, PyCFunction):
+ self.update_PyCFunction(parent)
+
+ def update_PyCFunction(self, parent):
+ ctype = self.ctype
+
+ 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:
+ input_doc_descr = None
+ if self.output_description is not None:
+ output_doc_descr = ' %s' % (self.output_description)
+ else:
+ output_doc_descr = None
+
+ # add components to parent:
+ parent += ctype.get_decl(self)
+ if self.input_intent=='required':
+ parent += ReqArg(self.name)
+ parent.signature += ReqArg(self.name)
+ parent += ReqKWList('"' + self.name + '"')
+ parent += ReqArgFmt(ctype.get_pyarg_fmt(self))
+ parent += ReqArgObj(ctype.get_pyarg_obj(self))
+ parent += ReqArgDoc(input_doc_title)
+ parent += ReqArgDoc(input_doc_descr)
+ elif self.input_intent=='optional':
+ parent += OptArg(self.name)
+ parent.signature += OptArg(self.name)
+ parent += OptKWList('"' + self.name + '"')
+ parent += OptArgFmt(ctype.get_pyarg_fmt(self))
+ parent += OptArgObj(ctype.get_pyarg_obj(self))
+ parent += OptArgDoc(input_doc_title)
+ parent += OptArgDoc(input_doc_descr)
+ elif self.input_intent=='extra':
+ parent += ExtArg(self.name)
+ parent.signature += ExtArg(self.name)
+ parent += ExtKWList('"' + self.name + '"')
+ parent += ExtArgFmt(ctype.get_pyarg_fmt(self))
+ parent += ExtArgObj(ctype.get_pyarg_obj(self))
+ parent += ExtArgDoc(input_doc_title)
+ parent += ExtArgDoc(input_doc_descr)
+ elif self.input_intent=='hide':
+ pass
+ else:
+ raise NotImplementedError('input_intent=%r' % (self.input_intent))
+
+ if self.output_intent=='return':
+ parent += RetArg(self.name)
+ parent.signature += RetArg(self.name)
+ parent += RetArgFmt(ctype.get_pyret_fmt(self))
+ parent += RetArgObj(ctype.get_pyret_obj(self))
+ parent += RetArgDoc(output_doc_title)
+ parent += RetArgDoc(output_doc_descr)
+ elif self.output_intent=='hide':
+ pass
+ else:
+ raise NotImplementedError('output_intent=%r' % (self.output_intent))
+
+class PyCReturn(PyCArgument):
+
+ def initialize(self, name, ctype = object, *components, **options):
+ return PyCArgument(name, ctype, input_intent='hide', output_intent='return', *components, **options)
+
+class PyCTypeSpec(CTypeSpec):
+
+ """
+ >>> s = PyCTypeSpec(object)
+ >>> print s
+ PyCTypeSpec('object')
+ >>> print s.generate()
+ PyObject*
+ """
+
+ typeinfo_map = dict(
+ int = ('PyInt_Type', 'PyIntObject*', 'O!', 'N', 'NULL'),
+ long = ('PyLong_Type', 'PyLongObject*', 'O!', 'N', 'NULL'),
+ float = ('PyFloat_Type', 'PyFloatObject*', 'O!', 'N', 'NULL'),
+ complex = ('PyComplex_Type', 'PyComplexObject*', 'O!', 'N', 'NULL'),
+ str = ('PyString_Type', 'PyStringObject*', 'S', 'N', 'NULL'),
+ unicode = ('PyUnicode_Type', 'PyUnicodeObject*', 'U', 'N', 'NULL'),
+ buffer = ('PyBuffer_Type', 'PyBufferObject*', 'O!', 'N', 'NULL'),
+ tuple = ('PyTuple_Type', 'PyTupleObject*', 'O!', 'N', 'NULL'),
+ list = ('PyList_Type', 'PyListObject*', 'O!', 'N', 'NULL'),
+ dict = ('PyDict_Type', 'PyDictObject*', 'O!', 'N', 'NULL'),
+ file = ('PyFile_Type', 'PyFileObject*', 'O!', 'N', 'NULL'),
+ instance = ('PyInstance_Type', 'PyObject*', 'O!', 'N', 'NULL'),
+ function = ('PyFunction_Type', 'PyFunctionObject*', 'O!', 'N', 'NULL'),
+ method = ('PyMethod_Type', 'PyObject*', 'O!', 'N', 'NULL'),
+ module = ('PyModule_Type', 'PyObject*', 'O!', 'N', 'NULL'),
+ iter = ('PySeqIter_Type', 'PyObject*', 'O!', 'N', 'NULL'),
+ property = ('PyProperty_Type', 'PyObject*', 'O!', 'N', 'NULL'),
+ slice = ('PySlice_Type', 'PyObject*', 'O!', 'N', 'NULL'),
+ cell = ('PyCell_Type', 'PyCellObject*', 'O!', 'N', 'NULL'),
+ generator = ('PyGen_Type', 'PyGenObject*', 'O!', 'N', 'NULL'),
+ set = ('PySet_Type', 'PySetObject*', 'O!', 'N', 'NULL'),
+ frozenset = ('PyFrozenSet_Type', 'PySetObject*', 'O!', 'N', 'NULL'),
+ cobject = (None, 'PyCObject*', 'O', 'N', 'NULL'),
+ type = ('PyType_Type', 'PyTypeObject*', 'O!', 'N', 'NULL'),
+ object = (None, 'PyObject*', 'O', 'N', 'NULL'),
+ numpy_ndarray = ('PyArray_Type', 'PyArrayObject*', 'O!', 'N', 'NULL'),
+ numpy_descr = ('PyArrayDescr_Type','PyArray_Descr', 'O!', 'N', 'NULL'),
+ numpy_ufunc = ('PyUFunc_Type', 'PyUFuncObject*', 'O!', 'N', 'NULL'),
+ numpy_iter = ('PyArrayIter_Type', 'PyArrayIterObject*', 'O!', 'N', 'NULL'),
+ numpy_multiiter = ('PyArrayMultiIter_Type', 'PyArrayMultiIterObject*', 'O!', 'N', 'NULL'),
+ numpy_int8 = ('PyInt8ArrType_Type', 'PyInt8ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_int16 = ('PyInt16ArrType_Type', 'PyInt16ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_int32 = ('PyInt32ArrType_Type', 'PyInt32ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_int64 = ('PyInt64ArrType_Type', 'PyInt64ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_int128 = ('PyInt128ArrType_Type', 'PyInt128ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_uint8 = ('PyUInt8ArrType_Type', 'PyUInt8ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_uint16 = ('PyUInt16ArrType_Type', 'PyUInt16ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_uint32 = ('PyUInt32ArrType_Type', 'PyUInt32ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_uint64 = ('PyUInt64ArrType_Type', 'PyUInt64ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_uint128 = ('PyUInt128ArrType_Type', 'PyUInt128ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_float16 = ('PyFloat16ArrType_Type', 'PyFloat16ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_float32 = ('PyFloat32ArrType_Type', 'PyFloat32ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_float64 = ('PyFloat64ArrType_Type', 'PyFloat64ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_float80 = ('PyFloat80ArrType_Type', 'PyFloat80ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_float96 = ('PyFloat96ArrType_Type', 'PyFloat96ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_float128 = ('PyFloat128ArrType_Type', 'PyFloat128ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_complex32 = ('PyComplex32ArrType_Type', 'PyComplex32ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_complex64 = ('PyComplex64ArrType_Type', 'PyComplex64ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_complex128 = ('PyComplex128ArrType_Type', 'PyComplex128ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_complex160 = ('PyComplex160ArrType_Type', 'PyComplex160ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_complex192 = ('PyComplex192ArrType_Type', 'PyComplex192ScalarObject*', 'O!', 'N', 'NULL'),
+ numpy_complex256 = ('PyComplex256ArrType_Type', 'PyComplex256ScalarObject*', 'O!', 'N', 'NULL'),
+ numeric_array = ('PyArray_Type', 'PyArrayObject*', 'O!', 'N', 'NULL'),
+ c_char = (None, 'char', 'b', 'b', '0'),
+ c_unsigned_char = (None, 'unsigned char', 'B', 'B', '0'),
+ c_short = (None, 'short int', 'h', 'h', '0'),
+ c_unsigned_short = (None, 'unsigned short int', 'H', 'H', '0'),
+ c_int = (None,'int', 'i', 'i', '0'),
+ c_unsigned_int = (None,'unsigned int', 'I', 'I', '0'),
+ c_long = (None,'long', 'l', 'l', '0'),
+ c_unsigned_long = (None,'unsigned long', 'k', 'k', '0'),
+ c_long_long = (None,'PY_LONG_LONG', 'L', 'L', '0'),
+ c_unsigned_long_long = (None,'unsigned PY_LONG_LONG', 'K', 'K', '0'),
+ c_Py_ssize_t = (None,'Py_ssize_t', 'n', 'n', '0'),
+ c_char1 = (None,'char', 'c', 'c', '"\\0"'),
+ c_float = (None,'float', 'f', 'f', '0.0'),
+ c_double = (None,'double', 'd', 'd', '0.0'),
+ c_Py_complex = (None,'Py_complex', 'D', 'D', '{0.0, 0.0}'),
+ c_const_char_ptr = (None,'const char *', 'z', 'z', 'NULL'),
+ c_Py_UNICODE = (None,'Py_UNICODE*','u','u', 'NULL'),
+ )
+
+ def initialize(self, typeobj):
+ if isinstance(typeobj, self.__class__):
+ return typeobj
+
+ m = self.typeinfo_map
+
+ key = None
+ if isinstance(typeobj, type):
+ if typeobj.__module__=='__builtin__':
+ key = typeobj.__name__
+ if key=='array':
+ key = 'numeric_array'
+ elif typeobj.__module__=='numpy':
+ key = 'numpy_' + typeobj.__name__
+ elif isinstance(typeobj, str):
+ key = typeobj
+ if key.startswith('numpy_'):
+ k = key[6:]
+ named_scalars = ['byte','short','int','long','longlong',
+ 'ubyte','ushort','uint','ulong','ulonglong',
+ 'intp','uintp',
+ 'float_','double',
+ 'longfloat','longdouble',
+ 'complex_',
+ ]
+ if k in named_scalars:
+ import numpy
+ key = 'numpy_' + getattr(numpy, k).__name__
+
+ try: item = m[key]
+ except KeyError:
+ raise NotImplementedError('%s: need %s support' % (self.__class__.__name__, typeobj))
+
+ self.typeobj_name = key
+ self.ctypeobj = item[0]
+ self.line = item[1]
+ self.arg_fmt = item[2]
+ self.ret_fmt = item[3]
+ self.cinit_value = item[4]
+
+ #if key.startswith('numpy_'):
+ # self.add(Component.get('arrayobject.h'), 'Header')
+ # self.add(Component.get('import_array'), 'ModuleInit')
+ if key.startswith('numeric_'):
+ raise NotImplementedError(self.__class__.__name__ + ': Numeric support')
+
+ return self
+
+ def __repr__(self):
+ return '%s(%s)' % (self.__class__.__name__, ', '.join([repr(self.typeobj_name)]+[repr(c) for (c,l) in self.components]))
+
+ def get_pyarg_fmt(self, arg):
+ if arg.input_intent=='hide': return None
+ return self.arg_fmt
+
+ def get_pyarg_obj(self, arg):
+ if arg.input_intent=='hide': return None
+ if self.arg_fmt=='O!':
+ return '&%s, &%s' % (self.ctypeobj, arg.pycvar)
+ return '&' + arg.pycvar
+
+ def get_pyret_fmt(self, arg):
+ if arg.output_intent=='hide': return None
+ return self.ret_fmt
+
+ def get_pyret_obj(self, arg):
+ if arg.output_intent=='return':
+ if self.get_pyret_fmt(arg)=='D':
+ return '&' + arg.retpycvar
+ return arg.retpycvar
+ return
+
+ def get_init_value(self, arg):
+ return self.cinit_value
+
+ def set_titles(self, arg):
+ if self.typeobj_name == 'object':
+ tn = 'a python ' + self.typeobj_name
+ else:
+ if self.typeobj_name.startswith('numpy_'):
+ tn = 'a numpy.' + self.typeobj_name[6:] + ' object'
+ elif self.typeobj_name.startswith('c_'):
+ n = self.typeobj_name[2:]
+ if not n.startswith('Py_'):
+ n = ' '.join(n.split('_'))
+ tn = 'a to C ' + n + ' convertable object'
+ else:
+ tn = 'a python ' + self.typeobj_name + ' object'
+ if arg.input_intent!='hide':
+ r = ''
+ if arg.input_title: r = ', ' + arg.input_title
+ arg.input_title = tn + r
+ if arg.output_intent!='hide':
+ r = ''
+ if arg.output_title: r = ', ' + arg.output_title
+ arg.output_title = tn + r
+
+ def get_decl(self, arg):
+ init_value = self.get_init_value(arg)
+ if init_value:
+ init = ' = %s' % (init_value)
+ else:
+ init = ''
+ if arg.pycvar and arg.pycvar==arg.retpycvar:
+ return CDeclaration(self, '%s%s' % (arg.pycvar, init))
+ else:
+ if arg.input_intent!='hide':
+ return CDeclaration(self, '%s%s' % (arg.pycvar, init))
+ if arg.output_intent!='hide':
+ return CDeclaration(self, '%s%s' % (arg.retpycvar, init))
+ return
+
+def _test():
+ import doctest
+ doctest.testmod()
+
+if __name__ == "__main__":
+ _test()