From numpy-svn at scipy.org Wed Aug 1 19:48:59 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Wed, 1 Aug 2007 18:48:59 -0500 (CDT) Subject: [Numpy-svn] r3938 - in trunk/numpy/lib: . tests Message-ID: <20070801234859.3D47D39C00F@new.scipy.org> Author: stefan Date: 2007-08-01 18:48:41 -0500 (Wed, 01 Aug 2007) New Revision: 3938 Modified: trunk/numpy/lib/tests/test_type_check.py trunk/numpy/lib/type_check.py Log: Fix asfarray to return an array instead of a matrix. Modified: trunk/numpy/lib/tests/test_type_check.py =================================================================== --- trunk/numpy/lib/tests/test_type_check.py 2007-07-28 19:44:07 UTC (rev 3937) +++ trunk/numpy/lib/tests/test_type_check.py 2007-08-01 23:48:41 UTC (rev 3938) @@ -270,5 +270,11 @@ b = real_if_close(a+1e-7j,tol=1e-6) assert_all(isrealobj(b)) +class test_array_conversion(NumpyTestCase): + def check_asfarray(self): + a = asfarray(array([1,2,3])) + assert_equal(a.__class__,ndarray) + assert issubdtype(a.dtype,float) + if __name__ == "__main__": NumpyTest().run() Modified: trunk/numpy/lib/type_check.py =================================================================== --- trunk/numpy/lib/type_check.py 2007-07-28 19:44:07 UTC (rev 3937) +++ trunk/numpy/lib/type_check.py 2007-08-01 23:48:41 UTC (rev 3938) @@ -46,7 +46,7 @@ dtype = _nx.obj2sctype(dtype) if not issubclass(dtype, _nx.inexact): dtype = _nx.float_ - return asanyarray(a,dtype=dtype) + return asarray(a,dtype=dtype) def real(val): """Return the real part of val. From numpy-svn at scipy.org Thu Aug 2 15:26:41 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Thu, 2 Aug 2007 14:26:41 -0500 (CDT) Subject: [Numpy-svn] r3939 - trunk/numpy/f2py Message-ID: <20070802192641.68218C7C00D@new.scipy.org> Author: rkern Date: 2007-08-02 14:26:40 -0500 (Thu, 02 Aug 2007) New Revision: 3939 Modified: trunk/numpy/f2py/crackfortran.py Log: Ignore blank lines when determining Fortran free format. Modified: trunk/numpy/f2py/crackfortran.py =================================================================== --- trunk/numpy/f2py/crackfortran.py 2007-08-01 23:48:41 UTC (rev 3938) +++ trunk/numpy/f2py/crackfortran.py 2007-08-02 19:26:40 UTC (rev 3939) @@ -247,7 +247,7 @@ n = 0 result = 1 while n>0 and line: - if line[0]!='!': + if line[0]!='!' and line.strip(): n -= 1 if (line[0]!='\t' and _free_f90_start(line[:5])) or line[-2:-1]=='&': result = 1 From numpy-svn at scipy.org Fri Aug 3 15:45:21 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Fri, 3 Aug 2007 14:45:21 -0500 (CDT) Subject: [Numpy-svn] r3940 - in trunk/numpy/f2py/lib: . extgen Message-ID: <20070803194521.201BA39C259@new.scipy.org> Author: pearu Date: 2007-08-03 14:44:53 -0500 (Fri, 03 Aug 2007) New Revision: 3940 Added: trunk/numpy/f2py/lib/extgen/ 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/predefined_components.py trunk/numpy/f2py/lib/extgen/pyc_function.py Log: Initial commit of extgen - Python Extension module Generator package. Added: trunk/numpy/f2py/lib/extgen/__init__.py =================================================================== --- trunk/numpy/f2py/lib/extgen/__init__.py 2007-08-02 19:26:40 UTC (rev 3939) +++ trunk/numpy/f2py/lib/extgen/__init__.py 2007-08-03 19:44:53 UTC (rev 3940) @@ -0,0 +1,12 @@ +""" +Python Extensions Generator +""" + +__all__ = ['ExtensionModule', 'PyCFunction', 'CCode'] + +import base +from extension_module import ExtensionModule +from pyc_function import PyCFunction +from c_code import CCode + +import predefined_components Added: trunk/numpy/f2py/lib/extgen/base.py =================================================================== --- trunk/numpy/f2py/lib/extgen/base.py 2007-08-02 19:26:40 UTC (rev 3939) +++ trunk/numpy/f2py/lib/extgen/base.py 2007-08-03 19:44:53 UTC (rev 3940) @@ -0,0 +1,348 @@ +""" +ExtGen --- Python Extension module Generator. + +Defines Base and Container classes. +""" + +import re +import sys +import time + +class BaseMetaClass(type): + + classnamespace = {} + + def __init__(cls,*args,**kws): + n = cls.__name__ + c = BaseMetaClass.classnamespace.get(n) + if c is None: + BaseMetaClass.classnamespace[n] = cls + else: + print 'Ignoring redefinition of %s: %s defined earlier than %s' % (n, c, cls) + type.__init__(cls, *args, **kws) + + def __getattr__(cls, name): + try: return BaseMetaClass.classnamespace[name] + except KeyError: pass + raise AttributeError("'%s' object has no attribute '%s'"% + (cls.__name__, name)) + +class Base(object): + + __metaclass__ = BaseMetaClass + + container_options = dict() + component_container_map = dict() + template = '' + + def __new__(cls, *args, **kws): + obj = object.__new__(cls) + obj._args = args + obj._provides = kws.get('provides', None) + obj.parent = None + obj.containers = {} # holds containers for named string lists + obj.components = [] # holds pairs (, ) + obj.initialize(*args, **kws) # initialize from constructor arguments + return obj + + def initialize(self, *args, **kws): + """ + Set additional attributes, add components to instance, etc. + """ + # self.myattr = .. + # map(self.add, args) + return + + @staticmethod + def warning(message): + print >> sys.stderr, 'extgen:',message + @staticmethod + def info(message): + print >> sys.stderr, message + + def __repr__(self): + return '%s%s' % (self.__class__.__name__, `self._args`) + + def get_container(self, key): + """ Return named container. + + Rules for returning containers: + (1) return local container if exists + (2) return parent container if exists + (3) create local container and return it with warning + """ + # local container + try: + return self.containers[key] + except KeyError: + pass + + # parent container + parent = self.parent + while parent is not None: + try: + return parent.containers[key] + except KeyError: + parent = parent.parent + continue + + # create local container + self.warning('Created container for %r with name %r, define it in'\ + ' .container_options mapping to get rid of this warning' \ + % (self.__class__.__name__, key)) + c = self.containers[key] = Container() + return c + + @property + def provides(self): + """ + Return a code idiom name that the current class defines. + + Used in avoiding redefinitions of functions and variables. + """ + if self._provides is None: + return '%s_%s' % (self.__class__.__name__, id(self)) + return self._provides + + def get_templates(self): + """ + Return instance templates. + """ + return self.template + + def generate(self): + """ + Generate code idioms (saved in containers) and + return evaluated template strings. + """ + # clean up containers + self.containers = {} + for k,kwargs in self.container_options.items(): + self.containers[k] = Container(**kwargs) + + # initialize code idioms + self.init_containers() + + # generate component code idioms + for component, container_key in self.components: + old_parent = component.parent + component.parent = self + result = component.generate() + if container_key is not None: + if isinstance(container_key, tuple): + assert len(result)==len(container_key),`len(result),container_key` + results = result + keys = container_key + else: + assert isinstance(result, str) and isinstance(container_key, str), `result, container_key` + results = result, + keys = container_key, + for r,k in zip(results, keys): + container = component.get_container(k) + container.add(r, component.provides) + else: + self.warning('no label specified for component %r, ignoring its result'\ + % (component.provides)) + component.parent = old_parent + + # update code idioms + self.update_containers() + + # fill templates with code idioms + templates = self.get_templates() + if isinstance(templates, str): + result = self.evaluate(templates) + else: + assert isinstance(templates, (tuple, list)),`type(templates)` + result = tuple(map(self.evaluate, templates)) + + return result + + def init_containers(self): + """ + Update containers before processing components. + """ + # container = self.get_container() + # container.add(, label=None) + return + + def update_containers(self): + """ + Update containers after processing components. + """ + # container = self.get_container() + # container.add(, label=None) + return + + def __iadd__(self, other): + """ Convenience add. + """ + self.add(other) + return self + + def add(self, component, container_label=None): + """ + Append component and its target container label to components list. + """ + if isinstance(component, str): + component = Base.CCode(component) + if container_label is None: + container_label = self.component_container_map.get(component.__class__.__name__, None) + assert isinstance(component, Base), `type(component)` + self.components.append((component, container_label)) + + @property + def show(self): + # display the content of containers + self.generate() + r = [self.__class__.__name__] + for k, v in self.containers.items(): + if v.list: + r.append('--- %s ---\n%s' % (k,v)) + return '\n'.join(r) + + def evaluate(self, template): + """ + Evaluate template using instance attributes and code + idioms from containers. + """ + d = self.containers.copy() + for n in dir(self): + if n in ['show', 'build'] or n.startswith('_'): + continue + v = getattr(self, n) + if isinstance(v, str): + d[n] = v + for label, container in self.containers.items(): + if container.use_indent is None: + continue + replace_list = set(re.findall(r'[ ]*%\('+label+r'\)s', template)) + for s in replace_list: + old_indent = container.use_indent + container.use_indent = len(s) - len(s.lstrip()) + i = template.index(s) + template = template[:i] + str(container) + template[i+len(s):] + container.use_indent = old_indent + return re.sub(r'[ \t]*[<]KILLLINE[>]\n','', template % d) + + _registered_components_map = {} + + @staticmethod + def register(*components): + """ + Register components so that component classes can use + predefined components via `.get()` method. + """ + d = Base._registered_components_map + for component in components: + provides = component.provides + if d.has_key(provides): + Base.warning('component that provides %r is already registered, ignoring.' % (provides)) + else: + d[provides] = component + return + + @staticmethod + def get(provides): + """ + Return predefined component with given provides property.. + """ + try: + return Base._registered_components_map[provides] + except KeyError: + pass + raise KeyError('no registered component provides %r' % (provides)) + + +class Container(object): + """ + Container of a list of named strings. + + >>> c = Container(separator=', ', prefix='"', suffix='"') + >>> c.add(1, 'hey') + >>> c.add(2, 'hoo') + >>> str(c) + '"hey, hoo"' + >>> c.add(1, 'hey') + >>> c.add(1, 'hey2') + Traceback (most recent call last): + ... + ValueError: Container item 1 exists with different value + + """ + __metaclass__ = BaseMetaClass + + def __init__(self, separator='\n', prefix='', suffix='', + skip_prefix_when_empty=False, + skip_suffix_when_empty=False, + default = '', reverse=False, + user_defined_str = None, + use_indent = None, + ): + self.list = [] + self.label_map = {} + + self.separator = separator + self.prefix = prefix + self.suffix = suffix + self.skip_prefix = skip_prefix_when_empty + self.skip_suffix = skip_suffix_when_empty + self.default = default + self.reverse = reverse + self.user_str = user_defined_str + self.use_indent = use_indent + + def has(self, label): + return self.label_map.has_key(label) + + def get(self, label): + return self.list[self.label_map[label]] + + def __iadd__(self, other): + self.add(other) + return self + + def add(self, content, label=None): + """ Add content to container using label. + If label is None, an unique label will be generated using time.time(). + """ + assert isinstance(content, str),`type(content)` + if label is None: + label = time.time() + if self.has(label): + d = self.get(label) + if d!=content: + raise ValueError("Container item %r exists with different value" % (label)) + return + self.list.append(content) + self.label_map[label] = len(self.list)-1 + return + + def __str__(self): + if self.user_str is not None: + return self.user_str(self) + if self.list: + l = self.list + if self.reverse: + l = l[:] + l.reverse() + r = self.separator.join(l) + r = self.prefix + r + r = r + self.suffix + else: + r = self.default + if not self.skip_prefix: + r = self.prefix + r + if not self.skip_suffix: + r = r + self.suffix + if r and self.use_indent: + indent = self.use_indent * ' ' + r = ''.join([indent + line for line in r.splitlines(True)]) + return r + +def _test(): + import doctest + doctest.testmod() + +if __name__ == "__main__": + _test() Added: trunk/numpy/f2py/lib/extgen/c_code.py =================================================================== --- trunk/numpy/f2py/lib/extgen/c_code.py 2007-08-02 19:26:40 UTC (rev 3939) +++ trunk/numpy/f2py/lib/extgen/c_code.py 2007-08-03 19:44:53 UTC (rev 3940) @@ -0,0 +1,32 @@ + +from base import Base + +class CCode(Base): + + """ + CCode(*lines, provides=..) + """ + + container_options = dict(CCodeLines=dict()) + + template = '%(CCodeLines)s' + + def initialize(self, *lines, **options): + self.lines = [] + map(self.add, lines) + + def update_containers(self): + CCodeLines = self.get_container('CCodeLines') + CCodeLines.add('\n'.join(self.lines)) + + def add(self, component, label=None): + if isinstance(component, str): + assert label is None,`label` + self.lines.append(component) + elif isinstance(component, CCode): + assert label is None,`label` + self.lines.extend(component.lines) + else: + Base.add(self, component. label) + + Added: trunk/numpy/f2py/lib/extgen/c_type.py =================================================================== --- trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-02 19:26:40 UTC (rev 3939) +++ trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-03 19:44:53 UTC (rev 3940) @@ -0,0 +1,156 @@ +""" +Defines C type declaration templates: + + CTypeAlias(name, ctype) --- typedef ctype name; + CTypeFunction(name, rtype, atype1, atype2,..) --- typedef rtype (*name)(atype1, atype2,...); + CTypeStruct(name, (name1,type1), (name2,type2), ...) --- typedef struct { type1 name1; type2 name2; .. } name; + CTypePtr(ctype) --- ctype * + CInt(), CLong(), ... --- int, long, ... + CPyObject() + +The instances of CTypeBase have the following public methods and properties: + + - .asPtr() + - .declare(name) +""" + + +from base import Base + +class CTypeBase(Base): + + def declare(self, name): + return '%s %s;' % (self.typename, name) + + def __str__(self): + return self.typename + + def asPtr(self): + return CTypePtr(self) + +class CTypeAlias(CTypeBase): + + def __new__(cls, typename, ctype): + obj = Base.__new__(cls) + assert isinstance(ctype, CTypeBase),`type(ctype)` + obj.add(typename, ctype) + return obj + + @property + def typename(self): return self.components[0][0] + @property + def ctype(self): return self.components[0][1] + + def local_generate(self, params=None): + container = self.get_container('TypeDef') + container.add(self.typename, 'typedef %s %s;' % (self.ctype, self.typename)) + return self.declare(params) + + +class CTypeFunction(CTypeBase): + + def __new__(cls, typename, rctype, *arguments): + obj = Base.__new__(cls) + assert isinstance(rctype, CTypeBase),`type(rctype)` + obj.add(typename, rctype) + for i in range(len(arguments)): + a = arguments[i] + assert isinstance(a, CTypeBase),`type(a)` + obj.add('_a%i' % (i), a) + return obj + + @property + def typename(self): return self.components[0][0] + @property + def rctype(self): return self.components[0][1] + @property + def arguments(self): return [v for n,v in self.components[1:]] + + def local_generate(self, params=None): + container = self.get_container('TypeDef') + container.add(self.typename, 'typedef %s (*%s)(%s);' \ + % (self.rctype, self.typename, + ', '.join([str(ctype) for ctype in self.arguments]))) + return self.declare(params) + +class CTypeStruct(CTypeBase): + + def __new__(cls, typename, *components): + obj = Base.__new__(cls, typename) + for n,v in components: + assert isinstance(v,CTypeBase),`type(v)` + obj.add(n,v) + return obj + + @property + def typename(self): return self._args[0] + + def local_generate(self, params=None): + container = self.get_container('TypeDef') + decls = [ctype.declare(name) for name, ctype in self.components] + if decls: + d = 'typedef struct {\n %s\n} %s;' % ('\n '.join(decls),self.typename) + else: + d = 'typedef struct {} %s;' % (self.typename) + container.add(self.typename, d) + return self.declare(params) + +class CTypePtr(CTypeBase): + + def __new__(cls, ctype): + obj = Base.__new__(cls) + assert isinstance(ctype, CTypeBase),`type(ctype)` + obj.add('*', ctype) + return obj + + @property + def ctype(self): return self.components[0][1] + + @property + def typename(self): + return self.ctype.typename + '*' + + def local_generate(self, params=None): + return self.declare(params) + +class CTypeDefined(CTypeBase): + + @property + def typename(self): return self._args[0] + +class CTypeIntrinsic(CTypeDefined): + + def __new__(cls, typename): + return Base.__new__(cls, typename) + +class CPyObject(CTypeDefined): + def __new__(cls): + return Base.__new__(cls, 'PyObject') + +class CInt(CTypeIntrinsic): + + def __new__(cls): + return Base.__new__(cls, 'int') + + 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) + Added: trunk/numpy/f2py/lib/extgen/doc.txt =================================================================== --- trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-02 19:26:40 UTC (rev 3939) +++ trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-03 19:44:53 UTC (rev 3940) @@ -0,0 +1,169 @@ +.. -*- rest -*- + +============================================ +ExtGen --- Python extension module generator +============================================ + +:Author: + Pearu Peterson +:Created: August 2007 + +.. contents:: Table of Contents + +Introduction +============ + +ExtGen is a pure Python package that provides a high-level +tool for constructing and building Python extension modules. +Hello example follows:: + + >>> from numpy.f2py.lib.extgen import * + >>> f = PyCFunction('hello') + >>> f.add('printf("Hello!\\n");') + >>> m = ExtensionModule('foo', f) + >>> m.generate() # returns a string containing C source to extension module + >>> foo = m.build + >>> foo.hello() + Hello! + >>> + + +Extending ExtGen +================ + +To extend ExtGen, one needs to understand the infrastructure of +generating extension modules. + +The `extgen` package provides many classes that are derived from Base +class (defined in extgen/base.py). Each such a class represents +certain code block or a code idiom in an extension module that is +defined in `.template` attribute. Most important `Base` methods, that +are used to generate code idioms, are: `.initialize()`, `.add()`, +`.generate()`, `init_containers()`, `.update_containers()`, +`.get_templates()`. + +Creating an extension module is carried out by the following steps: + +- create and add components to `Base` subclass instances, + for example, start with creating an `ExtensionModule` instance. + Components can be added with `.add(component, label=None)` method. + Note that some components (dependencies) may be added + in `.initialize()` method that is called by the constructor + of the `Base` subclass. + +- generate code by calling the `.generate()` method. + +- compile and build an extension module using the generated code. + ExtGen provides a way to do it via accessing the `.build` attribute + of the `ExtensionModule` instance. Accessing this attribute + will generate extension module, compilers it and returns the + corresponding extension module instance. + +These steps will be discussed in more detail below. + +The `.components` attribute is a list object that contains instances +of `Base` subclasses (components). For instance, the `CAPIFunction` instance +defined in the Hello example above, is a component of +`ExtensionModule` instances after calling `.add()` method. Similarly, +the C statement `'printf("Hello!\\n");'` is a component of +`CAPIFunction` instance after calling the `.add_execution()` method. + +The `.template` attribute is a string containing an template +to a code idiom. Such an template may contain string replacements +names that are replaced with code idioms generated by the components +--- template evaluation. +If the class should have more than one template then redefine +`.get_templates()` method that should return a tuple of templates. + +The `.containers` attribute is a mapping between a replacement name +(container label) used in template strings and a `Container` instance +holding code idioms from component generation process. The mapping +`.containers` is updated by the `.init_containers()` and +`.update_containers()` methods. These methods should use +`.get_container()` to inquire container instances +and `Container.add(, label=None)` method to add +new code idioms to containers. + +The `.generate()` method will call `.init_containers()` method, the +`.generate()` methods of components, and `.update_containers()` method +to generate code idioms and save the results to the corresponding +containers. Finally, it returns the results of applying +`.evaluate()` method to templates which replaces the +replacement names with code idioms from containers as well as string +valued attributes of the given `Base` subclass instance. One can set +attributes inside `.initilize()` method. + +Here follows a simplified version of `ExtensionModule.template`:: + + #include "Python.h" + + %(Header)s + %(TypeDef)s + %(Extern)s + %(CCode)s + %(CAPICode)s + %(ObjDecl)s + + static PyObject* extgen_module; + + static PyMethodDef extgen_module_methods[] = { + %(ModuleMethod)s + {NULL,NULL,0,NULL} + }; + + PyMODINIT_FUNC init%(modulename)s(void) { + extgen_module = Py_InitModule("%(modulename)s", extgen_module_methods); + %(ModuleInit)s + return; + capi_error: + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_RuntimeError, "failed to initialize %(modulename)s module."); + } + return; + } + +Here `Header`, `TypeDef`, etc are the labels of containers which will be replaced +during evaluation of templates. + +Using `Container` class +======================= + +`Container` class has the following optional arguments: + + - `separator='\n'` + - `prefix=''` + - `suffix=''` + - `skip_prefix_when_empty=False` + - `skip_suffix_when_empty=False` + - `default=''` + - `reverse=False` + - `user_defined_str=None` + +that can be used to change the behaviour of `Container.__str__()` +method. By default, `Container.__str__()` method returns +`prefix+separator.join(.list)+suffix`. + +One can add items to `Container` instance using `.add(, +label=None)` method. Here `label` should contain an unique value that +represents the content of ``. If `label` is `None` then +`label = time.time()` will be set. + +If one tries to add items with the same label to the container then +the equality of the corresponding string values will be checked. If +they are not equal then `ValueError` is raised, otherwise adding an +item is ignored. + + +Reference manual +================ + +ExtGen package defines the following extension module component classes: + + - `ExtensionModule(, *components, numpy=False, provides=..)` --- + represents an extension module, + + - `PyCFunction(, *components, provides=..)` --- + represents an extension function. + + - `CCode(*lines, provides=..)` --- represents any C code block or statement. + Added: trunk/numpy/f2py/lib/extgen/extension_module.py =================================================================== --- trunk/numpy/f2py/lib/extgen/extension_module.py 2007-08-02 19:26:40 UTC (rev 3939) +++ trunk/numpy/f2py/lib/extgen/extension_module.py 2007-08-03 19:44:53 UTC (rev 3940) @@ -0,0 +1,137 @@ + +from base import Base + +class ExtensionModule(Base): + + """ + ExtensionModule(, *components, numpy=False, provides=..) + + Hello example: + + >>> # in general use: + >>> # from numpy.f2py.lib.extgen import * + >>> # instead of the following import statement + >>> from __init__ import * #doctest: +ELLIPSIS + Ignoring... + >>> f = PyCFunction('hello') + >>> f.add('printf("Hello!\\\\n");') + >>> f.add('printf("Bye!\\\\n");') + >>> m = ExtensionModule('foo', f) + >>> foo = m.build #doctest: +ELLIPSIS + exec_command... + >>> foo.hello() + >>> # you should now see Hello! printed to stdout stream. + + """ + + container_options = dict(\ + Header=dict(default=''), + TypeDef=dict(default=''), + Extern=dict(default=''), + CCode=dict(default=''), + CAPICode=dict(default=''), + ObjDecl=dict(default=''), + ModuleMethod=dict(suffix=',', skip_suffix_when_empty=True, + default='', use_indent=True), + ModuleInit=dict(default='', use_indent=True), + ) + + component_container_map = dict(PyCFunction = 'CAPICode') + + template = '''\ +/* -*- c -*- */ +/* This Python C/API extension module "%(modulename)s" is generated + using extgen tool. extgen is part of numpy.f2py.lib package + developed by Pearu Peterson . +*/ + +#ifdef __cplusplus +extern \"C\" { +#endif + +%(Header)s +%(TypeDef)s +%(Extern)s +%(CCode)s +%(CAPICode)s +%(ObjDecl)s + +static PyObject* extgen_module; + +static PyMethodDef extgen_module_methods[] = { + %(ModuleMethod)s + {NULL,NULL,0,NULL} +}; + +PyMODINIT_FUNC init%(modulename)s(void) { + extgen_module = Py_InitModule("%(modulename)s", extgen_module_methods); + %(ModuleInit)s + return; +capi_error: + if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_RuntimeError, "failed to initialize %(modulename)s module."); + } + return; +} + +#ifdef __cplusplus +} +#endif +''' + + def initialize(self, modulename, *components, **options): + self.modulename = modulename + self._provides = options.get('provides', + '%s_%s' % (self.__class__.__name__, modulename)) + # all Python extension modules require Python.h + self.add(Base.get('Python.h'), 'Header') + if options.get('numpy'): + self.add(Base.get('arrayobject.h'), 'Header') + self.add(Base.get('import_array'), 'ModuleInit') + map(self.add, components) + return + + @property + def build(self): + import os + import sys + import subprocess + extfile = self.generate() + srcfile = os.path.abspath('%smodule.c' % (self.modulename)) + f = open(srcfile, 'w') + f.write(extfile) + f.close() + modulename = self.modulename + setup_py = """ +def configuration(parent_package='', top_path = ''): + from numpy.distutils.misc_util import Configuration + config = Configuration('',parent_package,top_path) + config.add_extension('%(modulename)s', + sources = ['%(srcfile)s']) + return config +if __name__ == '__main__': + from numpy.distutils.core import setup + setup(configuration=configuration) +""" % (locals()) + setupfile = os.path.abspath('setup_extgen.py') + f = open(setupfile, 'w') + f.write(setup_py) + f.close() + setup_args = ['build_ext','--build-lib','.'] + setup_cmd = ' '.join([sys.executable,setupfile]+setup_args) + build_dir = '.' + from numpy.distutils.exec_command import exec_command + sts = exec_command(setup_cmd) + #p = subprocess.Popen(setup_cmd, cwd=build_dir, shell=True, stdout=subprocess.PIPE,stderr=subprocess.PIPE) + #sts = os.waitpid(p.pid, 0) + if sts[0]: + raise "Failed to build (status=%s)." % (`sts`) + exec 'import %s as m' % (modulename) + return m + +def _test(): + import doctest + doctest.testmod() + +if __name__ == "__main__": + _test() Added: trunk/numpy/f2py/lib/extgen/predefined_components.py =================================================================== --- trunk/numpy/f2py/lib/extgen/predefined_components.py 2007-08-02 19:26:40 UTC (rev 3939) +++ trunk/numpy/f2py/lib/extgen/predefined_components.py 2007-08-03 19:44:53 UTC (rev 3940) @@ -0,0 +1,23 @@ + +from base import Base +from c_code import CCode + +Base.register( + + CCode('#include "Python.h"', provides='Python.h'), + + CCode('''\ +#define PY_ARRAY_UNIQUE_SYMBOL PyArray_API +#include "numpy/arrayobject.h" +#include "numpy/arrayscalars.h" +''', provides='arrayobject.h'), + + CCode('''\ +import_array(); +if (PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "failed to load array module."); + goto capi_error; +} +''', provides='import_array') + + ) Added: trunk/numpy/f2py/lib/extgen/pyc_function.py =================================================================== --- trunk/numpy/f2py/lib/extgen/pyc_function.py 2007-08-02 19:26:40 UTC (rev 3939) +++ trunk/numpy/f2py/lib/extgen/pyc_function.py 2007-08-03 19:44:53 UTC (rev 3940) @@ -0,0 +1,77 @@ + +from base import Base + +class PyCFunction(Base): + + """ + PyCFunction(, *components, provides=..) + + """ + + container_options = dict(FuncDoc=dict(separator='"\n"', prefix='"', suffix='"'), + Args = dict(), + Decl = dict(default='', use_indent=True), + KWList = dict(separator=', ', suffix=', ', skip_suffix_when_empty=True), + PyArgFormat = dict(separator=''), + PyArgObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), + FromPyObj = dict(default='', use_indent=True), + Exec = dict(default='', use_indent=True), + PyObjFrom = dict(default='', use_indent=True), + RetFormat = dict(separator=''), + RetObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), + CleanPyObjFrom = dict(default='', reverse=True, use_indent=True), + CleanExec = dict(default='', reverse=True, use_indent=True), + CleanFromPyObj = dict(default='', reverse=True, use_indent=True), + ) + + component_container_map = dict(CCode = 'Exec', + PyCArgument = 'Args') + + template = ''' +static char %(pyc_name)s_doc[] = %(FuncDoc)s; + +static PyObject* +%(pyc_name)s +(PyObject *pyc_self, PyObject *pyc_args, PyObject *pyc_keywds) { + PyObject * volatile pyc_buildvalue = NULL; + volatile int capi_success = 1; + %(Decl)s + static char *capi_kwlist[] = {%(KWList)sNULL}; + if (PyArg_ParseTupleAndKeywords(pyc_args, pyc_keywds,"%(PyArgFormat)s", capi_kwlist%(PyArgObj)s)) { + %(FromPyObj)s + %(Exec)s + capi_success = !PyErr_Occurred(); + if (capi_success) { + %(PyObjFrom)s + pyc_buildvalue = Py_BuildValue("%(RetFormat)s"%(RetObj)s); + %(CleanPyObjFrom)s + } + %(CleanExec)s + %(CleanFromPyObj)s + } + return pyc_buildvalue; +} +''' + + def initialize(self, name, *components, **options): + self.name = name + self.pyc_name = 'pyc_function_'+name + self._provides = options.get('provides', + '%s_%s' % (self.__class__.__name__, name)) + map(self.add, components) + + def init_containers(self): + # set header to FuncDoc, for example. + FuncDoc = self.get_container('FuncDoc') + FuncDoc.add(self.name) + return + + def update_containers(self, params=None): + ModuleMethod = self.get_container('ModuleMethod') + t = '{"%(name)s", (PyCFunction)%(pyc_name)s,\n METH_VARARGS | METH_KEYWORDS, %(pyc_name)s_doc}' + ModuleMethod.add(self.evaluate(t), self.name) + return + + + + From numpy-svn at scipy.org Fri Aug 3 17:21:20 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Fri, 3 Aug 2007 16:21:20 -0500 (CDT) Subject: [Numpy-svn] r3941 - trunk/numpy/doc/swig Message-ID: <20070803212120.4C9B739C063@new.scipy.org> Author: wfspotz at sandia.gov Date: 2007-08-03 16:21:10 -0500 (Fri, 03 Aug 2007) New Revision: 3941 Modified: trunk/numpy/doc/swig/numpy_swig.html trunk/numpy/doc/swig/numpy_swig.pdf trunk/numpy/doc/swig/numpy_swig.txt Log: In documentation, removed one of the reasons for not providing (out) typemaps, which turns out not to be true. Modified: trunk/numpy/doc/swig/numpy_swig.html =================================================================== --- trunk/numpy/doc/swig/numpy_swig.html 2007-08-03 19:44:53 UTC (rev 3940) +++ trunk/numpy/doc/swig/numpy_swig.html 2007-08-03 21:21:10 UTC (rev 3941) @@ -634,13 +634,9 @@

Output Arrays

The numpy.i interface file does not support typemaps for output -arrays, for several reasons. First, C/C++ function return arguments -do not have names, so signatures for %typemap(out) do not include -names. This means that if numpy.i supported them, they would -apply to all pointer return arguments for the supported numeric -types. This seems too dangerous. Second, C/C++ return arguments are +arrays, for several reasons. First, C/C++ return arguments are limited to a single value. This prevents obtaining dimension -information in a general way. Third, arrays with hard-coded lengths +information in a general way. Second, arrays with hard-coded lengths are not permitted as return arguments. In other words:

 double[3] newVector(double x, double y, double z);
@@ -1053,7 +1049,7 @@
 
Modified: trunk/numpy/doc/swig/numpy_swig.pdf =================================================================== --- trunk/numpy/doc/swig/numpy_swig.pdf 2007-08-03 19:44:53 UTC (rev 3940) +++ trunk/numpy/doc/swig/numpy_swig.pdf 2007-08-03 21:21:10 UTC (rev 3941) @@ -702,23 +702,24 @@ /ProcSet [ /PDF /Text ] >> endobj 206 0 obj << -/Length 3673 +/Length 3454 /Filter /FlateDecode >> stream -x??[[s??~???Kf???!.??)???;??I?v2I&CQ????????b??????? ,??b??'?'?.u??'?mKcjq????S%???:??|?????'m?i?Ku??TV??w@????L?a >??l? T4?????D??? ?{no????N???FTv E?)9?u5?@?HWXp?oO??fc?^???sG~?????Mq?R?????s:??t?k]????^??U?)???N?g?z??.PES???w???.?V=?=?V?#h?G?-????!?O????vj?4J??????"??w3q???E&?c8? ??? -I?{?!z?Y]????W??A????+F??=?&???^a??,?*????p?G??{,0?????????{p?1????.??&iM&Z?h?z?2??@q=],y??9?????????NX?3????g?8sa#???hjU??|?%O???%,??(?MV?u?????4B?G|e??? ?^j????R?6m+3y2_????3C)p?Lq??????RI?Tux?#r?L?? ????MN? OuD?F?VUM*?[?w?<.??????E? -?0?????F??e??`?;7.[[j)? -?m.Y??/.???????? h???????g~u???gBc? f??!:???m??T????Z-GLQ???Z0a?%fOS(t A at g?.? ????a aJYC?-yw?j?om?~%? V??K;?Kx089??_??x???+?s??????????=??????? n*????_s??~ ?F??g?)???GT[:?d?u??m??????>Q???????s??/?{??????oL??yu???i>????';???n#????h>??4D'????p~65_i?j?1?GT[??d?5??m?????????~E????5??ec???{L???@vT???Nz????????R????5)??QZ[????Tn$g?ha????? ??????2??!"??????rB /tQ???5@??dr????/>{?)|}?\?V(H??5E?4???;?qj?:?c??? A)???0&=MC??N? ??h???Q=Eb?4Q?kT?}?????=??^??5r???a?????5??j??R?;?0???Rhk??{O???????S?}mJm??????S?b??C?q ?M??Q?'Z4??|N????,+?B????Y?i~a ?6??S?c?#i?p8?Y?????, ?;]???/Y?*?pk??F????r ???$????A??????]?.??3?r"Fn?D??} ???????Dr???V??? ? ?K0a]??B=??????????v??'??yv~eGbtYY?N??uX>6??I?9U6????[?U?X?????????-J???_???????62?"?m??H?Z??2&?zinI3??8????R3?? -?-/??[.?D?????5??Bh ^1,?x(??aUW&??)????>??+???#???w1?L?3?Ot????? ?O?m? * ??[,??????????w.??????h?tG???r&oC?#=p ?????'???????vZ??Kf??s?>D5?e?)?P????????{?9e?f??????$?e?????E? -????mkn?$u ???????pI?G??Z?}y????,8??? ??????p?TI?????x?ed???,??????#??yir?F??n????????8,h?rj??a??VM?Z??+x?~"?=]?m1??F?[???f?STB???V??"z?????af?bX Mc????? ?s????????e? -??+??????D????_m?w?~????M?????j??@n?l???D ?a???w??"%l??US??9 n?!P?b?7_?T?x????]???-+??|vXm ??3?- 9u?????{??m?xn?d??????????D?+?p?e0?N?t|,??~???&t2?\I??+????>??z~\????????g??g??!Y???K??Yhv?? ???s???]DglH???t7N??u? ?]~2??zS??\??}?&>????r7M S.?oK?1?Vnu??n???" -?n???????H$Df? -6??x -????????V??8??h???8|D.?d?| J*??&???:??q9-E?,J??r?#z???0??????/Z?s&?U? '???,C?????w??????? ~????2M ?O??????jU???Jyd??pY?h.'?o::??h??'J-?JD??? ?>?t+L??+?[???$K)7???????F??4U{????? ?r?t3??v???o%??g?f?u&???x?I?m??h[L-?R?F?b?}j????5??o]??Ju?????)2T5????\x ???x?q?2? ???&Y?l? ?@??n?x??????Lm4?"?m?H??L?0???`7??Os??B??b? ]???zN?b?v -97???l?t?? -?!6]?]KO??,?s?H?;?????R???0g????mh???!t?Rjv?!e?h?\0???A?V?3yh?q?:K.(?i?})??Sy??(??U?_?;??.?7?6?b??e#??0?????{???????9n?8?g????y?w?U%Y:-R????? ?v?e???%??a{??2'???q#?]??????????-d??[??_,'?? ????:?qv???%?)??%K<H5?s~u<3????B?s?T??$??u??%?? :?}?????? j?? ?gS????pMS6??T8??]??|????,rd?R?4M?{?????s?(.?|PkKY7?(,?FDs+n ??? e3yw?O*?????endstream +x??ko????} pjt??s????????J? ???,???\??????$?q?)??????p8oRbU???jt?????V???????k????`?m??m?c?wcd]9k?j?"????g/?U??5F?.^sYQ5?mVW???8???????F5??wgJ???k???_>{?Vm?ZiK??W)'??{?????bPv?a >??l t4?c????, ?7?????wgi?;Dm7?t??3Z????$????3?hX??W?~~??/'F? +h?~?Tn?0=s???l??^_ ?7???U?)??w??????k?>+??v??x{l6??k????=W?#r?W?#n???Cl`?0??0fj??????"??w;`??UA?G?? ?????!Yz???JI]|???|????V?j???;??u??????x????vYi???!?g_]D????Rn??????^9????a?K?4?o????z??zyr>0?qA?=R????*?)?E?Z?b? ?8Gn?L?Z???Y???Hn=? +?k5 ???N?6????%) |7H???^??????????-?~??=?eO??F?[???? o?1???w?a?w(N[$ ?????L?cJ8???;Q??fk??mEbh????:???1?)???$A?G??K^?????]?x??e????l4??B??????) ?DV1??Wh?4??G? +??? a??z?F?~??GBx??[??????? 1?G??"???`?ojSfR4a??K????????t5e?F????F???:AuGr'4m????MDGz??Q??6? ??*On(?6?3*m??i?]Y?*+d{?VF?M:`l?FhO?? +??ZY?S???L?R?nb? ??r~?VJ?S????Q"=???=?????????? +???^?z???,l?x!D +]???: @?&C+$(????p??i????]??,!>?w??]*?????????oj{JB??Z<\?.????$ ?'-??s???UG&FE ++??q_rs?oS???[??????s?A??4???]FWN????+?!???_? ?]?b??8v?? ?? ???????O??/->!.????[C???v?'??nxw??!????????&*$?Mn|r??????K???4?X?6?o????-R???_?}="C??kdAE?m???Bem>???g?i??{??v??5*?+???m?-_B"%??????E1)?U!??-?w????=??s?{??R?? ??sRj??%?7>d??v????|???x?Bz?a5?fIL?? ?L??N?1pKi???`?HY?KT???r#D?3:? +Yas????E?? ???fNb????p???'?qzmB6>?%a??=!????%???eT???????,?$? ?~??????s???B'E9J?ZT?????_?????JQ??W?B??BJ;v|???????R??2?????" +?0CG?d?B???????NO?#?(j0???_?Q????D?~?A????c??[S?@??@??????U5t`M????~?>a7???~??P?aL?Z?:?L???+?6PH?[?O???)O?e?b?0?`^??\r??@NGL]"Q??I?????&??wL`???????r"????????]?EW??6mH?C?4??m?3?? ?[>??QVa?orO?????O,?@??T? :? ?-?0??p?/$????`?L???>aO???(??;???gSjF??#?qF????B??A???? )? ??=i5?_??`? ??0\????tI-???|nQ?E??q???f\???c?j$P [f?%????8?R?5J$9H???5?t:?|['??Li??$7Mr??? x?J??jd?? ???IL\?(???U??\8????_??????Z??4???p?h?L- d?????w??b?"?????cd?7t^???>?F??j f?M?p?u9??Lk1 +Y?m?d??;a ??L???2 +??2???$?t2?]v=?b?>??RTH??n???RT8?I / q??(?C?,?T ??#?Z??k?v?p?i?0?/?H??N????M?li9J;????'5??.?>7W?py??K?C?N?TvB???N$? lmm??N??;?y?|(?]`????Tb8r??+ .b?m?5??{?????ts3R/ZY????D$E1/???+??sy??.'??j-B??=~??y-r??r$64&?\tb{*?5IT???4?g??+?+???)H?????1Gh)'+?" ?b?v4??)??9S?8???P????T???e??J:o}??;?d?pVF??j Q??> >> endobj 213 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] -/Rect [112.7078 518.3544 141.8683 529.1936] +/Rect [112.7078 517.2966 141.8683 528.1359] /Subtype/Link/A<> >> endobj 214 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] -/Rect [73.4132 506.3992 105.8213 517.2384] +/Rect [73.4132 505.3415 105.8213 516.1807] /Subtype/Link/A<> >> endobj 217 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [333.1098 251.6809 423.3722 262.5201] +/Rect [333.1098 273.3621 423.3722 284.2013] /Subtype /Link /A << /S /GoTo /D (available-typemaps) >> >> endobj 218 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [253.4973 149.1272 313.0848 159.9664] +/Rect [253.4973 169.7506 313.0848 180.5899] /Subtype /Link /A << /S /GoTo /D (input-arrays) >> >> endobj 219 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] -/Rect [403.0247 149.1272 474.368 159.9664] +/Rect [403.0247 169.7506 474.368 180.5899] /Subtype /Link /A << /S /GoTo /D (in-place-arrays) >> >> endobj @@ -792,28 +793,28 @@ /D [205 0 R /XYZ 74.4095 753.0247 null] >> endobj 133 0 obj << -/D [205 0 R /XYZ 74.4095 507.3955 null] +/D [205 0 R /XYZ 74.4095 506.3377 null] >> endobj 34 0 obj << -/D [205 0 R /XYZ 74.4095 507.3955 null] +/D [205 0 R /XYZ 74.4095 506.3377 null] >> endobj 215 0 obj << -/D [205 0 R /XYZ 74.4095 472.7698 null] +/D [205 0 R /XYZ 74.4095 471.6552 null] >> endobj 134 0 obj << -/D [205 0 R /XYZ 74.4095 298.5925 null] +/D [205 0 R /XYZ 74.4095 320.3306 null] >> endobj 38 0 obj << -/D [205 0 R /XYZ 74.4095 298.5925 null] +/D [205 0 R /XYZ 74.4095 320.3306 null] >> endobj 216 0 obj << -/D [205 0 R /XYZ 74.4095 264.2459 null] +/D [205 0 R /XYZ 74.4095 285.9271 null] >> endobj 135 0 obj << -/D [205 0 R /XYZ 74.4095 138.1683 null] +/D [205 0 R /XYZ 74.4095 158.7917 null] >> endobj 42 0 obj << -/D [205 0 R /XYZ 74.4095 138.1683 null] +/D [205 0 R /XYZ 74.4095 158.7917 null] >> endobj 204 0 obj << /Font << /F51 119 0 R /F8 95 0 R /F14 193 0 R /F56 126 0 R >> @@ -1367,20 +1368,20 @@ /ProcSet [ /PDF /Text ] >> endobj 301 0 obj << -/Length 1806 +/Length 1807 /Filter /FlateDecode >> stream x??X???6}?W?????*2oi??-?6h\??- -??:?xW???&???????Z?BX^? ?????????*?0E??????????bu???Od?????????????R?`?J???"?^>2? Ah??Q:)JJD}?}???4+???[m?WRJ?J??????????g?????*? eaU.pB????>?U@?u???pj-??a??S?C????'??D,??????????D W?_?zB-?;+? ~H~[?N??\m?3`[??^Y?-?V.??%???{?n???g?????8V??*?[???Tz? ??``???^??DY???M?FU??u??s %??+? ???]_??N?E?"?g?????KQ???.X??B???a"X?H???Qv??? +??:?xW???&???????ZA?,/?s?????rU???*?0E??????????bu???Od?????????????R?`?J???"?^>2? Ah??Q:)JJD}?}???4+???[m?WRJ?J??????????g?????*? eaU.pB????>?U@?u???pj-??a??S?C????'??D,??????????D W?_?zB-?;+? ~H~[?N??\m?3`[??^Y?-?V.??%???{?n???g?????8V??*?[???Tz? ??``???^??DY???M?FU??u??s %??+? ???]_??N?E?"?g?????KQ???.X??B???a"X?H???Qv??? ???B?2??\?@s:?Bh[#??? ?]??@ ??Ehs????ZF?)?~??}???F ?T6??????i???#?3??R)'/?]?~?/???T,Z?W2?r???+L9Rc???m?P?pC?%[?h?DA1??@&EVmK??I??g???Wp?p?;R??\??? ???j>W?GoEg??d?O??c ?x\B? 2?????.?[??h??=???9-?????>Xr?F?W??BZ??dZD???E1??????hd??H? ?H?vU?.: ??5?lg?8?p?Gx?+?cm??M? %??kk^?PL^????c@s?R`GM)?? ?1??PA5??6??z+??1????????o??5? ?(??=?^??Z??)H??l?O ??1??"?~?9~I??\T?T??V8?SD?? G??? +nI??<)O??????:??r????^?k???n???> endobj 312 0 obj << -/Length1 1213 -/Length2 5702 +/Length1 1231 +/Length2 5942 /Length3 532 -/Length 6475 +/Length 6718 /Filter /FlateDecode >> stream -x???eXTm??AB?$???????`(i$?CB?I??FiiA??|$?? ??+Z?A?@11 @???? -? ?? ????^H????M??W?@? ?????Mk7{?Zd ?!@P??@????? q? Q0>CAn????????W???? -?tE???M???8? ????j!?? h'???)???iY;??G???Z;Aa^??G89??A?M??????/k?0????Y57k$??A|? -A]????6? d????B??C???@o?_xU??558???_)mk(?M???o?_?1?7?? ????????????,??J B??p?qX#??^??s?&!???!??'?//?????_?-??k??B^{/g{?W?_!a?3zH???(???D??xp??,??u????? ????k?pG??;?BP4Bw!`??a??oB??&t ??IT??????? ???oB?A^??????M?e??& zU?????Z????????????he??VF??h?????N???????????F?[???D+{???????#<}????????"B|?????DB?n=??s?o???? -????D?$?RjB???rF?q80??>?j?oo"??????k?p,T???????3x\??F4>?R? p?M??^GY??y???iz?93?m5?|>??|?ia?(?$?+s?{??6?????s?mf?m???"??i0????G????.E??a??????#A~ax????Fw?????k?3?P#???2??7????0b?????r?t????3??????,??????(??1??_??'???2???? ?d??????6#o?jt??g????@???3Dk7D@??0????(?YIgO7?e?9?u????{?m?^*`??!a?P,6??7Nt??)LL?[%? ?N?%8?x[?2??@??nB??y???~D??????k`;?G1????(?!t?)???'R[??#l/uV??-\xl??c???????lU}?a?O?p??e???r??f???$v?/???c?U$?hi?E.9-???\??p???????u)?]#?X -l[;B?????h?TSJ?l ??o????Z? Cg+??????.??G?#GX???Nk??7|?*?)g?2U??? ? ???AR =jE?uq??L?=_?q?{???)?q?????L??t?2?Y?!,??::B???m7????)??M??L???C1dKZ??x;?>T?@?????=?? ?t???n?[?y?+???RU???????_???o?h???M?Z?=x????/??S?:y ?eV??TR^<4?????y????z?C.l??? -??w???LiO=?z?b?o???F?H G"?0?????A?M??_??+\}???%?-??!????z4?g>????=?????n?8O/D[?.?{????g??|???2@?7???um?wW?%????I??????D?z??ZP????:? ?:?z*??P?oO?K???C? -??k???J?R??]????J3?K?h??2??6????????`.?mT?K?=v??8??Ak2?x?????"?#?p? ??Z??Ei?^??Ti??dDG?X?9?n? t???`??D??J?:?D?TLQE???.B??|???u??1??J???? @/????? ??BP?J???=????X?n??H?????????|?3??p????/??y?????????D???D&??I????BE????F?}?"i?F??e??BJ$mU3?????'?? 6)??s6????5-=G?-?????F???"{|?7?ii?g7s$??d -?8!tM????????I???D?R ???,x9???m? p?%j?h??#}??q?&?????Z:??4?8?E??pKK????{??t??F?'?c???ep??>???~Q?}9?E???'w???n?'???\~W?qy??????j [sb;?v?@?????????2T*3DcL9y10?]?A???2?'????x??b?????VZ4??W?T?[???A?m?n??:?/???kL???^??-c??????!?y?a?%he?{?+?e -T?=?????0y?"d?? d??????,????h????'?t?h????(OZ????_4?rQ2?????OB?F? 3}#?? ??????????????z?????????d???4?v???)???p(N????_L?{ ?1?????) ? ]k? ??z??Ic%??!??6?Z>?O?? md????:?-@?P?U??3?? -??5??u*?n?????P?MP???UNT~kX?'c?y?_I?;??l?d??xc??f????? f?.???y?p???n???J.?l?I ????Ju?e?L?????i?2&93???? ? ??????:??jb?>???=?/??????6??qA??QQA?i?T??g?)7,$.???????WJ????A?v*6O1??3??F;????^ey3?`V?M?f??]qg?ri??\????/sE?@{????'?`B??X??i??W?Q%?KW??{E??MZ?X9/! < ??1d?@??+??72?t?Mx^? 1;?.D?/??-?7?G??EL8$(??3?V??d?ky?? 4 <????V?t?(a?u,?-??????cF?d??EK?m3d?u?O_.?(6?H Ty?E??????j???p???"w?`+??Xs??R???v>ma???????K????"0*???? ?Y?L<gS=?;=L????q ???&/??]?3??[?iUZ1R???l|?rE&??\zY??;????t????????m???X?%=?j?[?? ?52PL&??+-???? ?;>??D??f?????>? ?X???>q |?????P?P???`?aU,??i~X1I>?]?Z?|?"?????9p?? ?|p?{??3aW & -(sm???F;B?+E9???}?aVK?????????????i??dfZ?5wk???? 7? M????b ???x???ep-?????dC?7??e??W j?{{d?a}T?o&?K????~??R\??3S??b~Zz3???;???.j???1np?l??a???Z?j? B??V?:?A&.?j???`??*&z??????R]??0???>???N??rK???d??t?????????DFB???/?L?,N?R??id0J?RK/0!8???? ????? -???O_?|???`????XW?-??:x??G?1???Y???H?_??"??T??b;Ni??m?U?#??fL?T??6???N????X?/?}??9FZn}??2U?z?[~&.????Q??P?H ???5?T 1R???bk5E??)???>?c????6s??-Z{wV\u????5?_N?LC?@?rp?r&?????D2??\H?y?pXE????h???????bX?2?#?w??b?-?z?? w?? ? -?g??R???sa??R-?? ??k???k?>7????4?o)?3Vo1ML(=?h?????????.5/?i????0?]?*??????q=A??G0rI????????S?=E??q?)?a???*Q.???*???'???2?C?????;??0?v?|R?1?di??^<7??q?@`_?????S&?i???W?_!d??f???mm?k/W??d??F????Zb??????`x?????#??`?k (?=?K???`H\??<:|?QfLUOh???F??l?7???9fIa?G?x??u?I?????Q=?"??K,??1 ? ?$??kB??????6a]?;???B?hY??`?3P3#h???z???np??y?Z??????!?G?A?D1???A????=??LDM??`V?T???r?$??g??%Af?y?#??#%T????6?T$~???a*?a[xL?<~?$"??$??? ??9U?????jU6??u?A?l??b??yx? ????Vn+;"I?6I?g NYH]?AI?p?>wE??Z?n&????Gor????/h=??k{??uDw??Rwu y?a7??5??9$4N?K??S?????t??:???,?t}aj???dK??????????? a>??i8};m??X???(j??? ??D??????]?????SH-?sk?f??d?-?I??? \???>???~?O4???I?c05{??k?c?k???Cl~M????J????n??-h,.???2?s ?*?z?????;??>??N,???C????=E?????? : 5????w?????????x??.??:????? ?????D?%{&??W??/ 0^T??^?? R(?X?u?7nK?t#a1??Y\zd(Y?`Q???9H?0?'2???B?= -?h?D???? -1\?5?#A??e0?wX???1??????6??@d?j??????????  b?tC8Y#??z&?endstream +x???e\???Az????Sz`?.?b?AJ?$??TBZ QB??A???;????>??|?W?sg??w????????? ??T???00?+??t?d? aQ7? +?? G"?|ar@??,???????e?$e?@5?W +??? ?S???H?? C??????+??u?#?p?o?0P??h?k???C???? ? ?:?\???/??3(?w?????)?c +??1y ????Dx?`?=$? ????????<??@LG?(q?1]? F???({?FF?b?? ?>??5??3I??????y'D?@?r?_?????*20DH\($?9Q???PZR4??*???P0??_????????? ??&?P?h?????0???x???.M?z???o??&?`{?~????_g~V?EE????p???~?p????l?j??~5+???? K7h???8j???q???$??????4???\t?V?????,;V??CWv???98??4?A?8??3????s?i)?s????b ?f???~?gE???W??4I?v6q?%~j?5?????d??=?/???.?(?*?4??GHTU???`F ?4???C]?=??vs?Kn)????v?v????%???"duc?'??????Q?F{S???v?=?x?z?? +?RV??8???Fh????ltB??C?.C?L???b8??????O\RX&-?N??????!???????%???M?{???f7??[X.n????H??????z^?r??2?-?v?????"K??DLp`?a??2?e? ?r???&?(/KOSM???!???=????'??|???'C????????>???DQ1?P??Y????u?t{??s? +?"?/J)????X???"B/?i??j??F?????Gqg?4?I??q?????H5??`/???Se??d?D{[?4Q??Q_Vp"?/???{nL?????b?T???c?^??1a@???>?OIK??.??????5k??0WR??>W???j ?/39??q ???Ab(z=???i???k +????{?????$?/?&?g??RQ2???Rx;?{ ??????A????4TZc?e?'?}?*f?/?m(f??????^??RS??y}?;??q??Y??_?CE =?!?'_????????F9j??G\)?I?? +?=??;U????M????????+/???L?+? +d???d???a~o*.e?;ny??5??G??w*??M4??4?oo.?5?=K???g@{? +?#;-?|v?* ??6$DW?W???9^?K?m?????(??deE?)L???)t?(2?3??e????;?m???v8n??s?(}(????NEo?X?Z-q??&?H?J????~ ???.???]? ?jW?????C????kTjm:"?x?9n?yc????????????(>?w?????C?~DB?L???5?o;? ??+o0,??'? ?????fe??O?????HB??d??m?u??t<#?1???5?0;??F?? WdA?s?w ??+?????????? +?u????$Wf??0?|r??a????H???F?{~ +;Y{?l5fF'?X"?=t7???@?\?8??#??@;??<e???????9/??]q??(L+v,iO?o?????ST?8????m???)? +u??(5??h????}'2? +.\6??f~?O??x?)J?n5????tH??????!??+j?6R?.K?#????nhH??g?,:?Q??~$vA???Q?eZI@@b??k?????3eg?K???X)xz??????u?DM?~=ok???)~?+?}?]H?????w"??r F??????????l??!????8;???t?K???[1?/?????????lGF|O??/??S?W4?%#?~I>*??&???N???XU?|m??EU??&I?lu??f???9|]&[W?????i???R?j??j????65??'???y???'??d?????????m?@?N54B}?}O???}a? V??,??\5"1????????????# J???/K???Y??v??P9w??=???????J???4?/?L?????Rh#?gj?U????6?,P[8UF?!??i$??????2???Y??2?G??Q?????+Q??jt??b??u?????????? wB?J???.???N????????1?7??#LH??????-CgXn7??H?x P??N???[u?L?h^?????Q?o?????r?|??'?Z??j?e?l????L?)? O?????U%?????|Y??/?? +??+???????6?`E?x???=R?.??1???c???\,o')d???B??u???[?}W:???]???Ps?M???}???r,?W??-*??P?\z??`????.?sB&5~?:?^L??? ? N????5}?rN?xg??/?>n^?????O9??*|?????!l???;??|??J?D?????F.r???(?~???E??? ??? ?wf5?????p?4?????-?Q?aO?e3?Y????n?????!?J???h???9??S??????X[?Rl?Nz??z?[2??>N??Ig?Q??i?? ??U^R??N?[;I?Q^> endobj 311 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 -/FontName /HTJMKC+CMR9 +/FontName /YHOGLV+CMR9 /ItalicAngle 0 /StemV 74 /XHeight 431 /FontBBox [-39 -250 1036 750] /Flags 4 -/CharSet (/hyphen/period/zero/one/two/three/four/seven/colon/C/D/G/S/T/U/a/b/c/d/e/f/i/l/m/n/o/r/s/t/u/x/y) +/CharSet (/hyphen/period/zero/one/two/three/seven/eight/nine/colon/C/D/G/S/T/U/a/b/c/d/e/f/i/l/m/n/o/r/s/t/u/x/y) /FontFile 312 0 R >> endobj 317 0 obj -[343 285 0 514 514 514 514 514 0 0 514 0 0 285 0 0 0 0 0 0 0 0 742 785 0 0 806 0 0 0 0 0 0 0 0 0 0 0 571 742 771 0 0 0 0 0 0 0 0 0 0 0 514 571 457 571 457 314 0 0 285 0 0 285 856 571 514 0 0 402 405 400 571 0 0 542 542 ] +[343 285 0 514 514 514 514 0 0 0 514 514 514 285 0 0 0 0 0 0 0 0 742 785 0 0 806 0 0 0 0 0 0 0 0 0 0 0 571 742 771 0 0 0 0 0 0 0 0 0 0 0 514 571 457 571 457 314 0 0 285 0 0 285 856 571 514 0 0 402 405 400 571 0 0 542 542 ] endobj 316 0 obj << /Type /Encoding -/Differences [ 0 /.notdef 45/hyphen/period 47/.notdef 48/zero/one/two/three/four 53/.notdef 55/seven 56/.notdef 58/colon 59/.notdef 67/C/D 69/.notdef 71/G 72/.notdef 83/S/T/U 86/.notdef 97/a/b/c/d/e/f 103/.notdef 105/i 106/.notdef 108/l/m/n/o 112/.notdef 114/r/s/t/u 118/.notdef 120/x/y 122/.notdef] +/Differences [ 0 /.notdef 45/hyphen/period 47/.notdef 48/zero/one/two/three 52/.notdef 55/seven/eight/nine/colon 59/.notdef 67/C/D 69/.notdef 71/G 72/.notdef 83/S/T/U 86/.notdef 97/a/b/c/d/e/f 103/.notdef 105/i 106/.notdef 108/l/m/n/o 112/.notdef 114/r/s/t/u 118/.notdef 120/x/y 122/.notdef] >> endobj 192 0 obj << /Length1 750 @@ -1535,11 +1539,11 @@ stream x?SU ?uL?OJu??+?5?3?Rp? ?44P0?3?RUu.JM,???sI,I?R0??4Tp,MW04U00?22?25?RUp?/?,?L?(Q?p?)2Wp?M-?LN?S?M,?H??????????ZR???????Q??Z?ZT????eh????\????????r?g^Z??9D8??&U?ZT t????? @'????T*???q????J???B7??4'?/1d<8?0?s3s*?*?s JKR?|?SR??????B????Y??.?Y???????????kh?g`l -??,v??HM ?,I?PHK?)N?????;|`???:F?hC?,???WRY??`?P ?"??P*??P?6?300*B+?2???????t#S3?????J.` +??,v??HM ?,I?PHK?)N?????;|`?????x??iC?,???WRY??`?P ?"??P*??P?6?300*B+?2???????t#S3?????J.` ?L? 2?RR+R+?.????/jQM?BZ~(Z??I? ??% q.L?89?WT?Y*?Z? 644S077?EQ?\ZT??WN+?????2?A??Z???u?Z~?uK??mm+?\_X????????7?D?????Rl:/P1?d????????(??l=U?h?d?_O??E?k?v-X1??t???`????i????_y. ?1?????????:?un~Q???3/??S??}??]?? ???$e~s?]F1????/??Q???m????|<?????/??q'}I???+6???E??g???xT.??G??gt???v??G??U|?????~??]?R????_k?9???:?{?p??G?? ??d}dN<6??-uB?o?H??=c?M?vH??z?q?a???RK?~,K???}????????m??????yo??~?????v? ?_????s>???.#????????{?/?????k????\m?|??r???X???????ad?j|?????R/?,2?p?0, H?IM,*??M,??K?r?endstream +??-??????W???d?????_?~?+ ????i?s?s?`??C???u?I^>??\m?|??r???X???????ad?j|?????R/?,2?p?0, H?IM,*??M,???r~endstream endobj 193 0 obj << /Type /Font @@ -1548,14 +1552,14 @@ /FirstChar 15 /LastChar 15 /Widths 319 0 R -/BaseFont /UAXOPP+CMSY10 +/BaseFont /VOLHMF+CMSY10 /FontDescriptor 191 0 R >> endobj 191 0 obj << /Ascent 750 /CapHeight 683 /Descent -194 -/FontName /UAXOPP+CMSY10 +/FontName /VOLHMF+CMSY10 /ItalicAngle -14.035 /StemV 85 /XHeight 431 @@ -1579,21 +1583,23 @@ /Filter /FlateDecode >> stream -x???y0?????g?+????}???????Fo!?_???ff???B???o?p????Z?=p????=JA??????gZ?/9 -+ =??El,?.????C ???X-??/,_M??f??1J????v??->?????l???Sc-????z?w?U???n?U ? Iw]P???? ??I;B???H?W??|I?\? ?ZH.??\2j7????_??eAhq??o???z?o]?????O?xSG~1????3???:*p?x1????NI?,x?:W6?l?B?gV??kt??C8?N??????g?LX? ?C?*???} ??U]???f?i?1[??????;??wy?2?ni_uVd5??#mT????r??? D??u?????[? -???? -??vEM?G ????(???$b U at s?oJ???'????Q???T??????????j?1Ln??.O6? -??=y5Bz_??e??+P???:|?I?Y?]%!?;?.?~?Bu?,??.d?^ -??8???J3+???]`  ??9?????e?47?P?M??v??g^2??Ry???z??y???f?[sO?$>???????????.o?????j????$???????Tm??ZAkpD?:cKx?6????4??? ?N???Tyx+?Z???+?f?mB?c?as????U ?8???}:?(??k?"+L?\??P?x?R???et?x????4????Y?Z?7y?=]?kTsb?c?f&??3?d??td??,?? a1?r?????:w???W????}??$[?q^??U?(S0?????lC???w????? E?|?PU?5???????? ???V}ss??cyW?e??x?ek????@?t??C??_i?????.???.??????t?N?V?w????1/ ??t=?:??Q?|?3D2?juf,#_?J6???;(Z%?u?????\???U???CUW???:???eo???g??????2?|?nrC?^?+?h@>-??r;????74e??[G??r?-^??=???#V?\?[???T??I?WxE?$??gLt?P.W??&???H????T?#?c???=???H?P??in???????f???]/?@=l?M??oW??B?????{K|[??f^Y??'????N???????a:b??4qMR??????Vr??fO`??Bh\???$????CA????????TK)?|?\??U?GC?$?? ?b??'^??k??????A?8cb{D?u?J~>?q?H:?X?th>x?~u??[???;?s??Vb?X?????[?g?,?U?(4~)?N7a?'??49ZsP?>?&G?c??????F~!?T?X?{?2~???<K???? ????|???X?E?????`?????5s'???????L?d -?-????GQ}?O?\ -?O?&o??s??;\U??? ????G?9??0{ 4???l??z?FC????A?M?@???Y.H??u?????????6?^wK???k??\;?m???rR?^O ?j?V?A?8t???( ???o 8i??????E?S??????>?N?Hv???q? -??*Y?6C?? ??N???3FKY?y???~[ICr/~->??]W_??3? --'?-T?k??x?Q?8?Q'?F3n?}???mL??nX>~?@S??? *D???@?w?0Dt2n-J??6?%!?o?v??[w??????L??O????????[<8In?L????w\??R???}????????Z???x)z?2 ??Z???d?\?1?R~Qr?cQ?<{??yofbx?nI???xN?z??;6??R???|Hn????4??~|?5?O?? ) ???A@?%KV????p?M~F?z??? 2^U??;?Q?B?%?{>KP??p???????b?????N?w>?k???kb?????r?/??M,f?????21x?0aEl??5,???U?0??qi,?=*??????*w?@?S??i??}????pbs\???????6-W?>???P[SX??c????;2^?V?,?p??-h???2@??x0??? ?O?,????.?:??n??7?8Pq???`?n??j>?qDUt?????????\]?&?>????????O???:?J5?DW??n??Z??6??B??ef?`??U??*v%?bi;??T,8??Z];UG???$??N?T?P?R???a2?x?2T|?|?j?m???]?*-OuA#?jr?!?JF?lT???.?'E?8????????d??H?Qf??S?Zs*x???kW?????'???c??kwINV???H=?????57?/?5c??x+>?K1;?F?:???z?^??e/G?C?LF?????3u?j^`?x??93?s{?g??E???????h????la????Y.??G?]??????E?p?gY???????1-[??6I????/???>????(F???????M7 M?;?a??,qk????h??????/???LvX?#??)??;P?0G?????]e6??4L%z??r?{? ?/????Z&???????)C?A.?y????y??@?G]?i??E3r?+jL?l???????Z?q?? [???j(?y?{?$?5??j?k?&??k?E`?????c?M??D???W??u ?9???-?^???b^P= A???&??H?u1d -? Cv?? b??endstream +x???WXS???)?E)K??iH??J??7?!Y?P??"E?"HEP?^E? ?$?? H????>??^???O?;k????????1???>jl=?#???$"??!????. a?&DZM1?xC????? ???O ???T?Hh??/???H????)?\A2?!??#?J????f$,????s..????)???@ ?D8???"???.O?? +? ??@?:x???3q?;??????????h?????1?@???????OF???"? >? ?^e$]H?????K???J ???_?? ?#???1F$Q?Kze??G??,?w???-? ??w????&o?V ? Iu^T??????I?B???H?S???xE?\????K,?5_6l3????_??eAhr?~????x~hY?y?????x[K~9???=???:&wp?x)????^Q?4x?*G&?t?\?gZ??cx??C8?n??g2/??? X?1?#? +???]5?6?5??e?M??S?6?7m???w???? fp???????rz?G???qu????5m7.|??[? ???????twEM??TN?0Q??{Y?*????l-?K?E7?K?:???,W??/?5?e?'TS??\!????n?0??}?"j????d=???/??q??$??J?;??CZvB\9????? JI=0U????9~ %J??fZ???;?.?Uu??p(5???IN8~?2?*|]?????D<"*?????)??,????i???d???'??ndB?+?s-??9"g??%????F?g?J ??}p??J#??n*???B?]???S?????n'?h??2?,\?/????z?????Q? ???Z+?K??N?Z`????????^6 ???b"*]E'(O????K??&?iN??T?? ?_????c??g?=??6Q=+?m&??j??p??7?L????@??:?c?{fe????uH?C?l???t?*{o????7?<?D?}?K11?% +f??m???m????????:Sz???O??????W=1Q\2?d????gfF?w?&?*?J?Po?h?p?P??*:y?????????'??????B|Ws????h??z????~U??*??T??6?????!?T????y??2??????h?(??&>J?? ????T???U^cT?|t?p????????IRV?n?@???? ?:?X?~A??$?K?? }?2_????"?oq ?c???pUF?s??PXER)o?v???U????????~?Q?B9\?g??B#????S4?D???????E???*?Uc?f%??u?{&???P?|e ?b????O??f???????S???0 +u7?|(??[5!?8:y?/?o?h???,???? ?G?.6#?I?????/ +??Z??~?4FZ?K/??CG U?"?:i?\g??????>R?????&{??r*?s??H?I???????hIv??k6?8??vz???m j?????2 ???y?Ie?}??5V??????{?$??S???jU?n??* ????A??B????l?????T_??F?p$???C;)?$Q?.?f?6?i???G??8?7??@m??sx?\??F?????(?e???????????/T7????L?;?]??;Q(??P???? ??e|??a????}+X??K? a??x???(???)??O?X_???|Q???U?:?M?P%-O??????C? +??E??I/]?~?Mkx?P?{L?7????ET?,?QN?V?9{?A?"?? M??w??d4xY7_??l;]?M]hIf- +????lO?[^???s?'?????>??V?????f????=??????&:o???????k????ETF?2???9?;?????m????p???>?)| ?? ????D???J????P? ?fW?@?????t-l?? +cTn??8I,?R;???9?K?s?r?X?????dQ???*m?|?_????_:?W???k? ^?? [??R???&hWI*1`_NO????&????N?5?X????*????$??0???|?NsV??p?3l?:_Q?Z+????? ??$?????? {??{[??y????????B<?"?c??B??_???ky????\??q?;v??#rL?2???uyLf????~Ib>^???? Zqb? [X????gD??.=???{P???(?N????!'?i????`???wrO???*????w???TC???A????z/ ?pV8U|&?ykC??:?????????9S???????u1o?Cny??"??!++?<?/A???i +T??1~X???> endobj 152 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 -/FontName /JXKHBD+CMTI10 +/FontName /HIPODC+CMTI10 /ItalicAngle -14.04 /StemV 68 /XHeight 431 @@ -1636,7 +1642,7 @@ x???UX???p?w'H?????????[pww ,??[pw???!k??????s??s? ????U????)H??D??L-$??XYxb ??,?FffQx -1??????????/???? ? ?rX?y?YA?1'go?????Z???$.????????`?fm???????dfc?????????+@????aa???0?1s?ZX?8?3??$?h????????? yX]AR?i?@??N???s Kx&E'P5 ???Z?{rIw{{E????N?_?&6?????????f(8?[?w????)X???;??Q7{3G+{ ??l\%m?,??m???n at w??-???h??e???)?*?M??M????????????g?'?_???A????1???????? ?W1 G3'sG++'?4??q|Y6??^ /?0????hO??N@?:??` ??8???;??????????O?????`?O?????L?@3 G??1n??(?j?????3?2M????r?Y?;?_??aV???????? ????L?D at R??????9?%d??We?????????????'?`rr??7s?d??,?;???/i8?? ??????4?????/i?????q? AV!????????B???_??? ??I??:V????_~????????%.*?????``]\l,?????if?@?????$?E??lizkXXxY???-;??}??h ? ?(?????jMTl??????n_>!?B????R???| }L????5??OeZ?{?Kb??????q?O?G??l?#g??? ?????Kp?????T???????"ejq??M?~=????O?\????a??l$???.???[????P[????mt?N]??/%??)?F`?fbBXE?W[gm"?????????b ?`M??L?9u?Yu1??k????s{j ??`?o?p???x'???0s??|6????3?Q???Xm?N?X?%;?'??_cnU??*x????7????`?t0?B?w?X?T?:O??&s ? a?7?????f?H{?jL??|???%$???4???@??1xL?u??????????-;?v????)?\?????sD??RH?8V???KX5????^j?T??z!_q?]?s?b?AjH?????????%????~Z?d(L?6??????By???t[Z???(j?7???7^m?)Ot???s)?I????????j?9?3 ???????<~^??,I?yp8?W???].??Q????F?edL???l?}/?? ?l ?????bF??WLoNI?D?H?  ???9???r ?&Q?"????????v?/ ??i??#?+D????=C?v?u4cU???&??3????Wt?z(???I?6??T?????z_??b4???g?/r?Q????N?NK?_n???\?y???A??????=?????FZ0??a?*? ?nE:???E:?gm8=qw?}?????l?????pl???`?????\?? m_?wU??????????t?????????*?? @@ -1683,7 +1689,7 @@ ?l?????;&???????&~?{?^`?Cr9u\?????5?{??0s+{D(??2?3???N$?J?"?? {???l?&}?r???S??*TA?6?????\????Hb??m??1B??9???3?X?by????,45?S?l3?* ?&?.ba??@f??:???|0?`???_5C?'???l?????Q/?2+?}D??;???^?u3#t?X?F?w?VuO????e?$????O"h{?B?u}?D7?Q??D????0?U???>F?+?????7????,)uS??????{???fb???? ????+X??I5??l/A?s? ????[Sw????z???5?^?9???????:;2?XUi=?? lgLug?[embZF ?g??M??{?tv?>2?`& h???J??Uz??? ?V?^????>???y.X!#[H??0???L?y?F?????x???(???:J! ?0\??t??b??=aK???}?K/?????n^m???:"?????"?^?a????4?!l??B?*??FF??? ???????'Z??????WQ??????(n?Q?S??z??67($???+%????c]?_;?d?????'?????W?{z??,w??T?????F????x??+??z????bP?e??1?5??????????Lv~?[?????????????d$?)??Kg??V@??????`???L??(:t'm?m.?N9HY??#C?Ia??M??P?!?=Y7????P?#??tC_/6?? E.?q????}?&???L?H1r?>X?i??G7??{\&?W????V?/?c????s? ?_yx.nl????,?U7?FlI?????Z@=???$?_????G????9L ^??DB| y G`w??'?s?c??~?3?????.??+WhO????8???|?? ?????-?M??5U ??? <9X'^??????PK??J?mm~?D 8?{?j??Q?y?]5!??Mi?2^??4??3???nya???+???????+??B_{?YT&?-? kR?B_D ?{e???X??????T???RK2q??????ZEyIMT?w0??]?^&??e?1??????e|??h?B??G?f??"-K??????"?^?o$??g?R?P-?P{????c?N????A??P???!pM8??jg?)?p? ?O????????N? ?@2???,??sh?>8j?*ia{xGI?Q?k???????q??]B E+<????C?T?????>U??+#? ?T????4?g?5j0?y$? *D^???o???(???2+?? Mrfk|?)?u?>??v?}Y|C?9?i3? ?c?* o?%??I???? ?r`?I??l>a????P??{? ?y3??G??LTX?|??1??_E???????:?$fn?_10?@}4}???`Op ?.???????? ??????j?[D?-???[)p???N?Q???jkzP??2?????A?P??I???j8?? e?Y???-??????bv??j?$y$?^?x1a?_??????HD? ?}]Zb`?.??O UH????? 0},?????????Y? ?h?4??E ???i??u3?k-?d?????A *???????OL`foatsr0?????? endstream + [p3??>x1a?_??????HD? ?}]Zb`?.??O UH????? 0},?????????Y? ?h?4??E ???i??u3?k-?d?????A *???????OL`foatsr0????K?endstream endobj 126 0 obj << /Type /Font @@ -1692,14 +1698,14 @@ /FirstChar 33 /LastChar 125 /Widths 323 0 R -/BaseFont /RVBRHX+CMTT10 +/BaseFont /YTBDRO+CMTT10 /FontDescriptor 124 0 R >> endobj 124 0 obj << /Ascent 611 /CapHeight 611 /Descent -222 -/FontName /RVBRHX+CMTT10 +/FontName /YTBDRO+CMTT10 /ItalicAngle 0 /StemV 69 /XHeight 431 @@ -1724,7 +1730,7 @@ >> stream x???e\????A???????A???s?.?????A$?AE?????g??|?u???~k??&:?W?N?P9'G7nNna????7??? ??I??89?????n!!n????? ??/? ?a2????a6V?ni????P? ?P?YC??=?????? ???h?5?? u??_?? ?????????P????*????mr????'B???~7???I?&???$J?&!P???~???x@??WQ?M??? ??? ?5?\S?7?5_?&?????????N ?7?????qs? -?@n??-??@???7????v ?????:?Fn????u?????}a ???????????cx?????~???@x ??????????//????.?+?????!?0????~????6???zA!??N???? ?e????Q???U?v??a?N?A?/Pra[?????$??@?????r?n???!w???1???a????L?w?????L????0v????6?0X??_??s?u7_?EFkm??????+?5???\??vDX3/?&~?KY$(b??% y~(4?6??}????????]??)???K??4o?U???????A??????T???W????fs???f?=;}?f????y?z,???Z ?T.?R?&?s[?6Bmb s?P?|A???????????J???"}D???Gq??w2????wqkX?X_?*?M'L???W???qM?????{_i??O??8?????ijo0uZ*??_??(?EF?Ht? C? ???c?l2?*?2??R? +?8Y at a???? ?W8)'???Qt??@$?????l\?l???6nk?%???w?h?????w?????????????`G7-o?d?????3|u`6^C.N..nx#???_??a&?q??q??|?0 ????p??rl-?^?<1???? >_?? ?????????P????*????mr????'B???~7???I?&???$J?&!P???~???x@??WQ?M??? ??? ?5?\S?7?5_?&?????????N ?7?????qs? -?@n??-??@???7????v ?????:?Fn????u?????}a ???????????cx?????~???@x ??????????//????.?+?????!?0????~????6???zA!??N???? ?e????Q???U?v??a?N?A?/Pra[?????$??@?????r?n???!w???1???a????L?w?????L????0v????6?0X??_??s?u7_?EFkm??????+?5???\??vDX3/?&~?KY$(b??% y~(4?6??}????????]??)???K??4o?U???????A??????T???W????fs???f?=;}?f????y?z,???Z ?T.?R?&?s[?6Bmb s?P?|A???????????J???"}D???Gq??w2????wqkX?X_?*?M'L???W???qM?????{_i??O??8?????ijo0uZ*??_??(?EF?Ht? C? ???c?l2?*?2??R? c2@????????R1^???z??F????wo??VJ???N?HV?>???v???{?|4?T??V????a??%??5???g??J?P??? ;?=F?~x???8?g????5YP {???k9?O????*?????@???????gy41c?kBF?8??vX?4(/`???_?ltRYuc/?? 3???nL0 ? ,`??=??W?[?m?????%?+??)???KW?r??s?2 ?i~C7-?Pgo?/??s?KZ???a?]?i??O}\??8??V?]?????? ????l??8????5????0???o?:?$??wB??USa?{?d?????I2p]_K|?,??? ;P??s??5'?7??j??guy?Z?@v??\$?i?2^???#?????????B???? f?b1V???Ek???Pi?D%Q??7?.z???B?> endobj 117 0 obj << /Ascent 694 /CapHeight 686 /Descent -194 -/FontName /PKDFYH+CMBX12 +/FontName /BILPZK+CMBX12 /ItalicAngle 0 /StemV 109 /XHeight 444 @@ -1794,7 +1800,7 @@ stream x???eT\????[?{???]????qw??????? ??$Xpr???|;9??????f0??5W????UtS?*?1????%?A.??L?|1UV+ ?(%??????$n??????$?&?7?_>N>N6$J????????? ?F???$n??????P0v????05????Z]?j{???'????x?7?????C?r?i?????I!z??z??sqkK??j???Q?????8??s?m??}???? @@ -1837,7 +1843,7 @@ m e2Q????W?p?????-Pa?W??|=_?eK;y?NK):?=????????????F??????N?SA?Q%%? 1??????K]?kd???I?Yd???DH?Z~GB{?n#u:????P??YU????(wf??D?M??n?72G&????\?r &??F*6?+.????t?9<>???????BM????-???_???{i?#??2l??g7?iD?????:;-?K[?????V5?????? ???????4??TR?-?t??? ? ???`B;????Wn\?T?)O9 =!????????wOc??????t? ???K7??????=??E???'?f???l????????jQ4?!N?S??Mx??y_ %?Q??%?>???g????????u3?0A?w???????/\)C?h??@*Y????????U???k?ap?p??]???l} ?\\P?D??????K?~&?C?4=??????Ox:}k? ?????^???R'p???????V[??3~?????pop |??]??5&Ti?2?A???z??C??Y?w?|?T}>h*??`Q??2T??A??hFi&???\V??|Nu?o&a??H? ?S`/?{ }?oh??E???_???vZ??#}e?HSp?|\i??E?K?~ -??SxtA?9???h???2;rR??????? ?:G9/??+?k??~^????'=?|\5?????? ?Qd?????????{?UZ?'???&l?KU;m?\o?????p???`????@%+&???????OL`j 4vr??3v?A?_=??endstream +??SxtA?9???h???2;rR??????? ?:G9/??+?k??~^????'=?|\5?????? ?Qd?????????{?UZ?'???&l?KU;m?\o?????p???`????@%+&???????OL`j 4vr??3v?A?_?2??endstream endobj 95 0 obj << /Type /Font @@ -1846,14 +1852,14 @@ /FirstChar 11 /LastChar 122 /Widths 327 0 R -/BaseFont /WVROWP+CMR10 +/BaseFont /SSCBGJ+CMR10 /FontDescriptor 93 0 R >> endobj 93 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 -/FontName /WVROWP+CMR10 +/FontName /SSCBGJ+CMR10 /ItalicAngle 0 /StemV 69 /XHeight 431 @@ -1879,7 +1885,7 @@ stream x???e\Tk?? ?)??s?F@B?[??r``JR??[R)A???[%i?w?9?}??}|?O???=?]k???[????AK(k ??(??@~~ H]???????'????C?{??<???? !???_BXH?O??9{??m?v?I?YG?? ?P#? ??V`(@feAx?d?P??O?t ??;????`mo?XBl??py?pRv??D? -[?9?{?wEJ???? %?aNP/?5??W?? ?t????????P ??????????^???9:?! p?:?w??TC?_rr0?m??C??d?l??_!{WE{O???=??`??B??C???S???x?dUU?u??u?.j???z^???#?O???????{L????G&"????????`??N?a{?"?I?o~???5??D??8??G???l`p??T??? ?C???KE?????? x?`????#"?^?H? ??????? ?W?oB???U??????8r????ih?"? ?!???o?4?? ?z??????7DJ?? ??????"????7Dj?~Cd?~C???o?????H+??i?? ?Vn?!???7DZy??H ?????7Dj ???WK?{J??`??@AdO??|???D|??L+78r~????6??W??X?.???$?R?BK? +[?9?{?wEJ???? %?aNP/?5??W?? ?t????????P ??????????^???9:?! p?:?w??TC?_rr0?m??C??d?l??_!{WE{O???=??`??B??C???S???x?????t??u?.j???z^???#?O???????{L????G&"????????`??N?a{?"?I?o~???5??D??8??G???l`p??T??? ?C???KE?????? x?`????#"?^?H? ??????? ?W?oB???U??????8r????ih?"? ?!???o?4?? ?z??????7DJ?? ??????"????7Dj?~Cd?~C???o?????H+??i?? ?Vn?!???7DZy??H ?????7Dj ???WK?{J??`??@AdO??|???D|??L+78r~????6??W??X?.???$?R?BK? ?K18Q?l??4???Z????Q????.?????>d<"???????v????=?x??%.m?n??b+?U#??I????3?E?Qs???aT?????$?w=o?z?????????P:L?k:2?ED?3??a!?Xt??\J???V??\`?&???\ZaFE?R??!???e}?jD?????_???r?JjG?y+??7M??nA??????6??]}?_?@?d?7/?gp9?z7D ????zb=?????'?K?? ????1V@^6??R??B??!lS3?????|G????sc?OfU?`p??m???5??~/???'???s??????S????n l(<9????? ?7!Qb##?) ?c6?<?????V+?l ?i?i??N p????*?y??????G*??*/?Z???w?D?H ?%x????k?hA?]??|?????466??Q+ +K??O???3[?N('?=???HZ???L&?o????jSf" ???c$?? ???#?-??FNP?rPT!??R??~??? ??1?8b-HF;g?*????*??*??+dne?ak???nkK?IW?l?u|F=?j?t?????C??????k??V?z????`???????p ? s?O??r~??????teqfG???1???q ?????y C?H??I?????z?q`5Y?j??m ???iO?x?hH? ??6?8nGL??a??????;U??W?z?2?U??Iz;?'??_?'~???r???y??H?qR??_ARl ?6???Y?jX>%=???? + @@ -1908,7 +1914,7 @@ ???l"yiN L9??}?????[r??8????M??\?L???_Z??2??????????B??> endobj 90 0 obj << /Ascent 694 /CapHeight 686 /Descent -194 -/FontName /BAKJYS+CMBX10 +/FontName /TDXMLS+CMBX10 /ItalicAngle 0 /StemV 114 /XHeight 444 @@ -1948,7 +1954,7 @@ /Filter /FlateDecode >> stream -x???e\T{??I?A?8(?0? !?)?? ?#0?P????? %?C????H?t?????;z?^??/w_?g?ys?O???????F???_?n??fn??p8 46??I=L?x??U???%???????,k?\G8??!?C??g???8/??r?x???)???Zo?n?????C??n??I????&ix.9?8 \????????????d??l\???R??B2???????????b?JI!?????????P??)w?????@??!?U?;?ZW??L????$??3@??7??S?X?J?/2{????? <??B?\?Q?@v????}_?#??b??dR????? f????\Z?R0??j???????!W;?:I???~??]??P???7??=2?S??jU???????X?^Rn????$VuEVG?)??zc???? )?"o???{h????"??a??*??^I????!???*???????9Hez r??????!?.J?f at O??M?:????????????c???r&??U?????M???U?#?? .#????_???XR??*?BY??F?|3}?#DF?????5C?7?????????2P?[??????? M?????>S??|#$?VK?-?L[sW????????a(f????>l?????.?@????????>?ZO]??0???J8????#?SQ????\????0J??f???m??!O?u ?P???Uhv???a?F??????uP?????,u????yLU?F?t??????0/.`~??#?z ??VV ?{?'?H?`$?e >?|L?w?P|$?? _l???a?&+f?dGH?U?%?????????????????aj?c?]????F????b?W???Y'5#???rK??+??4??[;??S?fJ???G`? K??AM?A??????w`?~??LK?_?*m?v??'\?b'?_??q33@???r??S?g?7??k?sw|?x]???? ?V?S??????`?}????;EX??M??e?4H??y???_??8/?????Eg-??R?/?i2?h????)?? ~???`??????2???????.?y??3?y???v??^Sy?N????????????a)?)?v?"a???????k?????qHR????6)]???}?=?j?>]??S?{?W?"S????E?<: M?{U?G2D {?[????!%????Y?@??kj#???.??1?9??? V-Qq??$?4?*K?$????{?ui<;????????P?k??g?" ??9?R???????????????XUH?G?)b@@9T?^)?"???????? ?;?4 ?M??Q?.?1???g1??O??6??^??????d%(??w??????U?61???0?mO??J?}KK???y?,C?"?????p?2?xl`? H* ??t????^/?tocp$|??????3v) %??1?????C?-?d???????l??????9??^y5]?q4??a????FG? [????8???Duc????g?i_?l?Y??g??R????AajJTk5[??#??&?N,`@?8???% ??w???]R?E??/}??????,?>?{?8Rf?W?\i?E???[??<=l???v??w??????.??????$???O?6?nQ?d6?????? ??68?LJ'?J-??q#.G??????-g}3?????????????'?*??R??16>????i?Hg??>??$???s?O'???????z? ??????]?P???I????4??m??? ?n???o???????1??? ??eI?dF? ???S? ??9P,t??m??Ei?u??gi??!5{Az_???=?U?9???????????5~?d?)??_?????E$?x? ?????n?????????k??}????h??8?*??2T?3??CF??|t?)???????+{???aL ?AK??G? ?=k[:?Z??&?????[IL H~??6??f?C?p???~}(?;????FF??? T?B?nL?Nn?=??Z1?^E??1??]_5?`/??98??J?? ??Y&?d?l?L-?]?Z???HF? ??????????E?????&v?m??=???V?????goe??_???$??????$r??"g???F?u?????????R@?k???2`-??s? ??b;PG? ?f??????dd>??1s????a?????????????w????I??N'nq(W?^???+??i\?,????oxM[YLG?i?X0~G>??DHq???e~!R??EQ??=?6m??$c?D???}??},9?t??\Oa???V?W???_-??v??&???Lgt??t#f"????????O??P4?E????5?endstream +?l<K)X???????M&?nL?Nn?=??Z1?^E??1??]_5?`/??98??J?? ??Y&?d?l?L-?]?Z???HF? ??????????E?????&v?m??=???V?????goe??_???$??????$r??"g???F?u?????????R@?k???2`-??s? ??b;PG? ?f??????dd>??1s????a?????????????w????I??N'nq(W?^???+??i\?,????oxM[YLG?i?X0~G>??DHq???e~!R??EQ??=?6m??$c?D???}??},9?t??\Oa???V?W???_-??v??&???Lgt??t#f"????????O??P4?E?????5?endstream endobj 89 0 obj << /Type /Font @@ -1969,14 +1975,14 @@ /FirstChar 46 /LastChar 121 /Widths 331 0 R -/BaseFont /QYUZPR+CMR17 +/BaseFont /OOTXZX+CMR17 /FontDescriptor 87 0 R >> endobj 87 0 obj << /Ascent 694 /CapHeight 683 /Descent -195 -/FontName /QYUZPR+CMR17 +/FontName /OOTXZX+CMR17 /ItalicAngle 0 /StemV 53 /XHeight 430 @@ -2169,7 +2175,7 @@ >> endobj 338 0 obj << /Author(Bill Spotz)/Title(numpy.i: a SWIG Interface File for NumPy)/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfeTeX-1.21a)/Keywords() -/CreationDate (D:20070413144342-06'00') +/CreationDate (D:20070803151919-06'00') /PTEX.Fullbanner (This is pdfeTeX, Version 3.141592-1.21a-2.2 (Web2C 7.5.4) kpathsea version 3.5.4) >> endobj xref @@ -2181,79 +2187,79 @@ 0000000000 00000 f 0000000009 00000 n 0000007627 00000 n -0000138991 00000 n +0000139016 00000 n 0000000055 00000 n 0000000081 00000 n 0000007810 00000 n -0000138905 00000 n +0000138930 00000 n 0000000131 00000 n 0000000162 00000 n 0000024622 00000 n -0000138817 00000 n +0000138842 00000 n 0000000214 00000 n 0000000246 00000 n 0000024809 00000 n -0000138692 00000 n +0000138717 00000 n 0000000303 00000 n 0000000340 00000 n 0000028586 00000 n -0000138618 00000 n +0000138643 00000 n 0000000391 00000 n 0000000422 00000 n 0000028773 00000 n -0000138531 00000 n +0000138556 00000 n 0000000476 00000 n 0000000510 00000 n 0000028961 00000 n -0000138444 00000 n +0000138469 00000 n 0000000562 00000 n 0000000594 00000 n -0000034799 00000 n -0000138357 00000 n +0000034580 00000 n +0000138382 00000 n 0000000646 00000 n 0000000678 00000 n -0000034987 00000 n -0000138270 00000 n +0000034768 00000 n +0000138295 00000 n 0000000740 00000 n 0000000783 00000 n -0000035175 00000 n -0000138196 00000 n +0000034956 00000 n +0000138221 00000 n 0000000848 00000 n 0000000894 00000 n -0000041244 00000 n -0000138071 00000 n +0000041025 00000 n +0000138096 00000 n 0000000949 00000 n 0000000984 00000 n -0000041432 00000 n -0000137997 00000 n +0000041213 00000 n +0000138022 00000 n 0000001029 00000 n 0000001054 00000 n -0000041620 00000 n -0000137923 00000 n +0000041401 00000 n +0000137948 00000 n 0000001101 00000 n 0000001128 00000 n -0000057076 00000 n -0000137798 00000 n +0000056857 00000 n +0000137823 00000 n 0000001195 00000 n 0000001242 00000 n -0000057264 00000 n -0000137724 00000 n +0000057045 00000 n +0000137749 00000 n 0000001297 00000 n 0000001332 00000 n -0000057452 00000 n -0000137637 00000 n +0000057233 00000 n +0000137662 00000 n 0000001387 00000 n 0000001422 00000 n -0000063466 00000 n -0000137563 00000 n +0000063247 00000 n +0000137588 00000 n 0000001473 00000 n 0000001504 00000 n -0000063653 00000 n -0000137475 00000 n +0000063434 00000 n +0000137500 00000 n 0000001550 00000 n 0000001576 00000 n -0000067690 00000 n -0000137400 00000 n +0000067472 00000 n +0000137425 00000 n 0000001631 00000 n 0000001666 00000 n 0000003729 00000 n @@ -2261,15 +2267,15 @@ 0000001716 00000 n 0000007444 00000 n 0000007505 00000 n -0000136200 00000 n -0000130894 00000 n -0000136041 00000 n -0000130083 00000 n -0000122421 00000 n -0000129923 00000 n -0000121169 00000 n -0000106419 00000 n -0000121010 00000 n +0000136225 00000 n +0000130919 00000 n +0000136066 00000 n +0000130108 00000 n +0000122446 00000 n +0000129948 00000 n +0000121194 00000 n +0000106444 00000 n +0000121035 00000 n 0000007566 00000 n 0000007687 00000 n 0000004026 00000 n @@ -2291,34 +2297,34 @@ 0000006618 00000 n 0000006771 00000 n 0000007748 00000 n -0000105552 00000 n -0000097602 00000 n -0000105390 00000 n +0000105577 00000 n +0000097627 00000 n +0000105415 00000 n 0000007871 00000 n 0000006933 00000 n 0000007103 00000 n 0000007273 00000 n -0000096113 00000 n -0000081781 00000 n -0000095951 00000 n -0000137023 00000 n +0000096138 00000 n +0000081806 00000 n +0000095976 00000 n +0000137048 00000 n 0000024560 00000 n 0000024746 00000 n 0000028524 00000 n 0000028710 00000 n 0000028898 00000 n -0000034736 00000 n -0000034924 00000 n -0000035112 00000 n -0000041181 00000 n -0000041369 00000 n -0000041557 00000 n -0000057013 00000 n -0000057201 00000 n -0000057389 00000 n -0000063403 00000 n -0000063591 00000 n -0000067627 00000 n +0000034517 00000 n +0000034705 00000 n +0000034893 00000 n +0000040962 00000 n +0000041150 00000 n +0000041338 00000 n +0000056794 00000 n +0000056982 00000 n +0000057170 00000 n +0000063184 00000 n +0000063372 00000 n +0000067409 00000 n 0000014683 00000 n 0000012144 00000 n 0000008052 00000 n @@ -2326,9 +2332,9 @@ 0000012382 00000 n 0000012553 00000 n 0000012723 00000 n -0000081297 00000 n -0000077270 00000 n -0000081135 00000 n +0000081322 00000 n +0000077295 00000 n +0000081160 00000 n 0000012896 00000 n 0000013070 00000 n 0000013243 00000 n @@ -2365,9 +2371,9 @@ 0000024153 00000 n 0000024871 00000 n 0000024324 00000 n -0000076950 00000 n -0000075560 00000 n -0000076789 00000 n +0000076975 00000 n +0000075585 00000 n +0000076814 00000 n 0000029023 00000 n 0000027605 00000 n 0000025043 00000 n @@ -2378,148 +2384,148 @@ 0000028835 00000 n 0000028115 00000 n 0000028287 00000 n -0000035237 00000 n -0000032885 00000 n +0000035018 00000 n +0000032666 00000 n 0000029132 00000 n -0000034610 00000 n -0000034673 00000 n -0000033091 00000 n -0000033264 00000 n -0000033437 00000 n -0000033610 00000 n -0000033782 00000 n -0000033953 00000 n -0000034861 00000 n -0000035049 00000 n -0000034125 00000 n -0000034290 00000 n -0000034449 00000 n -0000041682 00000 n -0000039113 00000 n -0000035346 00000 n -0000041055 00000 n -0000041118 00000 n -0000039327 00000 n -0000039500 00000 n -0000039674 00000 n -0000039847 00000 n -0000040019 00000 n -0000040191 00000 n -0000040364 00000 n -0000040535 00000 n -0000040708 00000 n -0000040881 00000 n -0000041306 00000 n -0000041494 00000 n -0000137139 00000 n -0000047578 00000 n -0000044782 00000 n -0000041790 00000 n -0000047452 00000 n -0000047515 00000 n -0000045028 00000 n -0000045201 00000 n -0000045375 00000 n -0000045548 00000 n -0000045721 00000 n -0000045894 00000 n -0000046068 00000 n -0000046240 00000 n -0000046414 00000 n -0000046587 00000 n -0000046760 00000 n -0000046933 00000 n -0000047106 00000 n -0000047279 00000 n -0000052403 00000 n -0000050575 00000 n -0000047699 00000 n -0000052340 00000 n -0000050781 00000 n -0000050954 00000 n -0000051128 00000 n -0000051302 00000 n -0000051475 00000 n -0000051647 00000 n -0000051820 00000 n -0000051994 00000 n -0000052166 00000 n -0000057514 00000 n -0000055552 00000 n -0000052511 00000 n -0000056950 00000 n -0000055742 00000 n -0000055914 00000 n -0000056087 00000 n -0000057138 00000 n -0000056259 00000 n -0000057326 00000 n -0000056433 00000 n -0000056606 00000 n -0000056777 00000 n -0000063777 00000 n -0000061482 00000 n -0000057635 00000 n -0000063277 00000 n -0000063340 00000 n -0000061688 00000 n -0000061857 00000 n -0000062030 00000 n -0000062201 00000 n -0000062375 00000 n -0000062560 00000 n -0000062744 00000 n -0000063528 00000 n -0000062933 00000 n -0000063714 00000 n -0000063104 00000 n -0000067815 00000 n -0000065784 00000 n -0000063898 00000 n -0000067564 00000 n -0000065990 00000 n -0000066161 00000 n -0000067752 00000 n -0000066334 00000 n -0000066505 00000 n -0000066679 00000 n -0000066850 00000 n -0000067023 00000 n -0000074693 00000 n -0000067937 00000 n -0000074533 00000 n -0000067190 00000 n -0000067373 00000 n -0000075221 00000 n -0000074983 00000 n -0000077183 00000 n -0000077159 00000 n -0000081601 00000 n -0000081519 00000 n -0000097003 00000 n -0000096641 00000 n -0000106098 00000 n -0000105843 00000 n -0000121981 00000 n -0000121596 00000 n -0000130621 00000 n -0000130369 00000 n -0000136665 00000 n -0000136447 00000 n -0000137256 00000 n -0000137326 00000 n -0000139063 00000 n -0000140759 00000 n -0000140798 00000 n -0000140836 00000 n -0000140965 00000 n +0000034391 00000 n +0000034454 00000 n +0000032872 00000 n +0000033045 00000 n +0000033218 00000 n +0000033391 00000 n +0000033563 00000 n +0000033734 00000 n +0000034642 00000 n +0000034830 00000 n +0000033906 00000 n +0000034071 00000 n +0000034230 00000 n +0000041463 00000 n +0000038894 00000 n +0000035127 00000 n +0000040836 00000 n +0000040899 00000 n +0000039108 00000 n +0000039281 00000 n +0000039455 00000 n +0000039628 00000 n +0000039800 00000 n +0000039972 00000 n +0000040145 00000 n +0000040316 00000 n +0000040489 00000 n +0000040662 00000 n +0000041087 00000 n +0000041275 00000 n +0000137164 00000 n +0000047359 00000 n +0000044563 00000 n +0000041571 00000 n +0000047233 00000 n +0000047296 00000 n +0000044809 00000 n +0000044982 00000 n +0000045156 00000 n +0000045329 00000 n +0000045502 00000 n +0000045675 00000 n +0000045849 00000 n +0000046021 00000 n +0000046195 00000 n +0000046368 00000 n +0000046541 00000 n +0000046714 00000 n +0000046887 00000 n +0000047060 00000 n +0000052184 00000 n +0000050356 00000 n +0000047480 00000 n +0000052121 00000 n +0000050562 00000 n +0000050735 00000 n +0000050909 00000 n +0000051083 00000 n +0000051256 00000 n +0000051428 00000 n +0000051601 00000 n +0000051775 00000 n +0000051947 00000 n +0000057295 00000 n +0000055333 00000 n +0000052292 00000 n +0000056731 00000 n +0000055523 00000 n +0000055695 00000 n +0000055868 00000 n +0000056919 00000 n +0000056040 00000 n +0000057107 00000 n +0000056214 00000 n +0000056387 00000 n +0000056558 00000 n +0000063558 00000 n +0000061263 00000 n +0000057416 00000 n +0000063058 00000 n +0000063121 00000 n +0000061469 00000 n +0000061638 00000 n +0000061811 00000 n +0000061982 00000 n +0000062156 00000 n +0000062341 00000 n +0000062525 00000 n +0000063309 00000 n +0000062714 00000 n +0000063495 00000 n +0000062885 00000 n +0000067597 00000 n +0000065566 00000 n +0000063679 00000 n +0000067346 00000 n +0000065772 00000 n +0000065943 00000 n +0000067534 00000 n +0000066116 00000 n +0000066287 00000 n +0000066461 00000 n +0000066632 00000 n +0000066805 00000 n +0000074718 00000 n +0000067719 00000 n +0000074558 00000 n +0000066972 00000 n +0000067155 00000 n +0000075254 00000 n +0000075014 00000 n +0000077208 00000 n +0000077184 00000 n +0000081626 00000 n +0000081544 00000 n +0000097028 00000 n +0000096666 00000 n +0000106123 00000 n +0000105868 00000 n +0000122006 00000 n +0000121621 00000 n +0000130646 00000 n +0000130394 00000 n +0000136690 00000 n +0000136472 00000 n +0000137281 00000 n +0000137351 00000 n +0000139088 00000 n +0000140784 00000 n +0000140823 00000 n +0000140861 00000 n +0000140990 00000 n trailer << /Size 339 /Root 337 0 R /Info 338 0 R -/ID [<6D5220E93E8808964213440D85A6832B> <6D5220E93E8808964213440D85A6832B>] +/ID [<50CBF96FECAFDF81A9BEF9F0C1E9A94F> <50CBF96FECAFDF81A9BEF9F0C1E9A94F>] >> startxref -141278 +141303 %%EOF Modified: trunk/numpy/doc/swig/numpy_swig.txt =================================================================== --- trunk/numpy/doc/swig/numpy_swig.txt 2007-08-03 19:44:53 UTC (rev 3940) +++ trunk/numpy/doc/swig/numpy_swig.txt 2007-08-03 21:21:10 UTC (rev 3941) @@ -318,13 +318,9 @@ ------------- The ``numpy.i`` interface file does not support typemaps for output -arrays, for several reasons. First, C/C++ function return arguments -do not have names, so signatures for ``%typemap(out)`` do not include -names. This means that if ``numpy.i`` supported them, they would -apply to all pointer return arguments for the supported numeric -types. This seems too dangerous. Second, C/C++ return arguments are +arrays, for several reasons. First, C/C++ return arguments are limited to a single value. This prevents obtaining dimension -information in a general way. Third, arrays with hard-coded lengths +information in a general way. Second, arrays with hard-coded lengths are not permitted as return arguments. In other words:: double[3] newVector(double x, double y, double z); From numpy-svn at scipy.org Fri Aug 3 18:19:14 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Fri, 3 Aug 2007 17:19:14 -0500 (CDT) Subject: [Numpy-svn] r3942 - trunk/numpy/distutils/fcompiler Message-ID: <20070803221914.0344F39C076@new.scipy.org> Author: rkern Date: 2007-08-03 17:19:13 -0500 (Fri, 03 Aug 2007) New Revision: 3942 Modified: trunk/numpy/distutils/fcompiler/intel.py Log: * Allow an Intel Fortran 10.0 for 64-bit version string that I've seen in the wild. * Use -fPIC instead of -KPIC for said wild compiler. Modified: trunk/numpy/distutils/fcompiler/intel.py =================================================================== --- trunk/numpy/distutils/fcompiler/intel.py 2007-08-03 21:21:10 UTC (rev 3941) +++ trunk/numpy/distutils/fcompiler/intel.py 2007-08-03 22:19:13 UTC (rev 3942) @@ -130,7 +130,7 @@ compiler_aliases = () description = 'Intel Fortran Compiler for EM64T-based apps' - version_match = intel_version_match('EM64T-based') + version_match = intel_version_match('EM64T-based|Intel\\(R\\) 64') possible_executables = ['ifort', 'efort', 'efc'] @@ -144,6 +144,14 @@ 'ranlib' : ["ranlib"] } + def get_flags(self): + v = self.get_version() + if v >= '10.0': + # Use -fPIC instead of -KPIC. + return ['-fPIC', '-cm'] + else: + return IntelFCompiler.get_flags(self) + def get_flags_arch(self): opt = [] if cpu.is_PentiumIV() or cpu.is_Xeon(): From numpy-svn at scipy.org Sat Aug 4 15:59:08 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Sat, 4 Aug 2007 14:59:08 -0500 (CDT) Subject: [Numpy-svn] r3943 - trunk/numpy/f2py/lib/extgen Message-ID: <20070804195908.5D70539C019@new.scipy.org> Author: pearu Date: 2007-08-04 14:58:57 -0500 (Sat, 04 Aug 2007) New Revision: 3943 Added: trunk/numpy/f2py/lib/extgen/pyc_argument.py Modified: trunk/numpy/f2py/lib/extgen/__init__.py trunk/numpy/f2py/lib/extgen/base.py trunk/numpy/f2py/lib/extgen/doc.txt trunk/numpy/f2py/lib/extgen/extension_module.py trunk/numpy/f2py/lib/extgen/pyc_function.py Log: Impl basic argument support and documentation generation. Modified: trunk/numpy/f2py/lib/extgen/__init__.py =================================================================== --- trunk/numpy/f2py/lib/extgen/__init__.py 2007-08-03 22:19:13 UTC (rev 3942) +++ trunk/numpy/f2py/lib/extgen/__init__.py 2007-08-04 19:58:57 UTC (rev 3943) @@ -2,11 +2,13 @@ Python Extensions Generator """ -__all__ = ['ExtensionModule', 'PyCFunction', 'CCode'] +__all__ = ['ExtensionModule', 'PyCFunction', 'PyCArgument', + 'CCode'] import base from extension_module import ExtensionModule from pyc_function import PyCFunction +from pyc_argument import PyCArgument from c_code import CCode import predefined_components Modified: trunk/numpy/f2py/lib/extgen/base.py =================================================================== --- trunk/numpy/f2py/lib/extgen/base.py 2007-08-03 22:19:13 UTC (rev 3942) +++ trunk/numpy/f2py/lib/extgen/base.py 2007-08-04 19:58:57 UTC (rev 3943) @@ -63,6 +63,11 @@ def __repr__(self): return '%s%s' % (self.__class__.__name__, `self._args`) + def __getattr__(self, attr): + if attr.startswith('container_'): + return self.get_container(attr[10:]) + raise AttributeError('%s instance has no attribute %r' % (self.__class__.__name__, attr)) + def get_container(self, key): """ Return named container. @@ -117,6 +122,11 @@ """ # clean up containers self.containers = {} + for n in dir(self): + if n.startswith('container_') and isinstance(getattr(self, n), Container): + delattr(self, n) + + # create containers for k,kwargs in self.container_options.items(): self.containers[k] = Container(**kwargs) @@ -201,7 +211,7 @@ r.append('--- %s ---\n%s' % (k,v)) return '\n'.join(r) - def evaluate(self, template): + def evaluate(self, template, **attrs): """ Evaluate template using instance attributes and code idioms from containers. @@ -213,17 +223,19 @@ v = getattr(self, n) if isinstance(v, str): d[n] = v + d.update(attrs) for label, container in self.containers.items(): - if container.use_indent is None: + if not container.use_indent: continue replace_list = set(re.findall(r'[ ]*%\('+label+r'\)s', template)) for s in replace_list: - old_indent = container.use_indent - container.use_indent = len(s) - len(s.lstrip()) + old_indent = container.indent_offset + container.indent_offset = old_indent + len(s) - len(s.lstrip()) i = template.index(s) template = template[:i] + str(container) + template[i+len(s):] - container.use_indent = old_indent - return re.sub(r'[ \t]*[<]KILLLINE[>]\n','', template % d) + container.indent_offset = old_indent + template = template % d + return re.sub(r'.*[<]KILLLINE[>].*\n','', template) _registered_components_map = {} @@ -253,31 +265,44 @@ pass raise KeyError('no registered component provides %r' % (provides)) + @property + def numpy_version(self): + import numpy + return numpy.__version__ class Container(object): """ Container of a list of named strings. >>> c = Container(separator=', ', prefix='"', suffix='"') - >>> c.add(1, 'hey') - >>> c.add(2, 'hoo') - >>> str(c) - '"hey, hoo"' - >>> c.add(1, 'hey') - >>> c.add(1, 'hey2') + >>> c.add('hey',1) + >>> c.add('hoo',2) + >>> print c + "hey, hoo" + >>> c.add('hey',1) + >>> c.add('hey2',1) Traceback (most recent call last): ... ValueError: Container item 1 exists with different value + + >>> c2 = Container() + >>> c2.add('bar') + >>> c += c2 + >>> print c + "hey, hoo, bar" """ __metaclass__ = BaseMetaClass - def __init__(self, separator='\n', prefix='', suffix='', + def __init__(self, + separator='\n', prefix='', suffix='', skip_prefix_when_empty=False, skip_suffix_when_empty=False, default = '', reverse=False, user_defined_str = None, - use_indent = None, + use_indent = False, + indent_offset = 0, + use_firstline_indent = False, # implies use_indent ): self.list = [] self.label_map = {} @@ -290,7 +315,12 @@ self.default = default self.reverse = reverse self.user_str = user_defined_str - self.use_indent = use_indent + self.use_indent = use_indent or use_firstline_indent + self.indent_offset = indent_offset + self.use_firstline_indent = use_firstline_indent + + def __notzero__(self): + return bool(self.list) def has(self, label): return self.label_map.has_key(label) @@ -298,14 +328,23 @@ def get(self, label): return self.list[self.label_map[label]] - def __iadd__(self, other): - self.add(other) + def __add__(self, other): + if isinstance(other, Container): + lst = [(i,l) for (l,i) in other.label_map.items()] + lst.sort() + for i,l in lst: + self.add(other.list[i], l) + else: + self.add(other) return self + __iadd__ = __add__ def add(self, content, label=None): """ Add content to container using label. If label is None, an unique label will be generated using time.time(). """ + if content is None: + return assert isinstance(content, str),`type(content)` if label is None: label = time.time() @@ -326,6 +365,15 @@ if self.reverse: l = l[:] l.reverse() + if self.use_firstline_indent: + new_l = [] + for l1 in l: + lines = l1.split('\\n') + i = len(lines[0]) - len(lines[0].lstrip()) + indent = i * ' ' + new_l.append(lines[0]) + new_l.extend([indent + l2 for l2 in lines[1:]]) + l = new_l r = self.separator.join(l) r = self.prefix + r r = r + self.suffix @@ -336,10 +384,31 @@ if not self.skip_suffix: r = r + self.suffix if r and self.use_indent: - indent = self.use_indent * ' ' - r = ''.join([indent + line for line in r.splitlines(True)]) + lines = r.splitlines(True) + indent = self.indent_offset * ' ' + r = ''.join([indent + line for line in lines]) return r + def copy(self, mapping=None, **extra_options): + options = dict(separator=self.separator, prefix=self.prefix, suffix=self.suffix, + skip_prefix_when_empty=self.skip_prefix, + skip_suffix_when_empty=self.skip_suffix, + default = self.default, reverse=self.reverse, + user_defined_str = self.user_str, + use_indent = self.use_indent, + indent_offset = self.indent_offset + ) + options.update(extra_options) + cpy = Container(**options) + if mapping is None: + cpy += self + else: + lst = [(i,l) for (l,i) in self.label_map.items()] + lst.sort() + for i,l in lst: + cpy.add(mapping(other.list[i]), l) + return cpy + def _test(): import doctest doctest.testmod() Modified: trunk/numpy/f2py/lib/extgen/doc.txt =================================================================== --- trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-03 22:19:13 UTC (rev 3942) +++ trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-04 19:58:57 UTC (rev 3943) @@ -18,11 +18,12 @@ Hello example follows:: >>> from numpy.f2py.lib.extgen import * + >>> m = ExtensionModule('foo') >>> f = PyCFunction('hello') - >>> f.add('printf("Hello!\\n");') - >>> m = ExtensionModule('foo', f) + >>> f += 'printf("Hello!\\n");' + >>> m += f >>> m.generate() # returns a string containing C source to extension module - >>> foo = m.build + >>> foo = m.build() >>> foo.hello() Hello! >>> @@ -137,6 +138,9 @@ - `skip_suffix_when_empty=False` - `default=''` - `reverse=False` + - `use_indent=False` + - `use_firstline_indent=False` + - `indent_offset=0` - `user_defined_str=None` that can be used to change the behaviour of `Container.__str__()` @@ -154,16 +158,24 @@ item is ignored. -Reference manual -================ +Component classes +================= ExtGen package defines the following extension module component classes: - - `ExtensionModule(, *components, numpy=False, provides=..)` --- + - `ExtensionModule(, *components, numpy=False, + provides=.., title=.., description=..)` --- represents an extension module, - - `PyCFunction(, *components, provides=..)` --- + - `PyCFunction(, *components, provides=.., title=.., description=..)` --- represents an extension function. + - `PyCArgument(, *components, provides=.., input_intent=.., + output_intent=.., input_title=.., input_description=.., + output_title=, output_description=..)` --- represents an argument component for + `PyCFunction`. Keyword arguments `input_intent` and + `output_intent` may have values `'required'`, `'optional'`, + `'extra'`, `'hide'` and `'hide'`, `'return'`, respectively. + - `CCode(*lines, provides=..)` --- represents any C code block or statement. Modified: trunk/numpy/f2py/lib/extgen/extension_module.py =================================================================== --- trunk/numpy/f2py/lib/extgen/extension_module.py 2007-08-03 22:19:13 UTC (rev 3942) +++ trunk/numpy/f2py/lib/extgen/extension_module.py 2007-08-04 19:58:57 UTC (rev 3943) @@ -13,28 +13,62 @@ >>> # instead of the following import statement >>> from __init__ import * #doctest: +ELLIPSIS Ignoring... - >>> f = PyCFunction('hello') - >>> f.add('printf("Hello!\\\\n");') - >>> f.add('printf("Bye!\\\\n");') - >>> m = ExtensionModule('foo', f) - >>> foo = m.build #doctest: +ELLIPSIS + >>> f = PyCFunction('hello', title='Say Hello\\nand Bye.') + >>> f += 'printf("Hello!\\\\n");' + >>> f += 'printf("Bye!\\\\n");' + >>> m = ExtensionModule('foo', f, title='Hello module', description='First line.\\nSecond line.') + >>> foo = m.build() #doctest: +ELLIPSIS exec_command... >>> foo.hello() >>> # you should now see Hello! printed to stdout stream. + We now add a new function to module and rebuild. But we need to change the + module name as one cannot reload extension modules in Python. + + >>> m.modulename = 'foo2' + >>> m += PyCFunction('hi', 'printf("Hi\\\\n");', title='Say just Hi.') + >>> foo = m.build() #doctest: +ELLIPSIS + exec_command... + >>> print foo.__doc__ #doctest: +ELLIPSIS + This module "foo2" is generated with ExtGen from NumPy version ... + + Hello module + + Description: + First line. + Second line. + + Functions: + hello() -> None + Say Hello + and Bye. + hi() -> None + Say just Hi. """ container_options = dict(\ - Header=dict(default=''), - TypeDef=dict(default=''), - Extern=dict(default=''), - CCode=dict(default=''), - CAPICode=dict(default=''), - ObjDecl=dict(default=''), - ModuleMethod=dict(suffix=',', skip_suffix_when_empty=True, - default='', use_indent=True), - ModuleInit=dict(default='', use_indent=True), - ) + Header=dict(default=''), + TypeDef=dict(default=''), + Extern=dict(default=''), + CCode=dict(default=''), + CAPICode=dict(default=''), + ObjDecl=dict(default=''), + ModuleMethod=dict(suffix=',', skip_suffix_when_empty=True,separator=',\n', + default='', use_indent=True), + ModuleInit=dict(default='', use_indent=True), + + ModuleTitle = dict(default='',prefix='"\\n\\n',suffix='"',separator='\\n"\n" ', + skip_prefix_when_empty=True, skip_suffix_when_empty=True, + use_firstline_indent=True), + ModuleDescr = dict(default='',prefix='"\\n\\nDescription:\\n"\n" ', + suffix='"',separator='\\n"\n" ', + skip_prefix_when_empty=True, skip_suffix_when_empty=True, + use_firstline_indent=True), + ModuleFuncDoc = dict(default='', prefix='"\\n\\nFunctions:\\n"\n" ', + separator='\\n"\n" ', suffix='"', + skip_prefix_when_empty=True, skip_suffix_when_empty=True, + use_firstline_indent=True), + ) component_container_map = dict(PyCFunction = 'CAPICode') @@ -63,9 +97,25 @@ {NULL,NULL,0,NULL} }; +static char %(modulename)s_doc[] = +"This module \\"%(modulename)s\\" is generated with ExtGen from NumPy version %(numpy_version)s." +%(ModuleTitle)s +%(ModuleDescr)s +%(ModuleFuncDoc)s +; + PyMODINIT_FUNC init%(modulename)s(void) { + PyObject* extgen_module_dict = NULL; + PyObject* extgen_str_obj = NULL; + extgen_module = Py_InitModule("%(modulename)s", extgen_module_methods); + if ((extgen_module_dict = PyModule_GetDict(extgen_module))==NULL) goto capi_error; + if ((extgen_str_obj = PyString_FromString(%(modulename)s_doc))==NULL) goto capi_error; + PyDict_SetItemString(extgen_module_dict, "__doc__", extgen_str_obj); + Py_DECREF(extgen_str_obj); + %(ModuleInit)s + return; capi_error: if (!PyErr_Occurred()) { @@ -88,10 +138,19 @@ if options.get('numpy'): self.add(Base.get('arrayobject.h'), 'Header') self.add(Base.get('import_array'), 'ModuleInit') + + self.title = options.get('title') + self.description = options.get('description') + map(self.add, components) return - @property + def update_containers(self): + if self.title is not None: + self.container_ModuleTitle += self.title.replace('\n','\\n') + if self.description is not None: + self.container_ModuleDescr += self.description.replace('\n','\\n') + def build(self): import os import sys @@ -121,11 +180,11 @@ setup_cmd = ' '.join([sys.executable,setupfile]+setup_args) build_dir = '.' from numpy.distutils.exec_command import exec_command - sts = exec_command(setup_cmd) + status, output = exec_command(setup_cmd) #p = subprocess.Popen(setup_cmd, cwd=build_dir, shell=True, stdout=subprocess.PIPE,stderr=subprocess.PIPE) #sts = os.waitpid(p.pid, 0) - if sts[0]: - raise "Failed to build (status=%s)." % (`sts`) + if status: + raise "Failed to build (status=%s)." % (`status`) exec 'import %s as m' % (modulename) return m Added: trunk/numpy/f2py/lib/extgen/pyc_argument.py =================================================================== --- trunk/numpy/f2py/lib/extgen/pyc_argument.py 2007-08-03 22:19:13 UTC (rev 3942) +++ trunk/numpy/f2py/lib/extgen/pyc_argument.py 2007-08-04 19:58:57 UTC (rev 3943) @@ -0,0 +1,135 @@ + +from base import Base + +class PyCArgument(Base): + + """ + PyCArgument(, *components, provides=.., + input_intent = 'required' | 'optional' | 'extra' | 'hide', + output_intent = 'hide' | 'return', + input_title = None, + output_title = None, + input_description = None, + output_description = None + ) + + """ + + template = '%(name)s' + + def initialize(self, name, *components, **options): + self.name = name + self._provides = options.get('provides', + '%s_%s' % (self.__class__.__name__, name)) + self.input_intent = options.get('input_intent','required') # 'optional', 'extra', 'hide' + self.output_intent = options.get('output_intent','hide') # 'return' + self.input_title = options.get('input_title', None) + self.output_title = options.get('output_title', None) + self.input_description = options.get('input_description', None) + self.output_description = options.get('output_description', None) + + map(self.add, components) + + def get_ctype(self): + # scan components for c types + return + + def init_containers(self): + ctype = self.get_ctype() + if ctype is None: + self.cname = self.name + else: + self.cname = self.provides + + def update_containers(self): + evaluate = self.evaluate + ctype = self.get_ctype() + + # get containers + ReqArgs = self.container_ReqArgs + OptArgs = self.container_OptArgs + ExtArgs = self.container_ExtArgs + RetArgs = self.container_RetArgs + + ReqArgsDoc = self.container_ReqArgsDoc + OptArgsDoc = self.container_OptArgsDoc + ExtArgsDoc = self.container_ExtArgsDoc + + Decl = self.container_Decl + + ReqKWList = self.container_ReqKWList + OptKWList = self.container_OptKWList + ExtKWList = self.container_ExtKWList + + ReqPyArgFmt = self.container_ReqPyArgFmt + OptPyArgFmt = self.container_OptPyArgFmt + ExtPyArgFmt = self.container_ExtPyArgFmt + + ReqPyArgObj = self.container_ReqPyArgObj + OptPyArgObj = self.container_OptPyArgObj + ExtPyArgObj = self.container_ExtPyArgObj + + RetDoc = self.container_RetDoc + RetFmt = self.container_RetFmt + 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) + else: + raise NotImplementedError('ctype=%r' % (ctype)) + + 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]) + 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]) + 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]) + elif self.input_intent=='hide': + ropt = (self.name, 'O', self.cname, output_doc_title, output_doc_descr) + 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]) + elif self.output_intent=='hide': + pass + else: + raise NotImplementedError('output_intent=%r' % (self.output_intent)) + + return + Modified: trunk/numpy/f2py/lib/extgen/pyc_function.py =================================================================== --- trunk/numpy/f2py/lib/extgen/pyc_function.py 2007-08-03 22:19:13 UTC (rev 3942) +++ trunk/numpy/f2py/lib/extgen/pyc_function.py 2007-08-04 19:58:57 UTC (rev 3943) @@ -4,31 +4,129 @@ class PyCFunction(Base): """ - PyCFunction(, *components, provides=..) - + PyCFunction(, *components, provides=..,title=.., description=..) + + >>> from __init__ import * #doctest: +ELLIPSIS + Ignoring... + >>> f = PyCFunction('hello', title='A function.', description='\\nFirst line.\\n2nd line.') + >>> a1_in_doc = '''First line.\\nSecond line.''' + >>> a1_out_doc = '''Single line.''' + >>> f += PyCArgument('a1',output_intent='return', input_title='a Python object', + ... input_description=a1_in_doc, output_description=a1_out_doc) + >>> f += PyCArgument('c1',input_intent='extra') + >>> f += PyCArgument('b1',input_intent='optional') + >>> f += PyCArgument('d2',input_intent='hide', output_intent='return') + >>> f += PyCArgument('a2',input_intent='required') + >>> f += PyCArgument('c2',input_intent='extra') + >>> f += PyCArgument('b2',input_intent='optional') + >>> m = ExtensionModule('foo', f) + >>> foo = m.build() #doctest: +ELLIPSIS + exec_command... + >>> print foo.hello.__doc__ + hello(a1, a2 [, b1, b2, c1, c2]) -> (a1, d2) + + A function. + + Required arguments: + a1 - a Python object + First line. + Second line. + a2 - None + + Optional arguments: + b1 - None + b2 - None + + Extra optional arguments: + c1 - None + c2 - None + + Return values: + a1 - None + Single line. + d2 - None + + Description: + + First line. + 2nd line. """ - container_options = dict(FuncDoc=dict(separator='"\n"', prefix='"', suffix='"'), - Args = dict(), - Decl = dict(default='', use_indent=True), - KWList = dict(separator=', ', suffix=', ', skip_suffix_when_empty=True), - PyArgFormat = dict(separator=''), - PyArgObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), - FromPyObj = dict(default='', use_indent=True), - Exec = dict(default='', use_indent=True), - PyObjFrom = dict(default='', use_indent=True), - RetFormat = dict(separator=''), - RetObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), - CleanPyObjFrom = dict(default='', reverse=True, use_indent=True), - CleanExec = dict(default='', reverse=True, use_indent=True), - CleanFromPyObj = dict(default='', reverse=True, use_indent=True), - ) + container_options = dict(\ + Args = dict(separator=', '), + ReqArgs = dict(separator=', '), + OptArgs = dict(separator=', '), + ExtArgs = dict(separator=', '), + RetArgs = dict(separator=', ', prefix='(', suffix=')', default = 'None', + skip_prefix_when_empty=True, skip_suffix_when_empty=True), + + OptExtArgs = dict(separator=', ', prefix=' [, ', skip_prefix_when_empty=True, + suffix=']', skip_suffix_when_empty=True), + + FuncTitle = dict(default='',prefix='"\\n\\n',suffix='"',separator='\\n"\n" ', + skip_prefix_when_empty=True, skip_suffix_when_empty=True, + use_firstline_indent=True), + FuncDescr = dict(default='',prefix='"\\n\\nDescription:\\n"\n" ', + suffix='"',separator='\\n"\n" ', + skip_prefix_when_empty=True, skip_suffix_when_empty=True, + use_firstline_indent=True), + ReqArgsDoc = dict(default='', prefix='"\\n\\nRequired arguments:\\n"\n" ', + separator='\\n"\n" ', suffix='"', + skip_prefix_when_empty=True, skip_suffix_when_empty=True, + use_firstline_indent=True), + OptArgsDoc = dict(default='', prefix='"\\n\\nOptional arguments:\\n"\n" ', + separator='\\n"\n" ', suffix='"', + skip_prefix_when_empty=True, skip_suffix_when_empty=True, + use_firstline_indent=True), + ExtArgsDoc = dict(default='', prefix='"\\n\\nExtra optional arguments:\\n"\n" ', + separator='\\n"\n" ', suffix='"', + skip_prefix_when_empty=True, skip_suffix_when_empty=True, + use_firstline_indent=True), + RetDoc = dict(default='"Return value:\\n None\\n"', prefix='"\\n\\nReturn values:\\n"\n" ', + separator='\\n"\n" ', suffix='"', + skip_prefix_when_empty=True, skip_suffix_when_empty=True, + use_firstline_indent=True), + + Decl = dict(default='', use_indent=True), + + ReqKWList = dict(separator=', ', suffix=', ', skip_suffix_when_empty=True), + OptKWList = dict(separator=', ', suffix=', ', skip_suffix_when_empty=True), + ExtKWList = dict(separator=', ', suffix=', ', skip_suffix_when_empty=True), + + ReqPyArgFmt = dict(separator=''), + OptPyArgFmt = dict(separator=''), + ExtPyArgFmt = dict(separator=''), + + ReqPyArgObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), + OptPyArgObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), + ExtPyArgObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), + + FromPyObj = dict(default='', use_indent=True), + Exec = dict(default='', use_indent=True), + PyObjFrom = dict(default='', use_indent=True), + + RetFmt = dict(separator=''), + RetObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), + + CleanPyObjFrom = dict(default='', reverse=True, use_indent=True), + CleanExec = dict(default='', reverse=True, use_indent=True), + CleanFromPyObj = dict(default='', reverse=True, use_indent=True), + ) + component_container_map = dict(CCode = 'Exec', PyCArgument = 'Args') template = ''' -static char %(pyc_name)s_doc[] = %(FuncDoc)s; +static char %(pyc_name)s_doc[] = +" %(name)s(%(ReqArgs)s%(OptExtArgs)s) -> %(RetArgs)s" +%(FuncTitle)s +%(ReqArgsDoc)s +%(OptArgsDoc)s +%(ExtArgsDoc)s +%(RetDoc)s +%(FuncDescr)s +; static PyObject* %(pyc_name)s @@ -36,14 +134,15 @@ PyObject * volatile pyc_buildvalue = NULL; volatile int capi_success = 1; %(Decl)s - static char *capi_kwlist[] = {%(KWList)sNULL}; - if (PyArg_ParseTupleAndKeywords(pyc_args, pyc_keywds,"%(PyArgFormat)s", capi_kwlist%(PyArgObj)s)) { + static char *capi_kwlist[] = {%(ReqKWList)s%(OptKWList)s%(ExtKWList)sNULL}; + if (PyArg_ParseTupleAndKeywords(pyc_args, pyc_keywds,"%(ReqPyArgFmt)s%(OptPyArgFmt)s%(ExtPyArgFmt)s", + capi_kwlist%(ReqPyArgObj)s%(OptPyArgObj)s%(ExtPyArgObj)s)) { %(FromPyObj)s %(Exec)s capi_success = !PyErr_Occurred(); if (capi_success) { %(PyObjFrom)s - pyc_buildvalue = Py_BuildValue("%(RetFormat)s"%(RetObj)s); + pyc_buildvalue = Py_BuildValue("%(RetFmt)s"%(RetObj)s); %(CleanPyObjFrom)s } %(CleanExec)s @@ -58,20 +157,44 @@ self.pyc_name = 'pyc_function_'+name self._provides = options.get('provides', '%s_%s' % (self.__class__.__name__, name)) + self.title = options.get('title', None) + self.description = options.get('description', None) map(self.add, components) def init_containers(self): - # set header to FuncDoc, for example. - FuncDoc = self.get_container('FuncDoc') - FuncDoc.add(self.name) return - def update_containers(self, params=None): - ModuleMethod = self.get_container('ModuleMethod') + def update_containers(self): + evaluate = self.evaluate + + # get containers + FuncTitle = self.container_FuncTitle + FuncDescr = self.container_FuncDescr + ReqArgs = self.container_ReqArgs + OptArgs = self.container_OptArgs + ExtArgs = self.container_ExtArgs + OptExtArgs = self.container_OptExtArgs + ModuleMethod = self.container_ModuleMethod + ModuleFuncDoc = self.container_ModuleFuncDoc + + # update ExtensionModule containers: t = '{"%(name)s", (PyCFunction)%(pyc_name)s,\n METH_VARARGS | METH_KEYWORDS, %(pyc_name)s_doc}' - ModuleMethod.add(self.evaluate(t), self.name) + ModuleMethod.add(evaluate(t), self.name) + + # update local containers: + OptExtArgs += OptArgs + ExtArgs + ModuleFuncDoc += evaluate('%(name)s(%(ReqArgs)s%(OptExtArgs)s) -> %(RetArgs)s') + if self.title is not None: + FuncTitle += self.title.replace('\n','\\n') + ModuleFuncDoc += ' ' + self.title.replace('\n','\\n') + if self.description is not None: + FuncDescr += self.description.replace('\n','\\n') return - - +def _test(): + import doctest + doctest.testmod() + +if __name__ == "__main__": + _test() From numpy-svn at scipy.org Sat Aug 4 16:10:11 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Sat, 4 Aug 2007 15:10:11 -0500 (CDT) Subject: [Numpy-svn] r3944 - trunk/numpy/f2py/lib/extgen Message-ID: <20070804201011.3074239C019@new.scipy.org> Author: pearu Date: 2007-08-04 15:10:05 -0500 (Sat, 04 Aug 2007) New Revision: 3944 Modified: trunk/numpy/f2py/lib/extgen/doc.txt Log: ExtGen: doc update. Modified: trunk/numpy/f2py/lib/extgen/doc.txt =================================================================== --- trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-04 19:58:57 UTC (rev 3943) +++ trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-04 20:10:05 UTC (rev 3944) @@ -55,19 +55,19 @@ - generate code by calling the `.generate()` method. - compile and build an extension module using the generated code. - ExtGen provides a way to do it via accessing the `.build` attribute - of the `ExtensionModule` instance. Accessing this attribute - will generate extension module, compilers it and returns the + ExtGen provides a way to do it via `.build()` method + of the `ExtensionModule` instance. Calling this method + will generate extension module, compiles it and returns the corresponding extension module instance. These steps will be discussed in more detail below. The `.components` attribute is a list object that contains instances -of `Base` subclasses (components). For instance, the `CAPIFunction` instance +of `Base` subclasses (components). For instance, the `PyCFunction` instance defined in the Hello example above, is a component of `ExtensionModule` instances after calling `.add()` method. Similarly, the C statement `'printf("Hello!\\n");'` is a component of -`CAPIFunction` instance after calling the `.add_execution()` method. +`PyCFunction` instance after calling the `.add()` method. The `.template` attribute is a string containing an template to a code idiom. Such an template may contain string replacements From numpy-svn at scipy.org Sat Aug 4 17:03:34 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Sat, 4 Aug 2007 16:03:34 -0500 (CDT) Subject: [Numpy-svn] r3945 - trunk/numpy/f2py/lib Message-ID: <20070804210334.A9B9139C019@new.scipy.org> Author: stefan Date: 2007-08-04 16:03:20 -0500 (Sat, 04 Aug 2007) New Revision: 3945 Modified: trunk/numpy/f2py/lib/setup.py Log: Add extgen subpackage. Modified: trunk/numpy/f2py/lib/setup.py =================================================================== --- trunk/numpy/f2py/lib/setup.py 2007-08-04 20:10:05 UTC (rev 3944) +++ trunk/numpy/f2py/lib/setup.py 2007-08-04 21:03:20 UTC (rev 3945) @@ -3,6 +3,7 @@ from numpy.distutils.misc_util import Configuration config = Configuration('lib',parent_package,top_path) config.add_subpackage('parser') + config.add_subpackage('extgen') config.add_data_files('*.txt','parser/*.txt') config.add_data_dir('src') return config From numpy-svn at scipy.org Sun Aug 5 11:23:47 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Sun, 5 Aug 2007 10:23:47 -0500 (CDT) Subject: [Numpy-svn] r3946 - trunk/numpy/f2py/lib/extgen Message-ID: <20070805152347.4F62A39C109@new.scipy.org> Author: pearu Date: 2007-08-05 10:23:30 -0500 (Sun, 05 Aug 2007) New Revision: 3946 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/predefined_components.py trunk/numpy/f2py/lib/extgen/pyc_argument.py trunk/numpy/f2py/lib/extgen/pyc_function.py Log: Impl CType classes and rewrote docs. Modified: trunk/numpy/f2py/lib/extgen/__init__.py =================================================================== --- trunk/numpy/f2py/lib/extgen/__init__.py 2007-08-04 21:03:20 UTC (rev 3945) +++ trunk/numpy/f2py/lib/extgen/__init__.py 2007-08-05 15:23:30 UTC (rev 3946) @@ -11,4 +11,8 @@ from pyc_argument import PyCArgument from c_code import CCode +import c_type +from c_type import * +__all__ += c_type.__all__ + import predefined_components Modified: trunk/numpy/f2py/lib/extgen/base.py =================================================================== --- trunk/numpy/f2py/lib/extgen/base.py 2007-08-04 21:03:20 UTC (rev 3945) +++ trunk/numpy/f2py/lib/extgen/base.py 2007-08-05 15:23:30 UTC (rev 3946) @@ -1,58 +1,70 @@ """ ExtGen --- Python Extension module Generator. -Defines Base and Container classes. +Defines Component and Container classes. """ import re import sys import time -class BaseMetaClass(type): +class ComponentMetaClass(type): classnamespace = {} def __init__(cls,*args,**kws): n = cls.__name__ - c = BaseMetaClass.classnamespace.get(n) + c = ComponentMetaClass.classnamespace.get(n) if c is None: - BaseMetaClass.classnamespace[n] = cls + ComponentMetaClass.classnamespace[n] = cls else: print 'Ignoring redefinition of %s: %s defined earlier than %s' % (n, c, cls) type.__init__(cls, *args, **kws) def __getattr__(cls, name): - try: return BaseMetaClass.classnamespace[name] + try: return ComponentMetaClass.classnamespace[name] except KeyError: pass raise AttributeError("'%s' object has no attribute '%s'"% (cls.__name__, name)) -class Base(object): +class Component(object): # XXX: rename Component to Component - __metaclass__ = BaseMetaClass + __metaclass__ = ComponentMetaClass container_options = dict() component_container_map = dict() + default_container_label = None + default_component_class_name = 'CCode' template = '' def __new__(cls, *args, **kws): obj = object.__new__(cls) - obj._args = args obj._provides = kws.get('provides', None) obj.parent = None obj.containers = {} # holds containers for named string lists - obj.components = [] # holds pairs (, ) + obj.components = [] # holds pairs (, ) obj.initialize(*args, **kws) # initialize from constructor arguments return obj - def initialize(self, *args, **kws): + def initialize(self, *components, **options): """ Set additional attributes, add components to instance, etc. """ # self.myattr = .. - # map(self.add, args) + # map(self.add, components) return + @property + def provides(self): + """ + Return a code idiom name that the current class defines. + + Used in avoiding redefinitions of functions and variables. + """ + if self._provides is None: + return '%s_%s' % (self.__class__.__name__, id(self)) + return self._provides + @staticmethod def warning(message): print >> sys.stderr, 'extgen:',message @@ -61,59 +73,48 @@ print >> sys.stderr, message def __repr__(self): - return '%s%s' % (self.__class__.__name__, `self._args`) + return '%s%s' % (self.__class__.__name__, `self.containers`) def __getattr__(self, attr): - if attr.startswith('container_'): + if attr.startswith('container_'): # convenience feature return self.get_container(attr[10:]) raise AttributeError('%s instance has no attribute %r' % (self.__class__.__name__, attr)) - def get_container(self, key): - """ Return named container. - - Rules for returning containers: - (1) return local container if exists - (2) return parent container if exists - (3) create local container and return it with warning - """ - # local container - try: - return self.containers[key] - except KeyError: - pass - - # parent container - parent = self.parent - while parent is not None: - try: - return parent.containers[key] - except KeyError: - parent = parent.parent - continue + def __add__(self, other): # convenience method + self.add(other) + return self + __iadd__ = __add__ - # create local container - self.warning('Created container for %r with name %r, define it in'\ - ' .container_options mapping to get rid of this warning' \ - % (self.__class__.__name__, key)) - c = self.containers[key] = Container() - return c - - @property - def provides(self): - """ - Return a code idiom name that the current class defines. + @staticmethod + def _get_class_names(cls): + if not issubclass(cls, Component): + return [cls] + r = [cls] + for b in cls.__bases__: + r += Component._get_class_names(b) + return r - Used in avoiding redefinitions of functions and variables. + def add(self, component, container_label=None): """ - if self._provides is None: - return '%s_%s' % (self.__class__.__name__, id(self)) - return self._provides - - def get_templates(self): + Append component and its target container label to components list. """ - Return instance templates. - """ - return self.template + if not isinstance(component, Component) and self.default_component_class_name!=component.__class__.__name__: + clsname = self.default_component_class_name + if clsname is not None: + component = getattr(Component, clsname)(component) + else: + raise ValueError('%s.add requires Component instance but got %r' \ + % (self.__class__.__name__, component.__class__.__name__)) + if container_label is None: + container_label = self.default_container_label + for n in self._get_class_names(component.__class__): + try: + container_label = self.component_container_map[n.__name__] + break + except KeyError: + pass + self.components.append((component, container_label)) + return def generate(self): """ @@ -135,10 +136,22 @@ # generate component code idioms for component, container_key in self.components: + if not isinstance(component, Component): + result = str(component) + if container_key == '': + pass + elif container_key is not None: + self.get_container(container_key).add(result) + else: + self.warning('%s: no container label specified for component %r'\ + % (self.__class__.__name__,component)) + continue old_parent = component.parent component.parent = self result = component.generate() - if container_key is not None: + if container_key == '': + pass + elif container_key is not None: if isinstance(container_key, tuple): assert len(result)==len(container_key),`len(result),container_key` results = result @@ -151,8 +164,8 @@ container = component.get_container(k) container.add(r, component.provides) else: - self.warning('no label specified for component %r, ignoring its result'\ - % (component.provides)) + self.warning('%s: no container label specified for component providing %r'\ + % (self.__class__.__name__,component.provides)) component.parent = old_parent # update code idioms @@ -184,33 +197,42 @@ # container.add(, label=None) return - def __iadd__(self, other): - """ Convenience add. + def get_container(self, name): + """ Return named container. + + Rules for returning containers: + (1) return local container if exists + (2) return parent container if exists + (3) create local container and return it with warning """ - self.add(other) - return self + # local container + try: + return self.containers[name] + except KeyError: + pass + + # parent container + parent = self.parent + while parent is not None: + try: + return parent.containers[name] + except KeyError: + parent = parent.parent + continue - def add(self, component, container_label=None): + # create local container + self.warning('Created container for %r with name %r, define it in'\ + ' .container_options mapping to get rid of this warning' \ + % (self.__class__.__name__, name)) + c = self.containers[name] = Container() + return c + + def get_templates(self): """ - Append component and its target container label to components list. + Return instance templates. """ - if isinstance(component, str): - component = Base.CCode(component) - if container_label is None: - container_label = self.component_container_map.get(component.__class__.__name__, None) - assert isinstance(component, Base), `type(component)` - self.components.append((component, container_label)) + return self.template - @property - def show(self): - # display the content of containers - self.generate() - r = [self.__class__.__name__] - for k, v in self.containers.items(): - if v.list: - r.append('--- %s ---\n%s' % (k,v)) - return '\n'.join(r) - def evaluate(self, template, **attrs): """ Evaluate template using instance attributes and code @@ -235,8 +257,9 @@ template = template[:i] + str(container) + template[i+len(s):] container.indent_offset = old_indent template = template % d - return re.sub(r'.*[<]KILLLINE[>].*\n','', template) + return re.sub(r'.*[<]KILLLINE[>].*(\n|$)','', template) + _registered_components_map = {} @staticmethod @@ -245,11 +268,11 @@ Register components so that component classes can use predefined components via `.get()` method. """ - d = Base._registered_components_map + d = Component._registered_components_map for component in components: provides = component.provides if d.has_key(provides): - Base.warning('component that provides %r is already registered, ignoring.' % (provides)) + Component.warning('component that provides %r is already registered, ignoring.' % (provides)) else: d[provides] = component return @@ -260,7 +283,7 @@ Return predefined component with given provides property.. """ try: - return Base._registered_components_map[provides] + return Component._registered_components_map[provides] except KeyError: pass raise KeyError('no registered component provides %r' % (provides)) @@ -269,6 +292,7 @@ def numpy_version(self): import numpy return numpy.__version__ + class Container(object): """ @@ -292,7 +316,7 @@ "hey, hoo, bar" """ - __metaclass__ = BaseMetaClass + __metaclass__ = ComponentMetaClass def __init__(self, separator='\n', prefix='', suffix='', @@ -303,6 +327,7 @@ use_indent = False, indent_offset = 0, use_firstline_indent = False, # implies use_indent + replace_map = {} ): self.list = [] self.label_map = {} @@ -318,8 +343,9 @@ self.use_indent = use_indent or use_firstline_indent self.indent_offset = indent_offset self.use_firstline_indent = use_firstline_indent + self.replace_map = replace_map - def __notzero__(self): + def __nonzero__(self): return bool(self.list) def has(self, label): @@ -353,6 +379,8 @@ if d!=content: raise ValueError("Container item %r exists with different value" % (label)) return + for old, new in self.replace_map.items(): + content = content.replace(old, new) self.list.append(content) self.label_map[label] = len(self.list)-1 return @@ -396,7 +424,9 @@ default = self.default, reverse=self.reverse, user_defined_str = self.user_str, use_indent = self.use_indent, - indent_offset = self.indent_offset + indent_offset = self.indent_offset, + use_firstline_indent = self.use_firstline_indent, + replace_map = self.replace_map ) options.update(extra_options) cpy = Container(**options) Modified: trunk/numpy/f2py/lib/extgen/c_code.py =================================================================== --- trunk/numpy/f2py/lib/extgen/c_code.py 2007-08-04 21:03:20 UTC (rev 3945) +++ trunk/numpy/f2py/lib/extgen/c_code.py 2007-08-05 15:23:30 UTC (rev 3946) @@ -1,7 +1,7 @@ -from base import Base +from base import Component -class CCode(Base): +class CCode(Component): """ CCode(*lines, provides=..) @@ -27,6 +27,6 @@ assert label is None,`label` self.lines.extend(component.lines) else: - Base.add(self, component. label) + Component.add(self, component. label) Modified: trunk/numpy/f2py/lib/extgen/c_type.py =================================================================== --- trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-04 21:03:20 UTC (rev 3945) +++ trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-05 15:23:30 UTC (rev 3946) @@ -1,137 +1,200 @@ """ -Defines C type declaration templates: +C types. - CTypeAlias(name, ctype) --- typedef ctype name; - CTypeFunction(name, rtype, atype1, atype2,..) --- typedef rtype (*name)(atype1, atype2,...); - CTypeStruct(name, (name1,type1), (name2,type2), ...) --- typedef struct { type1 name1; type2 name2; .. } name; - CTypePtr(ctype) --- ctype * - CInt(), CLong(), ... --- int, long, ... - CPyObject() -The instances of CTypeBase have the following public methods and properties: - - - .asPtr() - - .declare(name) """ +__all__ = ['CType', 'CTypeAlias', 'CTypeFuncAlias', 'CTypePtr', 'CTypeStruct', 'CDecl'] -from base import Base +from base import Component -class CTypeBase(Base): +class CTypeBase(Component): - def declare(self, name): - return '%s %s;' % (self.typename, name) + template = '%(name)s' + template_typedef = '' + default_container_label = '' + default_component_class_name = 'CType' + @property + def provides(self): + return '%s_%s' % (self.__class__.__name__, self.name) + + def initialize(self, name, *components): + self.name = name + map(self.add, components) + + def update_containers(self): + self.container_TypeDef += self.evaluate(self.template_typedef) + def __str__(self): - return self.typename + return self.name - def asPtr(self): - return CTypePtr(self) +class _CatchTypeDef(Component): # for doctest + template = '%(TypeDef)s' + default_container_label = '' + container_options = dict(TypeDef=dict(default='')) + def initialize(self, ctype): + self.add(ctype) +class CType(CTypeBase): + + """ CType() + + Represents any predefined type in C. + + >>> cint = CType('int') + >>> print cint + int + >>> _CatchTypeDef(cint).generate() + '' + """ + + def initialize(self, name): + self.name = name + + def update_containers(self): + pass + class CTypeAlias(CTypeBase): - def __new__(cls, typename, ctype): - obj = Base.__new__(cls) - assert isinstance(ctype, CTypeBase),`type(ctype)` - obj.add(typename, ctype) - return obj + """ CTypeAlias(, ) - @property - def typename(self): return self.components[0][0] - @property - def ctype(self): return self.components[0][1] + >>> aint = CTypeAlias('aint', 'int') + >>> print aint + aint + >>> print _CatchTypeDef(aint).generate() + typedef int aint; + """ - def local_generate(self, params=None): - container = self.get_container('TypeDef') - container.add(self.typename, 'typedef %s %s;' % (self.ctype, self.typename)) - return self.declare(params) + template_typedef = 'typedef %(ctype_name)s %(name)s;' + def initialize(self, name, ctype): + self.name = name + if isinstance(ctype, str): ctype = CType(ctype) + self.ctype_name = ctype.name + self.add(ctype) -class CTypeFunction(CTypeBase): +class CTypeFuncAlias(CTypeBase): - def __new__(cls, typename, rctype, *arguments): - obj = Base.__new__(cls) - assert isinstance(rctype, CTypeBase),`type(rctype)` - obj.add(typename, rctype) - for i in range(len(arguments)): - a = arguments[i] - assert isinstance(a, CTypeBase),`type(a)` - obj.add('_a%i' % (i), a) - return obj + """ + CTypeFuncAlias(, , *()) - @property - def typename(self): return self.components[0][0] - @property - def rctype(self): return self.components[0][1] - @property - def arguments(self): return [v for n,v in self.components[1:]] + >>> ifunc = CTypeFuncAlias('ifunc', 'int') + >>> print ifunc + ifunc + >>> print _CatchTypeDef(ifunc).generate() + typedef int (*ifunc)(void); + >>> ifunc += 'double' + >>> print _CatchTypeDef(ifunc).generate() + typedef int (*ifunc)(double); + """ - def local_generate(self, params=None): - container = self.get_container('TypeDef') - container.add(self.typename, 'typedef %s (*%s)(%s);' \ - % (self.rctype, self.typename, - ', '.join([str(ctype) for ctype in self.arguments]))) - return self.declare(params) + template_typedef = 'typedef %(RCType)s (*%(name)s)(%(ACType)s);' + container_options = dict(RCType = dict(default='void'), + ACType = dict(default='void', separator=', ')) + component_container_map = dict(CType = 'ACType') + default_component_class_name = 'CType' + def initialize(self, name, *components): + self.name = name + if components: + self.add(components[0], 'RCType') + map(self.add, components[1:]) + +class CTypePtr(CTypeBase): + + """ + CTypePtr() + + >>> int_ptr = CTypePtr('int') + >>> print int_ptr + int_ptr + >>> print _CatchTypeDef(int_ptr).generate() + typedef int* int_ptr; + >>> int_ptr_ptr = CTypePtr(int_ptr) + >>> print int_ptr_ptr + int_ptr_ptr + >>> print _CatchTypeDef(int_ptr_ptr).generate() + typedef int* int_ptr; + typedef int_ptr* int_ptr_ptr; + """ + + template_typedef = 'typedef %(ctype_name)s* %(name)s;' + + def initialize(self, ctype): + if isinstance(ctype, str): ctype = CType(ctype) + self.name = '%s_ptr' % (ctype) + self.ctype_name = ctype.name + self.add(ctype) + class CTypeStruct(CTypeBase): - def __new__(cls, typename, *components): - obj = Base.__new__(cls, typename) - for n,v in components: - assert isinstance(v,CTypeBase),`type(v)` - obj.add(n,v) - return obj + """ + CTypeStruct(, *()) - @property - def typename(self): return self._args[0] + >>> s = CTypeStruct('s', CDecl('int','a')) + >>> print s + s + >>> print _CatchTypeDef(s).generate() + typedef struct { + int a; + } s; + >>> s += CDecl(CTypeFuncAlias('ft'), 'f') + >>> print _CatchTypeDef(s).generate() + typedef void (*ft)(void); + typedef struct { + int a; + ft f; + } s; - def local_generate(self, params=None): - container = self.get_container('TypeDef') - decls = [ctype.declare(name) for name, ctype in self.components] - if decls: - d = 'typedef struct {\n %s\n} %s;' % ('\n '.join(decls),self.typename) - else: - d = 'typedef struct {} %s;' % (self.typename) - container.add(self.typename, d) - return self.declare(params) + """ -class CTypePtr(CTypeBase): + container_options = dict(Decl = dict(default='', use_indent=True)) + default_component_class_name = None #'CDecl' + component_container_map = dict(CDecl='Decl') - def __new__(cls, ctype): - obj = Base.__new__(cls) - assert isinstance(ctype, CTypeBase),`type(ctype)` - obj.add('*', ctype) - return obj + template_typedef = '''\ +typedef struct { + %(Decl)s +} %(name)s;''' - @property - def ctype(self): return self.components[0][1] - - @property - def typename(self): - return self.ctype.typename + '*' + def initialize(self, name, *components): + self.name = name + map(self.add, components) - def local_generate(self, params=None): - return self.declare(params) +class CDecl(Component): -class CTypeDefined(CTypeBase): + """ + CDecl(, *()) - @property - def typename(self): return self._args[0] + >>> ad = CDecl('int') + >>> ad.generate() + '' + >>> ad += 'a' + >>> print ad.generate() + int a; + >>> ad += 'b' + >>> print ad.generate() + int a, b; + >>> ad += 'c = 1' + >>> print ad.generate() + int a, b, c = 1; + """ -class CTypeIntrinsic(CTypeDefined): + template = '%(CTypeName)s %(Names)s;' + container_options = dict(Names=dict(default='', separator=', '), + CTypeName=dict()) + default_component_class_name = 'str' + component_container_map = dict(str = 'Names') - def __new__(cls, typename): - return Base.__new__(cls, typename) + def initialize(self, ctype, *names): + if isinstance(ctype, str): ctype = CType(ctype) + self.add(ctype, 'CTypeName') + map(self.add, names) -class CPyObject(CTypeDefined): - def __new__(cls): - return Base.__new__(cls, 'PyObject') -class CInt(CTypeIntrinsic): +if 0: - def __new__(cls): - return Base.__new__(cls, 'int') - def local_generate(self, params=None): container = self.get_container('CAPICode') code = '''\ @@ -154,3 +217,9 @@ return self.declare(params) +def _test(): + import doctest + doctest.testmod() + +if __name__ == "__main__": + _test() Modified: trunk/numpy/f2py/lib/extgen/doc.txt =================================================================== --- trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-04 21:03:20 UTC (rev 3945) +++ trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-05 15:23:30 UTC (rev 3946) @@ -22,78 +22,140 @@ >>> f = PyCFunction('hello') >>> f += 'printf("Hello!\\n");' >>> m += f - >>> m.generate() # returns a string containing C source to extension module + >>> print m.generate() # shows a string containing C source to extension module >>> foo = m.build() >>> foo.hello() Hello! >>> -Extending ExtGen -================ +Description of the ExtGen model +=============================== To extend ExtGen, one needs to understand the infrastructure of generating extension modules. -The `extgen` package provides many classes that are derived from Base -class (defined in extgen/base.py). Each such a class represents -certain code block or a code idiom in an extension module that is -defined in `.template` attribute. Most important `Base` methods, that -are used to generate code idioms, are: `.initialize()`, `.add()`, -`.generate()`, `init_containers()`, `.update_containers()`, -`.get_templates()`. +There are two important concepts in ExtGen model: components and +containers. Components (ref. class `Component`) define code blocks or +code idioms used in building up a code sources. Containers (ref. class +`Container`) are named string lists that are joined together with +specified rules resulting actual code sources. ExtGen uses two steps +for constructing code sources: -Creating an extension module is carried out by the following steps: +- creating code components and adding them together to a parent + component. For example, the `ExtensionModule` instance in the + hello example becomes a parent component to a `PyCFunction` instance + after executing `m += f`. -- create and add components to `Base` subclass instances, - for example, start with creating an `ExtensionModule` instance. - Components can be added with `.add(component, label=None)` method. - Note that some components (dependencies) may be added - in `.initialize()` method that is called by the constructor - of the `Base` subclass. +- generating code source by calling `.generate()` method of the + parent component. -- generate code by calling the `.generate()` method. +One can iterate the above process as one wishes. -- compile and build an extension module using the generated code. - ExtGen provides a way to do it via `.build()` method - of the `ExtensionModule` instance. Calling this method - will generate extension module, compiles it and returns the - corresponding extension module instance. +The method `ExtensionModule.build()` is defined for convenience. +It compiles the generated sources, builds an extension module, +imports the resulting module to Python, and returns the module object. -These steps will be discussed in more detail below. +All component classes must be derived from the base class `Component` +defined in `extgen/base.py` file. `Component` class defines the +following methods and attributes: -The `.components` attribute is a list object that contains instances -of `Base` subclasses (components). For instance, the `PyCFunction` instance -defined in the Hello example above, is a component of -`ExtensionModule` instances after calling `.add()` method. Similarly, -the C statement `'printf("Hello!\\n");'` is a component of -`PyCFunction` instance after calling the `.add()` method. +- `.initialize(self, *args, **kws)` is used to initialize the attributes + and subcomponents of the `Component` instance. Derived classes + usually redefine it to define the signature of the component + constructor. -The `.template` attribute is a string containing an template -to a code idiom. Such an template may contain string replacements -names that are replaced with code idioms generated by the components ---- template evaluation. -If the class should have more than one template then redefine -`.get_templates()` method that should return a tuple of templates. +- `.add(self, component, container_label=None)` is used to add + subcomponents to the `Component`. Derived classes can affect + the behavior of the `.add()` method by redefining the following + class attributes: -The `.containers` attribute is a mapping between a replacement name -(container label) used in template strings and a `Container` instance -holding code idioms from component generation process. The mapping -`.containers` is updated by the `.init_containers()` and -`.update_containers()` methods. These methods should use -`.get_container()` to inquire container instances -and `Container.add(, label=None)` method to add -new code idioms to containers. + - `.default_component_class_name` is used when the `component` + argument is not a `Component` instance. -The `.generate()` method will call `.init_containers()` method, the -`.generate()` methods of components, and `.update_containers()` method -to generate code idioms and save the results to the corresponding -containers. Finally, it returns the results of applying -`.evaluate()` method to templates which replaces the -replacement names with code idioms from containers as well as string -valued attributes of the given `Base` subclass instance. One can set -attributes inside `.initilize()` method. + - `.default_container_label` is used when component + `container_label` is undefined. + - `.component_containe_map` is used to find `container_label` + corresponding to `component` argument class. + +- `.generate(self)` returns a source code string. It recursively + processes all subcomponents, creates code containers, and + evaluates code templates. + +- `.provides(self)` property method returns an unique string + labeling the current component. The label is used to name + the result of `.generate()` method when storing it to a container. + The result is saved to container only if container does not + contain the given provides label. With this feature one avoids + redefining the same functions, variables, types etc that are needed + by different components. + +- `.init_containers(self)` is called before processing subcomponents. + Derived classes may redefine it. + +- `.update_containers(self)` is called after processing subcomponents. + Derived classes usually define it to fill up any containers. + +- `.get_templates(self)` is used by `.generate()` method to evaluate + the templates and return results. By default, `.get_templates()` + returns `.template` attribute. Derived classes may redefine it + to return a tuple of templates, then also `.generate()` will + return a tuple of source code strings. + +- `.get_container(self, name)` or `.container_` can be used + to retrive a container with a given name. If the current component + does not have requested container then the method tries to find + the container from parent classes. If it still does not find it, + then a new container with the given name will be created for + the current component. One should acctually avoid the last + solution and always define the containers in `.container_options` + class attribute. This attribute is a mapping between container + names and keyword options to the `Container` constructor. + See `Container` options below for more detail. + +- `.evaluate(self, template)` will evaluate `template` using + the attributes (with string values) and the code from containers. + +- `.info(message)`, `.warning(message)` are utility methods and + will write messages to `sys.stderr`. + +- `.register(*components)` will register predefined components + that can be retrived via `.get(provides)` method. + +Deriving a new `Component` class involves the following +tasks: + +- A component class must have a base class `Component`. + +- A component class may redefine `.initialize()`, + `.init_containers()`, `.update_containers()`, `.get_templates()` + methods, `.provides()` property method and `.container_options`, + `.component_container_map`, `.default_container_label`, + `.default_component_class_name`, `.template` attributes. + +- In `.initialize()` method one can process constructor options, + set new attributes and add predefined components. + +- In `.init_containers()` and `.update_containers()` methods + one may retrive containers from parents via `.get_container()` + method or `.container_` attribute and fill them using + `.add()` method of the container. + +- The attribute `.template` is a string containing formatting mapping keys + that correspond to containers names or instance attribute names. + +- The attribute `.container_options` is a mapping of container + names and keyword argument dictionaries used as options + to a `Container` constructor. + +- The attribute `.component_container_map` is a mapping between + subcomponent class names and the names of containers that should + be used to save the code generation results. + +- All classes derived from `Component` are available as + `Component.`. + Here follows a simplified version of `ExtensionModule.template`:: #include "Python.h" @@ -122,10 +184,13 @@ } return; } - -Here `Header`, `TypeDef`, etc are the labels of containers which will be replaced -during evaluation of templates. +Here formatting mapping keys `Header`, `TypeDef`, etc are the labels +of containers which will be used in the templare evaluation. +See `extgen/*.py` files for more examples how to redefine `Component` +class methods and attributes. + + Using `Container` class ======================= @@ -142,22 +207,41 @@ - `use_firstline_indent=False` - `indent_offset=0` - `user_defined_str=None` + - `replace_map={}` -that can be used to change the behaviour of `Container.__str__()` -method. By default, `Container.__str__()` method returns +that are used to enhance the behaviour of `Container.__str__()` +method. By default, `Container.__str__()` returns `prefix+separator.join(.list)+suffix`. One can add items to `Container` instance using `.add(, -label=None)` method. Here `label` should contain an unique value that -represents the content of ``. If `label` is `None` then -`label = time.time()` will be set. +label=None)` method. The items are saved in `.list` and `.label_map` +attributes. +`Container` instances can be combined using `+` operator and +copied with `.copy()` method. The `.copy()` method has the +same arguments as `Container` constructor and can be used +to change certain container properties. + +The `label` argument should contain an unique value that represents +the content of ``. If `label` is `None` then `label = +time.time()` will be set. + If one tries to add items with the same label to the container then the equality of the corresponding string values will be checked. If they are not equal then `ValueError` is raised, otherwise adding an item is ignored. +If `reverse` is `True` then the `.list` is reversed before joining +its items. If `use_indent` is `True` then each item in `.list` will +be prefixed with `indent_offset` spaces. If `use_firstline_indent` is +`True` then additional indention of the number of starting spaces +in `.line[0]` is used. The `replace_map` is used to apply +`.replace(key, value)` method to the result of `__str__()`. +Full control over the `__str__()` method is obtained via +defining `user_defined_str` that should be a callable object taking +list as input and return a string. + Component classes ================= @@ -165,10 +249,11 @@ - `ExtensionModule(, *components, numpy=False, provides=.., title=.., description=..)` --- - represents an extension module, + represents an extension module component. If `numpy` is `True` then + `NumPy` support will be added to an extension module. - `PyCFunction(, *components, provides=.., title=.., description=..)` --- - represents an extension function. + represents an extension function component. - `PyCArgument(, *components, provides=.., input_intent=.., output_intent=.., input_title=.., input_description=.., @@ -177,5 +262,39 @@ `output_intent` may have values `'required'`, `'optional'`, `'extra'`, `'hide'` and `'hide'`, `'return'`, respectively. - - `CCode(*lines, provides=..)` --- represents any C code block or statement. + - `CCode(*lines, provides=..)` --- represents any C code block or + statement component. + - `CType()` --- represents a predefined or intrinsic C type + with a given name. + + - `CTypeAlias(, )` --- represents `typedef ctype name;` + declaration. + + - `CTypeFuncAlias(, , )` --- + represents `typedef rctype (*name)(actype1,..)` declaration. + Use `.add()` method to add more argument types. + + - `CTypePtr()` --- represents `typedef ctype* ctype_ptr;` + declaration. + + - `CTypeStruct(, *declarations)` --- represents `typedef struct { + } name;` declaration. Use `.add()` method to add + more declarations. + + - `CDecl(, *names)` --- represents `ctype name1, name2, ..;` + declaration. Use `.add()` method to add more names. + + +Predefined components +===================== + +ExtGen defines the following components that can be retrived +using `Component.get()` method: + +- `'Python.h'` - include `Pyhton.h` header file. + +- `'arrayobject.h'` - include NumPy header files. + +- `'import_array'` - code for importing numpy package to extension + module. Modified: trunk/numpy/f2py/lib/extgen/extension_module.py =================================================================== --- trunk/numpy/f2py/lib/extgen/extension_module.py 2007-08-04 21:03:20 UTC (rev 3945) +++ trunk/numpy/f2py/lib/extgen/extension_module.py 2007-08-05 15:23:30 UTC (rev 3946) @@ -1,7 +1,7 @@ -from base import Base +from base import Component -class ExtensionModule(Base): +class ExtensionModule(Component): """ ExtensionModule(, *components, numpy=False, provides=..) @@ -59,15 +59,15 @@ ModuleTitle = dict(default='',prefix='"\\n\\n',suffix='"',separator='\\n"\n" ', skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True), + use_firstline_indent=True, replace_map = {'\n':'\\n'}), ModuleDescr = dict(default='',prefix='"\\n\\nDescription:\\n"\n" ', suffix='"',separator='\\n"\n" ', skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True), + use_firstline_indent=True, replace_map={'\n':'\\n'}), ModuleFuncDoc = dict(default='', prefix='"\\n\\nFunctions:\\n"\n" ', separator='\\n"\n" ', suffix='"', skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True), + use_firstline_indent=True, replace_map={'\n':'\\n'}), ) component_container_map = dict(PyCFunction = 'CAPICode') @@ -131,30 +131,31 @@ def initialize(self, modulename, *components, **options): self.modulename = modulename - self._provides = options.get('provides', + self._provides = options.pop('provides', '%s_%s' % (self.__class__.__name__, modulename)) + + self.title = options.pop('title', None) + self.description = options.pop('description', None) + + if options: self.warning('%s unused options: %s\n' % (self.__class__.__name__, options)) + # all Python extension modules require Python.h - self.add(Base.get('Python.h'), 'Header') + self.add(Component.get('Python.h'), 'Header') if options.get('numpy'): - self.add(Base.get('arrayobject.h'), 'Header') - self.add(Base.get('import_array'), 'ModuleInit') - - self.title = options.get('title') - self.description = options.get('description') - + self.add(Component.get('arrayobject.h'), 'Header') + self.add(Component.get('import_array'), 'ModuleInit') map(self.add, components) return def update_containers(self): if self.title is not None: - self.container_ModuleTitle += self.title.replace('\n','\\n') + self.container_ModuleTitle += self.title if self.description is not None: - self.container_ModuleDescr += self.description.replace('\n','\\n') + self.container_ModuleDescr += self.description def build(self): import os import sys - import subprocess extfile = self.generate() srcfile = os.path.abspath('%smodule.c' % (self.modulename)) f = open(srcfile, 'w') @@ -181,8 +182,6 @@ build_dir = '.' from numpy.distutils.exec_command import exec_command status, output = exec_command(setup_cmd) - #p = subprocess.Popen(setup_cmd, cwd=build_dir, shell=True, stdout=subprocess.PIPE,stderr=subprocess.PIPE) - #sts = os.waitpid(p.pid, 0) if status: raise "Failed to build (status=%s)." % (`status`) exec 'import %s as m' % (modulename) Modified: trunk/numpy/f2py/lib/extgen/predefined_components.py =================================================================== --- trunk/numpy/f2py/lib/extgen/predefined_components.py 2007-08-04 21:03:20 UTC (rev 3945) +++ trunk/numpy/f2py/lib/extgen/predefined_components.py 2007-08-05 15:23:30 UTC (rev 3946) @@ -1,8 +1,8 @@ -from base import Base +from base import Component from c_code import CCode -Base.register( +Component.register( CCode('#include "Python.h"', provides='Python.h'), Modified: trunk/numpy/f2py/lib/extgen/pyc_argument.py =================================================================== --- trunk/numpy/f2py/lib/extgen/pyc_argument.py 2007-08-04 21:03:20 UTC (rev 3945) +++ trunk/numpy/f2py/lib/extgen/pyc_argument.py 2007-08-05 15:23:30 UTC (rev 3946) @@ -1,7 +1,7 @@ -from base import Base +from base import Component -class PyCArgument(Base): +class PyCArgument(Component): """ PyCArgument(, *components, provides=.., @@ -19,19 +19,23 @@ def initialize(self, name, *components, **options): self.name = name - self._provides = options.get('provides', + self._provides = options.pop('provides', '%s_%s' % (self.__class__.__name__, name)) - self.input_intent = options.get('input_intent','required') # 'optional', 'extra', 'hide' - self.output_intent = options.get('output_intent','hide') # 'return' - self.input_title = options.get('input_title', None) - self.output_title = options.get('output_title', None) - self.input_description = options.get('input_description', None) - self.output_description = options.get('output_description', None) + 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) + + if options: self.warning('%s unused options: %s\n' % (self.__class__.__name__, options)) map(self.add, components) def get_ctype(self): - # scan components for c types + for component, container_label in self.components: + if isinstance(component, Component.CTypeBase): + return component return def init_containers(self): Modified: trunk/numpy/f2py/lib/extgen/pyc_function.py =================================================================== --- trunk/numpy/f2py/lib/extgen/pyc_function.py 2007-08-04 21:03:20 UTC (rev 3945) +++ trunk/numpy/f2py/lib/extgen/pyc_function.py 2007-08-05 15:23:30 UTC (rev 3946) @@ -1,7 +1,7 @@ -from base import Base +from base import Component -class PyCFunction(Base): +class PyCFunction(Component): """ PyCFunction(, *components, provides=..,title=.., description=..) @@ -66,27 +66,27 @@ FuncTitle = dict(default='',prefix='"\\n\\n',suffix='"',separator='\\n"\n" ', skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True), + use_firstline_indent=True, replace_map={'\n':'\\n'}), FuncDescr = dict(default='',prefix='"\\n\\nDescription:\\n"\n" ', suffix='"',separator='\\n"\n" ', skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True), + use_firstline_indent=True, replace_map={'\n':'\\n'}), ReqArgsDoc = dict(default='', prefix='"\\n\\nRequired arguments:\\n"\n" ', separator='\\n"\n" ', suffix='"', skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True), + use_firstline_indent=True, replace_map={'\n':'\\n'}), OptArgsDoc = dict(default='', prefix='"\\n\\nOptional arguments:\\n"\n" ', separator='\\n"\n" ', suffix='"', skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True), + use_firstline_indent=True, replace_map={'\n':'\\n'}), ExtArgsDoc = dict(default='', prefix='"\\n\\nExtra optional arguments:\\n"\n" ', separator='\\n"\n" ', suffix='"', skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True), + use_firstline_indent=True, replace_map={'\n':'\\n'}), RetDoc = dict(default='"Return value:\\n None\\n"', prefix='"\\n\\nReturn values:\\n"\n" ', separator='\\n"\n" ', suffix='"', skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True), + use_firstline_indent=True, replace_map={'\n':'\\n'}), Decl = dict(default='', use_indent=True), @@ -155,10 +155,13 @@ def initialize(self, name, *components, **options): self.name = name self.pyc_name = 'pyc_function_'+name - self._provides = options.get('provides', + self._provides = options.pop('provides', '%s_%s' % (self.__class__.__name__, name)) - self.title = options.get('title', None) - self.description = options.get('description', None) + self.title = options.pop('title', None) + self.description = options.pop('description', None) + + if options: self.warning('%s unused options: %s\n' % (self.__class__.__name__, options)) + map(self.add, components) def init_containers(self): @@ -185,10 +188,10 @@ OptExtArgs += OptArgs + ExtArgs ModuleFuncDoc += evaluate('%(name)s(%(ReqArgs)s%(OptExtArgs)s) -> %(RetArgs)s') if self.title is not None: - FuncTitle += self.title.replace('\n','\\n') - ModuleFuncDoc += ' ' + self.title.replace('\n','\\n') + FuncTitle += self.title + ModuleFuncDoc += ' ' + self.title if self.description is not None: - FuncDescr += self.description.replace('\n','\\n') + FuncDescr += self.description return From numpy-svn at scipy.org Sun Aug 5 17:14:00 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Sun, 5 Aug 2007 16:14:00 -0500 (CDT) Subject: [Numpy-svn] r3947 - trunk/numpy/f2py/lib/extgen Message-ID: <20070805211400.C282739C0FC@new.scipy.org> 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 (, ) - 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 = '' container_options = dict(TypeDef=dict(default='')) def initialize(self, ctype): self.add(ctype) - + return self + class CType(CTypeBase): """ CType() @@ -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()` @@ -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(, *components, provides=.., + PyCArgument(, 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 @@ 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 From numpy-svn at scipy.org Mon Aug 6 05:51:58 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Mon, 6 Aug 2007 04:51:58 -0500 (CDT) Subject: [Numpy-svn] r3948 - trunk/numpy/f2py/lib/extgen Message-ID: <20070806095158.97DAE39C13F@new.scipy.org> Author: pearu Date: 2007-08-06 04:51:47 -0500 (Mon, 06 Aug 2007) New Revision: 3948 Modified: trunk/numpy/f2py/lib/extgen/base.py trunk/numpy/f2py/lib/extgen/c_type.py trunk/numpy/f2py/lib/extgen/doc.txt trunk/numpy/f2py/lib/extgen/pyc_argument.py trunk/numpy/f2py/lib/extgen/pyc_function.py Log: extgen: Impl argument support to all Python types. Modified: trunk/numpy/f2py/lib/extgen/base.py =================================================================== --- trunk/numpy/f2py/lib/extgen/base.py 2007-08-05 21:13:49 UTC (rev 3947) +++ trunk/numpy/f2py/lib/extgen/base.py 2007-08-06 09:51:47 UTC (rev 3948) @@ -98,6 +98,9 @@ """ Append component and its target container label to components list. """ + if isinstance(component, tuple) and len(component)==2 and isinstance(component[0], Component): + assert container_label is None, `container_label` + component, container_label = component if not isinstance(component, Component) and self.default_component_class_name!=component.__class__.__name__: clsname = self.default_component_class_name if clsname is not None: Modified: trunk/numpy/f2py/lib/extgen/c_type.py =================================================================== --- trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-05 21:13:49 UTC (rev 3947) +++ trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-06 09:51:47 UTC (rev 3948) @@ -4,7 +4,8 @@ """ -__all__ = ['CType', 'CTypeAlias', 'CTypeFuncAlias', 'CTypePtr', 'CTypeStruct', 'CDecl'] +__all__ = ['CType', 'CTypeAlias', 'CTypeFuncAlias', 'CTypePtr', 'CTypeStruct', 'CDecl', + 'CTypePython'] from base import Component @@ -65,6 +66,10 @@ """ def initialize(self, name): + if isinstance(name, CTypeBase): + return name + if isinstance(name, type) or name in ['cell', 'generator', 'cobject']: + return CTypePython(name) try: return Component.get(name) except KeyError: @@ -120,6 +125,7 @@ if components: self.add(components[0], 'RCType') map(self.add, components[1:]) + return self class CTypePtr(CTypeBase): @@ -215,22 +221,139 @@ map(self.add, names) return self -class PyObjectPtr(CType): - name = provides = 'PyObject*' - def initialize(self): return self +class CTypePython(CTypeBase): + + """ CTypePython() + + >>> from __init__ import * #doctest: +ELLIPSIS + Ignoring... + >>> m = ExtensionModule('test_CTypePython') + >>> f = PyCFunction('func') + >>> f += PyCArgument('i', int, output_intent='return') + >>> f += PyCArgument('l', long, output_intent='return') + >>> f += PyCArgument('f', float, output_intent='return') + >>> f += PyCArgument('c', complex, output_intent='return') + >>> f += PyCArgument('s', str, output_intent='return') + >>> f += PyCArgument('u', unicode, output_intent='return') + >>> f += PyCArgument('t', tuple, output_intent='return') + >>> f += PyCArgument('lst', list, output_intent='return') + >>> f += PyCArgument('d', dict, output_intent='return') + >>> f += PyCArgument('set', set, output_intent='return') + >>> f += PyCArgument('o1', object, output_intent='return') + >>> f += PyCArgument('o2', object, output_intent='return') + >>> m += f + >>> b = m.build() #doctest: +ELLIPSIS + exec_command... + >>> b.func(23, 23l, 1.2, 1+2j, 'hello', u'hei', (2,'a'), [-2], {3:4}, set([1,2]), 2, '15') + (23, 23L, 1.2, (1+2j), 'hello', u'hei', (2, 'a'), [-2], {3: 4}, set([1, 2]), 2, '15') + + #>>> print b.func.__doc__ + + """ + @property + def provides(self): + return self.typeobj_name + def initialize(self, typeobj): + if isinstance(typeobj, type): + self.typeobj_name = typeobj.__name__ + elif isinstance(typeobj, str): + self.typeobj_name = typeobj + else: + raise ValueError('%s: unexpected input type %r' \ + % (self.__class__.__name__, type(typeobj))) + self.ctypeobj = dict(int='PyInt_Type', + long='PyLong_Type', + float='PyFloat_Type', + complex='PyComplex_Type', + str='PyString_Type', + unicode='PyUnicode_Type', + buffer='PyBuffer_Type', + tuple='PyTuple_Type', + list='PyList_Type', + dict='PyDict_Type', + file='PyFile_Type', + instance='PyInstance_Type', + function='PyFunction_Type', + method='PyMethod_Type', + module='PyModule_Type', + iter='PySeqIter_Type', + property='PyProperty_Type', + slice='PySlice_Type', + cell='PyCell_Type', + generator='PyGen_Type', + set='PySet_Type', + frozenset='PyFrozenSet_Type', + type='PyType_Type', + ).get(self.typeobj_name) + pyctypes = dict(int='PyIntObject', + long='PyLongObject', + float='PyFloatObject', + complex='PyComplexObject', + str='PyStringObject', + unicode='PyUnicodeObject', + buffer='PyBufferObject', + tuple='PyTupleObject', + list='PyListObject', + dict='PyDictObject', + file='PyFileObject', + instance='PyObject', + function='PyFunctionObject', + method='PyObject', + module='PyObject', + iter='PyObject', + property='PyObject', + slice='PyObject', + cobject='PyCObject', # XXX: check key + cell='PyCellObject', + type='PyTypeObject', + generator='PyGenObject', + set='PySetObject', + frozenset='PySetObject', + object='PyObject', + ) + try: + self.name = pyctypes[self.typeobj_name] + '*' + except KeyError: + raise NotImplementedError('%s: need %s support' % (self.__class__.__name__, typeobj)) + return self + + def set_titles(self, arg): + if self.typeobj_name == 'object': + tn = 'a python ' + self.typeobj_name + 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 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_pyarg_fmt(self, arg): + return dict(object='O', str='S', unicode='U', cobject='O' + ).get(self.typeobj_name, 'O!') # XXX: check cobject + + def get_pyarg_obj(self, arg): + if self.typeobj_name in ['object', 'str', 'unicode', 'cobject']: # XXX: check cobject + return '&' + arg.pycvar + return '&%s, &%s' % (self.ctypeobj, arg.pycvar) + def get_pyret_fmt(self, arg): if arg.input_intent=='hide': return 'O' - return 'N' + # return 'N' if arg is constructed inside PyCFunction + return 'O' def get_pyret_obj(self, arg): return arg.pycvar + class CInt(CType): name = provides = 'int' def initialize(self): return self @@ -244,7 +367,6 @@ def register(): Component.register( - PyObjectPtr(), CInt(), ) Modified: trunk/numpy/f2py/lib/extgen/doc.txt =================================================================== --- trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-05 21:13:49 UTC (rev 3947) +++ trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-06 09:51:47 UTC (rev 3948) @@ -286,7 +286,10 @@ - `CDecl(, *names)` --- represents `ctype name1, name2, ..;` declaration. Use `.add()` method to add more names. + -`CTypePython()` + --- represents python type object in C. + Predefined components ===================== @@ -301,5 +304,3 @@ module. - `'int'` - C `int` type support - -- `'PyObject*'` - `PyObject*` type support \ No newline at end of file Modified: trunk/numpy/f2py/lib/extgen/pyc_argument.py =================================================================== --- trunk/numpy/f2py/lib/extgen/pyc_argument.py 2007-08-05 21:13:49 UTC (rev 3947) +++ trunk/numpy/f2py/lib/extgen/pyc_argument.py 2007-08-06 09:51:47 UTC (rev 3948) @@ -37,9 +37,12 @@ self.pycvar = name + '_pyc' if ctype is None: - ctype = Component.get('PyObject*') + ctype = Component.CTypePython(object) + else: + ctype = Component.CType(ctype) self.ctype = ctype ctype.set_pyarg_decl(self) + ctype.set_titles(self) #self.add(ctype) return self @@ -48,34 +51,7 @@ evaluate = self.evaluate ctype = self.ctype - # get containers - ReqArgs = self.container_ReqArgs - OptArgs = self.container_OptArgs - ExtArgs = self.container_ExtArgs - RetArgs = self.container_RetArgs - - ReqArgsDoc = self.container_ReqArgsDoc - OptArgsDoc = self.container_OptArgsDoc - ExtArgsDoc = self.container_ExtArgsDoc - - ReqKWList = self.container_ReqKWList - OptKWList = self.container_OptKWList - ExtKWList = self.container_ExtKWList - - ReqPyArgFmt = self.container_ReqPyArgFmt - OptPyArgFmt = self.container_OptPyArgFmt - ExtPyArgFmt = self.container_ExtPyArgFmt - - ReqPyArgObj = self.container_ReqPyArgObj - OptPyArgObj = self.container_OptPyArgObj - ExtPyArgObj = self.container_ExtPyArgObj - - RetDoc = self.container_RetDoc - RetFmt = self.container_RetFmt - RetObj = self.container_RetObj - # update PyCFunction containers - 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: @@ -88,37 +64,37 @@ output_doc_descr = None if self.input_intent=='required': - 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 + self.container_ReqArgs += self.name + self.container_ReqKWList += '"' + self.name + '"' + self.container_ReqPyArgFmt += ctype.get_pyarg_fmt(self) + self.container_ReqPyArgObj += ctype.get_pyarg_obj(self) + self.container_ReqArgsDoc += input_doc_title + self.container_ReqArgsDoc += input_doc_descr elif self.input_intent=='optional': - 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 + self.container_OptArgs += self.name + self.container_OptKWList += '"' + self.name + '"' + self.container_OptPyArgFmt += ctype.get_pyarg_fmt(self) + self.container_OptPyArgObj += ctype.get_pyarg_obj(self) + self.container_OptArgsDoc += input_doc_title + self.container_OptArgsDoc += input_doc_descr elif self.input_intent=='extra': - 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 + self.container_ExtArgs += self.name + self.container_ExtKWList += '"' + self.name + '"' + self.container_ExtPyArgFmt += ctype.get_pyarg_fmt(self) + self.container_ExtPyArgObj += ctype.get_pyarg_obj(self) + self.container_ExtArgsDoc += input_doc_title + self.container_ExtArgsDoc += input_doc_descr elif self.input_intent=='hide': pass else: raise NotImplementedError('input_intent=%r' % (self.input_intent)) if self.output_intent=='return': - RetArgs += self.name - RetFmt += ctype.get_pyret_fmt(self) - RetObj += ctype.get_pyret_obj(self) - RetDoc += output_doc_title - RetDoc += output_doc_descr + self.container_RetArgs += self.name + self.container_RetFmt += ctype.get_pyret_fmt(self) + self.container_RetObj += ctype.get_pyret_obj(self) + self.container_RetDoc += output_doc_title + self.container_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 21:13:49 UTC (rev 3947) +++ trunk/numpy/f2py/lib/extgen/pyc_function.py 2007-08-06 09:51:47 UTC (rev 3948) @@ -11,7 +11,7 @@ >>> f = PyCFunction('hello', title='A function.', description='\\nFirst line.\\n2nd line.') >>> a1_in_doc = '''First line.\\nSecond line.''' >>> a1_out_doc = '''Single line.''' - >>> f += PyCArgument('a1',output_intent='return', input_title='a Python object', + >>> f += PyCArgument('a1',output_intent='return', input_title='anything', ... input_description=a1_in_doc, output_description=a1_out_doc) >>> f += PyCArgument('c1',input_intent='extra') >>> f += PyCArgument('b1',input_intent='optional') @@ -28,23 +28,23 @@ A function. Required arguments: - a1 - a Python object + a1 - a python object, anything First line. Second line. - a2 - None + a2 - a python object Optional arguments: - b1 - None - b2 - None + b1 - a python object + b2 - a python object Extra optional arguments: - c1 - None - c2 - None + c1 - a python object + c2 - a python object Return values: - a1 - None + a1 - a python object Single line. - d2 - None + d2 - a python object Description: From numpy-svn at scipy.org Mon Aug 6 08:43:16 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Mon, 6 Aug 2007 07:43:16 -0500 (CDT) Subject: [Numpy-svn] r3949 - in trunk/numpy/lib: . tests Message-ID: <20070806124316.956C939C014@new.scipy.org> Author: stefan Date: 2007-08-06 07:42:58 -0500 (Mon, 06 Aug 2007) New Revision: 3949 Modified: trunk/numpy/lib/polynomial.py trunk/numpy/lib/tests/test_polynomial.py Log: Fix string conversion of polynomial when leading coefficients are zero. Closes ticket #564. Modified: trunk/numpy/lib/polynomial.py =================================================================== --- trunk/numpy/lib/polynomial.py 2007-08-06 09:51:47 UTC (rev 3948) +++ trunk/numpy/lib/polynomial.py 2007-08-06 12:42:58 UTC (rev 3949) @@ -500,11 +500,15 @@ return self.order def __str__(self): - N = self.order thestr = "0" var = self.variable - for k in range(len(self.coeffs)): - coefstr ='%.4g' % abs(self.coeffs[k]) + + # Remove leading zeros + coeffs = self.coeffs[NX.logical_or.accumulate(self.coeffs != 0)] + N = len(coeffs)-1 + + for k in range(len(coeffs)): + coefstr ='%.4g' % abs(coeffs[k]) if coefstr[-4:] == '0000': coefstr = coefstr[:-5] power = (N-k) @@ -533,11 +537,11 @@ if k > 0: if newstr != '': - if self.coeffs[k] < 0: + if coeffs[k] < 0: thestr = "%s - %s" % (thestr, newstr) else: thestr = "%s + %s" % (thestr, newstr) - elif (k == 0) and (newstr != '') and (self.coeffs[k] < 0): + elif (k == 0) and (newstr != '') and (coeffs[k] < 0): thestr = "-%s" % (newstr,) else: thestr = newstr Modified: trunk/numpy/lib/tests/test_polynomial.py =================================================================== --- trunk/numpy/lib/tests/test_polynomial.py 2007-08-06 09:51:47 UTC (rev 3948) +++ trunk/numpy/lib/tests/test_polynomial.py 2007-08-06 12:42:58 UTC (rev 3949) @@ -82,5 +82,17 @@ def check_roots(self): assert_array_equal(N.roots([1,0,0]), [0,0]) + def check_str_leading_zeros(self): + p = N.poly1d([4,3,2,1]) + p[3] = 0 + assert_equal(str(p), + " 2\n" + "3 x + 2 x + 1") + + p = N.poly1d([1,2]) + p[0] = 0 + p[1] = 0 + assert_equal(str(p), " \n0") + if __name__ == "__main__": NumpyTest().run() From numpy-svn at scipy.org Mon Aug 6 09:07:18 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Mon, 6 Aug 2007 08:07:18 -0500 (CDT) Subject: [Numpy-svn] r3950 - trunk/numpy/f2py/lib/extgen Message-ID: <20070806130718.5597D39C018@new.scipy.org> Author: pearu Date: 2007-08-06 08:07:03 -0500 (Mon, 06 Aug 2007) New Revision: 3950 Modified: trunk/numpy/f2py/lib/extgen/base.py trunk/numpy/f2py/lib/extgen/c_type.py trunk/numpy/f2py/lib/extgen/doc.txt Log: Added numpy array and scalar support to PyCTypePython. Modified: trunk/numpy/f2py/lib/extgen/base.py =================================================================== --- trunk/numpy/f2py/lib/extgen/base.py 2007-08-06 12:42:58 UTC (rev 3949) +++ trunk/numpy/f2py/lib/extgen/base.py 2007-08-06 13:07:03 UTC (rev 3950) @@ -54,6 +54,9 @@ # map(self.add, components) return self + def __repr__(self): + return '%s(%s)' % (self.__class__.__name__, ', '.join([repr(c) for (c,l) in self.components])) + @property def provides(self): """ @@ -72,9 +75,6 @@ def info(message): print >> sys.stderr, message - def __repr__(self): - return '%s(%s)' % (self.__class__.__name__, `self.containers`) - def __getattr__(self, attr): if attr.startswith('container_'): # convenience feature return self.get_container(attr[10:]) Modified: trunk/numpy/f2py/lib/extgen/c_type.py =================================================================== --- trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-06 12:42:58 UTC (rev 3949) +++ trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-06 13:07:03 UTC (rev 3950) @@ -24,6 +24,9 @@ self.name = name map(self.add, components) return self + + def __repr__(self): + return '%s(%s)' % (self.__class__.__name__, ', '.join([repr(self.name)]+[repr(c) for (c,l) in self.components])) def update_containers(self): self.container_TypeDef += self.evaluate(self.template_typedef) @@ -31,19 +34,28 @@ def __str__(self): return self.name - def get_pyret_fmt(self, input_intent_hide = True): - if input_intent_hide: return 'O' - return 'N' + def set_pyarg_decl(self, arg): + if arg.input_intent=='return': + arg += CDecl(self, '%s = Py_None' % (arg.pycvar)) + else: + arg += CDecl(self, '%s = NULL' % (arg.pycvar)) + + def get_pyarg_fmt(self, arg): + if arg.input_intent=='hide': return None + return 'O' - def get_pyret_arg(self, cname): - return cname - - def get_pyarg_fmt(self): + def get_pyarg_obj(self, arg): + if arg.input_intent=='hide': return None + return '&' + arg.pycvar + + def get_pyret_fmt(self, arg): + if arg.output_intent=='hide': return None return 'O' + + def get_pyret_obj(self, arg): + if arg.output_intent=='hide': return None + return arg.pycvar - def get_pyarg_arg(self, cname): - return '&%s' % (cname) - class _CatchTypeDef(Component): # for doctest template = '%(TypeDef)s' default_container_label = '' @@ -68,7 +80,7 @@ def initialize(self, name): if isinstance(name, CTypeBase): return name - if isinstance(name, type) or name in ['cell', 'generator', 'cobject']: + if isinstance(name, type) or name in ['cell', 'generator', 'cobject', 'instance']: return CTypePython(name) try: return Component.get(name) @@ -79,6 +91,11 @@ def update_containers(self): pass + def set_pyarg_decl(self, arg): + pass + def set_titles(self, arg): + pass + class CTypeAlias(CTypeBase): """ CTypeAlias(, ) @@ -247,81 +264,201 @@ >>> b.func(23, 23l, 1.2, 1+2j, 'hello', u'hei', (2,'a'), [-2], {3:4}, set([1,2]), 2, '15') (23, 23L, 1.2, (1+2j), 'hello', u'hei', (2, 'a'), [-2], {3: 4}, set([1, 2]), 2, '15') - #>>> print b.func.__doc__ + >>> print b.func.__doc__ + func(i, l, f, c, s, u, t, lst, d, set, o1, o2) -> (i, l, f, c, s, u, t, lst, d, set, o1, o2) + + Required arguments: + i - a python int object + l - a python long object + f - a python float object + c - a python complex object + s - a python str object + u - a python unicode object + t - a python tuple object + lst - a python list object + d - a python dict object + set - a python set object + o1 - a python object + o2 - a python object + + Return values: + i - a python int object + l - a python long object + f - a python float object + c - a python complex object + s - a python str object + u - a python unicode object + t - a python tuple object + lst - a python list object + d - a python dict object + set - a python set object + o1 - a python object + o2 - a python object + + >>> import numpy + >>> m = ExtensionModule('test_CTypePython_numpy') + >>> f = PyCFunction('func_int') + >>> f += PyCArgument('i1', numpy.int8, output_intent='return') + >>> f += PyCArgument('i2', numpy.int16, output_intent='return') + >>> f += PyCArgument('i3', numpy.int32, output_intent='return') + >>> f += PyCArgument('i4', numpy.int64, output_intent='return') + >>> m += f + >>> f = PyCFunction('func_uint') + >>> f += PyCArgument('i1', numpy.uint8, output_intent='return') + >>> f += PyCArgument('i2', numpy.uint16, output_intent='return') + >>> f += PyCArgument('i3', numpy.uint32, output_intent='return') + >>> f += PyCArgument('i4', numpy.uint64, output_intent='return') + >>> m += f + >>> f = PyCFunction('func_float') + >>> f += PyCArgument('f1', numpy.float32, output_intent='return') + >>> f += PyCArgument('f2', numpy.float64, output_intent='return') + >>> f += PyCArgument('f3', numpy.float128, output_intent='return') + >>> m += f + >>> f = PyCFunction('func_complex') + >>> f += PyCArgument('c1', numpy.complex64, output_intent='return') + >>> f += PyCArgument('c2', numpy.complex128, output_intent='return') + >>> f += PyCArgument('c3', numpy.complex256, output_intent='return') + >>> m += f + >>> f = PyCFunction('func_array') + >>> f += PyCArgument('a1', numpy.ndarray, output_intent='return') + >>> m += f + >>> #f = PyCFunction('func_c_int') + >>> #f += PyCArgument('i1', 'c_int', output_intent='return') + >>> #m += f + >>> b = m.build() #doctest: +ELLIPSIS + exec_command... + >>> b.func_int(numpy.int8(-2), numpy.int16(-3), numpy.int32(-4), numpy.int64(-5)) + (-2, -3, -4, -5) + >>> b.func_uint(numpy.uint8(-1), numpy.uint16(-1), numpy.uint32(-1), numpy.uint64(-1)) + (255, 65535, 4294967295, 18446744073709551615) + >>> b.func_float(numpy.float32(1.2),numpy.float64(1.2),numpy.float128(1.2)) + (1.20000004768, 1.2, 1.19999999999999995559) + >>> b.func_complex(numpy.complex64(1+2j),numpy.complex128(1+2j),numpy.complex256(1+2j)) + ((1+2j), (1+2j), (1.0+2.0j)) + >>> b.func_array(numpy.array([1,2])) + array([1, 2]) + >>> b.func_array(numpy.array(2)) + array(2) + >>> b.func_array(2) + Traceback (most recent call last): + ... + TypeError: argument 1 must be numpy.ndarray, not int + >>> b.func_array(numpy.int8(2)) + Traceback (most recent call last): + ... + TypeError: argument 1 must be numpy.ndarray, not numpy.int8 + >>> #b.func_c_int(2) + """ + + typeinfo_map = dict( + # : (, , ) + int = ('PyInt_Type', 'PyIntObject*', 'O!'), + long = ('PyLong_Type', 'PyLongObject*', 'O!'), + float = ('PyFloat_Type', 'PyFloatObject*', 'O!'), + complex = ('PyComplex_Type', 'PyComplexObject*', 'O!'), + str = ('PyString_Type', 'PyStringObject*', 'S'), + unicode = ('PyUnicode_Type', 'PyUnicodeObject*', 'U'), + buffer = ('PyBuffer_Type', 'PyBufferObject*', 'O!'), + tuple = ('PyTuple_Type', 'PyTupleObject*', 'O!'), + list = ('PyList_Type', 'PyListObject*', 'O!'), + dict = ('PyDict_Type', 'PyDictObject*', 'O!'), + file = ('PyFile_Type', 'PyFileObject*', 'O!'), + instance = ('PyInstance_Type', 'PyObject*', 'O!'), + function = ('PyFunction_Type', 'PyFunctionObject*', 'O!'), + method = ('PyMethod_Type', 'PyObject*', 'O!'), + module = ('PyModule_Type', 'PyObject*', 'O!'), + iter = ('PySeqIter_Type', 'PyObject*', 'O!'), + property = ('PyProperty_Type', 'PyObject*', 'O!'), + slice = ('PySlice_Type', 'PyObject*', 'O!'), + cell = ('PyCell_Type', 'PyCellObject*', 'O!'), + generator = ('PyGen_Type', 'PyGenObject*', 'O!'), + set = ('PySet_Type', 'PySetObject*', 'O!'), + frozenset = ('PyFrozenSet_Type', 'PySetObject*', 'O!'), + cobject = (None, 'PyCObject*', 'O'), + type = ('PyType_Type', 'PyTypeObject*', 'O!'), + object = (None, 'PyObject*', 'O'), + numpy_ndarray = ('PyArray_Type', 'PyArrayObject*', 'O!'), + numpy_descr = ('PyArrayDescr_Type','PyArray_Descr', 'O!'), + numpy_ufunc = ('PyUFunc_Type', 'PyUFuncObject*', 'O!'), + numpy_iter = ('PyArrayIter_Type', 'PyArrayIterObject*', 'O!'), + numpy_multiiter = ('PyArrayMultiIter_Type', 'PyArrayMultiIterObject*', 'O!'), + numpy_int8 = ('PyInt8ArrType_Type', 'PyInt8ScalarObject*', 'O!'), + numpy_int16 = ('PyInt16ArrType_Type', 'PyInt16ScalarObject*', 'O!'), + numpy_int32 = ('PyInt32ArrType_Type', 'PyInt32ScalarObject*', 'O!'), + numpy_int64 = ('PyInt64ArrType_Type', 'PyInt64ScalarObject*', 'O!'), + numpy_int128 = ('PyInt128ArrType_Type', 'PyInt128ScalarObject*', 'O!'), + numpy_uint8 = ('PyUInt8ArrType_Type', 'PyUInt8ScalarObject*', 'O!'), + numpy_uint16 = ('PyUInt16ArrType_Type', 'PyUInt16ScalarObject*', 'O!'), + numpy_uint32 = ('PyUInt32ArrType_Type', 'PyUInt32ScalarObject*', 'O!'), + numpy_uint64 = ('PyUInt64ArrType_Type', 'PyUInt64ScalarObject*', 'O!'), + numpy_uint128 = ('PyUInt128ArrType_Type', 'PyUInt128ScalarObject*', 'O!'), + numpy_float16 = ('PyFloat16ArrType_Type', 'PyFloat16ScalarObject*', 'O!'), + numpy_float32 = ('PyFloat32ArrType_Type', 'PyFloat32ScalarObject*', 'O!'), + numpy_float64 = ('PyFloat64ArrType_Type', 'PyFloat64ScalarObject*', 'O!'), + numpy_float80 = ('PyFloat80ArrType_Type', 'PyFloat80ScalarObject*', 'O!'), + numpy_float96 = ('PyFloat96ArrType_Type', 'PyFloat96ScalarObject*', 'O!'), + numpy_float128 = ('PyFloat128ArrType_Type', 'PyFloat128ScalarObject*', 'O!'), + numpy_complex32 = ('PyComplex32ArrType_Type', 'PyComplex32ScalarObject*', 'O!'), + numpy_complex64 = ('PyComplex64ArrType_Type', 'PyComplex64ScalarObject*', 'O!'), + numpy_complex128 = ('PyComplex128ArrType_Type', 'PyComplex128ScalarObject*', 'O!'), + numpy_complex160 = ('PyComplex160ArrType_Type', 'PyComplex160ScalarObject*', 'O!'), + numpy_complex192 = ('PyComplex192ArrType_Type', 'PyComplex192ScalarObject*', 'O!'), + numpy_complex256 = ('PyComplex256ArrType_Type', 'PyComplex256ScalarObject*', 'O!'), + numeric_array = ('PyArray_Type', 'PyArrayObject*', 'O!'), + c_int = (None, 'int', 'i') + ) - """ - @property - def provides(self): - return self.typeobj_name def initialize(self, typeobj): + m = self.typeinfo_map + + key = None if isinstance(typeobj, type): - self.typeobj_name = typeobj.__name__ + 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): - self.typeobj_name = typeobj - else: - raise ValueError('%s: unexpected input type %r' \ - % (self.__class__.__name__, type(typeobj))) - self.ctypeobj = dict(int='PyInt_Type', - long='PyLong_Type', - float='PyFloat_Type', - complex='PyComplex_Type', - str='PyString_Type', - unicode='PyUnicode_Type', - buffer='PyBuffer_Type', - tuple='PyTuple_Type', - list='PyList_Type', - dict='PyDict_Type', - file='PyFile_Type', - instance='PyInstance_Type', - function='PyFunction_Type', - method='PyMethod_Type', - module='PyModule_Type', - iter='PySeqIter_Type', - property='PyProperty_Type', - slice='PySlice_Type', - cell='PyCell_Type', - generator='PyGen_Type', - set='PySet_Type', - frozenset='PyFrozenSet_Type', - type='PyType_Type', - ).get(self.typeobj_name) - pyctypes = dict(int='PyIntObject', - long='PyLongObject', - float='PyFloatObject', - complex='PyComplexObject', - str='PyStringObject', - unicode='PyUnicodeObject', - buffer='PyBufferObject', - tuple='PyTupleObject', - list='PyListObject', - dict='PyDictObject', - file='PyFileObject', - instance='PyObject', - function='PyFunctionObject', - method='PyObject', - module='PyObject', - iter='PyObject', - property='PyObject', - slice='PyObject', - cobject='PyCObject', # XXX: check key - cell='PyCellObject', - type='PyTypeObject', - generator='PyGenObject', - set='PySetObject', - frozenset='PySetObject', - object='PyObject', - ) - try: - self.name = pyctypes[self.typeobj_name] + '*' + 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.name = item[1] + self.pyarg_fmt = item[2] + + 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 set_titles(self, arg): if self.typeobj_name == 'object': tn = 'a python ' + self.typeobj_name else: - tn = 'a python ' + self.typeobj_name + ' object' + if self.typeobj_name.startswith('numpy_'): + tn = 'a numpy.' + self.typeobj_name[6:] + ' object' + else: + tn = 'a python ' + self.typeobj_name + ' object' if arg.input_intent!='hide': r = '' if arg.input_title: r = ', ' + arg.input_title @@ -338,22 +475,18 @@ arg += CDecl(self, '%s = NULL' % (arg.pycvar)) def get_pyarg_fmt(self, arg): - return dict(object='O', str='S', unicode='U', cobject='O' - ).get(self.typeobj_name, 'O!') # XXX: check cobject + if arg.input_intent=='hide': return None + return self.pyarg_fmt def get_pyarg_obj(self, arg): - if self.typeobj_name in ['object', 'str', 'unicode', 'cobject']: # XXX: check cobject - return '&' + arg.pycvar - return '&%s, &%s' % (self.ctypeobj, arg.pycvar) - - def get_pyret_fmt(self, arg): - if arg.input_intent=='hide': - return 'O' - # return 'N' if arg is constructed inside PyCFunction - return 'O' - def get_pyret_obj(self, arg): return arg.pycvar + if arg.input_intent=='hide': return None + if self.pyarg_fmt=='O!': + return '&%s, &%s' % (self.ctypeobj, arg.pycvar) + return '&' + arg.pycvar + + class CInt(CType): name = provides = 'int' def initialize(self): return self Modified: trunk/numpy/f2py/lib/extgen/doc.txt =================================================================== --- trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-06 12:42:58 UTC (rev 3949) +++ trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-06 13:07:03 UTC (rev 3950) @@ -266,7 +266,7 @@ - `CCode(*lines, provides=..)` --- represents any C code block or statement component. - - `CType()` --- represents a predefined or intrinsic C type + - `CType()` --- represents a predefined or intrinsic C type with a given name. - `CTypeAlias(, )` --- represents `typedef ctype name;` @@ -286,7 +286,7 @@ - `CDecl(, *names)` --- represents `ctype name1, name2, ..;` declaration. Use `.add()` method to add more names. - -`CTypePython()` + - `CTypePython()` --- represents python type object in C. From numpy-svn at scipy.org Tue Aug 7 05:03:56 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Tue, 7 Aug 2007 04:03:56 -0500 (CDT) Subject: [Numpy-svn] r3951 - trunk/numpy/f2py/lib/extgen Message-ID: <20070807090356.1535939C0D2@new.scipy.org> Author: pearu Date: 2007-08-07 04:03:40 -0500 (Tue, 07 Aug 2007) New Revision: 3951 Modified: trunk/numpy/f2py/lib/extgen/c_type.py trunk/numpy/f2py/lib/extgen/pyc_argument.py trunk/numpy/f2py/lib/extgen/pyc_function.py Log: extgen: added argument dependecies support, reviewed reference counting of input and output arguments. Modified: trunk/numpy/f2py/lib/extgen/c_type.py =================================================================== --- trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-06 13:07:03 UTC (rev 3950) +++ trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-07 09:03:40 UTC (rev 3951) @@ -34,12 +34,6 @@ def __str__(self): return self.name - def set_pyarg_decl(self, arg): - if arg.input_intent=='return': - arg += CDecl(self, '%s = Py_None' % (arg.pycvar)) - else: - arg += CDecl(self, '%s = NULL' % (arg.pycvar)) - def get_pyarg_fmt(self, arg): if arg.input_intent=='hide': return None return 'O' @@ -49,13 +43,83 @@ return '&' + arg.pycvar def get_pyret_fmt(self, arg): - if arg.output_intent=='hide': return None - return 'O' + if arg.output_intent=='return': + # set_converters ensures tha all return values a new references + return 'N' + return def get_pyret_obj(self, arg): - if arg.output_intent=='hide': return None - return arg.pycvar + if arg.output_intent=='return': + return arg.retpycvar + return + def set_Decl(self, arg): + if arg.input_intent!='hide': + arg += CDecl(self, '%s = NULL' % (arg.pycvar)) + + if arg.output_intent!='hide': + arg += CDecl(self, '%s = NULL' % (arg.retpycvar)) + + def set_converters(self, arg): + """ + Notes for user: + if arg is intent(optional, in, out) and not specified + as function argument then function may created but + it must then have *new reference* (ie use Py_INCREF + unless it is a new reference already). + """ + # this method is called from PyCFunction.update_containers(), + # note that self.parent is None put arg.parent is PyCFunction + # instance. + eval_a = arg.evaluate + FromPyObj = arg.container_FromPyObj + PyObjFrom = arg.container_PyObjFrom + if arg.output_intent=='return': + if arg.input_intent in ['optional', 'extra']: + FromPyObj += eval_a('''\ +if (!(%(pycvar)s==NULL)) { + /* make %(pycvar)r a new reference */ + %(retpycvar)s = %(pycvar)s; + Py_INCREF((PyObject*)%(retpycvar)s); +} +''') + PyObjFrom += eval_a('''\ +if (%(retpycvar)s==NULL) { + /* %(pycvar)r was not specified */ + if (%(pycvar)s==NULL) { + %(retpycvar)s = Py_None; + Py_INCREF((PyObject*)%(retpycvar)s); + } else { + %(retpycvar)s = %(pycvar)s; + /* %(pycvar)r must be a new reference or expect a core dump. */ + } +} elif (!(%(retpycvar)s == %(pycvar)s)) { + /* a new %(retpycvar)r was created, undoing %(pycvar)s new reference */ + Py_DECREF((PyObject*)%(pycvar)s); +} +''') + elif arg.input_intent=='hide': + PyObjFrom += eval_a('''\ +if (%(retpycvar)s==NULL) { + %(retpycvar)s = Py_None; + Py_INCREF((PyObject*)%(retpycvar)s); +} /* else %(retpycvar)r must be a new reference or expect a core dump. */ +''') + elif arg.input_intent=='required': + FromPyObj += eval_a('''\ +/* make %(pycvar)r a new reference */ +%(retpycvar)s = %(pycvar)s; +Py_INCREF((PyObject*)%(retpycvar)s); +''') + PyObjFrom += eval_a('''\ +if (!(%(retpycvar)s==%(pycvar)s)) { + /* a new %(retpycvar)r was created, undoing %(pycvar)r new reference */ + /* %(retpycvar)r must be a new reference or expect a core dump. */ + Py_DECREF((PyObject*)%(pycvar)s); +} +''') + return + class _CatchTypeDef(Component): # for doctest template = '%(TypeDef)s' default_container_label = '' @@ -405,7 +469,6 @@ numpy_complex192 = ('PyComplex192ArrType_Type', 'PyComplex192ScalarObject*', 'O!'), numpy_complex256 = ('PyComplex256ArrType_Type', 'PyComplex256ScalarObject*', 'O!'), numeric_array = ('PyArray_Type', 'PyArrayObject*', 'O!'), - c_int = (None, 'int', 'i') ) def initialize(self, typeobj): @@ -468,12 +531,6 @@ if arg.output_title: r = ', ' + arg.output_title arg.output_title = tn + r - 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): if arg.input_intent=='hide': return None return self.pyarg_fmt @@ -490,9 +547,6 @@ 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' Modified: trunk/numpy/f2py/lib/extgen/pyc_argument.py =================================================================== --- trunk/numpy/f2py/lib/extgen/pyc_argument.py 2007-08-06 13:07:03 UTC (rev 3950) +++ trunk/numpy/f2py/lib/extgen/pyc_argument.py 2007-08-07 09:03:40 UTC (rev 3951) @@ -10,7 +10,8 @@ input_title = None, output_title = None, input_description = None, - output_description = None + output_description = None, + depends = [] ) """ @@ -29,21 +30,37 @@ 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', []) if options: self.warning('%s unused options: %s\n' % (self.__class__.__name__, options)) map(self.add, components) + self.cvar = name - self.pycvar = name + '_pyc' + self.pycvar = None + self.retpycvar = None if ctype is None: ctype = Component.CTypePython(object) else: ctype = Component.CType(ctype) self.ctype = ctype - ctype.set_pyarg_decl(self) + + if isinstance(ctype, Component.CTypePython): + 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 + '_pyc' + self.retpycvar = name + '_pyc_r' + ctype.set_titles(self) - #self.add(ctype) + ctype.set_Decl(self) return self Modified: trunk/numpy/f2py/lib/extgen/pyc_function.py =================================================================== --- trunk/numpy/f2py/lib/extgen/pyc_function.py 2007-08-06 13:07:03 UTC (rev 3950) +++ trunk/numpy/f2py/lib/extgen/pyc_function.py 2007-08-07 09:03:40 UTC (rev 3951) @@ -19,7 +19,7 @@ >>> f += PyCArgument('a2',input_intent='required') >>> f += PyCArgument('c2',input_intent='extra') >>> f += PyCArgument('b2',input_intent='optional') - >>> m = ExtensionModule('foo', f) + >>> m = ExtensionModule('test_PyCFunction', f) >>> foo = m.build() #doctest: +ELLIPSIS exec_command... >>> print foo.hello.__doc__ @@ -175,32 +175,57 @@ def update_containers(self): evaluate = self.evaluate - # get containers - FuncTitle = self.container_FuncTitle - FuncDescr = self.container_FuncDescr - ReqArgs = self.container_ReqArgs - 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 - # update ExtensionModule containers: t = '{"%(name)s", (PyCFunction)%(pyc_name)s,\n METH_VARARGS | METH_KEYWORDS, %(pyc_name)s_doc}' - ModuleMethod.add(evaluate(t), self.name) + self.container_ModuleMethod.add(evaluate(t), self.name) # update local containers: - OptExtArgs += OptArgs + ExtArgs - OptExtPyArgFmt += OptPyArgFmt + ExtPyArgFmt - ModuleFuncDoc += evaluate('%(name)s(%(ReqArgs)s%(OptExtArgs)s) -> %(RetArgs)s') + self.container_OptExtArgs += self.container_OptArgs + self.container_ExtArgs + self.container_OptExtPyArgFmt += self.container_OptPyArgFmt + self.container_ExtPyArgFmt + self.container_ModuleFuncDoc += evaluate('%(name)s(%(ReqArgs)s%(OptExtArgs)s) -> %(RetArgs)s') if self.title is not None: - FuncTitle += self.title - ModuleFuncDoc += ' ' + self.title + self.container_FuncTitle += self.title + self.container_ModuleFuncDoc += ' ' + self.title if self.description is not None: - FuncDescr += self.description + self.container_FuncDescr += self.description + + # resolve dependencies + sorted_arguments = [] + sorted_names = [] + comp_map = {} + dep_map = {} + for (c,l) in self.components: + if not isinstance(c, Component.PyCArgument): + continue + d = [n for n in c.depends if n not in sorted_names] + if not d: + sorted_arguments.append((c,l)) + sorted_names.append(c.name) + else: + comp_map[c.name] = (c,l) + dep_map[c.name] = d + + while dep_map: + dep_map_copy = dep_map.copy() + for name, deps in dep_map.items(): + d = [n for n in deps if dep_map.has_key(n)] + if not d: + sorted_arguments.append(comp_map[name]) + del dep_map[name] + else: + dep_map[name] = d + if dep_map_copy==dep_map: + self.warnign('%s: detected cyclic dependencies in %r, incorrect behavior is expected.\n'\ + % (self.provides, dep_map)) + sorted_arguments += dep_map.values() + break + + for c, l in sorted_arguments: + old_parent = c.parent + c.parent = self + c.ctype.set_converters(c) + c.parent = old_parent + return From numpy-svn at scipy.org Tue Aug 7 06:32:17 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Tue, 7 Aug 2007 05:32:17 -0500 (CDT) Subject: [Numpy-svn] r3952 - trunk/numpy Message-ID: <20070807103217.6EF8139C037@new.scipy.org> Author: stefan Date: 2007-08-07 05:31:44 -0500 (Tue, 07 Aug 2007) New Revision: 3952 Modified: trunk/numpy/__init__.py Log: Make sure we import numpy's configuration. Closes ticket #565. Modified: trunk/numpy/__init__.py =================================================================== --- trunk/numpy/__init__.py 2007-08-07 09:03:40 UTC (rev 3951) +++ trunk/numpy/__init__.py 2007-08-07 10:31:44 UTC (rev 3952) @@ -17,7 +17,7 @@ """ try: - from __config__ import show as show_config + from numpy.__config__ import show as show_config except ImportError: show_config = None From numpy-svn at scipy.org Tue Aug 7 07:22:19 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Tue, 7 Aug 2007 06:22:19 -0500 (CDT) Subject: [Numpy-svn] r3953 - trunk/numpy/f2py/lib/extgen Message-ID: <20070807112219.77C5539C07C@new.scipy.org> Author: pearu Date: 2007-08-07 06:21:53 -0500 (Tue, 07 Aug 2007) New Revision: 3953 Modified: trunk/numpy/f2py/lib/extgen/c_type.py trunk/numpy/f2py/lib/extgen/doc.txt trunk/numpy/f2py/lib/extgen/pyc_argument.py trunk/numpy/f2py/lib/extgen/pyc_function.py Log: extgen: impl support to all scalar C types and strings that Python supports. Modified: trunk/numpy/f2py/lib/extgen/c_type.py =================================================================== --- trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-07 10:31:44 UTC (rev 3952) +++ trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-07 11:21:53 UTC (rev 3953) @@ -35,31 +35,34 @@ return self.name def get_pyarg_fmt(self, arg): - if arg.input_intent=='hide': return None - return 'O' + raise NotImplementedError('%s.get_pyarg_fmt()' % (self.__class__.__name__)) def get_pyarg_obj(self, arg): - if arg.input_intent=='hide': return None - return '&' + arg.pycvar + raise NotImplementedError('%s.get_pyarg_obj()' % (self.__class__.__name__)) def get_pyret_fmt(self, arg): - if arg.output_intent=='return': - # set_converters ensures tha all return values a new references - return 'N' - return + raise NotImplementedError('%s.get_pyret_fmt()' % (self.__class__.__name__)) def get_pyret_obj(self, arg): - if arg.output_intent=='return': - return arg.retpycvar + raise NotImplementedError('%s.get_pyret_obj()' % (self.__class__.__name__)) + + def get_init_value(self, arg): return def set_Decl(self, arg): - if arg.input_intent!='hide': - arg += CDecl(self, '%s = NULL' % (arg.pycvar)) + init_value = self.get_init_value(arg) + if init_value: + init = '= %s' % (init_value) + else: + init = '' + if arg.pycvar and arg.pycvar==arg.retpycvar: + arg += CDecl(self, '%s%s' % (arg.pycvar, init)) + else: + if arg.input_intent!='hide': + arg += CDecl(self, '%s%s' % (arg.pycvar, init)) + if arg.output_intent!='hide': + arg += CDecl(self, '%s%s' % (arg.retpycvar, init)) - if arg.output_intent!='hide': - arg += CDecl(self, '%s = NULL' % (arg.retpycvar)) - def set_converters(self, arg): """ Notes for user: @@ -74,16 +77,21 @@ eval_a = arg.evaluate FromPyObj = arg.container_FromPyObj PyObjFrom = arg.container_PyObjFrom + + argfmt = self.get_pyarg_fmt(arg) + retfmt = self.get_pyret_fmt(arg) + if arg.output_intent=='return': if arg.input_intent in ['optional', 'extra']: - FromPyObj += eval_a('''\ + if retfmt in 'SON': + FromPyObj += eval_a('''\ if (!(%(pycvar)s==NULL)) { /* make %(pycvar)r a new reference */ %(retpycvar)s = %(pycvar)s; Py_INCREF((PyObject*)%(retpycvar)s); } ''') - PyObjFrom += eval_a('''\ + PyObjFrom += eval_a('''\ if (%(retpycvar)s==NULL) { /* %(pycvar)r was not specified */ if (%(pycvar)s==NULL) { @@ -99,19 +107,21 @@ } ''') elif arg.input_intent=='hide': - PyObjFrom += eval_a('''\ + if retfmt in 'SON': + PyObjFrom += eval_a('''\ if (%(retpycvar)s==NULL) { %(retpycvar)s = Py_None; Py_INCREF((PyObject*)%(retpycvar)s); } /* else %(retpycvar)r must be a new reference or expect a core dump. */ ''') elif arg.input_intent=='required': - FromPyObj += eval_a('''\ + if retfmt in 'SON': + FromPyObj += eval_a('''\ /* make %(pycvar)r a new reference */ %(retpycvar)s = %(pycvar)s; Py_INCREF((PyObject*)%(retpycvar)s); ''') - PyObjFrom += eval_a('''\ + PyObjFrom += eval_a('''\ if (!(%(retpycvar)s==%(pycvar)s)) { /* a new %(retpycvar)r was created, undoing %(pycvar)r new reference */ /* %(retpycvar)r must be a new reference or expect a core dump. */ @@ -144,7 +154,7 @@ def initialize(self, name): if isinstance(name, CTypeBase): return name - if isinstance(name, type) or name in ['cell', 'generator', 'cobject', 'instance']: + if isinstance(name, type): return CTypePython(name) try: return Component.get(name) @@ -359,6 +369,47 @@ o1 - a python object o2 - a python object + >>> m = ExtensionModule('test_CTypePython_c') + >>> f = PyCFunction('func_c_int') + >>> f += PyCArgument('i1', 'c_char', output_intent='return') + >>> f += PyCArgument('i2', 'c_short', output_intent='return') + >>> f += PyCArgument('i3', 'c_int', output_intent='return') + >>> f += PyCArgument('i4', 'c_long', output_intent='return') + >>> f += PyCArgument('i5', 'c_long_long', output_intent='return') + >>> m += f + >>> f = PyCFunction('func_c_unsigned_int') + >>> f += PyCArgument('i1', 'c_unsigned_char', output_intent='return') + >>> f += PyCArgument('i2', 'c_unsigned_short', output_intent='return') + >>> f += PyCArgument('i3', 'c_unsigned_int', output_intent='return') + >>> f += PyCArgument('i4', 'c_unsigned_long', output_intent='return') + >>> f += PyCArgument('i5', 'c_unsigned_long_long', output_intent='return') + >>> m += f + >>> f = PyCFunction('func_c_float') + >>> f += PyCArgument('f1', 'c_float', output_intent='return') + >>> f += PyCArgument('f2', 'c_double', output_intent='return') + >>> m += f + >>> f = PyCFunction('func_c_complex') + >>> f += PyCArgument('c1', 'c_Py_complex', output_intent='return') + >>> m += f + >>> f = PyCFunction('func_c_string') + >>> f += PyCArgument('s1', 'c_const_char_ptr', output_intent='return') + >>> f += PyCArgument('s2', 'c_const_char_ptr', output_intent='return') + >>> f += PyCArgument('s3', 'c_Py_UNICODE', output_intent='return') + >>> f += PyCArgument('s4', 'c_char1', output_intent='return') + >>> m += f + >>> b = m.build() #doctest: +ELLIPSIS + exec_command... + >>> b.func_c_int(2,3,4,5,6) + (2, 3, 4, 5, 6L) + >>> b.func_c_unsigned_int(-1,-1,-1,-1,-1) + (255, 65535, 4294967295, 18446744073709551615L, 18446744073709551615L) + >>> b.func_c_float(1.2,1.2) + (1.2000000476837158, 1.2) + >>> b.func_c_complex(1+2j) + (1+2j) + >>> b.func_c_string('hei', None, u'tere', 'b') + ('hei', None, u'tere', 'b') + >>> import numpy >>> m = ExtensionModule('test_CTypePython_numpy') >>> f = PyCFunction('func_int') @@ -386,9 +437,6 @@ >>> f = PyCFunction('func_array') >>> f += PyCArgument('a1', numpy.ndarray, output_intent='return') >>> m += f - >>> #f = PyCFunction('func_c_int') - >>> #f += PyCArgument('i1', 'c_int', output_intent='return') - >>> #m += f >>> b = m.build() #doctest: +ELLIPSIS exec_command... >>> b.func_int(numpy.int8(-2), numpy.int16(-3), numpy.int32(-4), numpy.int64(-5)) @@ -411,64 +459,80 @@ Traceback (most recent call last): ... TypeError: argument 1 must be numpy.ndarray, not numpy.int8 - >>> #b.func_c_int(2) """ typeinfo_map = dict( - # : (, , ) - int = ('PyInt_Type', 'PyIntObject*', 'O!'), - long = ('PyLong_Type', 'PyLongObject*', 'O!'), - float = ('PyFloat_Type', 'PyFloatObject*', 'O!'), - complex = ('PyComplex_Type', 'PyComplexObject*', 'O!'), - str = ('PyString_Type', 'PyStringObject*', 'S'), - unicode = ('PyUnicode_Type', 'PyUnicodeObject*', 'U'), - buffer = ('PyBuffer_Type', 'PyBufferObject*', 'O!'), - tuple = ('PyTuple_Type', 'PyTupleObject*', 'O!'), - list = ('PyList_Type', 'PyListObject*', 'O!'), - dict = ('PyDict_Type', 'PyDictObject*', 'O!'), - file = ('PyFile_Type', 'PyFileObject*', 'O!'), - instance = ('PyInstance_Type', 'PyObject*', 'O!'), - function = ('PyFunction_Type', 'PyFunctionObject*', 'O!'), - method = ('PyMethod_Type', 'PyObject*', 'O!'), - module = ('PyModule_Type', 'PyObject*', 'O!'), - iter = ('PySeqIter_Type', 'PyObject*', 'O!'), - property = ('PyProperty_Type', 'PyObject*', 'O!'), - slice = ('PySlice_Type', 'PyObject*', 'O!'), - cell = ('PyCell_Type', 'PyCellObject*', 'O!'), - generator = ('PyGen_Type', 'PyGenObject*', 'O!'), - set = ('PySet_Type', 'PySetObject*', 'O!'), - frozenset = ('PyFrozenSet_Type', 'PySetObject*', 'O!'), - cobject = (None, 'PyCObject*', 'O'), - type = ('PyType_Type', 'PyTypeObject*', 'O!'), - object = (None, 'PyObject*', 'O'), - numpy_ndarray = ('PyArray_Type', 'PyArrayObject*', 'O!'), - numpy_descr = ('PyArrayDescr_Type','PyArray_Descr', 'O!'), - numpy_ufunc = ('PyUFunc_Type', 'PyUFuncObject*', 'O!'), - numpy_iter = ('PyArrayIter_Type', 'PyArrayIterObject*', 'O!'), - numpy_multiiter = ('PyArrayMultiIter_Type', 'PyArrayMultiIterObject*', 'O!'), - numpy_int8 = ('PyInt8ArrType_Type', 'PyInt8ScalarObject*', 'O!'), - numpy_int16 = ('PyInt16ArrType_Type', 'PyInt16ScalarObject*', 'O!'), - numpy_int32 = ('PyInt32ArrType_Type', 'PyInt32ScalarObject*', 'O!'), - numpy_int64 = ('PyInt64ArrType_Type', 'PyInt64ScalarObject*', 'O!'), - numpy_int128 = ('PyInt128ArrType_Type', 'PyInt128ScalarObject*', 'O!'), - numpy_uint8 = ('PyUInt8ArrType_Type', 'PyUInt8ScalarObject*', 'O!'), - numpy_uint16 = ('PyUInt16ArrType_Type', 'PyUInt16ScalarObject*', 'O!'), - numpy_uint32 = ('PyUInt32ArrType_Type', 'PyUInt32ScalarObject*', 'O!'), - numpy_uint64 = ('PyUInt64ArrType_Type', 'PyUInt64ScalarObject*', 'O!'), - numpy_uint128 = ('PyUInt128ArrType_Type', 'PyUInt128ScalarObject*', 'O!'), - numpy_float16 = ('PyFloat16ArrType_Type', 'PyFloat16ScalarObject*', 'O!'), - numpy_float32 = ('PyFloat32ArrType_Type', 'PyFloat32ScalarObject*', 'O!'), - numpy_float64 = ('PyFloat64ArrType_Type', 'PyFloat64ScalarObject*', 'O!'), - numpy_float80 = ('PyFloat80ArrType_Type', 'PyFloat80ScalarObject*', 'O!'), - numpy_float96 = ('PyFloat96ArrType_Type', 'PyFloat96ScalarObject*', 'O!'), - numpy_float128 = ('PyFloat128ArrType_Type', 'PyFloat128ScalarObject*', 'O!'), - numpy_complex32 = ('PyComplex32ArrType_Type', 'PyComplex32ScalarObject*', 'O!'), - numpy_complex64 = ('PyComplex64ArrType_Type', 'PyComplex64ScalarObject*', 'O!'), - numpy_complex128 = ('PyComplex128ArrType_Type', 'PyComplex128ScalarObject*', 'O!'), - numpy_complex160 = ('PyComplex160ArrType_Type', 'PyComplex160ScalarObject*', 'O!'), - numpy_complex192 = ('PyComplex192ArrType_Type', 'PyComplex192ScalarObject*', 'O!'), - numpy_complex256 = ('PyComplex256ArrType_Type', 'PyComplex256ScalarObject*', 'O!'), - numeric_array = ('PyArray_Type', 'PyArrayObject*', 'O!'), + # : (, , , RetFmt) + int = ('PyInt_Type', 'PyIntObject*', 'O!', 'N'), + long = ('PyLong_Type', 'PyLongObject*', 'O!', 'N'), + float = ('PyFloat_Type', 'PyFloatObject*', 'O!', 'N'), + complex = ('PyComplex_Type', 'PyComplexObject*', 'O!', 'N'), + str = ('PyString_Type', 'PyStringObject*', 'S', 'N'), + unicode = ('PyUnicode_Type', 'PyUnicodeObject*', 'U', 'N'), + buffer = ('PyBuffer_Type', 'PyBufferObject*', 'O!', 'N'), + tuple = ('PyTuple_Type', 'PyTupleObject*', 'O!', 'N'), + list = ('PyList_Type', 'PyListObject*', 'O!', 'N'), + dict = ('PyDict_Type', 'PyDictObject*', 'O!', 'N'), + file = ('PyFile_Type', 'PyFileObject*', 'O!', 'N'), + instance = ('PyInstance_Type', 'PyObject*', 'O!', 'N'), + function = ('PyFunction_Type', 'PyFunctionObject*', 'O!', 'N'), + method = ('PyMethod_Type', 'PyObject*', 'O!', 'N'), + module = ('PyModule_Type', 'PyObject*', 'O!', 'N'), + iter = ('PySeqIter_Type', 'PyObject*', 'O!', 'N'), + property = ('PyProperty_Type', 'PyObject*', 'O!', 'N'), + slice = ('PySlice_Type', 'PyObject*', 'O!', 'N'), + cell = ('PyCell_Type', 'PyCellObject*', 'O!', 'N'), + generator = ('PyGen_Type', 'PyGenObject*', 'O!', 'N'), + set = ('PySet_Type', 'PySetObject*', 'O!', 'N'), + frozenset = ('PyFrozenSet_Type', 'PySetObject*', 'O!', 'N'), + cobject = (None, 'PyCObject*', 'O', 'N'), + type = ('PyType_Type', 'PyTypeObject*', 'O!', 'N'), + object = (None, 'PyObject*', 'O', 'N'), + numpy_ndarray = ('PyArray_Type', 'PyArrayObject*', 'O!', 'N'), + numpy_descr = ('PyArrayDescr_Type','PyArray_Descr', 'O!', 'N'), + numpy_ufunc = ('PyUFunc_Type', 'PyUFuncObject*', 'O!', 'N'), + numpy_iter = ('PyArrayIter_Type', 'PyArrayIterObject*', 'O!', 'N'), + numpy_multiiter = ('PyArrayMultiIter_Type', 'PyArrayMultiIterObject*', 'O!', 'N'), + numpy_int8 = ('PyInt8ArrType_Type', 'PyInt8ScalarObject*', 'O!', 'N'), + numpy_int16 = ('PyInt16ArrType_Type', 'PyInt16ScalarObject*', 'O!', 'N'), + numpy_int32 = ('PyInt32ArrType_Type', 'PyInt32ScalarObject*', 'O!', 'N'), + numpy_int64 = ('PyInt64ArrType_Type', 'PyInt64ScalarObject*', 'O!', 'N'), + numpy_int128 = ('PyInt128ArrType_Type', 'PyInt128ScalarObject*', 'O!', 'N'), + numpy_uint8 = ('PyUInt8ArrType_Type', 'PyUInt8ScalarObject*', 'O!', 'N'), + numpy_uint16 = ('PyUInt16ArrType_Type', 'PyUInt16ScalarObject*', 'O!', 'N'), + numpy_uint32 = ('PyUInt32ArrType_Type', 'PyUInt32ScalarObject*', 'O!', 'N'), + numpy_uint64 = ('PyUInt64ArrType_Type', 'PyUInt64ScalarObject*', 'O!', 'N'), + numpy_uint128 = ('PyUInt128ArrType_Type', 'PyUInt128ScalarObject*', 'O!', 'N'), + numpy_float16 = ('PyFloat16ArrType_Type', 'PyFloat16ScalarObject*', 'O!', 'N'), + numpy_float32 = ('PyFloat32ArrType_Type', 'PyFloat32ScalarObject*', 'O!', 'N'), + numpy_float64 = ('PyFloat64ArrType_Type', 'PyFloat64ScalarObject*', 'O!', 'N'), + numpy_float80 = ('PyFloat80ArrType_Type', 'PyFloat80ScalarObject*', 'O!', 'N'), + numpy_float96 = ('PyFloat96ArrType_Type', 'PyFloat96ScalarObject*', 'O!', 'N'), + numpy_float128 = ('PyFloat128ArrType_Type', 'PyFloat128ScalarObject*', 'O!', 'N'), + numpy_complex32 = ('PyComplex32ArrType_Type', 'PyComplex32ScalarObject*', 'O!', 'N'), + numpy_complex64 = ('PyComplex64ArrType_Type', 'PyComplex64ScalarObject*', 'O!', 'N'), + numpy_complex128 = ('PyComplex128ArrType_Type', 'PyComplex128ScalarObject*', 'O!', 'N'), + numpy_complex160 = ('PyComplex160ArrType_Type', 'PyComplex160ScalarObject*', 'O!', 'N'), + numpy_complex192 = ('PyComplex192ArrType_Type', 'PyComplex192ScalarObject*', 'O!', 'N'), + numpy_complex256 = ('PyComplex256ArrType_Type', 'PyComplex256ScalarObject*', 'O!', 'N'), + numeric_array = ('PyArray_Type', 'PyArrayObject*', 'O!', 'N'), + c_char = (None, 'char', 'b', 'b'), + c_unsigned_char = (None, 'unsigned char', 'B', 'B'), + c_short = (None, 'short int', 'h', 'h'), + c_unsigned_short = (None, 'unsigned short int', 'H', 'H'), + c_int = (None,'int', 'i', 'i'), + c_unsigned_int = (None,'unsigned int', 'I', 'I'), + c_long = (None,'long', 'l', 'l'), + c_unsigned_long = (None,'unsigned long', 'k', 'k'), + c_long_long = (None,'PY_LONG_LONG', 'L', 'L'), + c_unsigned_long_long = (None,'unsigned PY_LONG_LONG', 'K', 'K'), + c_Py_ssize_t = (None,'Py_ssize_t', 'n', 'n'), + c_char1 = (None,'char', 'c', 'c'), + c_float = (None,'float', 'f', 'f'), + c_double = (None,'double', 'd', 'd'), + c_Py_complex = (None,'Py_complex', 'D', 'D'), + c_const_char_ptr = (None,'const char *', 'z', 'z'), + c_Py_UNICODE = (None,'Py_UNICODE*','u','u'), ) def initialize(self, typeobj): @@ -504,7 +568,8 @@ self.typeobj_name = key self.ctypeobj = item[0] self.name = item[1] - self.pyarg_fmt = item[2] + self.pyarg_fmt = item[2] + self.pyret_fmt = item[3] if key.startswith('numpy_'): self.add(Component.get('arrayobject.h'), 'Header') @@ -520,6 +585,11 @@ 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': @@ -541,20 +611,25 @@ 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.pyret_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): + retfmt = self.get_pyarg_fmt(arg) + if retfmt and retfmt in 'SON': + return 'NULL' + return dict(c_int='0').get(self.name) -class CInt(CType): - name = provides = 'int' - def initialize(self): return self - 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( - CInt(), ) def _test(): Modified: trunk/numpy/f2py/lib/extgen/doc.txt =================================================================== --- trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-07 10:31:44 UTC (rev 3952) +++ trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-07 11:21:53 UTC (rev 3953) @@ -22,7 +22,7 @@ >>> f = PyCFunction('hello') >>> f += 'printf("Hello!\\n");' >>> m += f - >>> print m.generate() # shows a string containing C source to extension module + >>> print m.generate() # shows a string containing C source to extension module, useful for debugging >>> foo = m.build() >>> foo.hello() Hello! @@ -286,8 +286,10 @@ - `CDecl(, *names)` --- represents `ctype name1, name2, ..;` declaration. Use `.add()` method to add more names. - - `CTypePython()` - --- represents python type object in C. + - `CTypePython()` + --- represents python type object in C, see + `CTypePython.typeinfo_map.keys()` for supported type names + (there are over 70 supported types). Predefined components @@ -303,4 +305,3 @@ - `'import_array'` - code for importing numpy package to extension module. -- `'int'` - C `int` type support Modified: trunk/numpy/f2py/lib/extgen/pyc_argument.py =================================================================== --- trunk/numpy/f2py/lib/extgen/pyc_argument.py 2007-08-07 10:31:44 UTC (rev 3952) +++ trunk/numpy/f2py/lib/extgen/pyc_argument.py 2007-08-07 11:21:53 UTC (rev 3953) @@ -41,20 +41,29 @@ self.retpycvar = None if ctype is None: - ctype = Component.CTypePython(object) + ctype = object + if isinstance(ctype, Component.CTypeBase): + pass + elif isinstance(ctype, type) or Component.CTypePython.typeinfo_map.has_key(ctype): + ctype = Component.CTypePython(ctype) else: ctype = Component.CType(ctype) self.ctype = ctype + retfmt = ctype.get_pyret_fmt(self) if isinstance(ctype, Component.CTypePython): - if self.output_intent == 'return': - if self.input_intent=='hide': - self.retpycvar = name - else: + 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 - self.retpycvar = name + '_return' - elif self.input_intent!='hide': + else: self.pycvar = name + self.retpycvar = name else: self.pycvar = name + '_pyc' self.retpycvar = name + '_pyc_r' @@ -83,22 +92,22 @@ if self.input_intent=='required': self.container_ReqArgs += self.name self.container_ReqKWList += '"' + self.name + '"' - self.container_ReqPyArgFmt += ctype.get_pyarg_fmt(self) - self.container_ReqPyArgObj += ctype.get_pyarg_obj(self) + self.container_ReqArgFmt += ctype.get_pyarg_fmt(self) + self.container_ReqArgObj += ctype.get_pyarg_obj(self) self.container_ReqArgsDoc += input_doc_title self.container_ReqArgsDoc += input_doc_descr elif self.input_intent=='optional': self.container_OptArgs += self.name self.container_OptKWList += '"' + self.name + '"' - self.container_OptPyArgFmt += ctype.get_pyarg_fmt(self) - self.container_OptPyArgObj += ctype.get_pyarg_obj(self) + self.container_OptArgFmt += ctype.get_pyarg_fmt(self) + self.container_OptArgObj += ctype.get_pyarg_obj(self) self.container_OptArgsDoc += input_doc_title self.container_OptArgsDoc += input_doc_descr elif self.input_intent=='extra': self.container_ExtArgs += self.name self.container_ExtKWList += '"' + self.name + '"' - self.container_ExtPyArgFmt += ctype.get_pyarg_fmt(self) - self.container_ExtPyArgObj += ctype.get_pyarg_obj(self) + self.container_ExtArgFmt += ctype.get_pyarg_fmt(self) + self.container_ExtArgObj += ctype.get_pyarg_obj(self) self.container_ExtArgsDoc += input_doc_title self.container_ExtArgsDoc += input_doc_descr elif self.input_intent=='hide': Modified: trunk/numpy/f2py/lib/extgen/pyc_function.py =================================================================== --- trunk/numpy/f2py/lib/extgen/pyc_function.py 2007-08-07 10:31:44 UTC (rev 3952) +++ trunk/numpy/f2py/lib/extgen/pyc_function.py 2007-08-07 11:21:53 UTC (rev 3953) @@ -96,14 +96,14 @@ OptKWList = dict(separator=', ', suffix=', ', skip_suffix_when_empty=True), ExtKWList = dict(separator=', ', suffix=', ', skip_suffix_when_empty=True), - ReqPyArgFmt = dict(separator=''), - OptPyArgFmt = dict(separator=''), - ExtPyArgFmt = dict(separator=''), - OptExtPyArgFmt = dict(separator='', prefix='|', skip_prefix_when_empty=True), + ReqArgFmt = dict(separator=''), + OptArgFmt = dict(separator=''), + ExtArgFmt = dict(separator=''), + OptExtArgFmt = 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), - ExtPyArgObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), + ReqArgObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), + OptArgObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), + ExtArgObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), FromPyObj = dict(default='', use_indent=True), Exec = dict(default='', use_indent=True), @@ -139,8 +139,8 @@ 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%(OptExtPyArgFmt)s", - capi_kwlist%(ReqPyArgObj)s%(OptPyArgObj)s%(ExtPyArgObj)s)) { + if (PyArg_ParseTupleAndKeywords(pyc_args, pyc_keywds,"%(ReqArgFmt)s%(OptExtArgFmt)s", + capi_kwlist%(ReqArgObj)s%(OptArgObj)s%(ExtArgObj)s)) { %(FromPyObj)s %(Exec)s capi_success = !PyErr_Occurred(); @@ -181,7 +181,7 @@ # update local containers: self.container_OptExtArgs += self.container_OptArgs + self.container_ExtArgs - self.container_OptExtPyArgFmt += self.container_OptPyArgFmt + self.container_ExtPyArgFmt + self.container_OptExtArgFmt += self.container_OptArgFmt + self.container_ExtArgFmt self.container_ModuleFuncDoc += evaluate('%(name)s(%(ReqArgs)s%(OptExtArgs)s) -> %(RetArgs)s') if self.title is not None: self.container_FuncTitle += self.title From numpy-svn at scipy.org Tue Aug 7 07:40:16 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Tue, 7 Aug 2007 06:40:16 -0500 (CDT) Subject: [Numpy-svn] r3954 - trunk/numpy/f2py/lib/extgen Message-ID: <20070807114016.3D6D439C07C@new.scipy.org> Author: pearu Date: 2007-08-07 06:39:58 -0500 (Tue, 07 Aug 2007) New Revision: 3954 Modified: trunk/numpy/f2py/lib/extgen/c_type.py Log: extgen: added initial values to C declarations. Modified: trunk/numpy/f2py/lib/extgen/c_type.py =================================================================== --- trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-07 11:21:53 UTC (rev 3953) +++ trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-07 11:39:58 UTC (rev 3954) @@ -52,7 +52,7 @@ def set_Decl(self, arg): init_value = self.get_init_value(arg) if init_value: - init = '= %s' % (init_value) + init = ' = %s' % (init_value) else: init = '' if arg.pycvar and arg.pycvar==arg.retpycvar: @@ -462,77 +462,77 @@ """ typeinfo_map = dict( - # : (, , , RetFmt) - int = ('PyInt_Type', 'PyIntObject*', 'O!', 'N'), - long = ('PyLong_Type', 'PyLongObject*', 'O!', 'N'), - float = ('PyFloat_Type', 'PyFloatObject*', 'O!', 'N'), - complex = ('PyComplex_Type', 'PyComplexObject*', 'O!', 'N'), - str = ('PyString_Type', 'PyStringObject*', 'S', 'N'), - unicode = ('PyUnicode_Type', 'PyUnicodeObject*', 'U', 'N'), - buffer = ('PyBuffer_Type', 'PyBufferObject*', 'O!', 'N'), - tuple = ('PyTuple_Type', 'PyTupleObject*', 'O!', 'N'), - list = ('PyList_Type', 'PyListObject*', 'O!', 'N'), - dict = ('PyDict_Type', 'PyDictObject*', 'O!', 'N'), - file = ('PyFile_Type', 'PyFileObject*', 'O!', 'N'), - instance = ('PyInstance_Type', 'PyObject*', 'O!', 'N'), - function = ('PyFunction_Type', 'PyFunctionObject*', 'O!', 'N'), - method = ('PyMethod_Type', 'PyObject*', 'O!', 'N'), - module = ('PyModule_Type', 'PyObject*', 'O!', 'N'), - iter = ('PySeqIter_Type', 'PyObject*', 'O!', 'N'), - property = ('PyProperty_Type', 'PyObject*', 'O!', 'N'), - slice = ('PySlice_Type', 'PyObject*', 'O!', 'N'), - cell = ('PyCell_Type', 'PyCellObject*', 'O!', 'N'), - generator = ('PyGen_Type', 'PyGenObject*', 'O!', 'N'), - set = ('PySet_Type', 'PySetObject*', 'O!', 'N'), - frozenset = ('PyFrozenSet_Type', 'PySetObject*', 'O!', 'N'), - cobject = (None, 'PyCObject*', 'O', 'N'), - type = ('PyType_Type', 'PyTypeObject*', 'O!', 'N'), - object = (None, 'PyObject*', 'O', 'N'), - numpy_ndarray = ('PyArray_Type', 'PyArrayObject*', 'O!', 'N'), - numpy_descr = ('PyArrayDescr_Type','PyArray_Descr', 'O!', 'N'), - numpy_ufunc = ('PyUFunc_Type', 'PyUFuncObject*', 'O!', 'N'), - numpy_iter = ('PyArrayIter_Type', 'PyArrayIterObject*', 'O!', 'N'), - numpy_multiiter = ('PyArrayMultiIter_Type', 'PyArrayMultiIterObject*', 'O!', 'N'), - numpy_int8 = ('PyInt8ArrType_Type', 'PyInt8ScalarObject*', 'O!', 'N'), - numpy_int16 = ('PyInt16ArrType_Type', 'PyInt16ScalarObject*', 'O!', 'N'), - numpy_int32 = ('PyInt32ArrType_Type', 'PyInt32ScalarObject*', 'O!', 'N'), - numpy_int64 = ('PyInt64ArrType_Type', 'PyInt64ScalarObject*', 'O!', 'N'), - numpy_int128 = ('PyInt128ArrType_Type', 'PyInt128ScalarObject*', 'O!', 'N'), - numpy_uint8 = ('PyUInt8ArrType_Type', 'PyUInt8ScalarObject*', 'O!', 'N'), - numpy_uint16 = ('PyUInt16ArrType_Type', 'PyUInt16ScalarObject*', 'O!', 'N'), - numpy_uint32 = ('PyUInt32ArrType_Type', 'PyUInt32ScalarObject*', 'O!', 'N'), - numpy_uint64 = ('PyUInt64ArrType_Type', 'PyUInt64ScalarObject*', 'O!', 'N'), - numpy_uint128 = ('PyUInt128ArrType_Type', 'PyUInt128ScalarObject*', 'O!', 'N'), - numpy_float16 = ('PyFloat16ArrType_Type', 'PyFloat16ScalarObject*', 'O!', 'N'), - numpy_float32 = ('PyFloat32ArrType_Type', 'PyFloat32ScalarObject*', 'O!', 'N'), - numpy_float64 = ('PyFloat64ArrType_Type', 'PyFloat64ScalarObject*', 'O!', 'N'), - numpy_float80 = ('PyFloat80ArrType_Type', 'PyFloat80ScalarObject*', 'O!', 'N'), - numpy_float96 = ('PyFloat96ArrType_Type', 'PyFloat96ScalarObject*', 'O!', 'N'), - numpy_float128 = ('PyFloat128ArrType_Type', 'PyFloat128ScalarObject*', 'O!', 'N'), - numpy_complex32 = ('PyComplex32ArrType_Type', 'PyComplex32ScalarObject*', 'O!', 'N'), - numpy_complex64 = ('PyComplex64ArrType_Type', 'PyComplex64ScalarObject*', 'O!', 'N'), - numpy_complex128 = ('PyComplex128ArrType_Type', 'PyComplex128ScalarObject*', 'O!', 'N'), - numpy_complex160 = ('PyComplex160ArrType_Type', 'PyComplex160ScalarObject*', 'O!', 'N'), - numpy_complex192 = ('PyComplex192ArrType_Type', 'PyComplex192ScalarObject*', 'O!', 'N'), - numpy_complex256 = ('PyComplex256ArrType_Type', 'PyComplex256ScalarObject*', 'O!', 'N'), - numeric_array = ('PyArray_Type', 'PyArrayObject*', 'O!', 'N'), - c_char = (None, 'char', 'b', 'b'), - c_unsigned_char = (None, 'unsigned char', 'B', 'B'), - c_short = (None, 'short int', 'h', 'h'), - c_unsigned_short = (None, 'unsigned short int', 'H', 'H'), - c_int = (None,'int', 'i', 'i'), - c_unsigned_int = (None,'unsigned int', 'I', 'I'), - c_long = (None,'long', 'l', 'l'), - c_unsigned_long = (None,'unsigned long', 'k', 'k'), - c_long_long = (None,'PY_LONG_LONG', 'L', 'L'), - c_unsigned_long_long = (None,'unsigned PY_LONG_LONG', 'K', 'K'), - c_Py_ssize_t = (None,'Py_ssize_t', 'n', 'n'), - c_char1 = (None,'char', 'c', 'c'), - c_float = (None,'float', 'f', 'f'), - c_double = (None,'double', 'd', 'd'), - c_Py_complex = (None,'Py_complex', 'D', 'D'), - c_const_char_ptr = (None,'const char *', 'z', 'z'), - c_Py_UNICODE = (None,'Py_UNICODE*','u','u'), + # : (, , , , ) + 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): @@ -570,7 +570,8 @@ self.name = item[1] self.pyarg_fmt = item[2] self.pyret_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') @@ -623,10 +624,7 @@ return def get_init_value(self, arg): - retfmt = self.get_pyarg_fmt(arg) - if retfmt and retfmt in 'SON': - return 'NULL' - return dict(c_int='0').get(self.name) + return self.cinit_value def register(): Component.register( From numpy-svn at scipy.org Wed Aug 8 18:31:54 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Wed, 8 Aug 2007 17:31:54 -0500 (CDT) Subject: [Numpy-svn] r3955 - trunk/numpy/distutils/command Message-ID: <20070808223154.9E83B39C0B0@new.scipy.org> Author: rkern Date: 2007-08-08 17:31:50 -0500 (Wed, 08 Aug 2007) New Revision: 3955 Modified: trunk/numpy/distutils/command/bdist_rpm.py trunk/numpy/distutils/command/sdist.py Log: Optionally use setuptools for commands that setuptools customizes. Modified: trunk/numpy/distutils/command/bdist_rpm.py =================================================================== --- trunk/numpy/distutils/command/bdist_rpm.py 2007-08-07 11:39:58 UTC (rev 3954) +++ trunk/numpy/distutils/command/bdist_rpm.py 2007-08-08 22:31:50 UTC (rev 3955) @@ -1,6 +1,9 @@ import os import sys -from distutils.command.bdist_rpm import bdist_rpm as old_bdist_rpm +if 'setuptools' in sys.modules: + from setuptools.command.bdist_rpm import bdist_rpm as old_bdist_rpm +else: + from distutils.command.bdist_rpm import bdist_rpm as old_bdist_rpm class bdist_rpm(old_bdist_rpm): Modified: trunk/numpy/distutils/command/sdist.py =================================================================== --- trunk/numpy/distutils/command/sdist.py 2007-08-07 11:39:58 UTC (rev 3954) +++ trunk/numpy/distutils/command/sdist.py 2007-08-08 22:31:50 UTC (rev 3955) @@ -1,4 +1,9 @@ -from distutils.command.sdist import sdist as old_sdist +import sys +if 'setuptools' in sys.modules: + from setuptools.command.sdist import sdist as old_sdist +else: + from distutils.command.sdist import sdist as old_sdist + from numpy.distutils.misc_util import get_data_files class sdist(old_sdist): From numpy-svn at scipy.org Thu Aug 9 06:04:23 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Thu, 9 Aug 2007 05:04:23 -0500 (CDT) Subject: [Numpy-svn] r3956 - trunk/numpy/distutils Message-ID: <20070809100423.5A8E139C290@new.scipy.org> Author: pearu Date: 2007-08-09 05:01:56 -0500 (Thu, 09 Aug 2007) New Revision: 3956 Modified: trunk/numpy/distutils/exec_command.py trunk/numpy/distutils/log.py Log: Fix an incorrect usage of log.set_verbosity(INFO) causing log always to be at DEBUG level, INFO is for set_threshold. Modified: trunk/numpy/distutils/exec_command.py =================================================================== --- trunk/numpy/distutils/exec_command.py 2007-08-08 22:31:50 UTC (rev 3955) +++ trunk/numpy/distutils/exec_command.py 2007-08-09 10:01:56 UTC (rev 3956) @@ -196,7 +196,7 @@ The following special keyword arguments can be used: use_shell - execute `sh -c command` use_tee - pipe the output of command through tee - execute_in - before command `cd execute_in` and after `cd -`. + execute_in - before run command `cd execute_in` and after `cd -`. On NT, DOS systems the returned status is correct for external commands. Wild cards will not work for non-posix systems or when use_shell=0. Modified: trunk/numpy/distutils/log.py =================================================================== --- trunk/numpy/distutils/log.py 2007-08-08 22:31:50 UTC (rev 3955) +++ trunk/numpy/distutils/log.py 2007-08-09 10:01:56 UTC (rev 3956) @@ -37,24 +37,28 @@ good = _global_log.good -def set_threshold(level): +def set_threshold(level, force=False): prev_level = _global_log.threshold - if prev_level > DEBUG: + if prev_level > DEBUG or force: # If we're running at DEBUG, don't change the threshold, as there's # likely a good reason why we're running at this level. _global_log.threshold = level + if level <= DEBUG: + info('set_threshold: setting thershold to DEBUG level, it can be changed only with force argument') + else: + info('set_threshold: not changing thershold from DEBUG level %s to %s' % (prev_level,level)) return prev_level -def set_verbosity(v): +def set_verbosity(v, force=False): prev_level = _global_log.threshold if v < 0: - set_threshold(ERROR) + set_threshold(ERROR, force) elif v == 0: - set_threshold(WARN) + set_threshold(WARN, force) elif v == 1: - set_threshold(INFO) + set_threshold(INFO, force) elif v >= 2: - set_threshold(DEBUG) + set_threshold(DEBUG, force) return {FATAL:-2,ERROR:-1,WARN:0,INFO:1,DEBUG:2}.get(prev_level,1) _global_color_map = { @@ -65,4 +69,5 @@ FATAL:red_text } -set_verbosity(INFO) +# don't use INFO,.. flags in set_verbosity, these flags are for set_threshold. +set_verbosity(0, force=True) From numpy-svn at scipy.org Fri Aug 10 02:01:38 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Fri, 10 Aug 2007 01:01:38 -0500 (CDT) Subject: [Numpy-svn] r3957 - branches Message-ID: <20070810060138.6FCF839C1E1@new.scipy.org> Author: jarrod.millman Date: 2007-08-10 01:01:19 -0500 (Fri, 10 Aug 2007) New Revision: 3957 Added: branches/1.0.3.x/ Log: branching from the 1.0.3 tag Copied: branches/1.0.3.x (from rev 3956, tags/1.0.3) From numpy-svn at scipy.org Fri Aug 10 02:08:03 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Fri, 10 Aug 2007 01:08:03 -0500 (CDT) Subject: [Numpy-svn] r3958 - branches/1.0.3.x/numpy Message-ID: <20070810060803.7CE0339C017@new.scipy.org> Author: jarrod.millman Date: 2007-08-10 01:07:55 -0500 (Fri, 10 Aug 2007) New Revision: 3958 Modified: branches/1.0.3.x/numpy/version.py Log: this is the development code for the 1.0.3.1 release Modified: branches/1.0.3.x/numpy/version.py =================================================================== --- branches/1.0.3.x/numpy/version.py 2007-08-10 06:01:19 UTC (rev 3957) +++ branches/1.0.3.x/numpy/version.py 2007-08-10 06:07:55 UTC (rev 3958) @@ -1,5 +1,5 @@ -version='1.0.3' -release=True +version='1.0.3.1' +release=False if not release: version += '.dev' From numpy-svn at scipy.org Fri Aug 10 03:57:15 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Fri, 10 Aug 2007 02:57:15 -0500 (CDT) Subject: [Numpy-svn] r3959 - branches/1.0.3.x/numpy/distutils Message-ID: <20070810075715.4915039C2B1@new.scipy.org> Author: jarrod.millman Date: 2007-08-10 02:57:02 -0500 (Fri, 10 Aug 2007) New Revision: 3959 Modified: branches/1.0.3.x/numpy/distutils/misc_util.py Log: adding back get_path, which is used by Lib/odr/setup.py in scipy 0.5.2 Modified: branches/1.0.3.x/numpy/distutils/misc_util.py =================================================================== --- branches/1.0.3.x/numpy/distutils/misc_util.py 2007-08-10 06:07:55 UTC (rev 3958) +++ branches/1.0.3.x/numpy/distutils/misc_util.py 2007-08-10 07:57:02 UTC (rev 3959) @@ -40,6 +40,31 @@ path = apath[len(pd)+1:] return path +def get_path(mod_name, parent_path=None): + """ Return path of the module. + + Returned path is relative to parent_path when given, + otherwise it is absolute path. + """ + if mod_name == '__builtin__': + #builtin if/then added by Pearu for use in core.run_setup. + d = os.path.dirname(os.path.abspath(sys.argv[0])) + else: + __import__(mod_name) + mod = sys.modules[mod_name] + if hasattr(mod,'__file__'): + filename = mod.__file__ + d = os.path.dirname(os.path.abspath(mod.__file__)) + else: + # we're probably running setup.py as execfile("setup.py") + # (likely we're building an egg) + d = os.path.abspath('.') + # hmm, should we use sys.argv[0] like in __builtin__ case? + + if parent_path is not None: + d = rel_path(d, parent_path) + return d or '.' + def get_path_from_frame(frame, parent_path=None): """ Return path of the module given a frame object from the call stack. From numpy-svn at scipy.org Fri Aug 10 04:19:22 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Fri, 10 Aug 2007 03:19:22 -0500 (CDT) Subject: [Numpy-svn] r3960 - branches/1.0.3.x/numpy/distutils Message-ID: <20070810081922.36AB339C2ED@new.scipy.org> Author: jarrod.millman Date: 2007-08-10 03:19:02 -0500 (Fri, 10 Aug 2007) New Revision: 3960 Modified: branches/1.0.3.x/numpy/distutils/misc_util.py Log: see changeset #3845 Modified: branches/1.0.3.x/numpy/distutils/misc_util.py =================================================================== --- branches/1.0.3.x/numpy/distutils/misc_util.py 2007-08-10 07:57:02 UTC (rev 3959) +++ branches/1.0.3.x/numpy/distutils/misc_util.py 2007-08-10 08:19:02 UTC (rev 3960) @@ -1034,7 +1034,7 @@ """ include_non_existing = kws.get('include_non_existing',True) return gpaths(paths, - local_path = self.path_in_package, + local_path = self.local_path, include_non_existing=include_non_existing) def _fix_paths_dict(self,kw): From numpy-svn at scipy.org Fri Aug 10 04:37:33 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Fri, 10 Aug 2007 03:37:33 -0500 (CDT) Subject: [Numpy-svn] r3961 - branches/1.0.3.x/numpy/distutils Message-ID: <20070810083733.F004239C10A@new.scipy.org> Author: jarrod.millman Date: 2007-08-10 03:37:24 -0500 (Fri, 10 Aug 2007) New Revision: 3961 Modified: branches/1.0.3.x/numpy/distutils/misc_util.py Log: see changeset [3848] Modified: branches/1.0.3.x/numpy/distutils/misc_util.py =================================================================== --- branches/1.0.3.x/numpy/distutils/misc_util.py 2007-08-10 08:19:02 UTC (rev 3960) +++ branches/1.0.3.x/numpy/distutils/misc_util.py 2007-08-10 08:37:24 UTC (rev 3961) @@ -565,11 +565,12 @@ # defines a configuration() function. if top_path is None: top_path = self.local_path + self.local_path = '' if package_path is None: package_path = self.local_path elif os.path.isdir(njoin(self.local_path,package_path)): package_path = njoin(self.local_path,package_path) - if not os.path.isdir(package_path): + if not os.path.isdir(package_path or '.'): raise ValueError("%r is not a directory" % (package_path,)) self.top_path = top_path self.package_path = package_path From numpy-svn at scipy.org Fri Aug 10 09:58:07 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Fri, 10 Aug 2007 08:58:07 -0500 (CDT) Subject: [Numpy-svn] r3962 - trunk/numpy/f2py/lib/extgen Message-ID: <20070810135807.F2EBB39C314@new.scipy.org> Author: pearu Date: 2007-08-10 08:57:35 -0500 (Fri, 10 Aug 2007) New Revision: 3962 Added: trunk/numpy/f2py/lib/extgen/c_support.py trunk/numpy/f2py/lib/extgen/py_support.py trunk/numpy/f2py/lib/extgen/setup_py.py trunk/numpy/f2py/lib/extgen/utils.py Modified: trunk/numpy/f2py/lib/extgen/__init__.py trunk/numpy/f2py/lib/extgen/base.py trunk/numpy/f2py/lib/extgen/doc.txt Log: extgen: rewrite, clean up, update docs, simple example from Python reference manual. Modified: trunk/numpy/f2py/lib/extgen/__init__.py =================================================================== --- trunk/numpy/f2py/lib/extgen/__init__.py 2007-08-10 08:37:24 UTC (rev 3961) +++ trunk/numpy/f2py/lib/extgen/__init__.py 2007-08-10 13:57:35 UTC (rev 3962) @@ -2,19 +2,26 @@ Python Extensions Generator """ -__all__ = ['Component', 'ExtensionModule', 'PyCFunction', 'PyCArgument', - 'CCode'] +__all__ = ['Component'] from base import Component -from extension_module import ExtensionModule -from pyc_function import PyCFunction -from pyc_argument import PyCArgument -from c_code import CCode -import c_type -from c_type import * -__all__ += c_type.__all__ +for _m in ['utils', 'c_support', 'py_support', 'setup_py']: + exec 'from %s import *' % (_m) + exec 'import %s as _m' % (_m) + __all__.extend(_m.__all__) -import predefined_components -import converters -c_type.register() +#from pyc_function import PyCFunction +#from pyc_argument import PyCArgument +#from c_code import CCode + +#import c_type +#from c_type import * +#__all__ += c_type.__all__ +#import c_struct +#from c_struct import * +#__all__ += c_struct.__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-10 08:37:24 UTC (rev 3961) +++ trunk/numpy/f2py/lib/extgen/base.py 2007-08-10 13:57:35 UTC (rev 3962) @@ -4,6 +4,7 @@ Defines Component and Container classes. """ +import os import re import sys import time @@ -12,14 +13,19 @@ classnamespace = {} - def __init__(cls,*args,**kws): + def __new__(mcls, *args, **kws): + cls = type.__new__(mcls, *args, **kws) n = cls.__name__ c = ComponentMetaClass.classnamespace.get(n) if c is None: ComponentMetaClass.classnamespace[n] = cls else: - print 'Ignoring redefinition of %s: %s defined earlier than %s' % (n, c, cls) - type.__init__(cls, *args, **kws) + if not c.__module__=='__main__': + sys.stderr.write('ComponentMetaClass: returning %s as %s\n'\ + % (cls, c)) + ComponentMetaClass.classnamespace[n] = c + cls = c + return cls def __getattr__(cls, name): try: return ComponentMetaClass.classnamespace[name] @@ -27,14 +33,14 @@ raise AttributeError("'%s' object has no attribute '%s'"% (cls.__name__, name)) -class Component(object): # XXX: rename Component to Component +class Component(object): __metaclass__ = ComponentMetaClass container_options = dict() component_container_map = dict() default_container_label = None - default_component_class_name = 'CCode' + default_component_class_name = 'Code' template = '' def __new__(cls, *args, **kws): @@ -42,10 +48,24 @@ obj._provides = kws.get('provides', None) obj.parent = None obj.containers = {} # holds containers for named string lists - obj.components = [] # holds pairs (, ) + obj._components = [] # holds pairs (, ) + obj._generate_components = {} # temporary copy of components used for finalize and generate methods. obj = obj.initialize(*args, **kws) # initialize from constructor arguments return obj + @property + def components(self): + if Component._running_generate: + try: + return self._generate_components[Component._running_generate_id] + except KeyError: + pass + while self._generate_components: # clean up old cache + self._generate_components.popitem() + self._generate_components[Component._running_generate_id] = l = list(self._components) + return l + return self._components + def initialize(self, *components, **options): """ Set additional attributes, add components to instance, etc. @@ -54,6 +74,12 @@ # map(self.add, components) return self + def finalize(self): + """ + Set components after all components are added. + """ + return + def __repr__(self): return '%s(%s)' % (self.__class__.__name__, ', '.join([repr(c) for (c,l) in self.components])) @@ -70,6 +96,7 @@ @staticmethod def warning(message): + #raise RuntimeError('extgen:' + message) print >> sys.stderr, 'extgen:',message @staticmethod def info(message): @@ -78,6 +105,8 @@ def __getattr__(self, attr): if attr.startswith('container_'): # convenience feature return self.get_container(attr[10:]) + if attr.startswith('component_'): # convenience feature + return self.get_component(attr[10:]) raise AttributeError('%s instance has no attribute %r' % (self.__class__.__name__, attr)) def __add__(self, other): # convenience method @@ -116,14 +145,56 @@ break except KeyError: pass + if container_label is None: + container_label = component.__class__.__name__ self.components.append((component, container_label)) + component.update_parent(self) return - def generate(self): + def update_parent(self, parent): + pass + + def get_path(self, *paths): + if not hasattr(self, 'path'): + if paths: + return os.path.join(*paths) + return '' + if not self.parent: + return os.path.join(*((self.path,) + paths)) + return os.path.join(*((self.parent.get_path(), self.path)+paths)) + + def get_component(self, cls): + if isinstance(cls, str): + cls = getattr(Component, cls) + if isinstance(self, cls): + return self + if self.parent: + return self.parent.get_component(cls) + self.warning('could not find %r parent component %s, returning self'\ + % (self.__class__.__name__, cls.__name__)) + return self + + _running_generate = False + _running_generate_id = 0 + _generate_dry_run = True + + def generate(self, dry_run=True): + old_dry_run = Component._generate_dry_run + Component._generate_dry_run = dry_run + Component._running_generate_id += 1 + Component._running_generate = True + result = self._generate() + Component._running_generate = False + Component._generate_dry_run = old_dry_run + return result + + def _generate(self): """ Generate code idioms (saved in containers) and return evaluated template strings. """ + self.finalize() + # clean up containers self.containers = {} for n in dir(self): @@ -151,7 +222,7 @@ continue old_parent = component.parent component.parent = self - result = component.generate() + result = component._generate() if container_key == '': pass elif container_key is not None: @@ -167,6 +238,7 @@ container = component.get_container(k) container.add(r, component.provides) else: + self.warning('%s: no container label specified for component providing %r'\ % (self.__class__.__name__,component.provides)) component.parent = old_parent @@ -181,7 +253,6 @@ else: assert isinstance(templates, (tuple, list)),`type(templates)` result = tuple(map(self.evaluate, templates)) - return result def init_containers(self): @@ -225,7 +296,7 @@ # create local container self.warning('Created container for %r with name %r, define it in'\ - ' .container_options mapping to get rid of this warning' \ + ' parent .container_options mapping to get rid of this warning' \ % (self.__class__.__name__, name)) c = self.containers[name] = Container() return c @@ -259,7 +330,10 @@ i = template.index(s) template = template[:i] + str(container) + template[i+len(s):] container.indent_offset = old_indent - template = template % d + try: + template = template % d + except KeyError, msg: + raise KeyError('%s.container_options needs %s item' % (self.__class__.__name__, msg)) return re.sub(r'.*[<]KILLLINE[>].*(\n|$)','', template) @@ -330,7 +404,9 @@ use_indent = False, indent_offset = 0, use_firstline_indent = False, # implies use_indent - replace_map = {} + replace_map = {}, + ignore_empty_content = False, + skip_prefix_suffix_when_single = False ): self.list = [] self.label_map = {} @@ -347,6 +423,8 @@ self.indent_offset = indent_offset self.use_firstline_indent = use_firstline_indent self.replace_map = replace_map + self.ignore_empty_content = ignore_empty_content + self.skip_prefix_suffix_when_single = skip_prefix_suffix_when_single def __nonzero__(self): return bool(self.list) @@ -374,6 +452,8 @@ """ if content is None: return + if content=='' and self.ignore_empty_content: + return assert isinstance(content, str),`type(content)` if label is None: label = time.time() @@ -406,8 +486,9 @@ new_l.extend([indent + l2 for l2 in lines[1:]]) l = new_l r = self.separator.join(l) - r = self.prefix + r - r = r + self.suffix + if not (len(self.list)==1 and self.skip_prefix_suffix_when_single): + r = self.prefix + r + r = r + self.suffix else: r = self.default if not self.skip_prefix: @@ -429,7 +510,9 @@ use_indent = self.use_indent, indent_offset = self.indent_offset, use_firstline_indent = self.use_firstline_indent, - replace_map = self.replace_map + replace_map = self.replace_map, + ignore_empty_content = self.ignore_empty_content, + skip_prefix_suffix_when_single = self.skip_prefix_suffix_when_single ) options.update(extra_options) cpy = Container(**options) Added: trunk/numpy/f2py/lib/extgen/c_support.py =================================================================== --- trunk/numpy/f2py/lib/extgen/c_support.py 2007-08-10 08:37:24 UTC (rev 3961) +++ trunk/numpy/f2py/lib/extgen/c_support.py 2007-08-10 13:57:35 UTC (rev 3962) @@ -0,0 +1,293 @@ + +__all__ = ['CLine', 'Keyword', 'CTypeSpec', 'CDeclarator', 'CDeclaration', + 'CArgument', 'CCode', 'CFunction', 'CSource', 'CHeader', 'CStdHeader'] + +from base import Component +from utils import Line, Code, FileSource + +class CLine(Line): + pass + +class Keyword(CLine): + pass + +class CInitExpr(CLine): + pass + +class CTypeSpec(CLine): + + """ + >>> i = CTypeSpec('int') + >>> print i.generate() + int + >>> print i.as_ptr().generate() + int* + """ + def as_ptr(self): return self.__class__(self.generate()+'*') + + +class CDeclarator(Component): + + """ + + >>> CDeclarator('name').generate() + 'name' + >>> CDeclarator('name','0').generate() + 'name = 0' + """ + container_options = dict( + Initializer = dict(default='',prefix=' = ', skip_prefix_when_empty=True, + ignore_empty_content = True + ), + ScalarInitializer = dict(default='',prefix=' = ', skip_prefix_when_empty=True, + ignore_empty_content = True + ), + SequenceInitializer = dict(default='',prefix=' = {\n', skip_prefix_when_empty=True, + suffix='}', skip_suffix_when_empty=True, + ignore_empty_content = True, + separator = ',\n', use_indent=True, + ), + StringInitializer = dict(default='',prefix=' = "', skip_prefix_when_empty=True, + suffix='"', skip_suffix_when_empty=True, + ignore_empty_content = True, + separator='\\n"\n"', replace_map = {'\n':'\\n'}, + use_firstline_indent = True, + ), + ) + + default_component_class_name = 'CInitExpr' + + component_container_map = dict( + CInitExpr = 'Initializer' + ) + + def __repr__(self): + return '%s(%s)' % (self.__class__.__name__, ', '.join(map(repr,[self.name]+[c for (c,l) in self.components]))) + + def initialize(self, name, *initvalues, **options): + self.name = name + self.is_string = options.get('is_string', None) + if self.is_string: + assert not options.get('is_scalar', None) + self.is_scalar = False + else: + if name.endswith(']'): + self.is_scalar = False + else: + self.is_scalar = options.get('is_scalar', True) + + map(self.add, initvalues) + return self + + def update_containers(self): + if self.is_scalar: + self.container_ScalarInitializer += self.container_Initializer + self.template = '%(name)s%(ScalarInitializer)s' + elif self.is_string: + self.container_StringInitializer += self.container_Initializer + self.template = '%(name)s%(StringInitializer)s' + elif len(self.containers)>1 or not self.is_scalar: + self.container_SequenceInitializer += self.container_Initializer + self.template = '%(name)s%(SequenceInitializer)s' + else: + self.container_ScalarInitializer += self.container_Initializer + self.template = '%(name)s%(ScalarInitializer)s' + +class CDeclaration(Component): + + """ + >>> d = CDeclaration('int', 'a') + >>> print d.generate() + int a + >>> d += 'b' + >>> print d.generate() + int a, b + >>> d += CDeclarator('c',1) + >>> print d.generate() + int a, b, c = 1 + """ + + template = '%(CTypeSpec)s %(CDeclarator)s' + + container_options = dict( + CTypeSpec = dict(default='int', separator=' '), + CDeclarator = dict(default='', separator=', '), + ) + + component_container_map = dict( + CTypeSpec = 'CTypeSpec', + CDeclarator = 'CDeclarator', + ) + + default_component_class_name = 'CDeclarator' + + def __repr__(self): + return '%s(%s)' % (self.__class__.__name__, ', '.join(map(repr,[c for (c,l) in self.components]))) + + def initialize(self, ctype, *declarators, **options): + ctype = CTypeSpec(ctype) + self.ctype = ctype + self.add(ctype) + map(self.add, declarators) + return self + +class CArgument(CDeclaration): + + def initialize(self, name, ctype, **options): + return CDeclaration.initialize(ctype, name, **options) + + +class CCode(Code): + parent_container_options = dict(default='', use_indent=True, ignore_empty_content=True) + +class CFunction(Component): + + """ + >>> f = CFunction('foo') + >>> print f.generate() + int + foo(void) { + } + >>> f += Keyword('static') + >>> f += CArgument('int', 'a') + >>> f += 'a = 2;' + >>> print f.generate() + static + int + foo(int a) { + a = 2; + } + >>> f += CArgument('float', 'b') + >>> f += CDeclaration('float', 'c') + >>> f += CDeclaration('float', CDeclarator('d','3.0')) + >>> print f.generate() + static + int + foo(int a, float b) { + float c; + float d = 3.0; + a = 2; + } + """ + + template = '''\ +%(CSpecifier)s +%(CTypeSpec)s +%(name)s(%(CArgument)s) { + %(CDeclaration)s + %(CBody)s +}''' + + container_options = dict( + CArgument = dict(separator=', ', default='void'), + CDeclaration = dict(default='', use_indent=True, ignore_empty_content=True, + separator = ';\n', suffix=';', skip_suffix_when_empty=True), + CBody = dict(default='', use_indent=True, ignore_empty_content=True), + CTypeSpec = dict(default='int', separator = ' ', ignore_empty_content=True), + CSpecifier = dict(default='', separator = ' ', ignore_empty_content = True) + ) + + component_container_map = dict( + CArgument = 'CArgument', + CDeclaration = 'CDeclaration', + CCode = 'CBody', + CTypeSpec = 'CTypeSpec', + Keyword = 'CSpecifier', + ) + + default_component_class_name = 'CCode' + + def initialize(self, name, rctype='int', *components, **options): + self.name = name + rctype = CTypeSpec(rctype) + self.rctype = rctype + self.add(rctype) + map(self.add, components) + if options: self.warning('%s unused options: %s\n' % (self.__class__.__name__, options)) + return self + + def __repr__(self): + return '%s(%s)' % (self.__class__.__name__, ', '.join(map(repr,[self.name, self.rctype]+[c for (c,l) in self.components]))) + +class CHeader(CLine): + + """ + >>> h = CHeader('noddy.h') + >>> print h.generate() + #include "noddy.h" + + """ + template = '#include "%(line)s"' + +class CStdHeader(CHeader): + template = '#include <%(line)s>' + +class CSource(FileSource): + + """ + >>> s = CSource('foo.c') + >>> print s.generate() #doctest: +ELLIPSIS + /* -*- c -*- */ + /* This file 'foo.c' is generated using ExtGen tool + from NumPy version ... + ExtGen is developed by Pearu Peterson . + For more information see http://www.scipy.org/ExtGen/ . + */ + #ifdef __cplusplus + extern "C" { + #endif + #ifdef __cplusplus + } + #endif + + """ + + container_options = dict( + CHeader = dict(default='', prefix='\n/* CHeader */\n', skip_prefix_when_empty=True), + CTypeDef = dict(default='', prefix='\n/* CTypeDef */\n', skip_prefix_when_empty=True), + CProto = dict(default='', prefix='\n/* CProto */\n', skip_prefix_when_empty=True), + CDefinition = dict(default='', prefix='\n/* CDefinition */\n', skip_prefix_when_empty=True), + CDeclaration = dict(default='', separator=';\n', suffix=';', + prefix='\n/* CDeclaration */\n', skip_prefix_when_empty=True), + CMainProgram = dict(default='', prefix='\n/* CMainProgram */\n', skip_prefix_when_empty=True), + ) + + template_c_header = '''\ +/* -*- c -*- */ +/* This file %(path)r is generated using ExtGen tool + from NumPy version %(numpy_version)s. + ExtGen is developed by Pearu Peterson . + For more information see http://www.scipy.org/ExtGen/ . +*/''' + + + template = template_c_header + ''' +#ifdef __cplusplus +extern \"C\" { +#endif +%(CHeader)s +%(CTypeDef)s +%(CProto)s +%(CDefinition)s +%(CDeclaration)s +%(CMainProgram)s +#ifdef __cplusplus +} +#endif +''' + + component_container_map = dict( + CHeader = 'CHeader', + CFunction = 'CDefinition', + CDeclaration = 'CDeclaration', + ) + + + + +def _test(): + import doctest + doctest.testmod() + +if __name__ == "__main__": + _test() Modified: trunk/numpy/f2py/lib/extgen/doc.txt =================================================================== --- trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-10 08:37:24 UTC (rev 3961) +++ trunk/numpy/f2py/lib/extgen/doc.txt 2007-08-10 13:57:35 UTC (rev 3962) @@ -15,23 +15,252 @@ ExtGen is a pure Python package that provides a high-level tool for constructing and building Python extension modules. -Hello example follows:: +Even an inexperienced user with no background on writing extension +modules can build extension modules on fly when using ExtGen tool! +Hello example follows + >>> from numpy.f2py.lib.extgen import * - >>> m = ExtensionModule('foo') - >>> f = PyCFunction('hello') - >>> f += 'printf("Hello!\\n");' - >>> m += f - >>> print m.generate() # shows a string containing C source to extension module, useful for debugging - >>> foo = m.build() - >>> foo.hello() + >>> m = PyCModule('foo') # define extension module component + >>> f = PyCFunction('hello') # define function component + >>> f += 'printf("Hello!\\n");' # put a C statement into function body + >>> m += f # add function to module + >>> print m.generate() # shows a string containing C source to extension module + # useful for debugging + >>> foo = m.build() # compile, build, and return extension module object + >>> foo.hello() # call function Hello! - >>> -Description of the ExtGen model -=============================== +Users reference manual +====================== +Writing a python extension module requires a knowledge of Pyhton C/API +details and may take lots of effort to get your first extension module +compile and working, even for a simple problem. See the `Simple Example`__ +in Python reference manual. ExtGen provides a high level tool for +constructing extension modules by automatically taking care of the +Pyhton C/API details while providing full control how an extension +module is created. + +__ http://docs.python.org/ext/ + +Getting started +--------------- + +Creating the `Simple Example`__ with the help of ExtGen tool is really simple + + >>> system = PyCFunction('system', + PyCArgument('command', 'c_const_char_ptr'), + PyCReturn('sts','c_int')) + >>> system += 'sts = system(command);' + >>> module = PyCModule('spam', system) + >>> spam = module.build() + >>> spam.system('pwd') + /home/pearu/svn/numpy/numpy/f2py/lib + 0 + +__ http://docs.python.org/ext/ + +ExtGen generated modules have automatically generated documentation +strings that accept also user input + + >>> a = PyCArgument('command', 'c_const_char_ptr', + input_description='a shell command string') + >>> r = PyCReturn('sts', 'c_int', + output_description='status value returned by shell command') + >>> system = PyCFunction('system', title='Execute a shell command.') + >>> system += a # add argument component to function + >>> system += r # add return value component to function + >>> system += 'sts = system(command);' # add C code to functon body + >>> module = PyCModule('spam', system) # create module instance with function component + >>> spam = module.build() + >>> print spam.__doc__ + This module 'spam' is generated with ExtGen from NumPy version 1.0.4.dev3744. + :Functions: + system(command) -> sts + >>> print spam.system.__doc__ + system(command) -> sts + Execute a shell command. + :Parameters: + command : a to C const char ptr convertable object + a shell command string + :Returns: + sts : a to C int convertable object + status value returned by shell command + >>> + +To see the source code that ExtGen generates, use `.generate()` method for any component instance + + >>> print system.generate() + static + char pyc_function_system_doc[] = + " system(command) -> sts" + "\n\nExecute a shell command." + "\n\n:Parameters:\n" + " command : a to C const char ptr convertable object\n" + " a shell command string" + "\n\n:Returns:\n" + " sts : a to C int convertable object\n" + " status value returned by shell command" + ; + static + PyObject* + pyc_function_system(PyObject *pyc_self, PyObject *pyc_args, PyObject *pyc_keywds) { + PyObject * volatile pyc_buildvalue = NULL; + volatile int capi_success = 1; + const char * command = NULL; + int sts = 0; + static char *capi_kwlist[] = {"command", NULL}; + if (PyArg_ParseTupleAndKeywords(pyc_args, pyc_keywds,"z", + capi_kwlist, &command)) { + sts = system(command); + capi_success = !PyErr_Occurred(); + if (capi_success) { + pyc_buildvalue = Py_BuildValue("i", sts); + } + } + return pyc_buildvalue; + } + >>> print module.generate() # prints full extension module source + ... + +Components +---------- + +All components are subclassed of `Component` base class that provides +the following methods: + +- `.generate(self)` --- return a generated component string +- `.add(self, component, container_label=None)` --- add subcomponent + to component instance. The `container_label` argument can be used to tell + `ExtGen` where this component should be used, see `Developers reference + manual` for more details, otherwise `EgtGen` figures that out by + looking at subcomponent class properties. +- `.__add__(self, other)`, `.__iadd__(self, other)` --- shortcuts + for `self.add(other)` call. + +ExtGen provides the following Python C/API related components: + +- `SetupPy(, *components)` --- generates a `setup.py` file + that is used to build extension modules to the given build directory. + It provides the following methods: + + - `.execute(self, *args)` --- runs `python setup.py` command with given + arguments. + + One can add `PyCModule` and `PySource` components to `SetupPy`. + +- `PyCModule(, *components, title=..., description=...)` --- + represents python extension module source. It provides the following + methods: + + - `.build(self, build_dir=None, clean_at_exit=None)` --- compilers, + builds, and returns extension module object. + + One can add `PyCFunction` components to `PyCModule`. + +- `PyCFunction(, *components, title=..., description=...)` --- + represents python extension module function source. + + One can add `PyCArgument`, `PyCReturn`, `CCode` components to `PyCfunction`. + String components are converted `CCode` components by default. + +- `PyCArgument(, ctype=, **components, + input_intent='required', input_title=..., input_description=..., + output_intent='hide', output_title=..., output_description=..., + title=..., description=..., + depends=)` --- represents argument + to python extension module function. + + `ctype` is `PyCTypeSpec` component instance or string. In the latter case + it is converted to `PyCTypeSpec` component. + +- `PyCReturn(, ctype=, **components)` --- + same as `PyCArgument` but with `input_intent='hide'` and `output_intent='return'` + options set. + +- `PyCTypeSpec()` --- represents variable type in a + python extension module. Over 70 types are supported: + + >>> typenames = PyCTypeSpec.typeinfo_map.keys() + >>> typenames.sort() + >>> print ', '.join(typenames) + buffer, c_Py_UNICODE, c_Py_complex, c_Py_ssize_t, c_char, c_char1, + c_const_char_ptr, c_double, c_float, c_int, c_long, c_long_long, + c_short, c_unsigned_char, c_unsigned_int, c_unsigned_long, + c_unsigned_long_long, c_unsigned_short, cell, cobject, complex, dict, + file, float, frozenset, function, generator, instance, int, iter, + list, long, method, module, numeric_array, numpy_complex128, + numpy_complex160, numpy_complex192, numpy_complex256, numpy_complex32, + numpy_complex64, numpy_descr, numpy_float128, numpy_float16, + numpy_float32, numpy_float64, numpy_float80, numpy_float96, + numpy_int128, numpy_int16, numpy_int32, numpy_int64, numpy_int8, + numpy_iter, numpy_multiiter, numpy_ndarray, numpy_ufunc, + numpy_uint128, numpy_uint16, numpy_uint32, numpy_uint64, numpy_uint8, + object, property, set, slice, str, tuple, type, unicode + + `typeobj` can be python type instance (e.g. `int`) or one of the string values + from the list of typenames above. + +- `PySource(, *components)` --- represents pure python module file. + + One can add `Code` components to `PySource`. + +ExtGen provides the following C related components: + +- `CSource` --- represents C file. Derived from `FileSource`. + + One can add `CCode` components to `CSource`. + String input is converted to `CCode` component. + +- `CHeader(
)`, `CStdHeader()`. Derived from `Line`. + +- `CCode(*components)` --- represents any C code block. Derived from `Code`. + +- `CFunction(, rctype=CTypeSpec('int'), *components)` --- represents + a C function. + + One can add `CArgument`, `CDeclaration`, `CCode` components to `CFunction`. + +- `CDeclaration(, *declarators)` --- represenets ` ` + code idiom. `` is `CTypeSpec` instance. + + One can add `CDeclarator` components to `CDeclaration`. + +- `CArgument(, )` --- C function argument. Derived from `CDeclaration`. + +- `CTypeSpec()` --- C type specifier. Derived from `Line`. + +- `CDeclarator(, *initvalues, is_string=..., is_scalar=...)` --- represents + ` [= ]` code idiom. + + String input is converted to `CInitExpr` component. + +ExtGen provides the following general purpose components: + +- `Word()` + + Nothing can be added to `Word`. + +- `Line(*strings)` + + One can add `Line` component to `Line`. + String input is converted to `Line` component. + +- `Code(*lines)` + + One can add `Line` and `Code` components to `Code`. + String input is converted to `Line` component. + +- `FileSource(, *components)`. + + One can add `Line` and `Code` components to `FileSource`. + String input is converted to `Code` component. + +Developers reference manual +=========================== + To extend ExtGen, one needs to understand the infrastructure of generating extension modules. @@ -43,7 +272,7 @@ for constructing code sources: - creating code components and adding them together to a parent - component. For example, the `ExtensionModule` instance in the + component. For example, the `PyCModule` instance in the hello example becomes a parent component to a `PyCFunction` instance after executing `m += f`. @@ -52,7 +281,7 @@ One can iterate the above process as one wishes. -The method `ExtensionModule.build()` is defined for convenience. +The method `PyCModule.build()` is defined for convenience. It compiles the generated sources, builds an extension module, imports the resulting module to Python, and returns the module object. @@ -79,6 +308,11 @@ - `.component_containe_map` is used to find `container_label` corresponding to `component` argument class. +- `.update_parent(self, parent)` is called after `parent.add(self,..)`. + +- `.finalize(self)` is called after finishing adding new components + and before `.generate()` method call. + - `.generate(self)` returns a source code string. It recursively processes all subcomponents, creates code containers, and evaluates code templates. @@ -129,7 +363,8 @@ - A component class must have a base class `Component`. - A component class may redefine `.initialize()`, - `.init_containers()`, `.update_containers()`, `.get_templates()` + `.init_containers()`, `.add()`, `update_parent()`, + `.update_containers()`, `.get_templates()` methods, `.provides()` property method and `.container_options`, `.component_container_map`, `.default_container_label`, `.default_component_class_name`, `.template` attributes. @@ -157,43 +392,12 @@ - All classes derived from `Component` are available as `Component.`. -Here follows a simplified version of `ExtensionModule.template`:: - - #include "Python.h" - - %(Header)s - %(TypeDef)s - %(Extern)s - %(CCode)s - %(CAPICode)s - %(ObjDecl)s - - static PyObject* extgen_module; - - static PyMethodDef extgen_module_methods[] = { - %(ModuleMethod)s - {NULL,NULL,0,NULL} - }; - - PyMODINIT_FUNC init%(modulename)s(void) { - extgen_module = Py_InitModule("%(modulename)s", extgen_module_methods); - %(ModuleInit)s - return; - capi_error: - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_RuntimeError, "failed to initialize %(modulename)s module."); - } - return; - } - -Here formatting mapping keys `Header`, `TypeDef`, etc are the labels -of containers which will be used in the templare evaluation. See `extgen/*.py` files for more examples how to redefine `Component` class methods and attributes. Using `Container` class -======================= +----------------------- `Container` class has the following optional arguments: @@ -209,6 +413,8 @@ - `indent_offset=0` - `user_defined_str=None` - `replace_map={}` + - `ignore_empty_content=False` + - `skip_prefix_suffix_when_single=False` that are used to enhance the behaviour of `Container.__str__()` method. By default, `Container.__str__()` returns @@ -241,67 +447,3 @@ Full control over the `__str__()` method is obtained via defining `user_defined_str` that should be a callable object taking list as input and return a string. - - -Component classes -================= - -ExtGen package defines the following extension module component classes: - - - `ExtensionModule(, *components, numpy=False, - provides=.., title=.., description=..)` --- - represents an extension module component. If `numpy` is `True` then - `NumPy` support will be added to an extension module. - - - `PyCFunction(, *components, provides=.., title=.., description=..)` --- - represents an extension function component. - - - `PyCArgument(, *components, provides=.., input_intent=.., - output_intent=.., input_title=.., input_description=.., - output_title=, output_description=..)` --- represents an argument component for - `PyCFunction`. Keyword arguments `input_intent` and - `output_intent` may have values `'required'`, `'optional'`, - `'extra'`, `'hide'` and `'hide'`, `'return'`, respectively. - - - `CCode(*lines, provides=..)` --- represents any C code block or - statement component. - - - `CType()` --- represents a predefined or intrinsic C type - with a given name. - - - `CTypeAlias(, )` --- represents `typedef ctype name;` - declaration. - - - `CTypeFuncAlias(, , )` --- - represents `typedef rctype (*name)(actype1,..)` declaration. - Use `.add()` method to add more argument types. - - - `CTypePtr()` --- represents `typedef ctype* ctype_ptr;` - declaration. - - - `CTypeStruct(, *declarations)` --- represents `typedef struct { - } name;` declaration. Use `.add()` method to add - more declarations. - - - `CDecl(, *names)` --- represents `ctype name1, name2, ..;` - declaration. Use `.add()` method to add more names. - - - `CTypePython()` - --- represents python type object in C, see - `CTypePython.typeinfo_map.keys()` for supported type names - (there are over 70 supported types). - - -Predefined components -===================== - -ExtGen defines the following components that can be retrived -using `Component.get()` method: - -- `'Python.h'` - include `Pyhton.h` header file. - -- `'arrayobject.h'` - include NumPy header files. - -- `'import_array'` - code for importing numpy package to extension - module. - Added: trunk/numpy/f2py/lib/extgen/py_support.py =================================================================== --- trunk/numpy/f2py/lib/extgen/py_support.py 2007-08-10 08:37:24 UTC (rev 3961) +++ trunk/numpy/f2py/lib/extgen/py_support.py 2007-08-10 13:57:35 UTC (rev 3962) @@ -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 . +# 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 ... + + This is first line. + Second line. + + 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='', + 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='', 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='', + separator = '"\n" ', suffix='"', skip_suffix_when_empty=True, + ), + Title = dict(default='',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='',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='', 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 + + Function title. + Second line. + + This is a function. + 2nd line. + + :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='',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='',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='', reverse=True, use_indent=True, ignore_empty_content=True), + CleanCBody = dict(default='', reverse=True, use_indent=True, ignore_empty_content=True), + CleanFromPyObj = dict(default='', 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 ... + + :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() Added: trunk/numpy/f2py/lib/extgen/setup_py.py =================================================================== --- trunk/numpy/f2py/lib/extgen/setup_py.py 2007-08-10 08:37:24 UTC (rev 3961) +++ trunk/numpy/f2py/lib/extgen/setup_py.py 2007-08-10 13:57:35 UTC (rev 3962) @@ -0,0 +1,103 @@ + +__all__ = ['SetupPy'] + +import os +import sys +from numpy.distutils.exec_command import exec_command +from base import Component +from utils import FileSource + +def write_files(container): + s = ['creating files and directories:'] + for filename, i in container.label_map.items(): + content = container.list[i] + d,f = os.path.split(filename) + if d and not os.path.isdir(d): + s.append(' %s/' % (d)) + if not Component._generate_dry_run: + os.makedirs(d) + s.append(' %s' % (filename)) + if not Component._generate_dry_run: + f = file(filename,'w') + f.write(content) + f.close() + return '\n'.join(s) + + +class SetupPy(Component): + + """ + >>> from __init__ import * + >>> s = SetupPy('SetupPy_doctest') + >>> s += PyCModule('foo') + >>> s,o = s.execute('build_ext', '--inplace') + >>> assert s==0,`s` + >>> import SetupPy_doctest as mypackage + >>> print mypackage.foo.__doc__ #doctest: +ELLIPSIS + This module 'foo' is generated with ExtGen from NumPy version... + + """ + template_setup_py_start = '''\ +def configuration(parent_package='', top_path = ''): + from numpy.distutils.misc_util import Configuration + config = Configuration('',parent_package,top_path)''' + template_setup_py_end = '''\ + return config +if __name__ == "__main__": + from numpy.distutils.core import setup + setup(configuration=configuration) +''' + template = '%(SourceWriter)s' + + container_options = dict( + SourceWriter = dict(user_defined_str = write_files), + TMP = dict() + ) + + component_container_map = dict( + FileSource = 'SourceWriter', + ExtensionModule = 'TMP', + ) + + def initialize(self, build_dir, *components, **options): + self.name = self.path = build_dir + if not self.path: + self.setup_py = setup_py = Component.PySource('extgen_setup.py') + self.init_py = init_py = Component.PySource('extgen__init__.py') + else: + self.setup_py = setup_py = Component.PySource('setup.py') + self.init_py = init_py = Component.PySource('__init__.py') + + setup_py += self.template_setup_py_start + + self += init_py + self += setup_py + + map(self.add, components) + + return self + + def finalize(self): + self.setup_py += self.template_setup_py_end + + def execute(self, *args): + """ + Run generated setup.py file with given arguments. + """ + if not args: + raise ValueError('need setup.py arguments') + self.info(self.generate(dry_run=False)) + cmd = [sys.executable,'setup.py'] + list(args) + self.info('entering %r directory' % (self.path)) + self.info('executing command %r' % (' '.join(cmd))) + r = exec_command(cmd, execute_in=self.path, use_tee=False) + self.info('leaving %r directory' % (self.path)) + return r + + +def _test(): + import doctest + doctest.testmod() + +if __name__ == "__main__": + _test() Added: trunk/numpy/f2py/lib/extgen/utils.py =================================================================== --- trunk/numpy/f2py/lib/extgen/utils.py 2007-08-10 08:37:24 UTC (rev 3961) +++ trunk/numpy/f2py/lib/extgen/utils.py 2007-08-10 13:57:35 UTC (rev 3962) @@ -0,0 +1,126 @@ + +__all__ = ['Word', 'Line', 'Code', 'FileSource'] + +from base import Component + +class Word(Component): + template = '%(word)s' + + def initialize(self, word): + if not word: return None + self.word = word + return self + + def add(self, component, container_label=None): + raise ValueError('%s does not take components' % (self.__class__.__name__)) + + def __repr__(self): + return '%s(%s)' % (self.__class__.__name__, ', '.join(map(repr,[self.word]+[c for (c,l) in self.components]))) + + +class Line(Component): + + """ + >>> l = Line('hey') + >>> l += ' you ' + >>> l += 2 + >>> print l + Line('hey you 2') + >>> print l.generate() + hey you 2 + >>> l += l + >>> print l.generate() + hey you 2hey you 2 + """ + + template = '%(line)s' + + def initialize(self, *strings): + self.line = '' + map(self.add, strings) + return self + + def add(self, component, container_label=None): + if isinstance(component, Line): + self.line += component.line + elif isinstance(component, str): + self.line += component + elif component is None: + pass + else: + self.line += str(component) + + def __repr__(self): + return '%s(%s)' % (self.__class__.__name__, ', '.join(map(repr,[self.line]+[c for (c,l) in self.components]))) + + +class Code(Component): + + """ + >>> c = Code('start') + >>> c += 2 + >>> c += 'end' + >>> c + Code(Line('start'), Line('2'), Line('end')) + >>> print c.generate() + start + 2 + end + """ + + template = '%(Line)s' + + container_options = dict( + Line = dict(default = '', ignore_empty_content=True) + ) + component_container_map = dict( + Line = 'Line' + ) + default_component_class_name = 'Line' + + def initialize(self, *lines): + map(self.add, lines) + return self + + def add(self, component, label=None): + if isinstance(component, Code): + assert label is None,`label` + self.components += component.components + else: + Component.add(self, component, label) + + +class FileSource(Component): + + container_options = dict( + Content = dict(default='') + ) + + template = '%(Content)s' + + default_component_class_name = 'Code' + + component_container_map = dict( + Line = 'Content', + Code = 'Content', + ) + + def initialize(self, path, *components, **options): + self.path = path + map(self.add, components) + self._provides = options.pop('provides', path) + if options: self.warning('%s unused options: %s\n' % (self.__class__.__name__, options)) + return self + + def finalize(self): + self._provides = self.get_path() or self._provides + + def __repr__(self): + return '%s(%s)' % (self.__class__.__name__, ', '.join(map(repr,[self.path]+[c for (c,l) in self.components]))) + +def _test(): + import doctest + doctest.testmod() + +if __name__ == "__main__": + _test() From numpy-svn at scipy.org Fri Aug 10 11:26:22 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Fri, 10 Aug 2007 10:26:22 -0500 (CDT) Subject: [Numpy-svn] r3963 - trunk/numpy/f2py/lib/extgen Message-ID: <20070810152622.AFE2839C040@new.scipy.org> Author: pearu Date: 2007-08-10 10:25:44 -0500 (Fri, 10 Aug 2007) New Revision: 3963 Modified: trunk/numpy/f2py/lib/extgen/base.py trunk/numpy/f2py/lib/extgen/c_support.py trunk/numpy/f2py/lib/extgen/py_support.py trunk/numpy/f2py/lib/extgen/setup_py.py Log: extgen: restored numpy support, fixed bugs. Modified: trunk/numpy/f2py/lib/extgen/base.py =================================================================== --- trunk/numpy/f2py/lib/extgen/base.py 2007-08-10 13:57:35 UTC (rev 3962) +++ trunk/numpy/f2py/lib/extgen/base.py 2007-08-10 15:25:44 UTC (rev 3963) @@ -183,17 +183,27 @@ Component._generate_dry_run = dry_run Component._running_generate_id += 1 Component._running_generate = True + self._finalize() result = self._generate() Component._running_generate = False Component._generate_dry_run = old_dry_run return result + def _finalize(self): + # recursively finalize all components. + for component, container_key in self.components: + old_parent = component.parent + component.parent = self + component._finalize() + component.parent = old_parent + self.finalize() + def _generate(self): """ Generate code idioms (saved in containers) and return evaluated template strings. """ - self.finalize() + #self.finalize() # clean up containers self.containers = {} Modified: trunk/numpy/f2py/lib/extgen/c_support.py =================================================================== --- trunk/numpy/f2py/lib/extgen/c_support.py 2007-08-10 13:57:35 UTC (rev 3962) +++ trunk/numpy/f2py/lib/extgen/c_support.py 2007-08-10 15:25:44 UTC (rev 3963) @@ -134,7 +134,7 @@ class CArgument(CDeclaration): def initialize(self, name, ctype, **options): - return CDeclaration.initialize(ctype, name, **options) + return CDeclaration.initialize(self, ctype, name, **options) class CCode(Code): @@ -149,7 +149,7 @@ foo(void) { } >>> f += Keyword('static') - >>> f += CArgument('int', 'a') + >>> f += CArgument('a', 'int') >>> f += 'a = 2;' >>> print f.generate() static @@ -157,7 +157,7 @@ foo(int a) { a = 2; } - >>> f += CArgument('float', 'b') + >>> f += CArgument('b', 'float') >>> f += CDeclaration('float', 'c') >>> f += CDeclaration('float', CDeclarator('d','3.0')) >>> print f.generate() Modified: trunk/numpy/f2py/lib/extgen/py_support.py =================================================================== --- trunk/numpy/f2py/lib/extgen/py_support.py 2007-08-10 13:57:35 UTC (rev 3962) +++ trunk/numpy/f2py/lib/extgen/py_support.py 2007-08-10 15:25:44 UTC (rev 3963) @@ -76,6 +76,7 @@ self.description = options.pop('description', None) self = CSource.initialize(self, '%smodule.c' % (pyname), **options) + self.need_numpy_support = False self.cdecl = PyCModuleCDeclaration(pyname) self += self.cdecl @@ -94,6 +95,22 @@ extmodulesrc = self.path) parent.init_py += 'import %s' % (self.pyname) + def finalize(self): + if self.need_numpy_support: + self.add(CCode(''' +#define PY_ARRAY_UNIQUE_SYMBOL PyArray_API +#include "numpy/arrayobject.h" +#include "numpy/arrayscalars.h" +'''), 'CHeader') + self.main.add(CCode(''' +import_array(); +if (PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "failed to load NumPy array module."); + goto capi_error; +} +'''),'CBody') + CSource.finalize(self) + def build(self, build_dir=None, clean_at_exit=None): """ build(build_dir=None, clean_at_exit=None) @@ -106,11 +123,6 @@ 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 @@ -118,15 +130,22 @@ if s: self.info('return status=%s' % (s)) self.info(o) - raise RuntimeError('failed to build extension module %r' % (self.pyname)) + raise RuntimeError('failed to build extension module %r,'\ + ' the build is located in %r directory'\ + % (self.pyname, build_dir)) + + 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)) + 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: @@ -469,7 +488,44 @@ self.container_OptExtArg += self.container_OptArg + self.container_ExtArg self.container_OptExtArgFmt += self.container_OptArgFmt + self.container_ExtArgFmt + # resolve dependencies + sorted_arguments = [] + sorted_names = [] + comp_map = {} + dep_map = {} + for (c,l) in self.components: + if not isinstance(c, Component.PyCArgument): + continue + d = [n for n in c.depends if n not in sorted_names] + if not d: + sorted_arguments.append((c,l)) + sorted_names.append(c.name) + else: + comp_map[c.name] = (c,l) + dep_map[c.name] = d + while dep_map: + dep_map_copy = dep_map.copy() + for name, deps in dep_map.items(): + d = [n for n in deps if dep_map.has_key(n)] + if not d: + sorted_arguments.append(comp_map[name]) + del dep_map[name] + else: + dep_map[name] = d + if dep_map_copy==dep_map: + self.warnign('%s: detected cyclic dependencies in %r, incorrect behavior is expected.\n'\ + % (self.provides, dep_map)) + sorted_arguments += dep_map.values() + break + + for c, l in sorted_arguments: + old_parent = c.parent + c.parent = self + c.ctype.set_converters(c) + c.parent = old_parent + + class PyCArgument(Component): """ @@ -583,7 +639,7 @@ output_doc_descr = None # add components to parent: - parent += ctype.get_decl(self) + parent += ctype.get_decl(self, parent) if self.input_intent=='required': parent += ReqArg(self.name) parent.signature += ReqArg(self.name) @@ -638,6 +694,145 @@ PyCTypeSpec('object') >>> print s.generate() PyObject* + + >>> from __init__ import * + >>> m = PyCModule('test_PyCTypeSpec') + >>> f = PyCFunction('func') + >>> f += PyCArgument('i', int, output_intent='return') + >>> f += PyCArgument('l', long, output_intent='return') + >>> f += PyCArgument('f', float, output_intent='return') + >>> f += PyCArgument('c', complex, output_intent='return') + >>> f += PyCArgument('s', str, output_intent='return') + >>> f += PyCArgument('u', unicode, output_intent='return') + >>> f += PyCArgument('t', tuple, output_intent='return') + >>> f += PyCArgument('lst', list, output_intent='return') + >>> f += PyCArgument('d', dict, output_intent='return') + >>> f += PyCArgument('set', set, output_intent='return') + >>> f += PyCArgument('o1', object, output_intent='return') + >>> f += PyCArgument('o2', object, output_intent='return') + >>> m += f + >>> b = m.build() #doctest: +ELLIPSIS + >>> b.func(23, 23l, 1.2, 1+2j, 'hello', u'hei', (2,'a'), [-2], {3:4}, set([1,2]), 2, '15') + (23, 23L, 1.2, (1+2j), 'hello', u'hei', (2, 'a'), [-2], {3: 4}, set([1, 2]), 2, '15') + >>> print b.func.__doc__ + func(i, l, f, c, s, u, t, lst, d, set, o1, o2) -> (i, l, f, c, s, u, t, lst, d, set, o1, o2) + + :Parameters: + i : a python int object + l : a python long object + f : a python float object + c : a python complex object + s : a python str object + u : a python unicode object + t : a python tuple object + lst : a python list object + d : a python dict object + set : a python set object + o1 : a python object + o2 : a python object + + :Returns: + i : a python int object + l : a python long object + f : a python float object + c : a python complex object + s : a python str object + u : a python unicode object + t : a python tuple object + lst : a python list object + d : a python dict object + set : a python set object + o1 : a python object + o2 : a python object + + >>> m = PyCModule('test_PyCTypeSpec_c') + >>> f = PyCFunction('func_c_int') + >>> f += PyCArgument('i1', 'c_char', output_intent='return') + >>> f += PyCArgument('i2', 'c_short', output_intent='return') + >>> f += PyCArgument('i3', 'c_int', output_intent='return') + >>> f += PyCArgument('i4', 'c_long', output_intent='return') + >>> f += PyCArgument('i5', 'c_long_long', output_intent='return') + >>> m += f + >>> f = PyCFunction('func_c_unsigned_int') + >>> f += PyCArgument('i1', 'c_unsigned_char', output_intent='return') + >>> f += PyCArgument('i2', 'c_unsigned_short', output_intent='return') + >>> f += PyCArgument('i3', 'c_unsigned_int', output_intent='return') + >>> f += PyCArgument('i4', 'c_unsigned_long', output_intent='return') + >>> f += PyCArgument('i5', 'c_unsigned_long_long', output_intent='return') + >>> m += f + >>> f = PyCFunction('func_c_float') + >>> f += PyCArgument('f1', 'c_float', output_intent='return') + >>> f += PyCArgument('f2', 'c_double', output_intent='return') + >>> m += f + >>> f = PyCFunction('func_c_complex') + >>> f += PyCArgument('c1', 'c_Py_complex', output_intent='return') + >>> m += f + >>> f = PyCFunction('func_c_string') + >>> f += PyCArgument('s1', 'c_const_char_ptr', output_intent='return') + >>> f += PyCArgument('s2', 'c_const_char_ptr', output_intent='return') + >>> f += PyCArgument('s3', 'c_Py_UNICODE', output_intent='return') + >>> f += PyCArgument('s4', 'c_char1', output_intent='return') + >>> m += f + >>> b = m.build() + >>> b.func_c_int(2,3,4,5,6) + (2, 3, 4, 5, 6L) + >>> b.func_c_unsigned_int(-1,-1,-1,-1,-1) + (255, 65535, 4294967295, 18446744073709551615L, 18446744073709551615L) + >>> b.func_c_float(1.2,1.2) + (1.2000000476837158, 1.2) + >>> b.func_c_complex(1+2j) + (1+2j) + >>> b.func_c_string('hei', None, u'tere', 'b') + ('hei', None, u'tere', 'b') + + >>> import numpy + >>> m = PyCModule('test_PyCTypeSpec_numpy') + >>> f = PyCFunction('func_int') + >>> f += PyCArgument('i1', numpy.int8, output_intent='return') + >>> f += PyCArgument('i2', numpy.int16, output_intent='return') + >>> f += PyCArgument('i3', numpy.int32, output_intent='return') + >>> f += PyCArgument('i4', numpy.int64, output_intent='return') + >>> m += f + >>> f = PyCFunction('func_uint') + >>> f += PyCArgument('i1', numpy.uint8, output_intent='return') + >>> f += PyCArgument('i2', numpy.uint16, output_intent='return') + >>> f += PyCArgument('i3', numpy.uint32, output_intent='return') + >>> f += PyCArgument('i4', numpy.uint64, output_intent='return') + >>> m += f + >>> f = PyCFunction('func_float') + >>> f += PyCArgument('f1', numpy.float32, output_intent='return') + >>> f += PyCArgument('f2', numpy.float64, output_intent='return') + >>> f += PyCArgument('f3', numpy.float128, output_intent='return') + >>> m += f + >>> f = PyCFunction('func_complex') + >>> f += PyCArgument('c1', numpy.complex64, output_intent='return') + >>> f += PyCArgument('c2', numpy.complex128, output_intent='return') + >>> f += PyCArgument('c3', numpy.complex256, output_intent='return') + >>> m += f + >>> f = PyCFunction('func_array') + >>> f += PyCArgument('a1', numpy.ndarray, output_intent='return') + >>> m += f + >>> b = m.build() + >>> b.func_int(numpy.int8(-2), numpy.int16(-3), numpy.int32(-4), numpy.int64(-5)) + (-2, -3, -4, -5) + >>> b.func_uint(numpy.uint8(-1), numpy.uint16(-1), numpy.uint32(-1), numpy.uint64(-1)) + (255, 65535, 4294967295, 18446744073709551615) + >>> b.func_float(numpy.float32(1.2),numpy.float64(1.2),numpy.float128(1.2)) + (1.20000004768, 1.2, 1.19999999999999995559) + >>> b.func_complex(numpy.complex64(1+2j),numpy.complex128(1+2j),numpy.complex256(1+2j)) + ((1+2j), (1+2j), (1.0+2.0j)) + >>> b.func_array(numpy.array([1,2])) + array([1, 2]) + >>> b.func_array(numpy.array(2)) + array(2) + >>> b.func_array(2) + Traceback (most recent call last): + ... + TypeError: argument 1 must be numpy.ndarray, not int + >>> b.func_array(numpy.int8(2)) + Traceback (most recent call last): + ... + TypeError: argument 1 must be numpy.ndarray, not numpy.int8 """ typeinfo_map = dict( @@ -752,15 +947,21 @@ 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') + + self.need_numpy_support = False + if key.startswith('numpy_'): + self.need_numpy_support = True + #self.add(Component.get('arrayobject.h'), 'CHeader') + #self.add(Component.get('import_array'), 'ModuleInit') if key.startswith('numeric_'): raise NotImplementedError(self.__class__.__name__ + ': Numeric support') return self + def finalize(self): + if self.need_numpy_support: + self.component_PyCModule.need_numpy_support = True + def __repr__(self): return '%s(%s)' % (self.__class__.__name__, ', '.join([repr(self.typeobj_name)]+[repr(c) for (c,l) in self.components])) @@ -810,21 +1011,91 @@ if arg.output_title: r = ', ' + arg.output_title arg.output_title = tn + r - def get_decl(self, arg): + def get_decl(self, arg, func): 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)) + func += 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)) + if self.get_pyret_obj(arg) is None: + if self.get_pyret_obj(arg) is not None: + func += CDeclaration(self, '%s%s' % (arg.pycvar, init)) + elif self.get_pyarg_obj(arg) is not None: + func += CDeclaration(self, '%s%s' % (arg.pycvar, init)) + func += CDeclaration(self,'%s%s' % (arg.retpycvar, init)) + else: + func += CDeclaration(self, '%s%s' % (arg.retpycvar, init)) return + def set_converters(self, arg): + """ + Notes for user: + if arg is intent(optional, in, out) and not specified + as function argument then function may created but + it must then have *new reference* (ie use Py_INCREF + unless it is a new reference already). + """ + # this method is called from PyCFunction.update_containers(), + # note that self.parent is None put arg.parent is PyCFunction + # instance. + eval_a = arg.evaluate + FromPyObj = arg.container_FromPyObj + PyObjFrom = arg.container_PyObjFrom + + argfmt = self.get_pyarg_fmt(arg) + retfmt = self.get_pyret_fmt(arg) + if arg.output_intent=='return': + if arg.input_intent in ['optional', 'extra']: + if retfmt in 'SON': + FromPyObj += eval_a('''\ +if (!(%(pycvar)s==NULL)) { + /* make %(pycvar)r a new reference */ + %(retpycvar)s = %(pycvar)s; + Py_INCREF((PyObject*)%(retpycvar)s); +} +''') + PyObjFrom += eval_a('''\ +if (%(retpycvar)s==NULL) { + /* %(pycvar)r was not specified */ + if (%(pycvar)s==NULL) { + %(retpycvar)s = Py_None; + Py_INCREF((PyObject*)%(retpycvar)s); + } else { + %(retpycvar)s = %(pycvar)s; + /* %(pycvar)r must be a new reference or expect a core dump. */ + } +} elif (!(%(retpycvar)s == %(pycvar)s)) { + /* a new %(retpycvar)r was created, undoing %(pycvar)s new reference */ + Py_DECREF((PyObject*)%(pycvar)s); +} +''') + elif arg.input_intent=='hide': + if retfmt in 'SON': + PyObjFrom += eval_a('''\ +if (%(retpycvar)s==NULL) { + %(retpycvar)s = Py_None; + Py_INCREF((PyObject*)%(retpycvar)s); +} /* else %(retpycvar)r must be a new reference or expect a core dump. */ +''') + elif arg.input_intent=='required': + if retfmt in 'SON': + FromPyObj += eval_a('''\ +/* make %(pycvar)r a new reference */ +%(retpycvar)s = %(pycvar)s; +Py_INCREF((PyObject*)%(retpycvar)s); +''') + PyObjFrom += eval_a('''\ +if (!(%(retpycvar)s==%(pycvar)s)) { + /* a new %(retpycvar)r was created, undoing %(pycvar)r new reference */ + /* %(retpycvar)r must be a new reference or expect a core dump. */ + Py_DECREF((PyObject*)%(pycvar)s); +} +''') + + def _test(): import doctest doctest.testmod() Modified: trunk/numpy/f2py/lib/extgen/setup_py.py =================================================================== --- trunk/numpy/f2py/lib/extgen/setup_py.py 2007-08-10 13:57:35 UTC (rev 3962) +++ trunk/numpy/f2py/lib/extgen/setup_py.py 2007-08-10 15:25:44 UTC (rev 3963) @@ -18,9 +18,25 @@ os.makedirs(d) s.append(' %s' % (filename)) if not Component._generate_dry_run: - f = file(filename,'w') - f.write(content) - f.close() + overwrite = True + if os.path.isfile(filename): + overwrite = False + f = file(filename, 'r') + i = 0 + for line in f: + if 'is generated using ExtGen tool' in line: + overwrite = True + break + i += 1 + if i>5: break + if not overwrite: + s[-1] += ' - unknown file exists, skipping' + else: + s[-1] += ' - extgen generated file exists, overwriting' + if overwrite: + f = file(filename,'w') + f.write(content) + f.close() return '\n'.join(s) @@ -90,8 +106,13 @@ cmd = [sys.executable,'setup.py'] + list(args) self.info('entering %r directory' % (self.path)) self.info('executing command %r' % (' '.join(cmd))) - r = exec_command(cmd, execute_in=self.path, use_tee=False) - self.info('leaving %r directory' % (self.path)) + try: + r = exec_command(cmd, execute_in=self.path, use_tee=False) + except: + self.info('leaving %r directory' % (self.path)) + raise + else: + self.info('leaving %r directory' % (self.path)) return r From numpy-svn at scipy.org Fri Aug 10 11:30:42 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Fri, 10 Aug 2007 10:30:42 -0500 (CDT) Subject: [Numpy-svn] r3964 - trunk/numpy/f2py/lib/extgen Message-ID: <20070810153042.8188E39C0E5@new.scipy.org> Author: pearu Date: 2007-08-10 10:30:24 -0500 (Fri, 10 Aug 2007) New Revision: 3964 Removed: trunk/numpy/f2py/lib/extgen/c_code.py trunk/numpy/f2py/lib/extgen/c_type.py trunk/numpy/f2py/lib/extgen/converters.py trunk/numpy/f2py/lib/extgen/extension_module.py trunk/numpy/f2py/lib/extgen/predefined_components.py trunk/numpy/f2py/lib/extgen/pyc_argument.py trunk/numpy/f2py/lib/extgen/pyc_function.py Log: extgen: removing old files Deleted: trunk/numpy/f2py/lib/extgen/c_code.py =================================================================== --- trunk/numpy/f2py/lib/extgen/c_code.py 2007-08-10 15:25:44 UTC (rev 3963) +++ trunk/numpy/f2py/lib/extgen/c_code.py 2007-08-10 15:30:24 UTC (rev 3964) @@ -1,33 +0,0 @@ - -from base import Component - -class CCode(Component): - - """ - CCode(*lines, provides=..) - """ - - container_options = dict(CCodeLines=dict()) - - template = '%(CCodeLines)s' - - def initialize(self, *lines, **options): - self.lines = [] - map(self.add, lines) - return self - - def update_containers(self): - CCodeLines = self.get_container('CCodeLines') - CCodeLines.add('\n'.join(self.lines)) - - def add(self, component, label=None): - if isinstance(component, str): - assert label is None,`label` - self.lines.append(component) - elif isinstance(component, CCode): - assert label is None,`label` - self.lines.extend(component.lines) - else: - Component.add(self, component. label) - - Deleted: trunk/numpy/f2py/lib/extgen/c_type.py =================================================================== --- trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-10 15:25:44 UTC (rev 3963) +++ trunk/numpy/f2py/lib/extgen/c_type.py 2007-08-10 15:30:24 UTC (rev 3964) @@ -1,638 +0,0 @@ -""" -C types. - - -""" - -__all__ = ['CType', 'CTypeAlias', 'CTypeFuncAlias', 'CTypePtr', 'CTypeStruct', 'CDecl', - 'CTypePython'] - -from base import Component - -class CTypeBase(Component): - - template = '%(name)s' - template_typedef = '' - default_container_label = '' - default_component_class_name = 'CType' - - @property - def provides(self): - return '%s_%s' % (self.__class__.__name__, self.name) - - def initialize(self, name, *components): - self.name = name - map(self.add, components) - return self - - def __repr__(self): - return '%s(%s)' % (self.__class__.__name__, ', '.join([repr(self.name)]+[repr(c) for (c,l) in self.components])) - - def update_containers(self): - self.container_TypeDef += self.evaluate(self.template_typedef) - - def __str__(self): - return self.name - - def get_pyarg_fmt(self, arg): - raise NotImplementedError('%s.get_pyarg_fmt()' % (self.__class__.__name__)) - - def get_pyarg_obj(self, arg): - raise NotImplementedError('%s.get_pyarg_obj()' % (self.__class__.__name__)) - - def get_pyret_fmt(self, arg): - raise NotImplementedError('%s.get_pyret_fmt()' % (self.__class__.__name__)) - - def get_pyret_obj(self, arg): - raise NotImplementedError('%s.get_pyret_obj()' % (self.__class__.__name__)) - - def get_init_value(self, arg): - return - - def set_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: - arg += CDecl(self, '%s%s' % (arg.pycvar, init)) - else: - if arg.input_intent!='hide': - arg += CDecl(self, '%s%s' % (arg.pycvar, init)) - if arg.output_intent!='hide': - arg += CDecl(self, '%s%s' % (arg.retpycvar, init)) - - def set_converters(self, arg): - """ - Notes for user: - if arg is intent(optional, in, out) and not specified - as function argument then function may created but - it must then have *new reference* (ie use Py_INCREF - unless it is a new reference already). - """ - # this method is called from PyCFunction.update_containers(), - # note that self.parent is None put arg.parent is PyCFunction - # instance. - eval_a = arg.evaluate - FromPyObj = arg.container_FromPyObj - PyObjFrom = arg.container_PyObjFrom - - argfmt = self.get_pyarg_fmt(arg) - retfmt = self.get_pyret_fmt(arg) - - if arg.output_intent=='return': - if arg.input_intent in ['optional', 'extra']: - if retfmt in 'SON': - FromPyObj += eval_a('''\ -if (!(%(pycvar)s==NULL)) { - /* make %(pycvar)r a new reference */ - %(retpycvar)s = %(pycvar)s; - Py_INCREF((PyObject*)%(retpycvar)s); -} -''') - PyObjFrom += eval_a('''\ -if (%(retpycvar)s==NULL) { - /* %(pycvar)r was not specified */ - if (%(pycvar)s==NULL) { - %(retpycvar)s = Py_None; - Py_INCREF((PyObject*)%(retpycvar)s); - } else { - %(retpycvar)s = %(pycvar)s; - /* %(pycvar)r must be a new reference or expect a core dump. */ - } -} elif (!(%(retpycvar)s == %(pycvar)s)) { - /* a new %(retpycvar)r was created, undoing %(pycvar)s new reference */ - Py_DECREF((PyObject*)%(pycvar)s); -} -''') - elif arg.input_intent=='hide': - if retfmt in 'SON': - PyObjFrom += eval_a('''\ -if (%(retpycvar)s==NULL) { - %(retpycvar)s = Py_None; - Py_INCREF((PyObject*)%(retpycvar)s); -} /* else %(retpycvar)r must be a new reference or expect a core dump. */ -''') - elif arg.input_intent=='required': - if retfmt in 'SON': - FromPyObj += eval_a('''\ -/* make %(pycvar)r a new reference */ -%(retpycvar)s = %(pycvar)s; -Py_INCREF((PyObject*)%(retpycvar)s); -''') - PyObjFrom += eval_a('''\ -if (!(%(retpycvar)s==%(pycvar)s)) { - /* a new %(retpycvar)r was created, undoing %(pycvar)r new reference */ - /* %(retpycvar)r must be a new reference or expect a core dump. */ - Py_DECREF((PyObject*)%(pycvar)s); -} -''') - return - -class _CatchTypeDef(Component): # for doctest - template = '%(TypeDef)s' - default_container_label = '' - container_options = dict(TypeDef=dict(default='')) - def initialize(self, ctype): - self.add(ctype) - return self - -class CType(CTypeBase): - - """ CType() - - Represents any predefined type in C. - - >>> cint = CType('int') - >>> print cint - int - >>> _CatchTypeDef(cint).generate() - '' - """ - - def initialize(self, name): - if isinstance(name, CTypeBase): - return name - if isinstance(name, type): - return CTypePython(name) - try: - return Component.get(name) - except KeyError: - pass - self.name = name - return self - def update_containers(self): - pass - - def set_pyarg_decl(self, arg): - pass - def set_titles(self, arg): - pass - -class CTypeAlias(CTypeBase): - - """ CTypeAlias(, ) - - >>> aint = CTypeAlias('aint', 'int') - >>> print aint - aint - >>> print _CatchTypeDef(aint).generate() - typedef int aint; - """ - - template_typedef = 'typedef %(ctype_name)s %(name)s;' - - def initialize(self, name, ctype): - self.name = name - if isinstance(ctype, str): ctype = CType(ctype) - self.ctype_name = ctype.name - self.add(ctype) - return self - -class CTypeFuncAlias(CTypeBase): - - """ - CTypeFuncAlias(, , *()) - - >>> ifunc = CTypeFuncAlias('ifunc', 'int') - >>> print ifunc - ifunc - >>> print _CatchTypeDef(ifunc).generate() - typedef int (*ifunc)(void); - >>> ifunc += 'double' - >>> print _CatchTypeDef(ifunc).generate() - typedef int (*ifunc)(double); - """ - - template_typedef = 'typedef %(RCType)s (*%(name)s)(%(ACType)s);' - container_options = dict(RCType = dict(default='void'), - ACType = dict(default='void', separator=', ')) - component_container_map = dict(CType = 'ACType') - default_component_class_name = 'CType' - - def initialize(self, name, *components): - self.name = name - if components: - self.add(components[0], 'RCType') - map(self.add, components[1:]) - return self - -class CTypePtr(CTypeBase): - - """ - CTypePtr() - - >>> int_ptr = CTypePtr('int') - >>> print int_ptr - int_ptr - >>> print _CatchTypeDef(int_ptr).generate() - typedef int* int_ptr; - >>> int_ptr_ptr = CTypePtr(int_ptr) - >>> print int_ptr_ptr - int_ptr_ptr - >>> print _CatchTypeDef(int_ptr_ptr).generate() - typedef int* int_ptr; - typedef int_ptr* int_ptr_ptr; - """ - - template_typedef = 'typedef %(ctype_name)s* %(name)s;' - - def initialize(self, ctype): - if isinstance(ctype, str): ctype = CType(ctype) - self.name = '%s_ptr' % (ctype) - self.ctype_name = ctype.name - self.add(ctype) - return self - -class CTypeStruct(CTypeBase): - - """ - CTypeStruct(, *()) - - >>> s = CTypeStruct('s', CDecl('int','a')) - >>> print s - s - >>> print _CatchTypeDef(s).generate() - typedef struct { - int a; - } s; - >>> s += CDecl(CTypeFuncAlias('ft'), 'f') - >>> print _CatchTypeDef(s).generate() - typedef void (*ft)(void); - typedef struct { - int a; - ft f; - } s; - - """ - - container_options = dict(Decl = dict(default='', use_indent=True)) - default_component_class_name = None #'CDecl' - component_container_map = dict(CDecl='Decl') - - template_typedef = '''\ -typedef struct { - %(Decl)s -} %(name)s;''' - - def initialize(self, name, *components): - self.name = name - map(self.add, components) - return self - -class CDecl(Component): - - """ - CDecl(, *()) - - >>> ad = CDecl('int') - >>> ad.generate() - '' - >>> ad += 'a' - >>> print ad.generate() - int a; - >>> ad += 'b' - >>> print ad.generate() - int a, b; - >>> ad += 'c = 1' - >>> print ad.generate() - int a, b, c = 1; - """ - - template = '%(CTypeName)s %(Names)s;' - container_options = dict(Names=dict(default='', separator=', '), - CTypeName=dict()) - default_component_class_name = 'str' - component_container_map = dict(str = 'Names') - - def initialize(self, ctype, *names): - if isinstance(ctype, str): ctype = CType(ctype) - self.add(ctype, 'CTypeName') - map(self.add, names) - return self - -class CTypePython(CTypeBase): - - """ CTypePython() - - >>> from __init__ import * #doctest: +ELLIPSIS - Ignoring... - >>> m = ExtensionModule('test_CTypePython') - >>> f = PyCFunction('func') - >>> f += PyCArgument('i', int, output_intent='return') - >>> f += PyCArgument('l', long, output_intent='return') - >>> f += PyCArgument('f', float, output_intent='return') - >>> f += PyCArgument('c', complex, output_intent='return') - >>> f += PyCArgument('s', str, output_intent='return') - >>> f += PyCArgument('u', unicode, output_intent='return') - >>> f += PyCArgument('t', tuple, output_intent='return') - >>> f += PyCArgument('lst', list, output_intent='return') - >>> f += PyCArgument('d', dict, output_intent='return') - >>> f += PyCArgument('set', set, output_intent='return') - >>> f += PyCArgument('o1', object, output_intent='return') - >>> f += PyCArgument('o2', object, output_intent='return') - >>> m += f - >>> b = m.build() #doctest: +ELLIPSIS - exec_command... - >>> b.func(23, 23l, 1.2, 1+2j, 'hello', u'hei', (2,'a'), [-2], {3:4}, set([1,2]), 2, '15') - (23, 23L, 1.2, (1+2j), 'hello', u'hei', (2, 'a'), [-2], {3: 4}, set([1, 2]), 2, '15') - - >>> print b.func.__doc__ - func(i, l, f, c, s, u, t, lst, d, set, o1, o2) -> (i, l, f, c, s, u, t, lst, d, set, o1, o2) - - Required arguments: - i - a python int object - l - a python long object - f - a python float object - c - a python complex object - s - a python str object - u - a python unicode object - t - a python tuple object - lst - a python list object - d - a python dict object - set - a python set object - o1 - a python object - o2 - a python object - - Return values: - i - a python int object - l - a python long object - f - a python float object - c - a python complex object - s - a python str object - u - a python unicode object - t - a python tuple object - lst - a python list object - d - a python dict object - set - a python set object - o1 - a python object - o2 - a python object - - >>> m = ExtensionModule('test_CTypePython_c') - >>> f = PyCFunction('func_c_int') - >>> f += PyCArgument('i1', 'c_char', output_intent='return') - >>> f += PyCArgument('i2', 'c_short', output_intent='return') - >>> f += PyCArgument('i3', 'c_int', output_intent='return') - >>> f += PyCArgument('i4', 'c_long', output_intent='return') - >>> f += PyCArgument('i5', 'c_long_long', output_intent='return') - >>> m += f - >>> f = PyCFunction('func_c_unsigned_int') - >>> f += PyCArgument('i1', 'c_unsigned_char', output_intent='return') - >>> f += PyCArgument('i2', 'c_unsigned_short', output_intent='return') - >>> f += PyCArgument('i3', 'c_unsigned_int', output_intent='return') - >>> f += PyCArgument('i4', 'c_unsigned_long', output_intent='return') - >>> f += PyCArgument('i5', 'c_unsigned_long_long', output_intent='return') - >>> m += f - >>> f = PyCFunction('func_c_float') - >>> f += PyCArgument('f1', 'c_float', output_intent='return') - >>> f += PyCArgument('f2', 'c_double', output_intent='return') - >>> m += f - >>> f = PyCFunction('func_c_complex') - >>> f += PyCArgument('c1', 'c_Py_complex', output_intent='return') - >>> m += f - >>> f = PyCFunction('func_c_string') - >>> f += PyCArgument('s1', 'c_const_char_ptr', output_intent='return') - >>> f += PyCArgument('s2', 'c_const_char_ptr', output_intent='return') - >>> f += PyCArgument('s3', 'c_Py_UNICODE', output_intent='return') - >>> f += PyCArgument('s4', 'c_char1', output_intent='return') - >>> m += f - >>> b = m.build() #doctest: +ELLIPSIS - exec_command... - >>> b.func_c_int(2,3,4,5,6) - (2, 3, 4, 5, 6L) - >>> b.func_c_unsigned_int(-1,-1,-1,-1,-1) - (255, 65535, 4294967295, 18446744073709551615L, 18446744073709551615L) - >>> b.func_c_float(1.2,1.2) - (1.2000000476837158, 1.2) - >>> b.func_c_complex(1+2j) - (1+2j) - >>> b.func_c_string('hei', None, u'tere', 'b') - ('hei', None, u'tere', 'b') - - >>> import numpy - >>> m = ExtensionModule('test_CTypePython_numpy') - >>> f = PyCFunction('func_int') - >>> f += PyCArgument('i1', numpy.int8, output_intent='return') - >>> f += PyCArgument('i2', numpy.int16, output_intent='return') - >>> f += PyCArgument('i3', numpy.int32, output_intent='return') - >>> f += PyCArgument('i4', numpy.int64, output_intent='return') - >>> m += f - >>> f = PyCFunction('func_uint') - >>> f += PyCArgument('i1', numpy.uint8, output_intent='return') - >>> f += PyCArgument('i2', numpy.uint16, output_intent='return') - >>> f += PyCArgument('i3', numpy.uint32, output_intent='return') - >>> f += PyCArgument('i4', numpy.uint64, output_intent='return') - >>> m += f - >>> f = PyCFunction('func_float') - >>> f += PyCArgument('f1', numpy.float32, output_intent='return') - >>> f += PyCArgument('f2', numpy.float64, output_intent='return') - >>> f += PyCArgument('f3', numpy.float128, output_intent='return') - >>> m += f - >>> f = PyCFunction('func_complex') - >>> f += PyCArgument('c1', numpy.complex64, output_intent='return') - >>> f += PyCArgument('c2', numpy.complex128, output_intent='return') - >>> f += PyCArgument('c3', numpy.complex256, output_intent='return') - >>> m += f - >>> f = PyCFunction('func_array') - >>> f += PyCArgument('a1', numpy.ndarray, output_intent='return') - >>> m += f - >>> b = m.build() #doctest: +ELLIPSIS - exec_command... - >>> b.func_int(numpy.int8(-2), numpy.int16(-3), numpy.int32(-4), numpy.int64(-5)) - (-2, -3, -4, -5) - >>> b.func_uint(numpy.uint8(-1), numpy.uint16(-1), numpy.uint32(-1), numpy.uint64(-1)) - (255, 65535, 4294967295, 18446744073709551615) - >>> b.func_float(numpy.float32(1.2),numpy.float64(1.2),numpy.float128(1.2)) - (1.20000004768, 1.2, 1.19999999999999995559) - >>> b.func_complex(numpy.complex64(1+2j),numpy.complex128(1+2j),numpy.complex256(1+2j)) - ((1+2j), (1+2j), (1.0+2.0j)) - >>> b.func_array(numpy.array([1,2])) - array([1, 2]) - >>> b.func_array(numpy.array(2)) - array(2) - >>> b.func_array(2) - Traceback (most recent call last): - ... - TypeError: argument 1 must be numpy.ndarray, not int - >>> b.func_array(numpy.int8(2)) - Traceback (most recent call last): - ... - TypeError: argument 1 must be numpy.ndarray, not numpy.int8 - """ - - 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): - 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.name = item[1] - self.pyarg_fmt = item[2] - self.pyret_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 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_pyarg_fmt(self, arg): - if arg.input_intent=='hide': return None - return self.pyarg_fmt - - def get_pyarg_obj(self, arg): - if arg.input_intent=='hide': return None - if self.pyarg_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.pyret_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 register(): - Component.register( - ) - -def _test(): - import doctest - doctest.testmod() - -if __name__ == "__main__": - _test() Deleted: trunk/numpy/f2py/lib/extgen/converters.py =================================================================== --- trunk/numpy/f2py/lib/extgen/converters.py 2007-08-10 15:25:44 UTC (rev 3963) +++ trunk/numpy/f2py/lib/extgen/converters.py 2007-08-10 15:30:24 UTC (rev 3964) @@ -1,22 +0,0 @@ - -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'), - - ) Deleted: trunk/numpy/f2py/lib/extgen/extension_module.py =================================================================== --- trunk/numpy/f2py/lib/extgen/extension_module.py 2007-08-10 15:25:44 UTC (rev 3963) +++ trunk/numpy/f2py/lib/extgen/extension_module.py 2007-08-10 15:30:24 UTC (rev 3964) @@ -1,195 +0,0 @@ - -from base import Component - -class ExtensionModule(Component): - - """ - ExtensionModule(, *components, numpy=False, provides=..) - - Hello example: - - >>> # in general use: - >>> # from numpy.f2py.lib.extgen import * - >>> # instead of the following import statement - >>> from __init__ import * #doctest: +ELLIPSIS - Ignoring... - >>> f = PyCFunction('hello', title='Say Hello\\nand Bye.') - >>> f += 'printf("Hello!\\\\n");' - >>> f += 'printf("Bye!\\\\n");' - >>> m = ExtensionModule('foo', f, title='Hello module', description='First line.\\nSecond line.') - >>> foo = m.build() #doctest: +ELLIPSIS - exec_command... - >>> foo.hello() - >>> # you should now see Hello! printed to stdout stream. - - We now add a new function to module and rebuild. But we need to change the - module name as one cannot reload extension modules in Python. - - >>> m.modulename = 'foo2' - >>> m += PyCFunction('hi', 'printf("Hi\\\\n");', title='Say just Hi.') - >>> foo = m.build() #doctest: +ELLIPSIS - exec_command... - >>> print foo.__doc__ #doctest: +ELLIPSIS - This module "foo2" is generated with ExtGen from NumPy version ... - - Hello module - - Description: - First line. - Second line. - - Functions: - hello() -> None - Say Hello - and Bye. - hi() -> None - Say just Hi. - """ - - container_options = dict(\ - Header=dict(default=''), - TypeDef=dict(default=''), - Extern=dict(default=''), - CCode=dict(default=''), - CAPICode=dict(default=''), - ObjDecl=dict(default=''), - ModuleMethod=dict(suffix=',', skip_suffix_when_empty=True,separator=',\n', - default='', use_indent=True), - ModuleInit=dict(default='', use_indent=True), - - ModuleTitle = dict(default='',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'}), - ModuleDescr = dict(default='',prefix='"\\n\\nDescription:\\n"\n" ', - suffix='"',separator='\\n"\n" ', - skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True, replace_map={'\n':'\\n'}), - ModuleFuncDoc = dict(default='', prefix='"\\n\\nFunctions:\\n"\n" ', - separator='\\n"\n" ', suffix='"', - skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True, replace_map={'\n':'\\n'}), - ) - - component_container_map = dict(PyCFunction = 'CAPICode') - - template = '''\ -/* -*- c -*- */ -/* This Python C/API extension module "%(modulename)s" is generated - using extgen tool. extgen is part of numpy.f2py.lib package - developed by Pearu Peterson . -*/ - -#ifdef __cplusplus -extern \"C\" { -#endif - -%(Header)s -%(TypeDef)s -%(Extern)s -%(CCode)s -%(CAPICode)s -%(ObjDecl)s - -static PyObject* extgen_module; - -static PyMethodDef extgen_module_methods[] = { - %(ModuleMethod)s - {NULL,NULL,0,NULL} -}; - -static char %(modulename)s_doc[] = -"This module \\"%(modulename)s\\" is generated with ExtGen from NumPy version %(numpy_version)s." -%(ModuleTitle)s -%(ModuleDescr)s -%(ModuleFuncDoc)s -; - -PyMODINIT_FUNC init%(modulename)s(void) { - PyObject* extgen_module_dict = NULL; - PyObject* extgen_str_obj = NULL; - - extgen_module = Py_InitModule("%(modulename)s", extgen_module_methods); - if ((extgen_module_dict = PyModule_GetDict(extgen_module))==NULL) goto capi_error; - if ((extgen_str_obj = PyString_FromString(%(modulename)s_doc))==NULL) goto capi_error; - PyDict_SetItemString(extgen_module_dict, "__doc__", extgen_str_obj); - Py_DECREF(extgen_str_obj); - - %(ModuleInit)s - - return; -capi_error: - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_RuntimeError, "failed to initialize %(modulename)s module."); - } - return; -} - -#ifdef __cplusplus -} -#endif -''' - - def initialize(self, modulename, *components, **options): - self.modulename = modulename - self._provides = options.pop('provides', - '%s_%s' % (self.__class__.__name__, modulename)) - - self.title = options.pop('title', None) - self.description = options.pop('description', None) - - if options: self.warning('%s unused options: %s\n' % (self.__class__.__name__, options)) - - # all Python extension modules require Python.h - self.add(Component.get('Python.h'), 'Header') - if options.get('numpy'): - self.add(Component.get('arrayobject.h'), 'Header') - self.add(Component.get('import_array'), 'ModuleInit') - map(self.add, components) - return self - - def update_containers(self): - if self.title is not None: - self.container_ModuleTitle += self.title - if self.description is not None: - self.container_ModuleDescr += self.description - - def build(self): - import os - import sys - extfile = self.generate() - srcfile = os.path.abspath('%smodule.c' % (self.modulename)) - f = open(srcfile, 'w') - f.write(extfile) - f.close() - modulename = self.modulename - setup_py = """ -def configuration(parent_package='', top_path = ''): - from numpy.distutils.misc_util import Configuration - config = Configuration('',parent_package,top_path) - config.add_extension('%(modulename)s', - sources = ['%(srcfile)s']) - return config -if __name__ == '__main__': - from numpy.distutils.core import setup - setup(configuration=configuration) -""" % (locals()) - setupfile = os.path.abspath('setup_extgen.py') - f = open(setupfile, 'w') - f.write(setup_py) - f.close() - setup_args = ['build_ext','--build-lib','.'] - setup_cmd = ' '.join([sys.executable,setupfile]+setup_args) - build_dir = '.' - from numpy.distutils.exec_command import exec_command - status, output = exec_command(setup_cmd) - if status: - raise "Failed to build (status=%s)." % (`status`) - exec 'import %s as m' % (modulename) - return m - -def _test(): - import doctest - doctest.testmod() - -if __name__ == "__main__": - _test() Deleted: trunk/numpy/f2py/lib/extgen/predefined_components.py =================================================================== --- trunk/numpy/f2py/lib/extgen/predefined_components.py 2007-08-10 15:25:44 UTC (rev 3963) +++ trunk/numpy/f2py/lib/extgen/predefined_components.py 2007-08-10 15:30:24 UTC (rev 3964) @@ -1,23 +0,0 @@ - -from base import Component -from c_code import CCode - -Component.register( - - CCode('#include "Python.h"', provides='Python.h'), - - CCode('''\ -#define PY_ARRAY_UNIQUE_SYMBOL PyArray_API -#include "numpy/arrayobject.h" -#include "numpy/arrayscalars.h" -''', provides='arrayobject.h'), - - CCode('''\ -import_array(); -if (PyErr_Occurred()) { - PyErr_SetString(PyExc_ImportError, "failed to load array module."); - goto capi_error; -} -''', provides='import_array') - - ) Deleted: trunk/numpy/f2py/lib/extgen/pyc_argument.py =================================================================== --- trunk/numpy/f2py/lib/extgen/pyc_argument.py 2007-08-10 15:25:44 UTC (rev 3963) +++ trunk/numpy/f2py/lib/extgen/pyc_argument.py 2007-08-10 15:30:24 UTC (rev 3964) @@ -1,130 +0,0 @@ - -from base import Component - -class PyCArgument(Component): - - """ - PyCArgument(, ctype, *components, provides=.., - input_intent = 'required' | 'optional' | 'extra' | 'hide', - output_intent = 'hide' | 'return', - input_title = None, - output_title = None, - input_description = None, - output_description = None, - depends = [] - ) - - """ - - template = '%(name)s' - - 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)) - 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', []) - - if options: self.warning('%s unused options: %s\n' % (self.__class__.__name__, options)) - - map(self.add, components) - - self.cvar = name - self.pycvar = None - self.retpycvar = None - - if ctype is None: - ctype = object - if isinstance(ctype, Component.CTypeBase): - pass - elif isinstance(ctype, type) or Component.CTypePython.typeinfo_map.has_key(ctype): - ctype = Component.CTypePython(ctype) - else: - ctype = Component.CType(ctype) - self.ctype = ctype - - retfmt = ctype.get_pyret_fmt(self) - if isinstance(ctype, Component.CTypePython): - 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) - ctype.set_Decl(self) - - return self - - def update_containers(self): - evaluate = self.evaluate - ctype = self.ctype - - # update PyCFunction containers - 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 - - if self.input_intent=='required': - self.container_ReqArgs += self.name - self.container_ReqKWList += '"' + self.name + '"' - self.container_ReqArgFmt += ctype.get_pyarg_fmt(self) - self.container_ReqArgObj += ctype.get_pyarg_obj(self) - self.container_ReqArgsDoc += input_doc_title - self.container_ReqArgsDoc += input_doc_descr - elif self.input_intent=='optional': - self.container_OptArgs += self.name - self.container_OptKWList += '"' + self.name + '"' - self.container_OptArgFmt += ctype.get_pyarg_fmt(self) - self.container_OptArgObj += ctype.get_pyarg_obj(self) - self.container_OptArgsDoc += input_doc_title - self.container_OptArgsDoc += input_doc_descr - elif self.input_intent=='extra': - self.container_ExtArgs += self.name - self.container_ExtKWList += '"' + self.name + '"' - self.container_ExtArgFmt += ctype.get_pyarg_fmt(self) - self.container_ExtArgObj += ctype.get_pyarg_obj(self) - self.container_ExtArgsDoc += input_doc_title - self.container_ExtArgsDoc += input_doc_descr - elif self.input_intent=='hide': - pass - else: - raise NotImplementedError('input_intent=%r' % (self.input_intent)) - - if self.output_intent=='return': - self.container_RetArgs += self.name - self.container_RetFmt += ctype.get_pyret_fmt(self) - self.container_RetObj += ctype.get_pyret_obj(self) - self.container_RetDoc += output_doc_title - self.container_RetDoc += output_doc_descr - elif self.output_intent=='hide': - pass - else: - raise NotImplementedError('output_intent=%r' % (self.output_intent)) - - return - Deleted: trunk/numpy/f2py/lib/extgen/pyc_function.py =================================================================== --- trunk/numpy/f2py/lib/extgen/pyc_function.py 2007-08-10 15:25:44 UTC (rev 3963) +++ trunk/numpy/f2py/lib/extgen/pyc_function.py 2007-08-10 15:30:24 UTC (rev 3964) @@ -1,237 +0,0 @@ - -from base import Component - -class PyCFunction(Component): - - """ - PyCFunction(, *components, provides=..,title=.., description=..) - - >>> from __init__ import * #doctest: +ELLIPSIS - Ignoring... - >>> f = PyCFunction('hello', title='A function.', description='\\nFirst line.\\n2nd line.') - >>> a1_in_doc = '''First line.\\nSecond line.''' - >>> a1_out_doc = '''Single line.''' - >>> f += PyCArgument('a1',output_intent='return', input_title='anything', - ... input_description=a1_in_doc, output_description=a1_out_doc) - >>> f += PyCArgument('c1',input_intent='extra') - >>> f += PyCArgument('b1',input_intent='optional') - >>> f += PyCArgument('d2',input_intent='hide', output_intent='return') - >>> f += PyCArgument('a2',input_intent='required') - >>> f += PyCArgument('c2',input_intent='extra') - >>> f += PyCArgument('b2',input_intent='optional') - >>> m = ExtensionModule('test_PyCFunction', f) - >>> foo = m.build() #doctest: +ELLIPSIS - exec_command... - >>> print foo.hello.__doc__ - hello(a1, a2 [, b1, b2, c1, c2]) -> (a1, d2) - - A function. - - Required arguments: - a1 - a python object, anything - First line. - Second line. - a2 - a python object - - Optional arguments: - b1 - a python object - b2 - a python object - - Extra optional arguments: - c1 - a python object - c2 - a python object - - Return values: - a1 - a python object - Single line. - d2 - a python object - - Description: - - First line. - 2nd line. - >>> print foo.hello(1, 2) - (1, None) - """ - - container_options = dict(\ - Args = dict(separator=', '), - - ReqArgs = dict(separator=', '), - OptArgs = dict(separator=', '), - ExtArgs = dict(separator=', '), - RetArgs = dict(separator=', ', prefix='(', suffix=')', default = 'None', - skip_prefix_when_empty=True, skip_suffix_when_empty=True), - - OptExtArgs = dict(separator=', ', prefix=' [, ', skip_prefix_when_empty=True, - suffix=']', skip_suffix_when_empty=True), - - FuncTitle = dict(default='',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'}), - FuncDescr = dict(default='',prefix='"\\n\\nDescription:\\n"\n" ', - suffix='"',separator='\\n"\n" ', - skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True, replace_map={'\n':'\\n'}), - ReqArgsDoc = dict(default='', prefix='"\\n\\nRequired arguments:\\n"\n" ', - separator='\\n"\n" ', suffix='"', - skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True, replace_map={'\n':'\\n'}), - OptArgsDoc = dict(default='', prefix='"\\n\\nOptional arguments:\\n"\n" ', - separator='\\n"\n" ', suffix='"', - skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True, replace_map={'\n':'\\n'}), - ExtArgsDoc = dict(default='', prefix='"\\n\\nExtra optional arguments:\\n"\n" ', - separator='\\n"\n" ', suffix='"', - skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True, replace_map={'\n':'\\n'}), - RetDoc = dict(default='"Return value:\\n None\\n"', prefix='"\\n\\nReturn values:\\n"\n" ', - separator='\\n"\n" ', suffix='"', - skip_prefix_when_empty=True, skip_suffix_when_empty=True, - use_firstline_indent=True, replace_map={'\n':'\\n'}), - - Decl = dict(default='', use_indent=True), - - ReqKWList = dict(separator=', ', suffix=', ', skip_suffix_when_empty=True), - OptKWList = dict(separator=', ', suffix=', ', skip_suffix_when_empty=True), - ExtKWList = dict(separator=', ', suffix=', ', skip_suffix_when_empty=True), - - ReqArgFmt = dict(separator=''), - OptArgFmt = dict(separator=''), - ExtArgFmt = dict(separator=''), - OptExtArgFmt = dict(separator='', prefix='|', skip_prefix_when_empty=True), - - ReqArgObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), - OptArgObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), - ExtArgObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), - - FromPyObj = dict(default='', use_indent=True), - Exec = dict(default='', use_indent=True), - PyObjFrom = dict(default='', use_indent=True), - - RetFmt = dict(separator=''), - RetObj = dict(separator=', ', prefix=', ', skip_prefix_when_empty=True), - - CleanPyObjFrom = dict(default='', reverse=True, use_indent=True), - CleanExec = dict(default='', reverse=True, use_indent=True), - CleanFromPyObj = dict(default='', reverse=True, use_indent=True), - ) - - component_container_map = dict(CCode = 'Exec', - PyCArgument = 'Args', - CDecl = 'Decl') - - template = ''' -static char %(pyc_name)s_doc[] = -" %(name)s(%(ReqArgs)s%(OptExtArgs)s) -> %(RetArgs)s" -%(FuncTitle)s -%(ReqArgsDoc)s -%(OptArgsDoc)s -%(ExtArgsDoc)s -%(RetDoc)s -%(FuncDescr)s -; - -static PyObject* -%(pyc_name)s -(PyObject *pyc_self, PyObject *pyc_args, PyObject *pyc_keywds) { - PyObject * volatile pyc_buildvalue = NULL; - volatile int capi_success = 1; - %(Decl)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 - %(Exec)s - capi_success = !PyErr_Occurred(); - if (capi_success) { - %(PyObjFrom)s - pyc_buildvalue = Py_BuildValue("%(RetFmt)s"%(RetObj)s); - %(CleanPyObjFrom)s - } - %(CleanExec)s - %(CleanFromPyObj)s - } - return pyc_buildvalue; -} -''' - - def initialize(self, name, *components, **options): - self.name = name - self.pyc_name = 'pyc_function_'+name - self._provides = options.pop('provides', - '%s_%s' % (self.__class__.__name__, name)) - self.title = options.pop('title', None) - self.description = options.pop('description', None) - - if options: self.warning('%s unused options: %s\n' % (self.__class__.__name__, options)) - - map(self.add, components) - return self - - def init_containers(self): - return - - def update_containers(self): - evaluate = self.evaluate - - # update ExtensionModule containers: - t = '{"%(name)s", (PyCFunction)%(pyc_name)s,\n METH_VARARGS | METH_KEYWORDS, %(pyc_name)s_doc}' - self.container_ModuleMethod.add(evaluate(t), self.name) - - # update local containers: - self.container_OptExtArgs += self.container_OptArgs + self.container_ExtArgs - self.container_OptExtArgFmt += self.container_OptArgFmt + self.container_ExtArgFmt - self.container_ModuleFuncDoc += evaluate('%(name)s(%(ReqArgs)s%(OptExtArgs)s) -> %(RetArgs)s') - if self.title is not None: - self.container_FuncTitle += self.title - self.container_ModuleFuncDoc += ' ' + self.title - if self.description is not None: - self.container_FuncDescr += self.description - - # resolve dependencies - sorted_arguments = [] - sorted_names = [] - comp_map = {} - dep_map = {} - for (c,l) in self.components: - if not isinstance(c, Component.PyCArgument): - continue - d = [n for n in c.depends if n not in sorted_names] - if not d: - sorted_arguments.append((c,l)) - sorted_names.append(c.name) - else: - comp_map[c.name] = (c,l) - dep_map[c.name] = d - - while dep_map: - dep_map_copy = dep_map.copy() - for name, deps in dep_map.items(): - d = [n for n in deps if dep_map.has_key(n)] - if not d: - sorted_arguments.append(comp_map[name]) - del dep_map[name] - else: - dep_map[name] = d - if dep_map_copy==dep_map: - self.warnign('%s: detected cyclic dependencies in %r, incorrect behavior is expected.\n'\ - % (self.provides, dep_map)) - sorted_arguments += dep_map.values() - break - - for c, l in sorted_arguments: - old_parent = c.parent - c.parent = self - c.ctype.set_converters(c) - c.parent = old_parent - - return - - -def _test(): - import doctest - doctest.testmod() - -if __name__ == "__main__": - _test() From numpy-svn at scipy.org Wed Aug 15 12:17:26 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Wed, 15 Aug 2007 11:17:26 -0500 (CDT) Subject: [Numpy-svn] r3965 - branches/1.0.3.x Message-ID: <20070815161726.B49F439C0C0@new.scipy.org> Author: jarrod.millman Date: 2007-08-15 11:17:24 -0500 (Wed, 15 Aug 2007) New Revision: 3965 Modified: branches/1.0.3.x/setup.py Log: finish reverting revision to old tag [3845] Modified: branches/1.0.3.x/setup.py =================================================================== --- branches/1.0.3.x/setup.py 2007-08-10 15:30:24 UTC (rev 3964) +++ branches/1.0.3.x/setup.py 2007-08-15 16:17:24 UTC (rev 3965) @@ -47,10 +47,9 @@ quiet=True) config.add_subpackage('numpy') - - config.add_data_files(('numpy','*.txt')) - config.add_data_files(('.','COMPATIBILITY'),('.','scipy_compatibility'), - ('.','site.cfg.example')) + + config.add_data_files(('numpy',['*.txt','COMPATIBILITY', + 'scipy_compatibility'])) config.get_version('numpy/version.py') # sets config.version From numpy-svn at scipy.org Wed Aug 15 16:48:18 2007 From: numpy-svn at scipy.org (numpy-svn at scipy.org) Date: Wed, 15 Aug 2007 15:48:18 -0500 (CDT) Subject: [Numpy-svn] r3966 - trunk/numpy/doc/swig Message-ID: <20070815204818.843E539C02E@new.scipy.org> Author: wfspotz at sandia.gov Date: 2007-08-15 15:48:11 -0500 (Wed, 15 Aug 2007) New Revision: 3966 Modified: trunk/numpy/doc/swig/numpy_swig.html trunk/numpy/doc/swig/numpy_swig.pdf trunk/numpy/doc/swig/numpy_swig.txt trunk/numpy/doc/swig/testing.pdf Log: Improved formatting of typemap signature lists Modified: trunk/numpy/doc/swig/numpy_swig.html =================================================================== --- trunk/numpy/doc/swig/numpy_swig.html 2007-08-15 16:17:24 UTC (rev 3965) +++ trunk/numpy/doc/swig/numpy_swig.html 2007-08-15 20:48:11 UTC (rev 3966) @@ -5,7 +5,7 @@ numpy.i: a SWIG Interface File for NumPy - +