pygccxml-commit Mailing List for C++ Python language bindings (Page 62)
Brought to you by:
mbaas,
roman_yakovenko
You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
(190) |
Apr
(166) |
May
(170) |
Jun
(75) |
Jul
(105) |
Aug
(131) |
Sep
(99) |
Oct
(84) |
Nov
(67) |
Dec
(54) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(66) |
Feb
(49) |
Mar
(25) |
Apr
(62) |
May
(21) |
Jun
(34) |
Jul
(9) |
Aug
(21) |
Sep
(5) |
Oct
|
Nov
(63) |
Dec
(34) |
2008 |
Jan
(10) |
Feb
(42) |
Mar
(26) |
Apr
(25) |
May
(6) |
Jun
(40) |
Jul
(18) |
Aug
(29) |
Sep
(6) |
Oct
(32) |
Nov
(14) |
Dec
(56) |
2009 |
Jan
(127) |
Feb
(52) |
Mar
(2) |
Apr
(10) |
May
(29) |
Jun
(3) |
Jul
|
Aug
(16) |
Sep
(4) |
Oct
(11) |
Nov
(8) |
Dec
(14) |
2010 |
Jan
(31) |
Feb
(1) |
Mar
(7) |
Apr
(9) |
May
(1) |
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2011 |
Jan
|
Feb
(8) |
Mar
(4) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2014 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <mb...@us...> - 2006-07-18 08:52:43
|
Revision: 316 Author: mbaas Date: 2006-07-18 01:52:35 -0700 (Tue, 18 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=316&view=rev Log Message: ----------- Added *.pyc files to the ignore list Property Changed: ---------------- pyplusplus_dev/contrib/arrayinfo/ pyplusplus_dev/contrib/pypp_api/pypp_api/ Property changes on: pyplusplus_dev/contrib/arrayinfo ___________________________________________________________________ Name: svn:ignore + *.pyc Property changes on: pyplusplus_dev/contrib/pypp_api/pypp_api ___________________________________________________________________ Name: svn:ignore + *.pyc This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-07-18 08:50:50
|
Revision: 315 Author: mbaas Date: 2006-07-18 01:50:44 -0700 (Tue, 18 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=315&view=rev Log Message: ----------- Added the contrib stuff to the source archive and fixed a syntax error in the manifest file that prevented the examples directory from being included in the source archive. Modified Paths: -------------- pyplusplus_dev/MANIFEST.in Modified: pyplusplus_dev/MANIFEST.in =================================================================== --- pyplusplus_dev/MANIFEST.in 2006-07-18 08:36:26 UTC (rev 314) +++ pyplusplus_dev/MANIFEST.in 2006-07-18 08:50:44 UTC (rev 315) @@ -15,4 +15,5 @@ include docs/tutorials/* prune docs/*/.svn prune docs/*/*/.svn -recursive-include examples/* +recursive-include examples * +recursive-include contrib *.py *.txt This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-07-18 08:36:36
|
Revision: 314 Author: mbaas Date: 2006-07-18 01:36:26 -0700 (Tue, 18 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=314&view=rev Log Message: ----------- Added the MANIFEST.in file to the source archive Modified Paths: -------------- pygccxml_dev/MANIFEST.in Modified: pygccxml_dev/MANIFEST.in =================================================================== --- pygccxml_dev/MANIFEST.in 2006-07-18 08:32:45 UTC (rev 313) +++ pygccxml_dev/MANIFEST.in 2006-07-18 08:36:26 UTC (rev 314) @@ -1,4 +1,5 @@ include LICENSE_1_0.txt +include MANIFEST.in include unittests/*.py include unittests/data/*.hpp include unittests/data/*.xml This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-07-18 08:32:55
|
Revision: 313 Author: mbaas Date: 2006-07-18 01:32:45 -0700 (Tue, 18 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=313&view=rev Log Message: ----------- Added the alternative pypp_api contribution that was formerly known as the 'experimental' API. Added Paths: ----------- pyplusplus_dev/contrib/pypp_api/ pyplusplus_dev/contrib/pypp_api/generate_docs.py pyplusplus_dev/contrib/pypp_api/pypp_api/ pyplusplus_dev/contrib/pypp_api/pypp_api/__init__.py pyplusplus_dev/contrib/pypp_api/pypp_api/argpolicy.py pyplusplus_dev/contrib/pypp_api/pypp_api/decltypes.py pyplusplus_dev/contrib/pypp_api/pypp_api/declwrapper.py pyplusplus_dev/contrib/pypp_api/pypp_api/filters.py pyplusplus_dev/contrib/pypp_api/pypp_api/modulebuilder.py pyplusplus_dev/contrib/pypp_api/pypp_api/selection.py pyplusplus_dev/contrib/pypp_api/pypp_api/treerange.py Added: pyplusplus_dev/contrib/pypp_api/generate_docs.py =================================================================== --- pyplusplus_dev/contrib/pypp_api/generate_docs.py (rev 0) +++ pyplusplus_dev/contrib/pypp_api/generate_docs.py 2006-07-18 08:32:45 UTC (rev 313) @@ -0,0 +1,12 @@ +# Generate documentation using epydoc +# +import os, os.path + +default_format = "epytext" + + +cmd_line = "epydoc -o html --docformat %s pypp_api"%(default_format) + +print "Running: ", cmd_line +os.system(cmd_line) + Added: pyplusplus_dev/contrib/pypp_api/pypp_api/__init__.py =================================================================== --- pyplusplus_dev/contrib/pypp_api/pypp_api/__init__.py (rev 0) +++ pyplusplus_dev/contrib/pypp_api/pypp_api/__init__.py 2006-07-18 08:32:45 UTC (rev 313) @@ -0,0 +1,72 @@ +# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +"""This is an experimental module to high-level API testing. + +This module provides a simplified high-level API for using +pygccxml and pyplusplus. It is currently under heavy construction. + +Quickstart Usage +================ + + 1. Create an instance of the L{ModuleBuilder} class that serves as main + entry point for controlling pygccxml and pyplusplus. Parameters for + configuring pygccxml/pyplusplus can be passed in the constructor:: + + from pypp_api import * + + mb = ModuleBuilder(...) + + 2. Parse the header files using L{parse()<ModuleBuilder.parse>} and + customize your bindings:: + + toplevel_namespace = mb.parse() + + MyClass = toplevel_namespace.Class("MyClass") + MyClass.expose() + + MyClass.Method("foo").setPolicy(return_internal_reference()) + ... + + 3. Write the C++ source files using + L{writeModule()<ModuleBuilder.writeModule>}:: + + mb.writeModule() + + +Detailed Usage +============== + +Add detailed usage here. + +@todo: Add quickstart and detailed documentation for API. +@author: Allen Bierbaum +@author: Matthias Baas +@license: Boost Software License, Version 1.0 (see http://www.boost.org/LICENSE_1_0.txt) +@copyright: 2006 Allen Bierbaum, Matthias Baas +""" + + +# Bring in call policies to use +from pyplusplus.decl_wrappers import return_self +from pyplusplus.decl_wrappers import return_internal_reference +from pyplusplus.decl_wrappers import with_custodian_and_ward +from pyplusplus.decl_wrappers import copy_const_reference +from pyplusplus.decl_wrappers import copy_non_const_reference +from pyplusplus.decl_wrappers import manage_new_object +from pyplusplus.decl_wrappers import reference_existing_object +from pyplusplus.decl_wrappers import return_by_value +from pyplusplus.decl_wrappers import return_opaque_pointer +from pyplusplus.decl_wrappers import return_value_policy + +from pygccxml.declarations import ACCESS_TYPES +PUBLIC = ACCESS_TYPES.PUBLIC +PROTECTED = ACCESS_TYPES.PROTECTED +PRIVATE = ACCESS_TYPES.PRIVATE + +from decltypes import arg, cpp +from argpolicy import * + +from modulebuilder import ModuleBuilder Added: pyplusplus_dev/contrib/pypp_api/pypp_api/argpolicy.py =================================================================== --- pyplusplus_dev/contrib/pypp_api/pypp_api/argpolicy.py (rev 0) +++ pyplusplus_dev/contrib/pypp_api/pypp_api/argpolicy.py 2006-07-18 08:32:45 UTC (rev 313) @@ -0,0 +1,574 @@ +# Copyright 2006 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# +# Initial author: Matthias Baas + +import sys, os.path, copy +from pygccxml import declarations +from pyplusplus import code_creators +from pyplusplus import decl_wrappers +from pyplusplus import file_writers +from declwrapper import IDecl + +# ArgPolicyManager +class ArgPolicyManager: + """Manages all argument policies for a project. + + Before the code creator tree is created, setArgPolicy() has to be + called on any method that requires this decoration. + After the decoration is done and the code creator tree has been + built, the updateCreators() method has be called to update the tree. + Finally, the writeFiles() method can be called to write the additional + wrapper files. + """ + + def __init__(self, includePaths=[]): + """Constructor. + + The includePaths argument should be the same list that was passed + to the module builder constructor. It is used to remove the + unnecessary parts from include file names. + + @param includePaths: List of include paths + @type includePaths: list of str + """ + + self.includePaths = includePaths + + # Key: Class declaration / Value: list of WrapperManagers + self.classes = {} + + # Key: Include file name / Value: Irrelevant + self.includes = {} + + # The root of the code creator tree + self.creator_root = None + + # setArgPolicy + def setArgPolicy(self, decl, policies): + """Assign argument policies to a declaration. + + @param decl: The calldef declaration that receives the policies + @param policies: A sequence of policy objects. + """ + # Get the class declaration that belongs to decl + cls = self._classDecl(decl) + if cls==None: + raise NotImplemented, "Arg policies on free functions are not supported yet" + # Create the wrapper "code creator"... + wm = WrapperManager(decl, policies) + wm.wrappername = self._wrapperName(cls, decl) + if cls in self.classes: + self.classes[cls].append(wm) + else: + self.classes[cls] = [wm] + + # Ignore the declaration and replace it with the wrapper... + decl.exclude() + arglist = wm.wrapperargs[1:] + if len(arglist)>0: + dummydecl = decl_wrappers.member_function_t(arguments=arglist) +# c = code_creators.function_t(dummydecl) + c = code_creators.mem_fun_t(dummydecl) +# args = c._keywords_args() + args = c.keywords_args() + cls.add_code('def( "%s", %s, %s)'%(decl.alias, wm.wrappername, args)) + else: + cls.add_code('def( "%s", %s)'%(decl.alias, wm.wrappername)) +# IDecl([cls]).cdef(decl.alias, wm.wrappername) + # Add the header to the include files... + incname = self._outputFilename(cls)+file_writers.multiple_files_t.HEADER_EXT + if incname not in self.includes: + self.includes[incname] = 1 + + # updateCreators + def updateCreators(self, root): + """Modifies the code creator tree. + + This method has to be called after the code creator tree was built + and before the files were written. + + @param root: The root of the code creator tree + @type root: module_t + """ + self.creator_root = root + for inc in self.includes: + root.adopt_include(code_creators.include_t(inc)) + + # writeFiles + def writeFiles(self, path): + """Write additional source files. + + @param path: The output directory + @type path: str + """ + + # Key: sigid / Value: list of (decl, proto) + sigids = {} + # This dict contains the ambiguous wrappers with the same sigid + # Key: sigid / Value: Reference to list in sigids + ambiguous = {} + + for cls in self.classes: + basename = self._outputFilename(cls) + hname = basename+file_writers.multiple_files_t.HEADER_EXT + cppname = basename+file_writers.multiple_files_t.SOURCE_EXT + + guard = "__%s_pyplusplus_wrapper__"%cls.alias + hsrc = "#ifndef %s\n"%guard + hsrc += "#define %s\n\n"%guard + hsrc += "#include <boost/python.hpp>\n" + # Add the include file where the original class is defined... + incd = code_creators.include_directories_t() + incd.user_defined = self.includePaths + header = incd.normalize_header(cls.location.file_name) + hsrc += "#include <%s>\n\n"%header + + # Include all 'global' include files... + cppsrc = "" + include_creators = filter(lambda creator: isinstance( creator, code_creators.include_t) +# and not isinstance(creator, code_creators.precompiled_header_t) + , self.creator_root.creators) + includes = map(lambda include_creator: include_creator.create() + , include_creators ) + cppsrc += os.linesep.join(includes) + cppsrc += "\n\n" + +# cppsrc += '#include "%s"\n\n'%hname + wms = self.classes[cls] + for wm in wms: + sigid,proto,src = wm.create() + if sigid in sigids: + sigids[sigid].append((wm.decl, proto)) + ambiguous[sigid] = sigids[sigid] + else: + sigids[sigid] = [(wm.decl, proto)] + hsrc += "%s;\n"%proto + cppsrc += (60*"/")+"\n" + cppsrc += "// Original:\n// %s\n"%wm.decl + cppsrc += (60*"/")+"\n" + cppsrc += "%s\n"%src + + hsrc += "\n#endif\n" + + file_writers.writer_t.write_file(os.path.join(path, hname), hsrc) + file_writers.writer_t.write_file(os.path.join(path, cppname), cppsrc) + + # Have there been any ambiguous wrappers? + if ambiguous!={}: + print 70*"=" + print "ERROR: There are ambiguous wrapper functions:" + for sigid in ambiguous: + print 70*"-" + for i, (decl,proto) in enumerate(ambiguous[sigid]): + print "(%d) %s"%(i+1, decl) + print "->" + for i, (decl,proto) in enumerate(ambiguous[sigid]): + print "(%d) %s"%(i+1, proto) + print 70*"-" + print "***ABORTING because of %d ambiguous wrapper functions***"%(len(ambiguous)) + sys.exit(1) + + + def _wrapperName(self, clsdecl, memberdecl): + """Return the name of the wrapper function. + """ + # The id of the memberdecl is added to make the name unique if there + # are several (overloaded) functions with the same name +# declid = abs(id(memberdecl)) + # Use a hash of the declaration string (i.e. the signature) because + # this doesn't change the source file between runs + declid = hex(abs(hash(str(memberdecl)))) + return "%s_%s_wrapper_%s"%(clsdecl.alias, memberdecl.alias, declid) + + def _outputFilename(self, cls): + """Return the output file name of the wrapper file (without extension). + """ + return "%s_wrappers"%cls.alias + + # _classDecl + def _classDecl(self, decl): + """Return the class declaration that belongs to a member declaration. + """ + while decl.parent!=None: + parent = decl.parent + if isinstance(parent, declarations.class_t): + return parent + decl = parent + return None + + +class ArgTransformerBase: + """Base class for an argument policy class. + """ + def __init__(self): + pass + +# def requireInclude(self, include): +# pass + + def prepareWrapper(self, wm): + pass + + def preCall(self, wm): + pass + + def postCall(self, wm): + pass + + def cleanup(self, wm): + pass + +# Output +class Output(ArgTransformerBase): + def __init__(self, idx): + ArgTransformerBase.__init__(self) + self.idx = idx + + def __str__(self): + return "Output(%d)"%(self.idx) + + def prepareWrapper(self, wm): + arg = wm.removeArg(self.idx) + + reftype = arg.type + if not (isinstance(reftype, declarations.reference_t) or + isinstance(reftype, declarations.pointer_t)): + raise ValueError, 'Output variable %d ("%s") must be a reference or a pointer (got %s)'%(self.idx, arg.name, arg.type) + + wm.declareLocal(arg.name, str(reftype.base)) + wm.appendResult(arg.name) + + if isinstance(reftype, declarations.pointer_t): + wm.replaceCallArg(self.idx, "&%s"%arg.name) + +# InputArray +class InputArray(ArgTransformerBase): + def __init__(self, idx, size): + ArgTransformerBase.__init__(self) + self.idx = idx + self.size = size + self.argname = None + self.basetype = None + self.carray = None + self.ivar = None + + def __str__(self): + return "InputArray(%d,%d)"%(self.idx, self.size) + + def prepareWrapper(self, wm): + # Remove the original argument... + arg = wm.removeArg(self.idx) + if not (isinstance(arg.type, declarations.pointer_t) or + isinstance(arg.type, declarations.array_t)): + raise ValueError, "Argument %d (%s) must be a pointer."%(self.idx, arg.name) + + # ...and replace it with a Python object. + newarg = declarations.argument_t(arg.name, "boost::python::object") + wm.insertArg(self.idx, newarg) + + self.argname = arg.name + self.basetype = str(arg.type.base).replace("const", "").strip() + + # Declare a variable that will hold the C array... + self.carray = wm.declareLocal("c_"+arg.name, self.basetype, size=self.size) + # and a int which is used for the loop + self.ivar = wm.declareLocal("i", "int") + + wm.replaceCallArg(self.idx, self.carray) + + def preCall(self, wm): + res = "" + res += "// Copy the sequence '%s' into '%s'...\n"%(self.argname, self.carray) + res += 'if (%s.attr("__len__")()!=%d)\n'%(self.argname, self.size) + res += '{\n' + res += ' PyErr_SetString(PyExc_ValueError, "Invalid sequence size (expected %d)");\n'%self.size + res += ' boost::python::throw_error_already_set();\n' + res += '}\n' + res += "for(%s=0; %s<%d; %s++)\n"%(self.ivar, self.ivar, self.size, self.ivar) + res += " %s[%s] = boost::python::extract< %s >(%s[%s]);"%(self.carray, self.ivar, self.basetype, self.argname , self.ivar) + return res + +# OutputArray +class OutputArray(ArgTransformerBase): + def __init__(self, idx, size): + ArgTransformerBase.__init__(self) + self.idx = idx + self.size = size + self.argname = None + self.basetype = None + self.pyval = None + self.cval = None + self.ivar = None + + def __str__(self): + return "OutputArray(%d,%d)"%(self.idx, self.size) + + def prepareWrapper(self, wm): + # Remove the original argument... + arg = wm.removeArg(self.idx) + if not (isinstance(arg.type, declarations.pointer_t) or + isinstance(arg.type, declarations.array_t)): + raise ValueError, "Argument %d (%s) must be a pointer."%(self.idx, arg.name) + + self.argname = arg.name + self.basetype = str(arg.type.base).replace("const", "").strip() + + # Declare a variable that will hold the C array... + self.cval = wm.declareLocal("c_"+self.argname, self.basetype, size=self.size) + # Declare a Python list which will receive the output... + self.pyval = wm.declareLocal(self.argname, "boost::python::list") + # ...and add it to the result + wm.appendResult(arg.name) + + # Declare an int which is used for the loop + self.ivar = wm.declareLocal("i", "int") + + wm.replaceCallArg(self.idx, self.cval) + + def postCall(self, wm): + res = "" + res += "// Copy the sequence '%s' into '%s'...\n"%(self.cval, self.pyval) + res += "for(%s=0; %s<%d; %s++)\n"%(self.ivar, self.ivar, self.size, self.ivar) + res += " %s.append(%s[%s]);"%(self.pyval, self.cval , self.ivar) + return res + + +# WrapperManager +class WrapperManager: + """ + represents source code for a wrapper function/method + """ + + def __init__(self, decl, transformers): + + self.decl = decl + self.transformers = transformers + + # The original function name + self.funcname = decl.name + + # Create the arg list of the original function (including the + # return type) + argnames = map(lambda a: a.name, decl.arguments) + if str(decl.return_type)=="void": + ret = None + argnames = [None]+argnames + else: + resname = self._makeNameUnique("res", argnames) + ret = declarations.argument_t(resname, decl.return_type, None) + argnames = [resname]+argnames + self.funcargs = [ret]+decl.arguments + # Initialize the argument strings used for invoking the original + # function + self.callargs = argnames + + # The name of the wrapper function + self.wrappername = "%s_wrapper"%decl.name + # The arguments of the wrapper function + self.wrapperargs = copy.copy(self.funcargs) + + # Result tuple + self.resulttuple = [] + + self.declared_vars = {} + self.local_var_list = [] + + # Return the original return value by default + if self.funcargs[0]!=None: + self.appendResult(self.funcargs[0].name) + + for trans in self.transformers: + trans.prepareWrapper(self) + + + # removeArg + def removeArg(self, idx): + """Remove an argument from the wrapper function. + + @param idx: Argument index of the original function + @type idx: int + @returns: Returns the argument_t object that was removed (or None + if idx is 0 and the function has no return type) + """ + if idx==0 and self.funcargs[0]==None: + raise ValueError, 'Function "%s" has no return value'%self.decl + argname = self.funcargs[idx].name + for i,arg in enumerate(self.wrapperargs): + if arg!=None: + if arg.name==argname: + res = self.wrapperargs[i] + if i>0: + del self.wrapperargs[i] + else: + self.wrapperargs[0] = None + return res + + raise ValueError, 'Argument %d ("%s") not found on the wrapper function'%(idx, argname) + + # insertArg + def insertArg(self, idx, arg): + """Insert a new argument into the argument list of the wrapper function. + + @param idx: New argument index + @type idx: int + @param arg: New argument object + @type arg: argument_t + """ + if idx>=0: + self.wrapperargs.insert(idx, arg) + else: + self.wrapperargs.insert(len(self.wrapperargs)+idx+1, arg) + + # appendResult + def appendResult(self, varname): + self.resulttuple.append(varname) + + # removeResult + def removeResult(self, varname): + self.resulttuple.remove(varname) + + # replaceCallArg + def replaceCallArg(self, idx, callstr): + self.callargs[idx] = callstr + + # declareLocal + def declareLocal(self, name, type, size=None, default=None): + """Declare a local variable and return its final name. + """ + name = self._makeNameUnique(name, self.declared_vars) + self.declared_vars[name] = (type,size,default) + self.local_var_list.append((name, type, size, default)) + return name + + # create + def create(self): + """ + Returns the signature id, the prototype and the function definition. + """ + + # Declare the args that are "output" only and that have been + # converted to local variables... +# newargnames = map(lambda a: a.name, self.wrapperargs[1:]) +# for a in self.funcargs[1:]: +# if a.name not in newargnames: +# self.declareLocal(a.name, str(a.type)) + + if self.funcargs[0]!=None: + self.declareLocal(self.funcargs[0].name, self.funcargs[0].type) + + if len(self.resulttuple)==0: + rettype = "void" + elif len(self.resulttuple)==1: + varname = self.resulttuple[0] + rettype = self.declared_vars[varname][0] + elif len(self.resulttuple)>1: + rettype = "boost::python::tuple" +# self.wrapperargs[0].type = boost_python_t("tuple") + +# if self.wrapperargs[0]==None: +# rettype = "void" +# else: +# rettype = str(self.wrapperargs[0].type) + + # Function header... + a = map(lambda a: str(a), self.wrapperargs[1:]) + asig = map(lambda a: str(a.type), self.wrapperargs[1:]) + cls = self._classDecl(self.decl) + if cls!=None: + a = ["%s& self"%cls.name]+a + asig = ["%s&"%cls.name]+asig + proto = "%s %s(%s)"%(rettype, self.wrappername, ", ".join(a)) + sigid = "%s(%s)"%(self.wrappername, ", ".join(asig)) + # Remove the default values for the function definition... + a2 = map(lambda s: s.split("=")[0], a) + proto2 = "%s %s(%s)"%(rettype, self.wrappername, ", ".join(a2)) + res = "%s\n{\n"%(proto2) + + # Add the declarations... + for varname,type,size,default in self.local_var_list: + if default==None: + res += " %s %s"%(type, varname) + else: + res += " %s %s = %s"%(type, varname, default) + if size!=None: + res += "[%d]"%size + res += ";\n" + res += "\n" + + # Precall code... + src = map(lambda trans: trans.preCall(self), self.transformers) + src = filter(lambda x: x!=None, src) + src = "\n\n".join(src) + res += self._indent(2, src) +# for trans in self.transformers: +# code = trans.preCall(self) +# if code!=None: +# res += self._indent(2, code) + + # Add the function call... + res += "\n // Invoke the wrapped function\n" + res += " " + if self.callargs[0]!=None: + res += "%s = "%self.callargs[0] + if cls!=None: + res += "self." + res += "%s(%s);\n\n"%(self.funcname, ", ".join(self.callargs[1:])) + + # Postcall code... + src = map(lambda trans: trans.postCall(self), self.transformers) + src = filter(lambda x: x!=None, src) + src = "\n\n".join(src) + res += self._indent(2, src) +# for trans in self.transformers: +# code = trans.postCall(self) +# if code!=None: +# res += self._indent(2, code) + + # Return the result + if len(self.resulttuple)==1: + res += " return %s;\n"%self.resulttuple[0] + elif len(self.resulttuple)>1: + res += " return boost::python::make_tuple(%s);\n"%(", ".join(self.resulttuple)) + + res += "}\n" + return sigid, proto, res.replace("\n\n\n", "\n\n") + + # _indent + def _indent(self, n, code): + """Indent source code. + """ + if code=="": + return "" + return "\n".join(map(lambda s: (n*" ")+s, code.split("\n")))+"\n" + + # _classDecl + def _classDecl(self, decl): + """Return the class declaration that belongs to a member declaration. + """ + while decl.parent!=None: + parent = decl.parent + if isinstance(parent, declarations.class_t): + return parent + decl = parent + return None + + # _makeNameUnique + def _makeNameUnique(self, name, names): + """Make a variable name unique so that there's no clash with other names. + + names must be a dict or a list. + """ + if name not in names: + return name + + n = 2 + while 1: + newname = "%s_%d"%(name, n) + if newname not in names: + return newname + n += 1 + + Added: pyplusplus_dev/contrib/pypp_api/pypp_api/decltypes.py =================================================================== --- pyplusplus_dev/contrib/pypp_api/pypp_api/decltypes.py (rev 0) +++ pyplusplus_dev/contrib/pypp_api/pypp_api/decltypes.py 2006-07-18 08:32:45 UTC (rev 313) @@ -0,0 +1,73 @@ +# Copyright 2006 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# +# Initial author: Matthias Baas + +"""This module contains some basic definitions. +""" + +NAMESPACE = 0x01 +CLASS = 0x02 +MEMBER_FUNCTION = 0x04 +METHOD = MEMBER_FUNCTION # this also includes constructors +FREE_FUNCTION = 0x08 +FUNCTION = FREE_FUNCTION +CONSTRUCTOR = 0x10 # limit to constructors +ENUM = 0x20 +VARIABLE = 0x40 + +CALLABLE = METHOD | FUNCTION | CONSTRUCTOR + +# cpp +class cpp: + """This class wraps C++ source code for default values. + + This class is used together with the 'arg' class to provide + C++ source code as default value. Example: + + method.cdef("foo", "&Foo::foo", arg("ptr", cpp("bp::object()"))) + + The cpp class prevents the generation of apostrophes (as it would + happen when only a string would be passed). + """ + def __init__(self, src): + self.src = src + + def __str__(self): + return self.src + +# arg +class arg: + """Provide keyword arguments for methods/functions. + + This class is equivalent to the Boost.Python arg class + and is used together with the Decl.cdef method. + """ + + def __init__(self, name, default=None): + """Constructor. + + @param name: Argument name + @type name: str + @param default: Optional default value + """ + self.name = name + self.default = default + + def __str__(self): + res = 'arg("%s")'%self.name + if self.default!=None: + res += "=%s"%self.py2cpp(self.default) + return res + + def py2cpp(self, val): + """Convert a Python value to a C++ value. + """ + if type(val)==bool: + return str(val).lower() + elif type(val)==str: + return '"%s"'%val + else: + return str(val) Added: pyplusplus_dev/contrib/pypp_api/pypp_api/declwrapper.py =================================================================== --- pyplusplus_dev/contrib/pypp_api/pypp_api/declwrapper.py (rev 0) +++ pyplusplus_dev/contrib/pypp_api/pypp_api/declwrapper.py 2006-07-18 08:32:45 UTC (rev 313) @@ -0,0 +1,748 @@ +# Copyright 2006 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# +# Initial author: Matthias Baas + +"""This module contains the 'Declaration wrapper' object. +""" + +import sys, os.path, inspect, types +from filters import * +import decltypes +import pygccxml +import pyplusplus +import selection + +# Create an alias for the builtin type() function +_type = type + +allow_empty_queries = False +default_recursive = False +query_log = None +decoration_log = None + +# If this is set to True an attempt to decorate a declaration will +# result in an error (this is set after the code creators have been created) +decl_lock = False + +# IDecl +class IDecl: + """Declaration interface. + + This class represents the interface to the declaration tree. Its + main purpose is to "decorate" the nodes in the tree with + information about how the binding is to be created. Instances of + this class are never created by the user, instead they are + returned by the API. + + You can think of this class as a container for declaration nodes + that are selected by matching a set of filters. + + @group Selection interface: Decl, Namespace, Class, Constructor, Method, Function, Enum, Var, Decls, Namespaces, Classes, Constructors, Methods, Functions, Enums, Vars + @group Decoration interface: expose, ignore, exclude, finalize, rename, setPolicy, setArgPolicy, disableKeywordArgs, setHeldType, addMethod, cdef, staticmethod + """ + + def __init__(self, decls, filter=None, modulebuilder=None): + """Constructor. + + @param decls: One or more declarations that should be stored in this instance + @type decls: declaration_t or list of declaration_t + @param filter: Filter string (only for informational purposes) + @type filter: str + @param modulebuilder: The module builder object this object belongs to + """ + global query_log + + self.modulebuilder = modulebuilder + + if type(decls)!=list: + decls = [decls] + + # A sequence containing the underlying pygccxml declaration nodes. + # (actually these are decl_wrapper nodes) + self.decl_handles = decls + + # Determine where this instance was created... + filename,funcname,linenr,sourceline = self._sourceInfo() + self.filename = filename + self.funcname = funcname + self.linenr = linenr + self.sourceline = sourceline + + # Dump info about this query... + if query_log: + print >>query_log, 70*"-" + if funcname==None: + print >>query_log, "%s, %d: %s"%(self.filename, self.linenr, self.sourceline) + else: + print >>query_log, "%s, %s(), %d: %s"%(self.filename, self.funcname, self.linenr, self.sourceline) + if filter!=None: + print >>query_log, "Filter: %s"%filter + for decl in self.decl_handles: + print >>query_log, " -> %s"%decl + if len(self.decl_handles)==0: + print >>query_log, " <no result>" + elif len(self.decl_handles)>1: + print >>query_log, " (%d declarations)"%len(self.decl_handles) + + + def __str__(self): + """Return a descriptive string.""" + if len(self.decl_handles)==0: + return "Decl: <empty>" + elif len(self.decl_handles)==1: + ds = getattr(self.decl_handles[0], "name", "?") + return 'Decl: "%s"'%(ds) + else: + return 'Decl: (%d declarations)'%(len(self.decl_handles)) + + def __iter__(self): + return self.iterContained() + + # iterContained + def iterContained(self): + """Iterate over all contained nodes. + + The iterator yields Decl objects. + """ + for decl in self._iterContained(): + yield IDecl([decl], modulebuilder=self.modulebuilder) + + # expose + def expose(self, flag=True): + """Expose the declarations in the generated module. + + If flag is True all contained declarations are marked + for being exposed, otherwise they are marked for being ignored. + + @param flag: Determines whether the declaration is actually exposed or ignored. + @type flag: bool + @returns: Returns self + @see: L{ignore()} + """ + self._checkLock() + for d in self._iterContained(): + if decoration_log!=None: + self._logDecoration("expose", d) + d.include() + return self + + # ignore + def ignore(self, flag=True): + """Ignore the declarations in the generated module. + + If flag is True all contained declarations are marked + for being ignored, otherwise they are marked for being exposed. + + @param flag: Determines whether the declaration is actually ignored or exposed. + @type flag: bool + @return: Returns self + @see: L{expose()} + """ + self._checkLock() + for d in self._iterContained(): + if decoration_log!=None: + self._logDecoration("ignore", d) + d.exclude() + return self + + # exclude + def exclude(self, flag=True): + """This is an alias for L{ignore()}.""" + return self.ignore(flag) + + # rename + def rename(self, name): + """Rename a declaration. + + The declaration will receive a new name under which it is exposed + in the Python module. + If there are currently several declarations referenced the new + name is assigned to all of them. However, only the declarations + that were directly matched will receive a new name, children are + always ignored. + + @param name: New name for the declaration + @type name: str + """ + self._checkLock() + for decl in self._iterContained(recursive=False): + if decoration_log!=None: + self._logDecoration("rename(%s)"%name, decl) + decl.rename(name) + return self + + # finalize + def finalize(self): + """Finalize virtual member functions or an entire class. + + Prevents the generation of wrappers for virtual member functions. + """ + self._checkLock() + for decl in self._iterContained(): + if decoration_log!=None: + self._logDecoration("finalize", decl) + decl.finalize() + return self + + # setPolicy + def setPolicy(self, policy): + """Set policies for functions or methods. + + @param policy: Policy to apply to the contained functions/methods. + @type policy: ...policy... + """ + self._checkLock() + for decl in self._iterContained(): + if decoration_log!=None: + self._logDecoration("setPolicy(...)", decl) + decl.call_policies = policy + + # setHeldType + def setHeldType(self, heldtype): + """Explicitly set the held type. + + Ex: C{setHeldType("boost::shared_ptr<Class>")} + """ + self._checkLock() + for decl in self._iterContained(): + if decoration_log!=None: + self._logDecoration("setHeldType(%s)"%heldtype, decl) + decl.held_type = heldType + return self + + # disableKeywordArgs + def disableKeywordArgs(self): + """Disable generation of keyword arguments. + """ + + self._checkLock() + for decl in self._iterContained(): + if decoration_log!=None: + self._logDecoration("disableKeyWord", decl) + decl.use_keywords = False +# if ( isinstance(decl, calldef_t) and +# not isinstance(decl, destructor_t) and +# getattr(decl, "access_type", None)!=PRIVATE): +# decl._use_keywords = False + return self + + # setArgPolicy + def setArgPolicy(self, *policies): + """Append argument policies. + + This method takes a variable number of arguments. Each argument + must be an ArgPolicy object. + """ + self._checkLock() + for decl in self._iterContained(): + if decoration_log!=None: + ps = ", ".join(map(lambda x: str(x), policies)) + self._logDecoration("setArgPolicy(%s)"%ps, decl) + self.modulebuilder.mArgPolicyManager.setArgPolicy(decl, policies) + + # addMethod + def addMethod(self, name, impl): + """Add a new method to a class. + + Adds a new method to a class. The implementation is given as a + C/C++ function that is defined elsewhere. + The return value is a Decl object that can be + used to further customize the method. + + @Note: This method isn't implemented yet! + + @param name: The method name as it will appear in the Python module + @type name: str + @param impl: The name of the C/C++ function that implements the method. + @type impl: str + """ + self.cdef(name, impl) + + + # def + def cdef(self, name, fn=None, *args): + """Apply a raw def() statement. + + This method is equivalent to the Boost.Python def() method. + Example:: + + Class("Foo").cdef("spam", "cspam", return_internal_reference(), (arg("a"), arg("b", 0)), "The spam method") + + It is up to the user to ensure that the C/C++ function cspam + is declared and implemented somewhere. + + If fn is None, the string name is not quoted. You can use this form + to wrap constructors or operators. Example:: + + Class("Foo").cdef("bp::init< const MFoo& >()") + + @param name: Name of the Python method or a valid Boost.Python construct + @type name: str + @param fn: Name of the C++ function that implements the method or None + @type fn: str + @param args: There can be up to three additional arguments in any order: A doc string, the call policies and the keywords. + @see: L{staticmethod()} + """ + + self._checkLock() + doc,policies,keywords = self._parseDefArgs(args) + if fn==None: + args = ['%s'%name] + else: + args = ['"%s"'%name, fn] + if policies!=None: + pass # todo + if keywords!=None: + args.append("(%s)"%", ".join(map(lambda x: "bp::"+str(x), keywords))) + if doc!=None: + a = map(lambda x: "%s\\n"%x, doc.split("\n")) + while len(a)>0 and a[-1]=="\\n": + a = a[:-1] + if len(a)>0: + # Remove the newline in the last line + a[-1] = a[-1][:-2] + args.append('%s'%"\n".join(map(lambda x: '"%s"'%x, a))) + src = 'def( %s )'%(", ".join(args)) + for decl in self._iterContained(recursive=False): + # Add the 'def' source code... + decl.add_code(src) + + return self + + # staticmethod + def staticmethod(self, name): + """Apply a raw staticmethod() statement. + + @param name: Name of the method. + @type name: str + @see: L{cdef()} + """ + + self._checkLock() + for decl in self._iterContained(recursive=False): + src = 'staticmethod( "%s" )'%name + decl.add_code(src) + + return self + + + # Decl + def Decls(self, + name=None, + fullname=None, + type=None, + retval=None, + args=None, + anyarg=None, + signature=None, + header=None, + headerdir=None, + accesstype=None, + filter=None, + recursive=None, + allow_empty=None, + assert_count=None + ): + """Obtain a Decl object referencing one or more declarations. + + Filters all contained declarations and returns a new Decl + object that only contains declarations matching the filtering + rules as specified by the arguments. If an argument is None, + that particular filtering operation is disabled. If several + arguments are provided, all of them must be matched. + + For any filter that is based on strings (such as name) the + following rules apply: + + - A string must match exactly the corresponding attribute of the + declaration (C{name="wxFrame"} will only return the class + "wxFrame"). + - A string that is bracketed by a leading and trailing slash '/' is + interpreted as a regular expression (C{name="/wx.*/"} will return + all classes that begin with "wx"). + + Any argument can also be passed a list of values which duplicates + the filter. These filter are concatenated with OR, so a declaration + has to match only one of the filters. For example, you can select all + classes starting with either "wx" or "WX" by setting + C{name=["/wx.*/", "/WX.*/"}]. + + The user defined filter function filter must accept a Decl + object as argument and has to return True when the declaration + is matched. + + @param name: Select declarations by name + @type name: str + @param fullname: Select declarations by name (which includes namespaces) + @type fullname: str + @param type: Select declarations by type. The type is given by a combination of flags (CLASS, MEMBER_FUNCTION/METHOD, FREE_FUNCTION/FUNCTION, ENUM, ...) + @type type: int + @param retval: Select functions/methods based on their return value (this implies the type flags MEMBER_FUNCTION | FREE_FUNCTION) + @type retval: str + @param args: Select functions/methods bases on their arguments (this implies the type flags MEMBER_FUNCTION | FREE_FUNCTION) + @type args: list of str + @param anyarg: Select all functions/methods that have the specified argument somewhere in their argument list (this implies the type flags MEMBER_FUNCTION | FREE_FUNCTION) + @type anyarg: str + @param signature: Select declarations by their signature (this implies the type flags MEMBER_FUNCTION | FREE_FUNCTION) + @type signature: str + @param header: Select declarations by the header file in which they are defined + @type header: str + @param headerdir: Select declarations by the directory in which their header file is located + @type headerdir: str + @param accesstype: Access type (PUBLIC or PROTECTED). This implies the type flag MEMBER_FUNCTION. + @param filter: User defined filter function + @type callable + @param recursive: Extend the search to grandchildren? If not specified, a global (customizable) default value is used. + @type recursive: bool + @param allow_empty: Allow empty results. If not specified, a global (customizable) default value is used. + @type allow_empty: bool + @param assert_count: Check the number of matched declarations in the resulting Decl object + @type assert_count: int + @returns: Returns a Decl object that may reference an arbitrary number of declarations. + @rtype: IDecl + @see: Namespace(), Class(), Method(), Function(), Enum() + """ + global allow_empty_queries, default_recursive + + itype = 0 + filters = [] + + if recursive==None: + recursive = default_recursive + if allow_empty==None: + allow_empty = allow_empty_queries + + def addFilter(arg, filtercls): + if arg!=None: + if _type(arg)==list: + filters.append(OrFilter(map(lambda x: filtercls(x), arg))) + else: + filters.append(filtercls(arg)) + + # name filter + addFilter(name, NameFilter) + # fullname filter + addFilter(fullname, FullNameFilter) + # retval filter + if retval!=None: + addFilter(retval, RetValFilter) + itype |= CALLABLE + # args filter + if args!=None: + filters.append(ArgsFilter(args)) + itype |= CALLABLE + # anyarg filter + if anyarg!=None: + raise NotImplementedError, "anyarg filter is not yet implemented" + # signature filter + if signature!=None: + raise NotImplementedError, "signature filter is not yet implemented" + # header filter + addFilter(header, HeaderFilter) + # headerdir filter + addFilter(headerdir, HeaderDirFilter) + # accesstype filter + if accesstype!=None: + addFilter(accesstype, AccessTypeFilter) + itype |= METHOD + # custom filters + if filter!=None: + if _type(filter)==list: + filters.extend(map(lambda x: CustomFilter(x), filter)) + else: + filters.append(CustomFilter(filter)) + + # XXX + if itype!=0: + if type==None: + type = 0 + if (type & CALLABLE)==0: + type |= itype + addFilter(type, TypeFilter) + + # Add parent filters... + pfs = [] + for decl in self.decl_handles: + pfs.append(ParentFilter(decl, recursive)) + if len(pfs)>0: + if len(pfs)==1: + filters.append(pfs[0]) + else: + filters.append(OrFilter(pfs)) + + # Create the final filter by combining the individual filters + # with AND... + if len(filters)==0: + filter = TrueFilter() + elif len(filters)==1: + filter = filters[0] + else: + filter = AndFilter(filters) + +# print "Filter:",filter + if len(self.decl_handles)==0: + decls = [] + else: + decls = selection.select(self.decl_handles, filter) + + res = IDecl(decls, str(filter), modulebuilder=self.modulebuilder) + count = res.count + if allow_empty and count==0: + return res + if count==0: + raise RuntimeError, "Query produced no results (filter: %s)"%filter + res_count = res.count + # If all contained declarations are from one single set of overloads + # then treat that as one single declaration + if res._checkOverloads(): + res_count = 1 + if assert_count!=None: + if res_count!=assert_count: + raise RuntimeError, "Query produced the wrong number of results (%d instead of %d)"%(res_count, assert_count) + return res + + + # Namespace + def Namespaces(self, name=None, type=0, **args): + """Obtain a Decl object referencing one or more namespaces. + + This method is equivalent to calling Decl() with the flag NAMESPACE + set in its type filter. + + See Decl() for a full description of this method. + + @returns: Returns a Decl object that may reference an arbitrary number of declarations. + @see: L{Decl()} + """ + return self.Decls(name=name, type=type|NAMESPACE, **args) + + # Classes + def Classes(self, name=None, type=0, **args): + return self.Decls(name=name, type=type|CLASS, **args) + + # Methods + def Methods(self, name=None, type=0, **args): + return self.Decls(name=name, type=type|METHOD|CONSTRUCTOR, **args) + + # Constructors + def Constructors(self, name=None, type=0, **args): + return self.Decls(name=name, type=type|CONSTRUCTOR, **args) + + # Functions + def Functions(self, name=None, type=0, **args): + return self.Decls(name=name, type=type|FUNCTION, **args) + + # Enums + def Enums(self, name=None, type=0, **args): + return self.Decls(name=name, type=type|ENUM, **args) + + # Vars + def Vars(self, name=None, type=0, **args): + return self.Vars(name=name, type=type|VARIABLE, **args) + + # Decl + def Decl(self, name=None, **args): + return self.Decls(name, assert_count=1, **args) + + # Namespace + def Namespace(self, name=None, **args): + return self.Namespaces(name, assert_count=1, **args) + + # Class + def Class(self, name=None, **args): + return self.Classes(name, assert_count=1, **args) + + # Method + def Method(self, name=None, **args): + return self.Methods(name, assert_count=1, **args) + + # Constructor + def Constructor(self, name=None, **args): + return self.Constructors(name, assert_count=1, **args) + + # Function + def Function(self, name=None, **args): + return self.Functions(name, assert_count=1, **args) + + # Enum + def Enum(self, name=None, **args): + return self.Enums(name, assert_count=1, **args) + + # Var + def Var(self, name=None, **args): + return self.Vars(name, assert_count=1, **args) + + + # Private methods: + + def _getCount(self): + """Return the number of matched declarations. + """ + return len(self.decl_handles) + + count = property(_getCount, None, None, "The number of matched declarations.") + + def _getTotalCount(self): + """Return the total number of contained declarations (including the children). + """ + return len(list(self)) + + totalcount = property(_getTotalCount, None, None, "The total number of contained declarations.") + + def _checkLock(self): + """Check that the decoration is not locked. + + If it is locked, an exception is thrown. + """ + global decl_lock + if decl_lock: + raise RuntimeError, "You have to decorate the declarations before the code creators have been built." + + def _checkOverloads(self): + """Check if all contained declarations are from the same set of overloads. + + @returns: True if all contained declarations are from the same set of overloads. + @rtype: bool + """ + if len(self.decl_handles)==0: + return False + # Get a list with the overloaded functions + overloads = getattr(self.decl_handles[0], "overloads", None) + if overloads==None: + return False + + # Check if the decls are all contained in overloads... + for decl in self.decl_handles[1:]: + if decl not in overloads: + return False + + return True + + def _parseDefArgs(self, args): + """Determine which of the args is the doc string, call policies and keywords argument. + + @returns: Returns a tuple (doc, policies, keywords). + """ + if len(args)>3: + raise ValueError, "Too many arguments (%d)"%len(args) + + doc = None + policies = None + keywords = None +# call_policy_t = pyplusplus.code_creators.call_policies.call_policy_t + call_policy_t = pyplusplus.decl_wrappers.call_policies.call_policy_t + for a in args: + if isinstance(a, types.StringTypes): + doc = a + elif isinstance(a, call_policy_t): + policies = a + elif type(a)==tuple: + keywords = a + elif isinstance(a, decltypes.arg): + keywords = (a,) + else: + raise ValueError, "Invalid argument: %s"%a + return doc,policies,keywords + + def _iterContained(self, recursive=True): + """Iterate over all contained declarations. + + The generator yields pygccxml declaration objects. + + @param recursive: Determines whether the method also yields children nodes + @type recursive: bool + """ + global _timestamp + _timestamp += 1 + for rootdecl in self.decl_handles: + for decl in self._iterdecls(rootdecl, recursive=recursive): + # Get the time stamp and check if this declaration hasn't + # been visited yet + ts = getattr(decl, "_timestamp", -1) + if ts!=_timestamp: + decl._timestamp = _timestamp + yield decl + + # _iterdecls + def _iterdecls(self, rootdecl, recursive=True): + """Depth first iteration over one or more declaration trees. + + rootdecl can be either a single declaration, a list of + declarations or None. A declaration must be an object derived + from the declaration_t class. If recursive is False, only the + root is returned. + + @param recursive: Determines whether the method also yields children nodes + @type recursive: bool + """ + if rootdecl==None: + return + + if type(rootdecl) is not list: + rootdecl = [rootdecl] + + for root in rootdecl: + yield root + if recursive: + children = getattr(root, "declarations", None) + for node in self._iterdecls(children): + yield node + + # _logDecoration + def _logDecoration(self, operation, decl): + """Write a line into the decoration log. + + @param operation: Name of the decoration operation + @type operation: str + @param decl: Declaration that was decorated + @type decl: declaration_t + """ + global decoration_log + if self.funcname==None: + print >>decoration_log, "%s,%d;%s; %s "%(self.filename, self.linenr, operation, decl) + else: + print >>decoration_log, "%s,%s(),%d;%s; %s "%(self.filename, self.funcname, self.linenr, operation, decl) + + # _sourceInfo + def _sourceInfo(self): + """Determine where in the user's source code this instance was created. + + Returns a tuple (filename, funcname, linenr, sourceline) that + describes the source code line that created this instance. + funcname is None if the source code is not located inside a function. + + @returns: (filename, funcname, linenr, sourceline) + @rtype: 4-tuple + """ + frame = inspect.currentframe() + try: + records = inspect.getouterframes(frame) + # Determine the directory where this source file is located + apidir = os.path.dirname(records[0][1]) + for rec in records[1:]: + file = rec[1] + dir = os.path.dirname(file) + # Return the first record that is not within the API directory + # (this must then be code from the user) + if dir!=apidir: + linenr = rec[2] + funcname = rec[3] + srcindex = rec[5] + sourceline = rec[4][srcindex] + sourceline = sourceline.strip() + if funcname=="?": + funcname = None + return file,funcname,linenr,sourceline + finally: + del frame + + # We should never get here... + return "?", None, 0, "?" + + +# This value is used to determine if a declaration was already visited or not +_timestamp = 0 + Added: pyplusplus_dev/contrib/pypp_api/pypp_api/filters.py =================================================================== --- pyplusplus_dev/contrib/pypp_api/pypp_api/filters.py (rev 0) +++ pyplusplus_dev/contrib/pypp_api/pypp_api/filters.py 2006-07-18 08:32:45 UTC (rev 313) @@ -0,0 +1,446 @@ +# Copyright 2006 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# +# Initial author: Matthias Baas + +"""This module contains the filters that are used to select declarations. +""" + +import re, os.path +from pygccxml.declarations import * +from decltypes import * +from treerange import TreeRange + +# _StringMatcher +class _StringMatcher: + """Helper class to match strings. + + This class can be used to match a string with a pattern that may + either be an ordinary string or contain a regular expression + enclosed in '/'. + """ + + def __init__(self, pattern): + """Constructor. + + pattern may contain a regular expression enclosed between two '/'. + + @param pattern: The pattern used for matching + @type pattern: str + """ + + self.regexp = None + self.pattern = pattern + + # Is pattern a regular expression? + if len(pattern)>=2 and pattern[0]=="/" and pattern[-1]=="/": + self.regexp = re.compile(pattern[1:-1]) + + # match + def match(self, txt): + """Check if a string matches the pattern. + + @param txt: The string to match + @type txt: str + @returns: True if txt matches the pattern + """ + if self.regexp==None: + return txt==self.pattern + else: + m = self.regexp.match(txt) + if m==None: + return False + # It was only a successful match when the entire string was matched + return m.end()==len(txt) + + +# FilterBase +class FilterBase: + """Base class for all filters. + """ + def __init__(self): + pass + + def __call__(self, decl): + raise NotImplementedError, "filters must always implement the __call__() method." + + def __invert__(self): + """NOT-operator (~)""" + return NotFilter(self) + + def __and__(self, other): + """AND-operator (&)""" + return AndFilter([self, other]) + + def __or__(self, other): + """OR-Operator (|)""" + return OrFilter([self, other]) + + def filterRange(self): + """Return the range of the filter. + + A return value of None means the filter's range is unlimited. + + @returns: Filter range or None + @rtype: TreeRange + """ + return None + + def parentConstraints(self): + """Return the parent constraints. + + *** obsolete *** + + A filter can use this method to indicate that it will always + return False if the parent is not a particular node. + + The following return values are possible: + + - C{None}: There are no constraints. The filter may return True on any node. + - C{[]}: The filter will always return False. + - C{[(parent, recursive),...]}: The parent constraints. + + A single parent constraint (I{parent}, I{recursive}) means that the + filter may only return True on children of I{parent}. If I{recursive} + is set to True these can also be grand-children, otherwise they + are only the direct children. On all other nodes, the filter will + always return False so the search algorithm may decide not to visit + them at all to speed up the search. + + @returns: None, an empty list or a list of tuples (parent, recursive). + """ + return None + +# TrueFilter +class TrueFilter(FilterBase): + """Returns always True. + """ + def __call__(self, decl): + return True + + def __str__(self): + return "True" + +# FalseFilter +class FalseFilter(FilterBase): + """Returns always False. + """ + def __call__(self, decl): + return False + + def __str__(self): + return "False" + +# AndFilter +class AndFilter(FilterBase): + """Combine several other filters with AND. + """ + def __init__(self, filters): + FilterBase.__init__(self) + self.filters = filters + + def __str__(self): + return " & ".join(map(lambda x: "(%s)"%str(x), self.filters)) + + def __call__(self, decl): + for f in self.filters: + if not f(decl): + return False + return True + + def filterRange(self): + res = None + for f in self.filters: + rng = f.filterRange() + if rng!=None: + if res==None: + res = rng + else: + res = res.intersect(rng) + return res + + +# OrFilter +class OrFilter(FilterBase): + "... [truncated message content] |
From: <mb...@us...> - 2006-07-18 08:28:07
|
Revision: 312 Author: mbaas Date: 2006-07-18 01:27:57 -0700 (Tue, 18 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=312&view=rev Log Message: ----------- Added some info messages Modified Paths: -------------- pyplusplus_dev/contrib/arrayinfo/createarrayinfo.py Modified: pyplusplus_dev/contrib/arrayinfo/createarrayinfo.py =================================================================== --- pyplusplus_dev/contrib/arrayinfo/createarrayinfo.py 2006-07-18 08:13:37 UTC (rev 311) +++ pyplusplus_dev/contrib/arrayinfo/createarrayinfo.py 2006-07-18 08:27:57 UTC (rev 312) @@ -153,11 +153,17 @@ sys.exit(1) if options.output!=None: + print >>sys.stderr, "Output file: %s"%options.output output = file(options.output, "wt") +headerpath = args[0] +headernames = os.path.join(headerpath, "*.h") +print >>sys.stderr, "Input files: %s"%headernames + cppargs = options.cppargs +print >>sys.stderr, "Preprocessor args: %s"%cppargs -headerpath = args[0] -headers = glob.glob(os.path.join(headerpath, "*.h")) +headers = glob.glob(headernames) +print >>sys.stderr, "%d header files found"%len(headers) for header in headers: parseHeader(header, cpp, cppargs, output) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-18 08:13:44
|
Revision: 311 Author: roman_yakovenko Date: 2006-07-18 01:13:37 -0700 (Tue, 18 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=311&view=rev Log Message: ----------- small refactoring. This refactoring should make easier to introduce new functionality - splitting code of single class to many files Modified Paths: -------------- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py Modified: pyplusplus_dev/pyplusplus/file_writers/multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-07-18 05:52:30 UTC (rev 310) +++ pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-07-18 08:13:37 UTC (rev 311) @@ -91,7 +91,7 @@ value_class = class_traits.get_declaration( element_type ) return self.create_value_traits_header_name( value_class ) - def create_source( self, file_name, function_name, creators ): + def create_source( self, file_name, function_name, registration_creators, declaration_creators=None ): """Return the content of a cpp file. @param file_name: The base name of the corresponding include file (without extension) @@ -103,6 +103,10 @@ @returns: The content for a cpp file @rtype: str """ + + if None is declaration_creators: + declaration_creators = [] + creators = registration_creators + declaration_creators answer = [] if self.extmodule.license: @@ -110,12 +114,13 @@ answer.append( '#include "%s%s"' % ( file_name, self.HEADER_EXT ) ) - # Include all 'global' include files... + # Include all 'global' include files... include_creators = filter( lambda creator: isinstance( creator, code_creators.include_t ) , self.extmodule.creators ) includes = map( lambda include_creator: include_creator.create() - , include_creators ) - for creator in creators: + , include_creators ) + + for creator in registration_creators: value_traits_header = self.find_out_value_traits_header( creator ) if value_traits_header: includes.append( '#include "%s"' % value_traits_header ) @@ -136,38 +141,43 @@ answer.append( os.linesep.join(namespace_aliases) ) # Write wrapper classes... - for creator in creators: - if isinstance( creator, code_creators.class_t ) and creator.wrapper: - answer.append( '' ) - answer.append( creator.wrapper.create() ) + for creator in declaration_creators: + answer.append( '' ) + answer.append( creator.create() ) # Write the register() function... answer.append( '' ) answer.append( 'void %s(){' % function_name ) - for creator in creators: + for creator in registration_creators: answer.append( code_creators.code_creator_t.indent( creator.create() ) ) answer.append( '' ) answer.append( '}' ) return os.linesep.join( answer ) - def __split_class_impl( self, class_creator): + def split_class_impl( self, class_creator): function_name = 'register_%s_class' % class_creator.alias file_path = os.path.join( self.directory_path, class_creator.alias ) # Write the .h file... header_name = file_path + self.HEADER_EXT self.write_file( header_name , self.create_header( class_creator.alias - , self.create_function_code( function_name ) ) ) - # Write the .cpp file... - self.write_file( file_path + self.SOURCE_EXT - , self.create_source( class_creator.alias - , function_name - , [class_creator] )) - if isinstance( class_creator, code_creators.class_t ) and class_creator.wrapper: + , self.create_function_code( function_name ) ) ) + class_wrapper = None + decl_creators = None + if isinstance( class_creator, code_creators.class_t ) and class_creator.wrapper: + class_wrapper = class_creator.wrapper + decl_creators = [ class_creator.wrapper ] + # Write the .cpp file... + cpp_code = self.create_source( class_creator.alias + , function_name + , [class_creator] + , decl_creators ) + self.write_file( file_path + self.SOURCE_EXT, cpp_code ) + if class_wrapper: # The wrapper has already been written above, so replace the create() # method with a new 'method' that just returns an empty string because # this method is later called again for the main source file. - class_creator.wrapper.create = lambda: '' + class_wrapper.create = lambda: '' # Replace the create() method so that only the register() method is called # (this is called later for the main source file). class_creator.create = lambda: function_name +'();' @@ -185,7 +195,7 @@ @type class_creator: class_t """ try: - self.__split_class_impl( class_creator ) + self.split_class_impl( class_creator ) except IOError, error: msg = [ 'Failed to write code for class "%s" into file.' % class_creator.declaration.name ] msg.append( "May be the class name is too long?." ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-18 05:52:38
|
Revision: 310 Author: roman_yakovenko Date: 2006-07-17 22:52:30 -0700 (Mon, 17 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=310&view=rev Log Message: ----------- adding templates directory Added Paths: ----------- pyplusplus_dev/contrib/templates/ pyplusplus_dev/contrib/templates/readme.txt Added: pyplusplus_dev/contrib/templates/readme.txt =================================================================== --- pyplusplus_dev/contrib/templates/readme.txt (rev 0) +++ pyplusplus_dev/contrib/templates/readme.txt 2006-07-18 05:52:30 UTC (rev 310) @@ -0,0 +1,4 @@ +Content: + This directory will contain functionality, that will help users to + instantiate template classes/function from Python script. + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-17 19:37:31
|
Revision: 309 Author: roman_yakovenko Date: 2006-07-17 12:37:17 -0700 (Mon, 17 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=309&view=rev Log Message: ----------- adding documentation to generated code Modified Paths: -------------- pyplusplus_dev/docs/pyplusplus.rest pyplusplus_dev/pyplusplus/module_builder/builder.py pyplusplus_dev/pyplusplus/module_creator/creator.py pyplusplus_dev/unittests/fundamental_tester_base.py Added Paths: ----------- pyplusplus_dev/contrib/doc_extractors/ pyplusplus_dev/contrib/doc_extractors/doxygen.py pyplusplus_dev/contrib/doc_extractors/readme.txt Added: pyplusplus_dev/contrib/doc_extractors/doxygen.py =================================================================== --- pyplusplus_dev/contrib/doc_extractors/doxygen.py (rev 0) +++ pyplusplus_dev/contrib/doc_extractors/doxygen.py 2006-07-17 19:37:17 UTC (rev 309) @@ -0,0 +1,112 @@ +""" +extracting from C++ doxygen documented file +Author G.D. +""" + +class doc_extractor: + """ + extracts doxigen styled documentation from source + or generates from description + """ + def __init__(self): + #for caching source + self.file_name = None + self.source = None + + def __call__(self, declaration): + try: + if self.file_name != declaration.location.file_name: + self.file_name = declaration.location.file_name + self.source = open(declaration.location.file_name).readlines() + + find_block_end = False + doc_lines = [] + for lcount in xrange(declaration.location.line - 1, -1, -1): + line = source[lcount] + if not find_block_end: + try: + if line.rstrip()[-2:] == "*/": + find_block_end = True + except: + pass + if find_block_end: + try: + if line.lstrip()[:2] == "/*": + find_block_end = False + except: + pass + final_str = clear_str(line) + if not find_block_end and code(line): + break + if final_str: + doc_lines.insert(0, final_str) + + if doc_lines: + doc_lines.insert(0, self.get_generic_doc()) + return ''.join(doc_lines) + + except: + pass + + return self.get_generic_doc(declaration) + + def get_generic_doc(self, declaration): + """ + generate call information about function or method + """ + try: + return "Help on %s\n" % str(declaration) + except: + pass + + return '' + + +def clear_str(str): + """ + replace */! by Space and \breaf, \fn, \param, ... + """ + clean = lambda str, sym, change2 = '': str.replace(sym, change2) + + str = reduce(clean, [str, '/', '*', '!', "\brief", "\fn",\ + "@brief", "@fn", "@ref", "\ref"]) + + str = clean(str, "@param", "Param: ") + str = clean(str, "\param", "Param: ") + str = clean(str, "@ingroup", "Group") + str = clean(str, "\ingroup", "Group") + str = clean(str, "@return", "It return") + str = clean(str, "\return", "It return") + return " " + str.lstrip() + + +def code(str): + """ + detect str is code? + """ + try: + beg = str.lstrip()[:2] + return beg != "//" and beg != "/*" + except: + pass + return False + +if __name__ == '__main__': + class loc: + def __init__(self, f, l): + self.file_name = f + self.line = l + + class x_decl: + def __init__(self, str, file_name, line): + self.str = str + self.location = loc(file_name, line) + + def __str__(self): + return self.str + + print doc_extractor()(x_decl("myfunc(int x, int y)","core.h",45)) + print doc_extractor()(x_decl("","core.h",209)) + + + Added: pyplusplus_dev/contrib/doc_extractors/readme.txt =================================================================== --- pyplusplus_dev/contrib/doc_extractors/readme.txt (rev 0) +++ pyplusplus_dev/contrib/doc_extractors/readme.txt 2006-07-17 19:37:17 UTC (rev 309) @@ -0,0 +1,19 @@ +Content: + This directory contains functionality that extracts documentation string +from C++ source files. + +How to integrate the functionality with pyplusplus? + + mb = module_builder_t( ... ) + mb.build_code_creator( ..., doc_extractor=my_doc_extractor ) + +What is "my_doc_extractor"? Well, "my_doc_extractor" is callable object, +that takes only one argument - declaration reference and returns documentation +string. Something like this: + +def my_doc_extractor( decl ): + return decl.location.file_name + str( decl.location.line ) + +Yes, every declaration contains next information: + 1. Full path to file it was defined in. + 2. Line number. Modified: pyplusplus_dev/docs/pyplusplus.rest =================================================================== --- pyplusplus_dev/docs/pyplusplus.rest 2006-07-17 18:18:24 UTC (rev 308) +++ pyplusplus_dev/docs/pyplusplus.rest 2006-07-17 19:37:17 UTC (rev 309) @@ -175,6 +175,9 @@ * user license is written at the top of every file + * extracting documentation from source files and integrating it with generated + source code + * ... ------- Modified: pyplusplus_dev/pyplusplus/module_builder/builder.py =================================================================== --- pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-07-17 18:18:24 UTC (rev 308) +++ pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-07-17 19:37:17 UTC (rev 309) @@ -173,7 +173,8 @@ , call_policies_resolver_=None , types_db=None , target_configuration=None - , enable_indexing_suite=True): + , enable_indexing_suite=True + , doc_extractor=None): """ Creates L{module_t} code creator. @@ -187,6 +188,10 @@ @param call_policies_resolver_: callable, that will be invoked on every calldef object. It should return call policies. @type call_policies_resolver_: callable + + @param doc_extractor: callable, that takes as argument reference to declaration + and returns documentation string + @type doc_extractor: callable or None """ creator = mcreator_package.creator_t( self.global_ns , module_name @@ -195,7 +200,8 @@ , call_policies_resolver_ , types_db , target_configuration - , enable_indexing_suite) + , enable_indexing_suite + , doc_extractor) self.__code_creator = creator.create() #I think I should ask users, what they expect #self.__code_creator.user_defined_directories.append( self.__working_dir ) Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-17 18:18:24 UTC (rev 308) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-17 19:37:17 UTC (rev 309) @@ -3,14 +3,15 @@ # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) +import time +import types_database +import class_organizer +import call_policies_resolver from pygccxml import declarations +from pyplusplus import decl_wrappers from pyplusplus import code_creators -import class_organizer -import call_policies_resolver -import types_database from pyplusplus import code_repository -from sets import Set as set -from pyplusplus import decl_wrappers +from pyplusplus import _logging_ ACCESS_TYPES = declarations.ACCESS_TYPES VIRTUALITY_TYPES = declarations.VIRTUALITY_TYPES @@ -67,7 +68,8 @@ , call_policies_resolver_=None , types_db=None , target_configuration=None - , enable_indexing_suite=True): + , enable_indexing_suite=True + , doc_extractor=None): """Constructor. @param decls: Declarations that should be exposed in the final module. @@ -77,6 +79,7 @@ @param call_policies_resolver_: Callable that takes one declaration (calldef_t) as input and returns a call policy object which should be used for this declaration. @param types_db: ...todo... @param target_configuration: A target configuration object can be used to customize the generated source code to a particular compiler or a particular version of Boost.Python. + @param doc_extractor: callable, that takes as argument declaration reference and returns documentation string @type decls: list of declaration_t @type module_name: str @type boost_python_ns_name: str @@ -84,9 +87,11 @@ @type call_policies_resolver_: callable @type types_db: L{types_database_t<types_database.types_database_t>} @type target_configuration: L{target_configuration_t<code_creators.target_configuration_t>} + @type doc_extractor: callable """ declarations.decl_visitor_t.__init__(self) - + self.logger = _logging_.loggers.module_builder + self.__enable_indexing_suite = enable_indexing_suite self.__target_configuration = target_configuration if not self.__target_configuration: @@ -113,22 +118,32 @@ self.__module_body = code_creators.module_body_t( name=module_name ) self.__extmodule.adopt_creator( self.__module_body ) - decls = declarations.make_flatten( decls ) - self.__decls = self._filter_decls( self._reorder_decls( self._prepare_decls( decls ) ) ) + prepared_decls = self._prepare_decls( decls, doc_extractor ) + self.__decls = self._filter_decls( self._reorder_decls( prepared_decls ) ) self.curr_code_creator = self.__module_body self.curr_decl = None self.__cr_array_1_included = False self.__array_1_registered = set() #(type.decl_string,size) self.__free_operators = [] - - def _prepare_decls( self, decls ): + + def _prepare_decls( self, decls, doc_extractor ): + decls = declarations.make_flatten( decls ) #leave only declarations defined under namespace, but remove namespaces decls = filter( lambda x: not isinstance( x, declarations.namespace_t ) \ and isinstance( x.parent, declarations.namespace_t ) , decls ) #leave only decls that should be exported decls = filter( lambda x: not x.ignore, decls ) + if doc_extractor: + start_time = time.clock() + self.logger.debug( 'Documentation extraction process started.' ) + + for decl in decls: + decl.documentation = doc_extractor( decl ) + + self.logger.debug( 'Documentation extraction process finished in %F seconds' + % ( time.clock() - start_time ) ) return decls def _reorder_decls(self, decls ): Modified: pyplusplus_dev/unittests/fundamental_tester_base.py =================================================================== --- pyplusplus_dev/unittests/fundamental_tester_base.py 2006-07-17 18:18:24 UTC (rev 308) +++ pyplusplus_dev/unittests/fundamental_tester_base.py 2006-07-17 19:37:17 UTC (rev 309) @@ -60,8 +60,9 @@ for decl in mb.decls(): decl.documentation = '"documentation"' self.customize( mb ) + doc_extractor = lambda decl: decl.documentation if not mb.has_code_creator(): - mb.build_code_creator( self.__module_name ) + mb.build_code_creator( self.__module_name, doc_extractor=doc_extractor ) mb.code_creator.std_directories.extend( autoconfig.scons_config.cpppath ) mb.code_creator.user_defined_directories.append( autoconfig.data_directory ) mb.code_creator.precompiled_header = "boost/python.hpp" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-17 18:18:38
|
Revision: 308 Author: roman_yakovenko Date: 2006-07-17 11:18:24 -0700 (Mon, 17 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=308&view=rev Log Message: ----------- adding documentation to generated code Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/calldef.py pyplusplus_dev/pyplusplus/code_creators/class_declaration.py pyplusplus_dev/pyplusplus/code_creators/declaration_based.py pyplusplus_dev/pyplusplus/code_creators/member_variable.py pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py pyplusplus_dev/unittests/fundamental_tester_base.py Modified: pyplusplus_dev/pyplusplus/code_creators/calldef.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-07-17 14:03:30 UTC (rev 307) +++ pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-07-17 18:18:24 UTC (rev 308) @@ -71,7 +71,10 @@ return '%s.def' % self.parent.class_var_name else: return 'def' - + + def create_doc(self): + return self.documentation + def create_function_ref_code( self, use_function_alias=False ): raise NotImplementedError() @@ -100,8 +103,8 @@ result.append( self.create_def_code() + '( ' ) result.append( os.linesep + self.indent( '"%s"' % self.alias ) ) + result.append( self.param_sep() ) - result.append( self.create_function_ref_code( not self.works_on_instance ) ) if self.declaration.use_keywords: @@ -114,6 +117,11 @@ else: result.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) + doc = self.create_doc() + if doc: + result.append( self.param_sep() ) + result.append( doc ) + result.append( ' )' ) if not self.works_on_instance: result.append( ';' ) @@ -316,6 +324,9 @@ ftype = self.wrapper.function_type() result.append( 'typedef %s;' % ftype.create_typedef( self.default_function_type_alias ) ) return ''.join( result ) + + def create_doc(self): + return None def create_function_ref_code(self, use_function_alias=False): result = [] @@ -817,10 +828,16 @@ init_identifier = algorithm.create_identifier( self, '::boost::python::init' ) args = [ self._generate_definition_args() ] answer = [ '%s' % declarations.templates.join( init_identifier, args ) ] + answer.append( '(' ) + keywords_args = None if self.declaration.use_keywords: - answer.append( '(%s)' % self.keywords_args() ) - else: - answer.append( '()' ) + keywords_args = self.keywords_args() + answer.append( '%s' % keywords_args ) + if self.documentation: + if keywords_args: + answer.append( ', ' ) + answer.append( self.documentation ) + answer.append( ')' ) if self.declaration.call_policies: answer.append('[%s]' % self.declaration.call_policies.create( self ) ) #I think it better not to print next line @@ -1063,7 +1080,7 @@ self._call_policies = None def _create_impl(self): - template = 'def( "%(function_name)s", &%(class_name)s::operator %(destination_type)s %(call_policies)s )' + template = 'def( "%(function_name)s", &%(class_name)s::operator %(destination_type)s %(call_policies)s%(doc)s )' class_name = algorithm.create_identifier( self , declarations.full_name( self.declaration.parent ) ) @@ -1071,11 +1088,16 @@ policies = '/*, undefined call policies */' if self.declaration.call_policies: policies = ',' + self.declaration.call_policies.create( self ) - + + doc = '' + if self.documentation: + doc = ', %s' % self.documentation + return template % { 'function_name' : self.declaration.alias , 'class_name' : class_name , 'destination_type' : self.declaration.return_type.decl_string , 'call_policies' : policies + , 'doc' : doc } class casting_constructor_t( declaration_based.declaration_based_t ): Modified: pyplusplus_dev/pyplusplus/code_creators/class_declaration.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-07-17 14:03:30 UTC (rev 307) +++ pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-07-17 18:18:24 UTC (rev 308) @@ -190,6 +190,8 @@ result = [] result.append( '(' ) result.append( ' "%s"' % self.alias ) + if self.documentation: + result.append( ', %s' % self.documentation ) used_init = None inits = filter( lambda x: isinstance( x, calldef.constructor_t ), self.creators ) if ( self.declaration.is_abstract \ Modified: pyplusplus_dev/pyplusplus/code_creators/declaration_based.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/declaration_based.py 2006-07-17 14:03:30 UTC (rev 307) +++ pyplusplus_dev/pyplusplus/code_creators/declaration_based.py 2006-07-17 18:18:24 UTC (rev 308) @@ -37,7 +37,6 @@ def _get_alias(self): return self.declaration.alias - def _set_alias(self, alias): self.declaration.alias = alias alias = property( _get_alias, _set_alias ) @@ -45,4 +44,9 @@ def _get_decl_identifier( self ): return algorithm.create_identifier( self, self.declaration.decl_string ) decl_identifier = property( _get_decl_identifier ) - \ No newline at end of file + + @property + def documentation( self ): + if None is self.declaration.documentation: + return '' + return self.declaration.documentation Modified: pyplusplus_dev/pyplusplus/code_creators/member_variable.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/member_variable.py 2006-07-17 14:03:30 UTC (rev 307) +++ pyplusplus_dev/pyplusplus/code_creators/member_variable.py 2006-07-17 18:18:24 UTC (rev 308) @@ -36,9 +36,12 @@ #> On Wednesday, 19. April 2006 23:05, Ralf W. Grosse-Kunstleve wrote: #> .add_property("p", make_function(&A::get_p, return_value_policy<reference_existing_object>())) def _generate_for_pointer( self ): + doc = '' #static property does not support documentation if self.declaration.type_qualifiers.has_static: add_property = 'add_static_property' else: + if self.documentation: + doc = self.documentation add_property = 'add_property' answer = [ add_property ] answer.append( '( ' ) @@ -66,6 +69,9 @@ , 'setter_type' : self.wrapper.setter_type , 'wfname' : self.wrapper.setter_full_name , 'call_pol' : call_pol } ) + if doc: + answer.append( self.PARAM_SEPARATOR ) + answer.append( doc ) answer.append( ' ) ' ) code = ''.join( answer ) @@ -80,18 +86,21 @@ def _generate_for_none_pointer( self ): tmpl = None if self.declaration.type_qualifiers.has_static: - tmpl = '%(access)s( "%(alias)s", %(name)s )' + tmpl = '%(access)s( "%(alias)s", %(name)s%(doc)s )' else: - tmpl = '%(access)s( "%(alias)s", &%(name)s )' + tmpl = '%(access)s( "%(alias)s", &%(name)s%(doc)s )' access = 'def_readwrite' if self.is_read_only(): access = 'def_readonly' - + doc = '' + if self.documentation: + doc = ', %s' % self.documentation result = tmpl % { 'access' : access , 'alias' : self.alias - , 'name' : algorithm.create_identifier( self, self.declaration.decl_string ) } + , 'name' : algorithm.create_identifier( self, self.declaration.decl_string ) + , 'doc' : doc } return result @@ -232,9 +241,12 @@ member_variable_base_t.__init__( self, variable=variable, wrapper=wrapper ) def _create_impl( self ): + doc = '' if self.declaration.type_qualifiers.has_static: add_property = 'add_static_property' else: + if self.documentation: + doc = self.documentation add_property = 'add_property' answer = [ add_property ] answer.append( '( ' ) @@ -247,6 +259,9 @@ answer.append( self.PARAM_SEPARATOR ) answer.append( '(%s)(&%s)' % ( self.wrapper.setter_type, self.wrapper.setter_full_name ) ) + if doc: + answer.append( self.PARAM_SEPARATOR ) + answer.append( doc ) answer.append( ' ) ' ) code = ''.join( answer ) @@ -327,9 +342,12 @@ def _create_impl( self ): assert isinstance( self.wrapper, array_mv_wrapper_t ) + doc = '' if self.declaration.type_qualifiers.has_static: answer = [ 'add_static_property' ] else: + if self.documentation: + doc = self.documentation answer = [ 'add_property' ] answer.append( '( ' ) answer.append('"%s"' % self.declaration.name ) @@ -344,6 +362,9 @@ temp.append( call_policies.with_custodian_and_ward_postcall( 0, 1 ).create(self) ) temp.append( ' )' ) answer.append( ''.join( temp ) ) + if doc: + answer.append( self.PARAM_SEPARATOR ) + answer.append( doc ) answer.append( ' );' ) return ''.join( answer ) @@ -423,6 +444,9 @@ answer.append( self.declaration.getter_call_policies.create( self ) ) else: answer.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) + if self.documentation: + answer.append( self.param_sep ) + answer.append( self.documentation ) answer.append( ' )' ) return ''.join( answer ) Modified: pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-07-17 14:03:30 UTC (rev 307) +++ pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-07-17 18:18:24 UTC (rev 308) @@ -34,11 +34,20 @@ self._ignore = False self._exportable = None self._exportable_reason = None + self._documentation = None @property def logger( self ): return _logging_.loggers.declarations - + + def _get_documentation( self ): + return self._documentation + + def _set_documentation( self, value ): + self._documentation = value + documentation = property( _get_documentation, _set_documentation + , doc="Using this property you can set documentatio of exported declaration." ) + def _generate_valid_name(self, name=None): if name == None: name = self.name Modified: pyplusplus_dev/unittests/fundamental_tester_base.py =================================================================== --- pyplusplus_dev/unittests/fundamental_tester_base.py 2006-07-17 14:03:30 UTC (rev 307) +++ pyplusplus_dev/unittests/fundamental_tester_base.py 2006-07-17 18:18:24 UTC (rev 308) @@ -57,6 +57,8 @@ , include_paths=[autoconfig.boost.include] , undefine_symbols=['__MINGW32__'] , indexing_suite_version=self.__indexing_suite_version) + for decl in mb.decls(): + decl.documentation = '"documentation"' self.customize( mb ) if not mb.has_code_creator(): mb.build_code_creator( self.__module_name ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-07-17 14:03:35
|
Revision: 307 Author: mbaas Date: 2006-07-17 07:03:30 -0700 (Mon, 17 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=307&view=rev Log Message: ----------- Issued a warning message (max_arity) via warning() instead of info() Modified Paths: -------------- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-17 08:10:52 UTC (rev 306) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-17 14:03:30 UTC (rev 307) @@ -103,7 +103,7 @@ msg = "Function '%s' has more than %d arguments ( %d ). " msg = msg + " You should adjust BOOST_PYTHON_MAX_ARITY." msg = msg + " For more information see: http://mail.python.org/pipermail/c++-sig/2002-June/001554.html" - self.logger.info( msg % ( self.decl_string, calldef_t.BOOST_PYTHON_MAX_ARITY, len( self.arguments ) ) ) + self.logger.warning( msg % ( self.decl_string, calldef_t.BOOST_PYTHON_MAX_ARITY, len( self.arguments ) ) ) all_types = [ arg.type for arg in self.arguments ] all_types.append( self.return_type ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-17 08:10:59
|
Revision: 306 Author: roman_yakovenko Date: 2006-07-17 01:10:52 -0700 (Mon, 17 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=306&view=rev Log Message: ----------- adding FAQs documentation to py++ Modified Paths: -------------- pyplusplus_dev/docs/faqs/faqs.rest Modified: pyplusplus_dev/docs/faqs/faqs.rest =================================================================== --- pyplusplus_dev/docs/faqs/faqs.rest 2006-07-13 08:27:50 UTC (rev 305) +++ pyplusplus_dev/docs/faqs/faqs.rest 2006-07-17 08:10:52 UTC (rev 306) @@ -59,6 +59,62 @@ That's all. +------------------------------------------------------- +How to expose function, which has hand-written wrapper? +------------------------------------------------------- +:: + + struct window_t{ + ... + void get_size( int& height, int& widht ) const; + ... + }; + +You can not expose ``get_size`` function as is - ``int`` is immutable type in +Python. So, we need to create a wrapper to the function: +:: + + boost::python::tuple get_size_wrapper( const window_t& win ){ + int height(0), width( 0 ); + win.get_size( height, widht ); + return boost::python::make_tuple( height, width ); + } + +:: + + class_<window_t>( ... ) + .def( "get_size", &get_size_wrapper ) + ... + ; + +Now, after you know how this problem is solved. I will show how this solution +could be integrated with `pyplusplus`_. + + +:: + + wrapper_code = """ + static boost::python::tuple get_size( const window_t& win ){ + int height(0), width( 0 ); + win.get_size( height, widht ); + return boost::python::make_tuple( height, width ); + } + """ + +:: + + registration_code = 'def( "get_size", &%s::get_size )' % window.wrapper_alias + +:: + + mb = module_builder_t( ... ) + window = mb.class_( "window_t" ) + window.member_function( "get_size" ).exclude() + window.add_wrapper_code( wrapper_code ) + window.add_code( registration_code ) + +That's all. + .. _`pyplusplus` : ./../pyplusplus.html .. _`boost.python`: http://www.boost.org/libs/python/doc/index.html .. _`Python`: http://www.python.org This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-13 08:29:31
|
Revision: 305 Author: roman_yakovenko Date: 2006-07-13 01:27:50 -0700 (Thu, 13 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=305&view=rev Log Message: ----------- adding FAQs documentation to py++ Added Paths: ----------- pyplusplus_dev/docs/faqs/ pyplusplus_dev/docs/faqs/faqs.rest pyplusplus_dev/docs/faqs/www_configuration.py Added: pyplusplus_dev/docs/faqs/faqs.rest =================================================================== --- pyplusplus_dev/docs/faqs/faqs.rest (rev 0) +++ pyplusplus_dev/docs/faqs/faqs.rest 2006-07-13 08:27:50 UTC (rev 305) @@ -0,0 +1,73 @@ +====================== +C++ containers support +====================== + +.. contents:: Table of contents + +---------------------------------------- +How to add custom exception translation? +---------------------------------------- +:: + + struct my_exception{ + ... + const std::string& error() const; + ... + } + +Generate exception translation function. +---------------------------------------- + +First of all you have to generate a header file, that will contain exception +translation function: +:: + + void translate(const my_exception &exception){ + PyErr_SetString( PyExc_RuntimeError, exception.error().c_str() ); + } + +Register exception translation function. +---------------------------------------- + +:: + + from pyplusplus import code_creators + +:: + + mb.build_code_creator( ... ) + mb.code_creator.add_include( generated header file name ) + +:: + + code = "boost::python::register_exception_translator<my_exception>(&translate);" + my_exc_translator = code_creators.custom_text_t( code ) + mb.code_creator.body.adopt_creator( my_exc_translator ) + +Small usage advice. +------------------- + +`pyplusplus`_ allows you to define a query that will return you all exception classes: + +:: + + mb = module_builder_t( ... ) + exception_classes = mb.decls( lambda decl: decl.name.endswith( 'exception' ) ) + +Now you can iterate on ``exception_classes``, generate and register translate +code for every class. + +That's all. + +.. _`pyplusplus` : ./../pyplusplus.html +.. _`boost.python`: http://www.boost.org/libs/python/doc/index.html +.. _`Python`: http://www.python.org +.. _`GCC-XML`: http://www.gccxml.org + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + End: Added: pyplusplus_dev/docs/faqs/www_configuration.py =================================================================== --- pyplusplus_dev/docs/faqs/www_configuration.py (rev 0) +++ pyplusplus_dev/docs/faqs/www_configuration.py 2006-07-13 08:27:50 UTC (rev 305) @@ -0,0 +1 @@ +name = 'FAQs' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-12 19:06:53
|
Revision: 304 Author: roman_yakovenko Date: 2006-07-12 12:06:37 -0700 (Wed, 12 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=304&view=rev Log Message: ----------- improving indexing suite Modified Paths: -------------- pygccxml_dev/unittests/data/core_cache.hpp pyplusplus_dev/pyplusplus/code_creators/indexing_suites.py pyplusplus_dev/pyplusplus/module_creator/creator.py pyplusplus_dev/pyplusplus/module_creator/types_database.py pyplusplus_dev/unittests/data/indexing_suites2_to_be_exported.hpp pyplusplus_dev/unittests/data/indexing_suites_to_be_exported.hpp Modified: pygccxml_dev/unittests/data/core_cache.hpp =================================================================== --- pygccxml_dev/unittests/data/core_cache.hpp 2006-07-12 17:56:21 UTC (rev 303) +++ pygccxml_dev/unittests/data/core_cache.hpp 2006-07-12 19:06:37 UTC (rev 304) @@ -22,4 +22,4 @@ #endif//__core_cache_hpp__ -//touch//touch//touch//touch \ No newline at end of file +//touch//touch//touch//touch//touch \ No newline at end of file Modified: pyplusplus_dev/pyplusplus/code_creators/indexing_suites.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/indexing_suites.py 2006-07-12 17:56:21 UTC (rev 303) +++ pyplusplus_dev/pyplusplus/code_creators/indexing_suites.py 2006-07-12 19:06:37 UTC (rev 304) @@ -31,15 +31,16 @@ def _create_suite_declaration( self ): suite_identifier = algorithm.create_identifier( self, self.guess_suite_name() ) args = [ self.container.decl_string ] + try: + no_proxy = str( self.configuration.no_proxy ).lower() + except: + no_proxy = 'false' if self.configuration.derived_policies: - if self.configuration.no_proxy: - args.append( 'true' ) - else: - args.append( 'false' ) + args.append( no_proxy ) args.append( self.configuration.derived_policies ) else: - if self.configuration.no_proxy: - args.append( 'true' ) + if 'true' == no_proxy: + args.append( no_proxy) return declarations.templates.join( suite_identifier, args ) def _create_impl(self): Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-12 17:56:21 UTC (rev 303) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-12 19:06:37 UTC (rev 304) @@ -26,7 +26,25 @@ # }; #}; +INDEXING_SUITE_1_CONTAINERS = { + 'vector<' : "boost/python/suite/indexing/vector_indexing_suite.hpp" + , 'map<' : "boost/python/suite/indexing/map_indexing_suite.hpp" +} +INDEXING_SUITE_2_CONTAINERS = { + 'vector<' : "boost/python/suite/indexing/vector.hpp" + , 'deque<' : "boost/python/suite/indexing/deque.hpp" + , 'list<' : "boost/python/suite/indexing/list.hpp" + , 'map<' : "boost/python/suite/indexing/map.hpp" + , 'hash_map<' : "boost/python/suite/indexing/map.hpp" + , 'set<' : "boost/python/suite/indexing/set.hpp" + , 'hash_set<' : "boost/python/suite/indexing/set.hpp" + #TODO: queue, priority, stack, multimap, hash_multimap, multiset, hash_multiset +} + +INDEXING_SUITE_2_MAIN_HEADER = "boost/python/suite/indexing/container_suite.hpp" + + class creator_t( declarations.decl_visitor_t ): """Creating code creators. @@ -376,6 +394,10 @@ pass def _treat_indexing_suite( self ): + global INDEXING_SUITE_1_CONTAINERS + global INDEXING_SUITE_2_CONTAINERS + global INDEXING_SUITE_2_MAIN_HEADER + def create_explanation(cls): msg = '//WARNING: the next line of code will not compile, because "%s" does not have operator== !' msg = msg % cls.indexing_suite.element_type.decl_string @@ -390,27 +412,10 @@ if not self.__types_db.used_containers: return - #supported container : [ header file, is already used ] - used_headers = set() - isuite1 = { - 'vector<' : "boost/python/suite/indexing/vector_indexing_suite.hpp" - , 'map<' : "boost/python/suite/indexing/map_indexing_suite.hpp" - } - isuite2 = { - 'vector<' : "boost/python/suite/indexing/vector.hpp" - , 'deque<' : "boost/python/suite/indexing/deque.hpp" - , 'list<' : "boost/python/suite/indexing/list.hpp" - , 'map<' : "boost/python/suite/indexing/map.hpp" - , 'hash_map<' : "boost/python/suite/indexing/map.hpp" - , 'set<' : "boost/python/suite/indexing/set.hpp" - , 'hash_set<' : "boost/python/suite/indexing/set.hpp" - #TODO: queue, priority, stack, multimap, hash_multimap, multiset, hash_multiset - } + creators = [] - container_suite_header = "boost/python/suite/indexing/container_suite.hpp" - cmp_by_name = lambda cls1, cls2: cmp( cls1.decl_string, cls2.decl_string ) used_containers = list( self.__types_db.used_containers ) used_containers.sort( cmp_by_name ) @@ -418,43 +423,61 @@ container_name = cls.name.split( '<' )[0] + '<' if isinstance( cls.indexing_suite, decl_wrappers.indexing_suite1_t ): - isuite = isuite1 + isuite = INDEXING_SUITE_1_CONTAINERS else: - isuite = isuite2 + isuite = INDEXING_SUITE_2_CONTAINERS if not isuite.has_key( container_name ): continue #not supported - if isuite is isuite2: - used_headers.add( container_suite_header ) + if isuite is INDEXING_SUITE_2_CONTAINERS: + used_headers.add( INDEXING_SUITE_2_MAIN_HEADER ) used_headers.add( isuite[ container_name ] ) cls_creator = create_cls_cc( cls ) - element_type = cls.indexing_suite.element_type - if isuite is isuite1: - if declarations.is_class( element_type ) and not declarations.has_public_equal( element_type ): + creators.append( cls_creator ) + try: + element_type = cls.indexing_suite.element_type + except: + element_type = None + if isuite is INDEXING_SUITE_1_CONTAINERS: + if not ( None is element_type ) \ + and declarations.is_class( element_type ) \ + and not declarations.has_public_equal( element_type ): cls_creator.adopt_creator( create_explanation( cls ) ) cls_creator.adopt_creator( code_creators.indexing_suite1_t(cls) ) else: class_traits = declarations.class_traits - if class_traits.is_my_case( element_type ): + if not ( None is element_type ) \ + and class_traits.is_my_case( element_type ): value_cls = class_traits.get_declaration( element_type ) element_type_cc = code_creators.value_traits_t( value_cls ) self.__extmodule.adopt_creator( element_type_cc, self.__extmodule.creators.index( self.__module_body ) ) cls_creator.adopt_creator( code_creators.indexing_suite2_t(cls) ) - self.__module_body.adopt_creator( cls_creator ) - if container_suite_header in used_headers: + if INDEXING_SUITE_2_MAIN_HEADER in used_headers: #I want this header to be the first one. - used_headers.remove( container_suite_header ) - self.__extmodule.add_system_header( container_suite_header ) - self.__extmodule.add_include( container_suite_header ) + used_headers.remove( INDEXING_SUITE_2_MAIN_HEADER ) + self.__extmodule.add_system_header( INDEXING_SUITE_2_MAIN_HEADER ) + self.__extmodule.add_include( INDEXING_SUITE_2_MAIN_HEADER ) for header in used_headers: self.__extmodule.add_system_header( header ) self.__extmodule.add_include( header ) - + + #I am going tp find last class registration and to add all container creators + #after it. + last_cls_index = -1 + for i in range( len( self.__module_body.creators ) - 1, -1, -1 ): + if isinstance( self.__module_body.creators[i], code_creators.class_t ): + last_cls_index = i + break + insert_position = last_cls_index + 1 + creators.reverse() + for creator in creators: + self.__module_body.adopt_creator( creator, insert_position ) + def create(self, decl_headers=None): """Create and return the module for the extension. Modified: pyplusplus_dev/pyplusplus/module_creator/types_database.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/types_database.py 2006-07-12 17:56:21 UTC (rev 303) +++ pyplusplus_dev/pyplusplus/module_creator/types_database.py 2006-07-12 19:06:37 UTC (rev 304) @@ -73,11 +73,12 @@ try: check_extraction = container_cls.indexing_suite.element_type except RuntimeError, error: - msg = 'pyplusplus found "%s" instantiation declaration, ' % container_cls.name - msg = msg + 'but can not find out value type!' - msg = msg + os.linesep + 'This class will not be exported!' - _logging_.loggers.declarations.warn( msg ) - return False + msg = [] + msg.append( 'pyplusplus found class "%s" - instantiation declaration, not definition.' % container_cls.name ) + msg.append( 'pyplusplus can not find out container value_type( mapped_type )!' ) + msg.append( 'This class will be exported, but there is a posiblity, that generated code will not compile.' ) + msg.append( 'The solution to the problem is to create a variable of the class.' ) + _logging_.loggers.declarations.warn( os.linesep.join( msg ) ) self.__containers.add( container_cls ) return True Modified: pyplusplus_dev/unittests/data/indexing_suites2_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/indexing_suites2_to_be_exported.hpp 2006-07-12 17:56:21 UTC (rev 303) +++ pyplusplus_dev/unittests/data/indexing_suites2_to_be_exported.hpp 2006-07-12 19:06:37 UTC (rev 304) @@ -7,8 +7,13 @@ #define __indexing_suites2_to_be_exported_hpp__ #include <vector> +#include <string> namespace indexing_suites2 { + +typedef std::vector< std::string > strings_t; + +inline void do_nothing( const strings_t& ){} struct item_t{ item_t() : value( -1 ){} Modified: pyplusplus_dev/unittests/data/indexing_suites_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/indexing_suites_to_be_exported.hpp 2006-07-12 17:56:21 UTC (rev 303) +++ pyplusplus_dev/unittests/data/indexing_suites_to_be_exported.hpp 2006-07-12 19:06:37 UTC (rev 304) @@ -7,8 +7,13 @@ #define __indexing_suites_to_be_exported_hpp__ #include <vector> +#include <string> namespace indexing_suites { + +typedef std::vector< std::string > strings_t; + +inline void do_nothing( const strings_t& ){} struct item_t{ item_t() : value( -1 ){} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-12 17:56:29
|
Revision: 303 Author: roman_yakovenko Date: 2006-07-12 10:56:21 -0700 (Wed, 12 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=303&view=rev Log Message: ----------- adding docs configuration Added Paths: ----------- pyplusplus_dev/docs/std_containers/indexing_suite_v2_files/www_configuration.py Added: pyplusplus_dev/docs/std_containers/indexing_suite_v2_files/www_configuration.py =================================================================== --- pyplusplus_dev/docs/std_containers/indexing_suite_v2_files/www_configuration.py (rev 0) +++ pyplusplus_dev/docs/std_containers/indexing_suite_v2_files/www_configuration.py 2006-07-12 17:56:21 UTC (rev 303) @@ -0,0 +1 @@ +expose_to_web = False \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-12 12:08:13
|
Revision: 302 Author: roman_yakovenko Date: 2006-07-12 05:07:35 -0700 (Wed, 12 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=302&view=rev Log Message: ----------- adding indexing suite v2 to the repository. Added Paths: ----------- pyplusplus_dev/indexing_suite_v2/ pyplusplus_dev/indexing_suite_v2/docs/ pyplusplus_dev/indexing_suite_v2/docs/indexing_suite_v2.html pyplusplus_dev/indexing_suite_v2/docs/indexing_suite_v2_files/ pyplusplus_dev/indexing_suite_v2/docs/indexing_suite_v2_files/boost.css pyplusplus_dev/indexing_suite_v2/docs/indexing_suite_v2_files/cboost.gif pyplusplus_dev/indexing_suite_v2/indexing/ pyplusplus_dev/indexing_suite_v2/indexing/algorithms.hpp pyplusplus_dev/indexing_suite_v2/indexing/container_proxy.hpp pyplusplus_dev/indexing_suite_v2/indexing/container_suite.hpp pyplusplus_dev/indexing_suite_v2/indexing/container_traits.hpp pyplusplus_dev/indexing_suite_v2/indexing/deque.hpp pyplusplus_dev/indexing_suite_v2/indexing/element_proxy.hpp pyplusplus_dev/indexing_suite_v2/indexing/element_proxy_traits.hpp pyplusplus_dev/indexing_suite_v2/indexing/int_slice_helper.hpp pyplusplus_dev/indexing_suite_v2/indexing/iterator_range.hpp pyplusplus_dev/indexing_suite_v2/indexing/iterator_traits.hpp pyplusplus_dev/indexing_suite_v2/indexing/list.hpp pyplusplus_dev/indexing_suite_v2/indexing/map.hpp pyplusplus_dev/indexing_suite_v2/indexing/methods.hpp pyplusplus_dev/indexing_suite_v2/indexing/proxy_iterator.hpp pyplusplus_dev/indexing_suite_v2/indexing/python_iterator.hpp pyplusplus_dev/indexing_suite_v2/indexing/readme.txt pyplusplus_dev/indexing_suite_v2/indexing/set.hpp pyplusplus_dev/indexing_suite_v2/indexing/shared_proxy_impl.hpp pyplusplus_dev/indexing_suite_v2/indexing/slice.hpp pyplusplus_dev/indexing_suite_v2/indexing/slice_handler.hpp pyplusplus_dev/indexing_suite_v2/indexing/suite_utils.hpp pyplusplus_dev/indexing_suite_v2/indexing/value_traits.hpp pyplusplus_dev/indexing_suite_v2/indexing/vector.hpp pyplusplus_dev/indexing_suite_v2/indexing/visitor.hpp pyplusplus_dev/indexing_suite_v2/indexing/workaround.hpp pyplusplus_dev/indexing_suite_v2/readme.txt pyplusplus_dev/indexing_suite_v2/src/ pyplusplus_dev/indexing_suite_v2/src/indexing/ pyplusplus_dev/indexing_suite_v2/src/indexing/indexing_slice.cpp pyplusplus_dev/indexing_suite_v2/src/indexing/python_iterator.cpp pyplusplus_dev/indexing_suite_v2/src/readme.txt Added: pyplusplus_dev/indexing_suite_v2/docs/indexing_suite_v2.html =================================================================== --- pyplusplus_dev/indexing_suite_v2/docs/indexing_suite_v2.html (rev 0) +++ pyplusplus_dev/indexing_suite_v2/docs/indexing_suite_v2.html 2006-07-12 12:07:35 UTC (rev 302) @@ -0,0 +1,2213 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html><head> + + + <meta name="generator" content="A human being"> + <meta http-equiv="Content-Type" content="text/html; charset=us-ascii"> + <link rel="stylesheet" type="text/css" href="indexing_suite_v2_files/boost.css"><title>Boost.Python - C++ Container Support</title></head><body> + <table summary="header" border="0" cellpadding="7" cellspacing="0" width="100%"> + <tbody><tr> + <td valign="top" width="300"> + <h3> + <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/index.htm"><img alt="C++ Boost" src="indexing_suite_v2_files/cboost.gif" border="0" height="86" width="277"></a> + </h3> + </td> + <td valign="top"> + <h1 align="center"> + <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/doc/index.html">Boost.Python</a><br> + C++ Container Support + </h1> + </td> + </tr> + </tbody></table> + + <hr> + + <h2> + Contents + </h2> + + <dl class="page-index"> + <dt> + <a href="#introduction">Introduction</a> + </dt> + <dt> + <a href="#design_goals">Design goals</a> + </dt> + <dt> + <a href="#interface">Interface</a> + </dt> + <dd> + <dl class="page-index"> + <dt> + <a href="#container_suite">container_suite.hpp</a> + </dt> + <dt> + <a href="#specific">Container-specific headers</a> + </dt> + <dt> + <a href="#policies">Using policies</a> + </dt> + <dt> + <a href="#visitor_flags">Visitor flag values</a> + </dt> + <dt> + <a href="#extending">Extending and customizing</a> + </dt> + <dd> + <dl class="page-index"> + <dt> + <a href="#ValueTraits">ValueTraits</a> + </dt> + <dt> + <a href="#ContainerTraits">ContainerTraits</a> + </dt> + <dt> + <a href="#Algorithms">Algorithms</a> + </dt> + <dt> + <a href="#SliceHelper">SliceHelper</a> + </dt> + </dl> + </dd> + <dt> + <a href="#extending">Container adapters</a> + </dt> + <dd> + <dl class="page-index"> + <dt> + <a href="#container_proxy">container_proxy</a> + </dt> + <dt> + <a href="#iterator_range">iterator_range</a> + </dt> + </dl> + </dd> + <dt> + <a href="#workarounds">Compiler workarounds</a> + </dt> + <dt> + <a href="#limitations">Known limitations</a> + </dt> + </dl> + </dd> + <dt> + <a href="#references">References</a> + </dt> + <dt> + <a href="#acknoweldegments">Acknowledgements and Copyright</a> + </dt> + </dl> + + <h2><a name="introduction">Introduction</a></h2> + + The purpose of the container indexing suite is to allow Python + code to access C++ containers using regular Python + interfaces. Since each C++ container is different, it is + non-trivial to decide what Python methods can be emulated, and how + to map them to C++ function calls. The indexing suite provides a + framework for representing those decisions, as well as bindings + for the standard C++ container templates. The indexing headers are + in the Boost subdirectory + <i>boost/python/suite/indexing</i> and non-template + implementations are in + <i>libs/python/src/indexing</i>. Various tests, which can also + serve as examples are in <i>libs/python/test</i>. + + <h2><a name="design_goals">Design goals</a></h2> + + The primary design goals of the container indexing suite are as + follows. The suite should: + + <ul> + <li> + + Support instances of all useful standard container templates + + </li> + <li> + + Provide as much of the normal Python interface as is + reasonable for each container + + </li> + <li> + + Be extensible to user-defined container types + + </li> + <li> + + Support client-provided <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/doc/v2/CallPolicies.html">CallPolicies</a> + + </li> + </ul> + + Secondary design goals are as follows. The library should: + + <ul> + <li> + + Provide an emulation of Python reference semantics for + <i>values</i> in vector-like containers. + + </li> + <li> + + Provide an emulation of container semantics for iterator + ranges. + + </li> + </ul> + + <h2><a name="interface">Interface</a></h2> + + <p> + + The main iterface to the library is via the templated class + <code>container_suite</code>, an object of which adds a number + of Python functions to an extension class via a single + <code>def</code> call. Support is provided for all of the + standard container templates <a href="#Note1">[1]</a> via + container-specific header files, as shown in the following + example: + + </p> + +<pre>#include <boost/python/suite/indexing/container_suite.hpp> +#include <boost/python/suite/indexing/vector.hpp> +#include <boost/python/class.hpp> +#include <boost/python/module.hpp> +#include <vector> + +BOOST_PYTHON_MODULE(example) { + class_< std::vector<int> > ("vector_int") + .def (indexing::container_suite< std::vector<int> >()); +} +</pre> + + <p> + + The <code>container_suite</code> object achieves this using the + <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/doc/v2/def_visitor.html">def_visitor interface</a>, which + provides a hook for the <code>def</code> function to install + multiple Python methods in one call. If the container element + type (<code>int</code> in the example above) is a user-defined + type, you would have to expose this type to Python via a + separate <code>class_</code> instance. + + </p> + <p> + + <a name="Note1">[1]</a> Automatic operation with the standard + containers works properly if your compiler supports partial + template specializations. Otherwise, refer to the <a href="#workarounds">compiler workarounds</a> section. + + </p> + + <h2><a name="container_suite">boost/python/suite/indexing/container_suite.hpp</a></h2> + + <p> + + The <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/boost/python/suite/indexing/container_suite.hpp"><code>container_suite.hpp</code></a> + header is summarized below: + + </p> + <p> +</p><pre>#include <boost/python/suite/indexing/algo_selector.hpp> +#include <boost/python/suite/indexing/visitor.hpp> + +#include <boost/python/return_by_value.hpp> +#include <boost/python/return_value_policy.hpp> + +namespace boost { namespace python { namespace indexing { + typedef return_value_policy<return_by_value> default_container_policies; + + template<class Container, + int Flags = 0, + class Algorithms = algo_selector<Container> > + struct container_suite + : public visitor<Algorithms, default_container_policies, Flags> + { + typedef Algorithms algorithms; + + template<typename Policy> + static visitor<Algorithms, Policy, Flags> + with_policies (Policy const &policy) + { + return visitor <Algorithms, Policy> (policy); + } + }; +} } } +</pre> + <p></p> + + <p> + + Some important points to note about <code>container_suite</code>: + + </p><ol> + <li> + + It does not include any of the container-specific headers + (like <code>vector.hpp</code> or <code>set.hpp</code>), so + these must be included separately to add support each type + of container. + + </li> + <li> + + It derives from the <code>indexing::visitor</code> + template, using a <code>return_by_value</code> return + policy. This is a reasonable default, and follows the + Boost.Python idiom of passing a default-constructed object + to the <code>def</code> function. + + </li> + <li> + + The <code>with_policies</code> static function template + generates different instances of the + <code>indexing::visitor</code> template, with + client-provided policies. + + </li> + <li> + + The template parameter <code>Flags</code> allows client code + to disable unneeded features in order to reduce code + size. Details are provided <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/doc/v2/visitor_flags">below</a>. + + </li> + </ol> + + <p></p> + + <h2><a name="specific">Container-specific headers</a></h2> + + <p> + + The container indexing suite includes support for many of the + standard C++ container templates, but note that the support code + for each is in a separate header file. These header files (in + the <i>boost/python/suite/indexing</i> subdirectory) are: + <code>vector.hpp</code>, <code>deque.hpp</code>, + <code>list.hpp</code>, <code>set.hpp</code> and + <code>map.hpp</code>. These correspond in the obvious way to the + standard headers <code>vector</code>, <code>deque</code>, + etc. The header files for the <a href="#container_proxy"><code>container_proxy</code></a> and <a href="#iterator_range"><code>iterator_range</code></a> templates + provide their own support implicitly. + + </p> + + <h2><a name="policies">Using policies</a></h2> + + You can select call policies using the + <code>container_suite</code> static member function + <code>with_policies</code> as in the following example: + +<pre> class_< std::list<heavy_class> > ("list_heavy_class") + .def (indexing::container_suite< std::list<heavy_class> > + ::with_policies (my_policies)); +</pre> + + <h3>Caution with policies</h3> + + <p> + + It can be tempting to use <code>return_internal_reference</code> + if the container elements are expensive to copy. However, this + can be quite dangerous, since references to the elements can + easily become invalid (e.g. if the element is deleted or + moved). The Boost.Python code for + <code>return_internal_reference</code> can only manage the + lifetime of the entire container object, and not those of the + elements actually being referenced. Various alternatives exist, + the best of which is to store the container elements indirectly, + using <code>boost::shared_ptr</code> or an equivalent. If this + is not possible, + <code><a href="#container_proxy">container_proxy</a></code> + may provide a + solution, at least for vector-like containers. + + </p> + + <h3>Internal policies detail</h3> + + <p> + + The <code>container_suite</code> object typically adds more than + one function to the Python class, and not all of those functions + can, or should, use exactly the same policies. For instance, the + Python <code>len</code> method, if provided, should always + return its result by value. The library actually uses up to + three different sets of policies derived from the one provided + to the <code>with_policies</code> function. These are: + + </p><ol> + <li> + + The supplied policies, unchanged + + </li> + <li> + + The supplied precall policy only, using <code>default_call_policies</code> for result conversion. + + </li> + <li> + + The supplied precall policies, and the supplied result + conversion policies applied to <i>each element</i> of a + returned list. + + </li> + </ol> + + Roughly speaking, methods returning a single container element + use the first option, while methods returning an integer value + (or <code>void</code>) use the second option. The third option + applies only to the slice version of <code>__getitem__</code>, + which generates a Python list by applying the return conversion + policies to each element in the list. + + <p></p> + + <h2><a name="visitor_flags">Visitor Flag values</a></h2> + + <p> + + The <code>container_suite</code> template has an optional + <code>Flags</code> parameter that allows client code to disable + various optional features of the suite. This can lead to + significant savings in the size of object files and executables + if features such as sorting or Python slice support are not + needed. The <code>Flags</code> parameter (an integer) can be any + bitwise combination of the following values (defined in the + <code>boost::python::indexing</code> namespace by <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/boost/python/suite/indexing/visitor.hpp"><code>visitor.hpp</code></a>): + + </p> + + <p> + + <table border="1"> + <tbody><tr> + <th>Flag</th> + <th>Effect</th> + </tr> + <tr> + + <td><code>disable_len</code></td> + + <td>omits the Python <code>__len__</code> method</td> + + </tr> + <tr> + + <td><code>disable_slices</code></td> + + <td>omits slice support code from <code>__getitem__</code>, + <code>__setitem__</code> and <code>__delitem__</code>.</td> + + </tr> + <tr> + + <td><code>disable_search</code></td> + + <td>omits the container search methods <code>count<code>, + </code>index</code> and <code>__contains__</code></td> + + </tr> + <tr> + + <td><code>disable_reorder</code></td> + + <td>omits the container reordering operations + <code>sort</code> and <code>reverse</code></td> + + </tr> + <tr> + + <td><code>disable_extend</code></td> + + <td>omits the <code>extend</code> method</td> + + </tr> + <tr> + + <td><code>disable_insert</code></td> + + <td>omits the <code>insert</code> method</td> + + </tr> + </tbody></table> + + </p> + + <p> + + Note that some containers don't support some of the optional + features at all, in which case the relevant flags are + ignored. The value <code>minimum_support</code> may be passed as + a flag value to disable all optional features. A simple example + is provided in <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/test/test_vector_disable.cpp"><code>test_vector_disable.cpp</code></a> + + </p> + + <h2><a name="extending">Extending and customizing</a></h2> + + <p> + + The <code>container_suite</code> template relies on seven main + support templates, five of which are suitable for specialization + or replacement by client code. The following diagram shows the + templates <a href="#Note2">[2]</a> and their dependencies, with + the replaceable ones highlighted in grey. For full details, + refer to the specific section on each component – what + follows here is an overview. + + </p> + + <table align="right"> + <tbody><tr> + <td> + + <img src="indexing_suite_v2_files/overview.png" alt="Dependencies between main templates" height="261" width="486"> + + </td> + </tr> + <tr> + <td><font size="-1"> + + Diagram 1. Overview of class dependencies + + </font></td> + </tr> + </tbody></table> + + <p> + + The <code>visitor</code> template, which implements the <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/doc/v2/def_visitor.html">def_visitor interface</a>, decides what + Python methods to provide for a container. It takes two template + parameters, <code>Algorithms</code> and <code>Policy</code> (the + <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/doc/v2/CallPolicies.html">CallPolicies</a> for the Python + methods on the container). The <code>Algorithms</code> argument + must provide implementations for the Python methods that the + container supports, as well as a matching + <code>ContainerTraits</code> type. This type provides various + compile-time constants that <code>visitor</code> uses to decide + what Python features the container provides. It also provides a + <code>value_traits</code> typedef, which has similar + compile-time constants related to the values stored in the + container. If the <code>visitor</code> instance decides to + provide Python slice support for the container, it instantiates + the <code>slice_handler</code> template, which also takes + <code>Algorithms</code> and <code>Policy</code> parameters. In + such cases, the <code>Algorithms</code> argument must supply a + <code>SliceHelper</code> type and factory function. + + </p> + <p> + + The high-level <code>container_suite</code> template uses the + <code>algo_selector</code> template to determine what types to + use in the instantiation of <code>visitor</code>. The + <code>algo_selector</code> template has partial specializations + for all of the STL container templates. + + </p> + + <p> + + <a name="Note2">[2]</a> Note that <code>Algorithms</code> and + <code>ContainerTraits</code> don't represent individual + templates in the diagram, but <i>groups</i> of related + templates. For instance, there are actually templates called + <code>list_algorithms</code> and <code>assoc_algorithms</code>, + among others. + + </p> + + + <h2><a name="ValueTraits">ValueTraits</a></h2> + + <p> + + A <code>ValueTraits</code> class provides simple information + about the type of value stored within a container that will be + exposed to Python via the <code>container_suite</code> + interface. It controls the provision of some operations that are + dependant on the operations supported by container elements (for + instance, <code>find</code> requires a comparison operator for + the elements). A <code>ValueTraits</code> class also provides a + hook called during initialization of the Python class, which can + be used for custom processing at this point. + + </p> + <p> + + The following table lists the static constants required in a + <code>ValueTraits</code> class: + + </p> + + <p> + <table border="1"> + <tbody><tr> + <th align="left"> + Static constant + </th> + <th align="center"> + Type + </th> + <th align="left"> + Meaning + </th> + </tr> + + <tr> + <td> + <code>equality_comparable</code> + </td> + <td> + bool + </td> + <td> + + Whether the value supports comparison via + <code>operator==</code>. + + </td> + </tr> + + <tr> + <td> + <code>lessthan_comparable</code> + </td> + <td> + bool + </td> + <td> + + Whether the value supports comparison via + <code>operator<</code>. + + </td> + </tr> + + </tbody></table> + </p> + + <p> + + A <code>ValueTraits</code> class should provide the following + member function template, which will be called during execution + of the <code>def</code> call for the container suite: + + </p> + + <p> + +</p><pre>template <typename PythonClass, typename Policy> +static void visitor_helper (PythonClass &, Policy const &); +</pre> + + <p></p> + + <h3>Usage notes for ValueTraits</h3> + + <p> + + In order to include a custom <code>ValueTraits</code> class into + the container suite, it is easiest to supply it as a + specialization of the template + <code>indexing::value_traits</code> for the container's element + type. The existing <code>ContainerTraits</code> classes all + make use of + <code>value_traits<container::value_type></code>, and so + will use a specialization for the value type if available. The + default, unspecialized, version of <code>value_traits</code> + sets both of the static constants to <code>true</code> and has + an empty implementation of <code>visitor_helper</code>. + + </p> + <p> + + As an example, if a user defined type does not have any + comparison operations, then there will probably be compile-time + errors caused by an attempt to provide the Python + <code>find</code> or <code>sort</code> methods. The solution is + to write a specialized version of + <code>indexing::value_traits</code> that disables the + appropriate features. For example: + + </p> + + <p> +</p><pre>namespace boost { namespace python { namespace indexing { + template<> + struct value_traits<my_type> : public value_traits<int> + { + static bool const equality_comparable = false; + static bool const lessthan_comparable = false; + }; +} } } +</pre> + <p></p> + + <p> + + In this example, there is no need to perform any processing in + the <code>visitor_helper</code> function, and deriving from an + unspecialized version of the template (e.g. + <code>value_traits<int></code>) exposes an empty + <code>visitor_helper</code>. + + </p> + + <h3>Synopsis: boost/python/suite/indexing/value_traits.hpp</h3> + + <p> +</p><pre>namespace boost { namespace python { namespace indexing { + template<typename T> + struct value_traits { + static bool const equality_comparable = true; + static bool const lessthan_comparable = true; + + template<typename PythonClass, typename Policy> + static void visitor_helper (PythonClass &, Policy const &) + { } + }; +} } } +</pre> + <p></p> + + <h2><a name="ContainerTraits">ContainerTraits</a></h2> + + <p> + + A <code>ContainerTraits</code> class serves three + purposes. Firstly, it identifies what facilities the container + supports in principle (i.e. either directly or via some support + code). Secondly, it identifies the types used to pass values + into and out of the supported operations. Thirdly, it provides a + hook for additional code to run during initialization of the + Python class (i.e. during the <code>def</code> call for the + suite). + + </p> + <p> + + Note that a <code>ContainerTraits</code> class can be any class, + derived from the existing implementations or not, as long as it + meets the requirements listed in the following sections. + + </p> + + <h3>Static constants for ContainerTraits</h3> + + The following table lists the static constants that a + <code>ContainerTraits</code> class should define. Note that these + must be <i>compile-time constants</i>, since parts of the library + use these constants to select between template specializations. + The constants must at least be convertible to the type shown in + the second column. + + <p> + <table border="1"> + <tbody><tr> + <th align="left"> + Static constant + </th> + <th align="center"> + Type + </th> + <th align="left"> + Meaning + </th> + <th align="left"> + Influence + </th> + </tr> + <tr> + <td> + <code>has_copyable_iter</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + + Whether copies of an iterator are independant <a href="#Note3">[3]</a> + + </td> + <td> + + Required for <code>len</code> and <code>__iter__</code> + + </td> + </tr> + + <tr> + <td> + <code>is_reorderable</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + + Whether it is possible to re-order the contents of the + container. + + </td> + <td> + + Required for <code>reverse</code> and <code>sort</code> + + </td> + </tr> + + <tr> + <td> + <code>has_mutable_ref</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + Whether container elements can be altered via a reference + </td> + <td> + Determines <code>is_reorderable</code> for most containers. + </td> + </tr> + + <tr> + <td> + <code>has_find</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + + Whether find is possible in principle (via member function + or otherwise) + + </td> + <td> + <code>__contains__</code>, + <code>index</code>, + <code>count</code>, + <code>has_key</code> + </td> + </tr> + + <tr> + <td> + <code>has_insert</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + + Whether it is possible to insert new elements into the container. + + </td> + <td> + <code>insert</code>, + <code>extend</code>, + slice version of <code>__setitem__</code> + </td> + </tr> + + <tr> + <td> + <code>has_erase</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + + Whether it is possible to erase elements from the container. + + </td> + <td> + <code>__delitem__</code>, + slice version of <code>__setitem__</code> + </td> + </tr> + + <tr> + <td> + <code>has_push_back</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + + Whether container supports insertion at the end. + + </td> + <td> + <code>append</code> + </td> + </tr> + + <tr> + <td> + <code>has_pop_back</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + + Whether container supports element deletion at the end. + + </td> + <td> + Currently unused + </td> + </tr> + + <tr> + <td> + <code>index_style</code> + </td> + <td align="center"> + <code>index_style_t</code> + </td> + <td> + + Type of indexing the container supports <a href="#Note4">[4]</a> + + </td> + <td> + <code>__getitem__</code>, + <code>__setitem__</code>, + <code>__delitem__</code>, + <code>__iter__</code>, + <code>extend</code>, + <code>index</code>, + <code>count</code>, + <code>has_key</code> + </td> + </tr> + </tbody></table> + </p> + + <p> + </p><h3>Notes</h3> + + <table> + <tbody><tr> + <td valign="top"> + <a name="Note3">[3]</a> + </td> + <td> + + For example, copies of stream iterators are <i>not</i> + independant. All iterator copies refer to the same stream, + which has only one read and one write position. + + </td> + </tr> + + <tr> + <td valign="top"> + <a name="Note4">[4]</a> + </td> + <td> + + <code>index_style_none</code>, no indexing at all + (e.g. <code>list</code>)<br> + + <code>index_style_linear</code>, continuous integer-like + index type (e.g. <code>vector</code>)<br> + + <code>index_style_nonlinear</code>, indexing via other + types (e.g. <code>map</code>). + + </td> + </tr> + </tbody></table> + + <p></p> + + <h3>Member types for ContainerTraits</h3> + + <p> + + The following table lists the type names that must be defined in + a compatible implementation of <code>ContainerTraits</code>. + The large number of types is supposed to provide flexibility for + containers with differing interfaces. For example, + <code>map</code> uses the same type for searching and "indexing" + (i.e. <code>find</code> and <code>operator[]</code>) so + <code>key_type</code> and <code>index_type</code> would have to + be the same. In contrast, searching a <code>vector</code> would + typically use a different type to that used for indexing into a + vector. + + </p> + + <p> + <table border="1"> + <tbody><tr> + <th align="left"> + Type name + </th> + <th align="left"> + Meaning + </th> + </tr> + + <tr> + <td> + <code>container</code> + </td> + <td> + The type of the C++ container. + </td> + </tr> + + <tr> + <td> + <code>size_type</code> + </td> + <td> + + The type used to represent the number of elements in the + container. + + </td> + </tr> + + <tr> + <td> + <code>iterator</code> + </td> + <td> + + The container's iterator type. This should be a non-const + iterator unless the container itself is const. + + </td> + </tr> + + <tr> + <td> + <code>index_type</code> + </td> + <td> + + The type used to represent indexes extracted from a + <code>__getitem__</code> call (and others). For + <code>index_style_linear</code>, this <i>should be a + signed type</i>, so that negative indices can be + processed. For <code>index_style_nonlinear</code>, this + will most likely be the same type as + <code>key_type</code>. + + </td> + </tr> + + <tr> + <td> + <code>index_param</code> + </td> + <td> + + The type to use when passing <code>index_type</code> into + a function. + + </td> + </tr> + + <tr> + <td> + <code>value_type</code> + </td> + <td> + + The type to use when copying a value into or out of the + container. + + </td> + </tr> + + <tr> + <td> + <code>value_param</code> + </td> + <td> + + The type to use when passing <code>value_type</code> into + a function. + + </td> + </tr> + + <tr> + <td> + <code>key_type</code> + </td> + <td> + + The type used for search operations like <code>find</code> + and <code>count</code>. + + </td> + </tr> + + <tr> + <td> + <code>key_param</code> + </td> + <td> + + The type to use when passing <code>key_type</code> into a + function. + + </td> + </tr> + + <tr> + <td> + <code>reference</code> + </td> + <td> + + The type to use when returning a reference to a container + element. + + </td> + </tr> + + <tr> + <td> + <code>value_traits_</code> + </td> + <td> + + Traits for the container elements. See <a href="#ValueTraits">the ValueTraits section</a> for + information about the requirements on this type. + + </td> + </tr> + + </tbody></table> + + </p> + + <h3>Member functions for ContainerTraits</h3> + + In order to support additional initialization code to run, a + <code>ContainerTraits</code> class should provide a static member + function template as follows: + + <p> +</p><pre>template <typename PythonClass, typename Policy> +static void visitor_helper (PythonClass &, Policy const &); +</pre> + <p></p> + + <p> + + Typically, the implementation would just forward the call to the + equivalent function in the <code>value_traits_</code> class. + + </p> + + <h3>Usage notes for ContainerTraits</h3> + + <p> + + It may be possible to mix your own <code>ContainerTraits</code> + class with one of the existing <code>Algorithms</code> + implementations, thus saving yourself a fair bit of work. The + easiest way to do this would be to specialize the + <code>algo_selector</code> template for your container type, + using public deriviation to get the implementation from one of + the existing <code>Algorithms</code> templates. For example, + assuming that <code>default_algorithms</code> is suitable for + your container: + + </p> + + <p> +</p><pre>namespace boost { namespace python { namespace indexing { + template<> + struct algo_selector<my_container> + : public default_algorithms<my_container_traits> + { + }; +} } } +</pre> + <p></p> + <p> + + Alternatively, you could select the algorithms and traits using + the <code>visitor</code> template directly, as described in the + <a href="#workarounds">compiler workarounds</a> section. + + </p> + + <h3><a name="simple_ctraits">Simplistic ContainerTraits example</a></h3> + + <p> + + The following block of code shows a simplistic implementation of + <code>ContainerTraits</code> for the container + <code>std::map<std::string, int></code>. The actual + implementation used by the suite relies on template + metaprogramming techniques, whereas this example is designed to + show only the essential elements of a + <code>ContainerTraits</code> implementation. + + </p> + + <p> +</p><pre>#include <map> +#include <string> +#include <boost/python/suite/indexing/suite_utils.hpp> +// Include suite_utils to get index_style_t + +struct simple_map_traits { + // Traits information for std::map<std::string, int> + + typedef std::map<std::string, int> container; + typedef container::size_type size_type; + typedef container::iterator iterator; + + typedef int value_type; + typedef int & reference; + typedef std::string key_type; + typedef std::string index_type; + + typedef int value_param; + typedef std::string const & key_param; + typedef std::string const & index_param; + + static bool const has_copyable_iter = true; + static bool const has_mutable_ref = true; + static bool const has_find = true; + static bool const has_insert = true; + static bool const has_erase = true; + static bool const has_pop_back = false; + static bool const has_push_back = false; + static bool const is_reorderable = false; + + static boost::python::indexing::index_style_t const index_style + = boost::python::indexing::index_style_nonlinear; + + struct value_traits_ { + // Traits information for our value_type + static bool const equality_comparable = true; + static bool const lessthan_comparable = true; + }; + + template<typename PythonClass, typename Policy> + static void visitor_helper (PythonClass &, Policy const &) + { + // Empty + } +}; +</pre> + <p></p> + + <p> + + Example usage of the <code>simple_map_traits</code>: + + </p> + + <p> +</p><pre>#include "simple_map_traits.hpp" + +#include <boost/python/suite/indexing/container_suite.hpp> + +#include <boost/python/module.hpp> +#include <boost/python/class.hpp> + +BOOST_PYTHON_MODULE(test_simple) { + using namespace boost::python; + + typedef std::map<std::string, int> container_t; + typedef indexing::map_algorithms<simple_map_traits> algorithms_t; + + class_<container_t> ("map") + .def (indexing::container_suite<container_t, algorithms_t>()); +} +</pre> + <p></p> + + <h2><a name="Algorithms">Algorithms</a></h2> + + <p> + + The <code>Algorithms</code> requirements are designed to provide + a predictable interface to any container, so that the same + <code>visitor</code> code can expose any supported container to + Python. An implemention of <code>Algorithms</code> does this by + providing functions and typedefs with fixed names. The exact + interfaces to the functions can vary to some extent, since the + <code>def</code> function calls used internally by the + <code>visitor</code> deduce the function type + automatically. However, certain points should be confomed to: + + </p><ol> + <li> + + The functions should be static, with + <code>container &</code> as first parameter. + + </li> + + <li> + + The functions should <i>not</i> be overloaded – this + avoids problems with type deduction. + + </li> + <li> + + Generally, not all of the possible functions need to be + implemented, dependant on the static constants in the + <code>ContainerTraits</code>. + + </li> + </ol> + + <p></p> + + <p> + + The block of code below shows the definition of the + <code>default_algorithms</code> class template, which is the + basis for all current implementations of + <code>Algorithms</code>. The typedefs that it defines are + primarily for convenience within the implementation itself, + however <code>container</code>, <code>reference</code> and + <code>slice_helper</code> are also required by the + <code>slice_handler</code> template, if slices are + supported. Note that <code>default_algorithms</code> derives all + of the type information from its <code>ContainerTraits</code> + template argument, which allows the same implementation to be + used for various container types. + + </p> + + <h3>Partial boost/python/suite/indexing/algorithms.hpp</h3> + + <p> +</p><pre>namespace boost { namespace python { namespace indexing { + template<typename ContainerTraits, typename Ovr = detail::no_override> + class default_algorithms + { + typedef default_algorithms<ContainerTraits, Ovr> self_type; + + public: + typedef ContainerTraits container_traits; + + typedef typename ContainerTraits::container container; + typedef typename ContainerTraits::iterator iterator; + typedef typename ContainerTraits::reference reference; + typedef typename ContainerTraits::size_type size_type; + typedef typename ContainerTraits::value_type value_type; + typedef typename ContainerTraits::value_param value_param; + typedef typename ContainerTraits::index_param index_param; + typedef typename ContainerTraits::key_param key_param; + + typedef int_slice_helper<self_type, integer_slice> slice_helper; + + static size_type size (container &); + static iterator find (container &, key_param); + static size_type get_index (container &, key_param); + static size_type count (container &, key_param); + static bool contains (container &, key_param); + static void reverse (container &); + static reference get (container &, index_param); + static void assign (container &, index_param, value_param); + static void insert (container &, index_param, value_param); + static void erase_one (container &, index_param); + static void erase_range(container &, index_param, index_param); + static void push_back (container &, value_param); + static void sort (container &); + + static slice_helper make_slice_helper (container &c, slice const &); + + template<typename PythonClass, typename Policy> + static void visitor_helper (PythonClass &, Policy const &); + }; +} } } +</pre> + <p></p> + + <h3>Slice support</h3> + <p> + + For containers that support Python slices, the + <code>visitor</code> template will instantiate and use + internally the <code>slice_handler</code> template. This + template requires a type called <code>slice_helper</code> and a + factory function called <code>make_slice_helper</code> from its + <code>Algorithms</code> argument. More details are provided in + the section <a href="#SliceHelper">SliceHelper</a>. + + </p> + + <h3>Usage notes for Algorithms</h3> + + <p> + + The existing <code>indexing::algo_selector</code> template uses + partial specializations and public derivation to select an + <code>Algorithms</code> implementation suitable for any of the + standard container types. Exactly how it does this should be + considered an implementation detail, and uses some tricks to + reuse various existing <code>Algorithms</code> + implementations. In any case, client code can specialize the + <code>algo_selector</code> template for new container types, as + long as the specialized instances conform to the requirements + for <code>Algorithms</code> as already given. + + </p> + <p> + + A new implementation of <code>Algorithms</code> could derive + from any one of the existing implementation templates, or be + completely independant. The existing implementation templates + are listed in the following table. They each take one template + parameter, which should be a valid <code>ContainerTraits</code> + class, as specified in a <a href="#ContainerTraits">previous + section</a>. + + </p> + + <p> + <table border="1"> + <tbody><tr> + <th> + Template name + </th> + <th> + Description + </th> + </tr> + + <tr> + <td> + + <code>default_algorithms</code> + + </td> + <td> + + Uses standard iterator-based algorithms wherever + possible. Assumes that the container provides + <code>begin</code> and end <code>end</code> member + functions that return iterators, and some or all of + <code>size</code>, <code>insert</code>, <code>erase</code> + and <code>push_back</code>, depending on what functions get + instantiated. + + </td> + </tr> + + <tr> + <td> + + <code>list_algorithms</code> + + </td> + <td> + + Similar to the above (in fact, it derives from + <code>default_algorithms</code>) except that it uses + container member functions <code>reverse</code> and + <code>sort</code> instead of the iterator-based + versions. Defined in + <code>boost/python/suite/indexing/list.hpp</code>. + + </td> + </tr> + + <tr> + <td> + + <code>assoc_algorithms</code> + + </td> + <td> + + Also derived from <code>default_algorithms</code>, for use + with associative containers. Uses the container member + function <code>find</code> for indexing, and member + function <code>count</code> instead of iterator-based + implementations. + + </td> + </tr> + + <tr> + <td> + + <code>set_algorithms</code> + + </td> + <td> + + Derived from <code>assoc_algorithms</code> to handle + <code>set</code> insertion operations, which are slightly + different to the <code>map</code> versions. + + </td> + </tr> + + <tr> + <td> + + <code>map_algorithms</code> + + </td> + <td> + + Derived from <code>assoc_algorithms</code> to handle + <code>map</code> insertion and lookup, which are slightly + different to the <code>set</code> versions. + + </td> + </tr> + </tbody></table> + + </p> + <p> + + The <code>default_algorithms</code> template attempts to place + as few restrictions as possible on the container type, by using + iterators and standard algorithms in most of its functions. It + accepts an optional second template parameter, which can be used + via the curiously recurring template idiom to replace any of its + functions that it relies on internally. For instance, if you've + created an iterator-style interface to a container that is not + at all STL-like (let's call it <code>weird_container</code>), + you might be able to re-use most of + <code>default_algorithms</code> by replacing its basic functions + like this: + + </p> + <p> +</p><pre>namespace indexing = boost::python::indexing; + +struct my_algorithms + : public indexing::default_algorithms < + weird_container_traits, my_algorithms + > +{ + size_t size (weird_container const &c) { + return ...; + } + + my_iterator_t begin (weird_container &c) { + return ...; + } + + my_iterator_t end (weird_container &c) { + return ...; + } +}; +</pre> + <p></p> + + <h2><a name="SliceHelper">SliceHelper</a></h2> + + <p> + + Support code for Python slices is split into two portions, the + <code>slice_handler</code> template, and a "slice helper" that + can easily be replaced by client code via a typedef and factory + function in the <code>Algorithms</code> argument supplied to + <code>container_suite</code>. The slice helper object takes care + of reading and writing elements from a slice in a C++ container, + and optionally insertion and deletion. Effectively, the slice + helper object maintains a pointer to the current element of the + slice within the container, and provides a <code>next</code> + function to advance to the next element of the slice. The + container suite uses the following interface for slices: + + </p> + <p> + <table border="1"> + <tbody><tr> + <th> + + Expression + + </th> + <th> + + Return type + + </th> + <th> + + Notes + + </th> + </tr> + <tr> + <td> + + <code>Algorithms::</code> <code>make_slice_helper</code> + <code>(c, s)</code> + + </td> + <td> + + <code>Algorithms::</code> <code>slice_helper</code> + + </td> + <td> + + <code>c</code> is of type + <code>Algorithms::</code> <code>container &</code> and + <code>s</code> is of type <code>indexing::</code> + <code>slice const &</code>. + Returns a newly constructed <code>slice_helper</code> + object by value. + + </td> + </tr> + + <tr> + <td> + + <code>slice_helper.</code><code>next()</code> + + </td> + <td> + + <code>bool</code> + + </td> + <td> + + Advances the slice helper's current element pointer to the + next element of the slice. Returns true if such an element + exists, and false otherwise. The first time this function + is called, it should set the current pointer to the first + element of the slice (if any). + + </td> + </tr> + + <tr> + <td> + + <code>slice_helper.</code> <code>current()</code> + + </td> + <td> + + <code>Algorithms::</code> <code>reference</code> + + </td> + <td> + + Returns a reference to the current element of the + slice. This will only be called if the last call to + <code>next()</code> returned true. + + </td> + </tr> + <tr> + <td> + + <code>slice_helper.</code><code>write (v)</code> + + </td> + <td> + + <code>void</code> + + </td> + <td> + + The parameter <code>v</code> is of type + <code>Algorthims::value_param</code>. Advances to the + next element of the slice, as defined in + <code>next</code>, and writes the given value + <code>v</code> at the new location in the container.If the + slice is exhausted (i.e. <code>next</code> would return + false) then <code>write</code> <i>either</i> inserts the + value into the container at the next location (past the + end of the slice), <i>or</i> sets a Python exception and + throws. + + </td> + </tr> + <tr> + <td> + + <code>slice_helper.</code> <code>erase_remaining()</code> + + </td> + <td> + + <code>void</code> + + </td> + <td> + + <i>Either</i> erases any remaining elements in the slice + not already consumed by calls to <code>next</code> or + <code>write</code>, + <i>or</i> sets a Python exception and throws. + + </td> + </tr> + </tbody></table> + </p> + + <p> + + The container suite provides a generic implementation of the + <code>SliceHelper</code> requirements for containers that have + integer-like indexes. It is parameterized with a + <code>SliceType</code> parameter that allows the integer index + values to come from various different sources, the default being + the <code>PySlice_GetIndices</code> function. Refer to the + header file <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/boost/python/suite/indexing/int_slice_helper.hpp"><code>int_slice_helper.hpp</code></a> + and the references to it in the <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/boost/python/suite/indexing/algorithms.hpp"><code>algorithms.hpp</code></a> + header for details. + + </p> + + <h2><a name="container_proxy">container_proxy</a></h2> + + <p> + + The <code>container_proxy</code> template provides an emulation + of Python reference semantics for objects held by value in a + vector-like container. Of course, this introduces some + performance penalties in terms of memory usage and run time, so + the primary application of this template is in situations where + all of the following apply: + + </p><ol> + <li> + + It is not practical to switch to a container of shared + pointers + + </li> + <li> + + Python code requires reference semantics for the objects + within the container + + </li> + <li> + + Element insertion, deletion or assignment takes place, so + that using <code>return_internal_reference</code> would be + dangerous. + + </li> + </ol> + + <p></p> + + <p> + + + The <code>container_proxy</code> template wraps any vector-like + container and presents an interface that is similar to that of + <code>std::vector</code>, but which returns + <code>element_proxy</code> objects instead of plain references + to values stored in the wrapped container. During an operation + that alters the position of an element within the container + (e.g. <code>insert</code>) the <code>container_proxy</code> code + updates the relevant proxy objects, so that they still refer to + the <i>same</i> elements at their new locations. Any operation + that would delete or overwrite a value in the container + (e.g. <code>erase</code>) copies the to-be-deleted value into + its corresponding proxy object. This means that a proxy's + "reference" to an element is robust in the face of changes to + the element's position in the container, and even the element's + removal. + + </p> + <p> + + Ideally, any code that changes the positions of elements within + the container would use only the <code>container_proxy</code> + interface, to ensure that the proxies are maintained in + synchronization. Code that otherwise makes direct modifications + to the raw container must notify the + <code>container_proxy</code> of the changes, as detailed in the + following section. + + </p> + + <h3>container_proxy interface</h3> + + <p> + + The <code>container_proxy</code> template takes three + parameters, only the first of which is mandatory: + + </p> + <p> + +</p><pre>template<class Container + , class Holder = identity<Container> + , class Generator = vector_generator> class container_proxy; +</pre> + + <p></p> + <p> + + The <code>Container</code> argument is the raw container type + that the <code>container_proxy</code> will manage. It must + provide random-access indexing. + + </p> + <p> + + The <code>Holder</code> argument determines how the + <code>container_proxy</code> stores the raw container object. + There are currently two types of holder implemented, the default + <code>identity</code> template which will store the raw + container by value within the <code>container_proxy</code>, and + the <code>deref</code> template which stores a (plain) pointer + to an external object. It would also be possible, for instance, + to create a holder that uses a <code>shared_pointer</code>, or + one that stores a pointer but performs deep copies. + + </p> + <p> + + The <code>Generator</code> argument determines what container to + use for storing the proxy objects. The argument must be a + suitable class so that + <code>Generator::apply<proxy_t>::type</code> is a typedef + for the container to use for storing the proxies. The default is + <code>vector_generator</code>, which generates + <code>std::vector</code> instances. The usefulness of allowing + other generators can be seen from the example + + <code>container_proxy<std::deque<...> ></code>. + + Insertion at the beginning of this <code>container_proxy</code> + requires an insertion at the beginning of the + <code>std::deque</code> raw container, which has amortized + constant time complexity. However, it also requires an insertion + at the beginning of the proxy container, which (using the + <code>std::vector</code> provided by + <code>vector_generator</code>) has linear time complexity. If + this is a significant issue, you can use a custom + <code>Generator</code> to match the performance characteristics + of the proxy container to those of the raw container. + + </p> + <p> + + Examples in <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/test/test_container_proxy.cpp">libs/python/test/test_container_proxy.cpp</a> + ... + + </p> + + <h3>Synopsis: boost/python/suite/indexing/container_proxy.hpp</h3> + +<pre>namespace boost { namespace python { namespace indexing { + template<class Container + , class Holder = identity<Container> + , class Generator = vector_generator> + class container_proxy + { + public: + typedef typename Container::size_type size_type; + typedef typename Container::difference_type difference_type; + typedef typename Container::value_type raw_value_type; + + typedef typename Holder::held_type held_type; + + typedef <i>implementation defined</i> value_type; + typedef <i>implementation defined</i> const_value_type; + typedef <i>implementation defined</i> iterator; + typedef <i>implementation defined</i> const_iterator; + + typedef value_type reference; // Has reference semantics + typedef const_value_type const_reference; // Has reference semantics + + container_proxy (); + explicit container_proxy (held_type const &); + template<typename Iter> container_proxy (Iter, Iter); + + container_proxy (container_proxy const &); + container_proxy &operator= (container_proxy const &); + ~... [truncated message content] |
From: <rom...@us...> - 2006-07-12 09:43:05
|
Revision: 301 Author: roman_yakovenko Date: 2006-07-12 02:42:52 -0700 (Wed, 12 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=301&view=rev Log Message: ----------- small bug fixes in indexing suite functionality Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/type_traits.py pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pygccxml_dev/pygccxml/declarations/type_traits.py =================================================================== --- pygccxml_dev/pygccxml/declarations/type_traits.py 2006-07-11 18:59:43 UTC (rev 300) +++ pygccxml_dev/pygccxml/declarations/type_traits.py 2006-07-12 09:42:52 UTC (rev 301) @@ -15,6 +15,7 @@ within this module works on L{type_t} class hierarchy and\\or L{class_t}. """ +import types import filters import typedef import calldef @@ -853,6 +854,14 @@ if not found: if cpptypes.FUNDAMENTAL_TYPES.has_key( value_type_str ): return cpptypes.FUNDAMENTAL_TYPES[value_type_str] + elif is_std_string( value_type_str ): + string_ = global_ns.typedef( '::std::string' ) + return remove_declarated( string_ ) + elif is_std_wstring( value_type_str ): + string_ = global_ns.typedef( '::std::wstring' ) + return remove_declarated( string_ ) + else: + return None if len( found ) == 1: return found[0] else: @@ -892,17 +901,23 @@ decl_strings = [ '::std::basic_string<char,std::char_traits<char>,std::allocator<char> >' , '::std::basic_string<char, std::char_traits<char>, std::allocator<char> >' - , '::std::string' ] - type = remove_alias( type ) - return remove_cv( type ).decl_string in decl_strings + , '::std::string' ] + if isinstance( type, types.StringTypes ): + return type in decl_strings + else: + type = remove_alias( type ) + return remove_cv( type ).decl_string in decl_strings def is_std_wstring( type ): decl_strings = [ '::std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >' , '::std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >' , '::std::wstring' ] - type = remove_alias( type ) - return remove_cv( type ).decl_string in decl_strings + if isinstance( type, types.StringTypes ): + return type in decl_strings + else: + type = remove_alias( type ) + return remove_cv( type ).decl_string in decl_strings Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-11 18:59:43 UTC (rev 300) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-12 09:42:52 UTC (rev 301) @@ -415,14 +415,14 @@ used_containers = list( self.__types_db.used_containers ) used_containers.sort( cmp_by_name ) for cls in used_containers: - container_name = cls.name.split( '<' )[0] + '<' + container_name = cls.name.split( '<' )[0] + '<' if isinstance( cls.indexing_suite, decl_wrappers.indexing_suite1_t ): isuite = isuite1 else: isuite = isuite2 - if not isuite.has_key( container_name ): + if not isuite.has_key( container_name ): continue #not supported if isuite is isuite2: @@ -432,15 +432,9 @@ cls_creator = create_cls_cc( cls ) element_type = cls.indexing_suite.element_type - if declarations.is_class( element_type ): - class_traits = declarations.class_traits - value_cls = class_traits.get_declaration( element_type ) - if value_cls.ignore: - continue #this collection could not be exported, because - #the value_type of collection is not exported if isuite is isuite1: if declarations.is_class( element_type ) and not declarations.has_public_equal( element_type ): - cls_creator.adopt_creator( create_explanation( cls ) ) + cls_creator.adopt_creator( create_explanation( cls ) ) cls_creator.adopt_creator( code_creators.indexing_suite1_t(cls) ) else: class_traits = declarations.class_traits This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-11 18:59:50
|
Revision: 300 Author: roman_yakovenko Date: 2006-07-11 11:59:43 -0700 (Tue, 11 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=300&view=rev Log Message: ----------- updating indexng suite v2 documentation Modified Paths: -------------- pyplusplus_dev/docs/std_containers/containers.rest Modified: pyplusplus_dev/docs/std_containers/containers.rest =================================================================== --- pyplusplus_dev/docs/std_containers/containers.rest 2006-07-11 18:37:14 UTC (rev 299) +++ pyplusplus_dev/docs/std_containers/containers.rest 2006-07-11 18:59:43 UTC (rev 300) @@ -75,7 +75,7 @@ ------------------- By default, `pyplusplus`_ works with built-in indexing suite. If you want to use -next version of indexing suite, you should tell this to ``module_builder_t.__init__`` +next version of indexing suite, you should tell this to the ``module_builder_t.__init__`` method: :: @@ -86,13 +86,13 @@ of ``indexing_suite1_t`` or ``indexing_suite2_t`` class. -How does `pyplusplus`_ know that a class represents stl container instantiation? +How does `pyplusplus`_ know, that a class represents stl container instantiation? Well, it uses ``pygccxml.declarations.container_traits`` to find out this. ``pygccxml.declarations.container_traits`` class, provides all functionality -needed to identify container and to find out its ``value_type`` -( ``mapped_type`` ). - +needed to identify container and to find out its ``value_type`` +( ``mapped_type`` ). + Built-in indexing suite API --------------------------- @@ -172,76 +172,22 @@ flags. `pyplusplus`_ allows you to specify what methods you want to disable or enable. ``indexing_suite2_t.METHODS`` containes names of all supported methods. +* ``[disable|enable]_methods_group`` - almost same as above, but allows you + to specify what group of methods you want to disable or enable. + ``indexing_suite2_t.METHOD_GROUPS`` containes names of all supported groups. -In this case, `pyplusplus` - -Generated code --------------- -All generated code will have next form: -:: - - class_< container, other class parameters >(name) - .def( concrete indexing suite class< container, proxy, derived policies >() ) - ; - -Usage example -------------- -C++ code: -:: - - #include <map> - #include <vector> - -:: - - std::vector<string> get_options(){...} - -:: - - struct my_data{...}; - std::map< int, my_data > get_data(); - -Assumption: user wants to use ``get_options`` and ``get_data`` functions. Next -steps will describe what `pyplusplus`_ will do in this case: - -1. `pyplusplus`_ will analyze functions return type and arguments. - -2. It will understand that ``std::vector< std::string >`` and ``std::map< int, my_data >`` - classes should be exported too. - -3. It will understand that those classes should be exported using indexing suite - functionality provided by `boost.python`_ library or `pyplusplus`_ - ``code repository``. - -4. It will generate the code, that will use that functionality. - -So far, so good. Sometimes, there are use cases, when user has to change default -values, for example ``NoProxy`` or ``DerivedPolicies``. What interface `pyplusplus`_ -will provide in order to change the defaults? Well, ``std::vector< std::string >`` -is the class that could be found in declarations tree, right? User can find the -class and change the defaults: -:: - - mb = module_builder_t( ... ) - #the next line will not work, because the real name of std::vector< std::string > - #is platform dependent and much longer. It is there for simplicity. - vector_of_strings = mb.class_( "std::vector< std::string >" ) - vector_of_strings.alias = "StringVector" - vector_of_strings.held_type = ... - vector_of_strings.indexing_suite.no_proxy = False - - -Please, pay attention to the next line: -:: - - vector_of_strings.indexing_suite.no_proxy = False - -Every class, that represents instantiation of some std container will have -class variable ``indexing_suite``, that will be intitialized with relevant -indexing suite class. +Small tips/hints +---------------- - +1. If you set ``equality_comparable`` or ``less_than_comparable`` to ``False``. + The indexing suite will disable relevant functionality. You don't have + explicitly to disable method or mothods group. +2. The documentation of new indexing suite containes few small mistakes. + I hope, I will have time to fix them. Any way, `pyplusplus`_ generates + correct code. + + .. _`pyplusplus` : ./../pyplusplus.html .. _`boost.python`: http://www.boost.org/libs/python/doc/index.html .. _`Python`: http://www.python.org This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-11 18:37:26
|
Revision: 299 Author: roman_yakovenko Date: 2006-07-11 11:37:14 -0700 (Tue, 11 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=299&view=rev Log Message: ----------- updatng example Modified Paths: -------------- pyplusplus_dev/docs/std_containers/containers.rest pyplusplus_dev/examples/custom_code_creator/generate_code.py pyplusplus_dev/examples/custom_code_creator/generated/properties.py.cpp Modified: pyplusplus_dev/docs/std_containers/containers.rest =================================================================== --- pyplusplus_dev/docs/std_containers/containers.rest 2006-07-11 18:04:20 UTC (rev 298) +++ pyplusplus_dev/docs/std_containers/containers.rest 2006-07-11 18:37:14 UTC (rev 299) @@ -70,9 +70,9 @@ analizes the container ``value_type`` ( or in case of mapping container ``mapped_type`` ), in order to set reasonable defaults, when it generates the code. ------------------------ -Code, show me the code! ------------------------ +------------------- +Indexing suites API +------------------- By default, `pyplusplus`_ works with built-in indexing suite. If you want to use next version of indexing suite, you should tell this to ``module_builder_t.__init__`` Modified: pyplusplus_dev/examples/custom_code_creator/generate_code.py =================================================================== --- pyplusplus_dev/examples/custom_code_creator/generate_code.py 2006-07-11 18:04:20 UTC (rev 298) +++ pyplusplus_dev/examples/custom_code_creator/generate_code.py 2006-07-11 18:37:14 UTC (rev 299) @@ -25,9 +25,9 @@ from pyplusplus import module_builder class property_creator_t( code_creators.code_creator_t ): - def __init__( self, get_function, set_function, parent=None ): + def __init__( self, get_function, set_function ): #get/set functions are references to relevant declarations - code_creators.code_creator_t.__init__( self, parent ) + code_creators.code_creator_t.__init__( self ) self.__get_function = get_function self.__set_function = set_function Modified: pyplusplus_dev/examples/custom_code_creator/generated/properties.py.cpp =================================================================== --- pyplusplus_dev/examples/custom_code_creator/generated/properties.py.cpp 2006-07-11 18:04:20 UTC (rev 298) +++ pyplusplus_dev/examples/custom_code_creator/generated/properties.py.cpp 2006-07-11 18:37:14 UTC (rev 299) @@ -1,23 +1,37 @@ -// This file has been generated by pyplusplus. - -#include "boost/python.hpp" - -#include "properties.hpp" - -namespace bp = boost::python; - -BOOST_PYTHON_MODULE(properties){ - bp::class_< geometry::point_t >( "point_t", bp::init< bp::optional< int, int > >(( bp::arg("x")=0, bp::arg("y")=0 ))[bp::default_call_policies()] ) - .add_property( "y", &::geometry::point_t::get_y, &::geometry::point_t::set_y ) - .add_property( "x", &::geometry::point_t::get_x, &::geometry::point_t::set_x ); - - bp::def("extract_y" - , &::geometry::extract_y - , ( bp::arg("pt") ) - , bp::default_call_policies() ); - - bp::def("extract_x" - , &::geometry::extract_x - , ( bp::arg("pt") ) - , bp::default_call_policies() ); -} +// This file has been generated by pyplusplus. + +#include "boost/python.hpp" + +#include "properties.hpp" + +namespace bp = boost::python; + +BOOST_PYTHON_MODULE(properties){ + bp::class_< geometry::point_t >( "point_t", bp::init< bp::optional< int, int > >(( bp::arg("x")=(int)(0), bp::arg("y")=(int)(0) ))[bp::default_call_policies()] ) + .add_property( "y", &::geometry::point_t::get_y, &::geometry::point_t::set_y ) + .add_property( "x", &::geometry::point_t::get_x, &::geometry::point_t::set_x ); + + { //::geometry::extract_x + + typedef int ( *function_ptr_t )( ::geometry::point_t const & ); + + bp::def( + "extract_x" + , function_ptr_t( &::geometry::extract_x ) + , ( bp::arg("pt") ) + , bp::default_call_policies() ); + + } + + { //::geometry::extract_y + + typedef int ( *function_ptr_t )( ::geometry::point_t const & ); + + bp::def( + "extract_y" + , function_ptr_t( &::geometry::extract_y ) + , ( bp::arg("pt") ) + , bp::default_call_policies() ); + + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-11 18:04:27
|
Revision: 298 Author: roman_yakovenko Date: 2006-07-11 11:04:20 -0700 (Tue, 11 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=298&view=rev Log Message: ----------- improving generated code stability Modified Paths: -------------- pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-11 15:44:30 UTC (rev 297) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-11 18:04:20 UTC (rev 298) @@ -410,7 +410,11 @@ } container_suite_header = "boost/python/suite/indexing/container_suite.hpp" - for cls in self.__types_db.used_containers: + + cmp_by_name = lambda cls1, cls2: cmp( cls1.decl_string, cls2.decl_string ) + used_containers = list( self.__types_db.used_containers ) + used_containers.sort( cmp_by_name ) + for cls in used_containers: container_name = cls.name.split( '<' )[0] + '<' if isinstance( cls.indexing_suite, decl_wrappers.indexing_suite1_t ): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-11 15:44:36
|
Revision: 297 Author: roman_yakovenko Date: 2006-07-11 08:44:30 -0700 (Tue, 11 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=297&view=rev Log Message: ----------- improving generated code stability( order of generated code should not change from one generation to another ) Modified Paths: -------------- pyplusplus_dev/pyplusplus/module_creator/class_organizer.py Modified: pyplusplus_dev/pyplusplus/module_creator/class_organizer.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/class_organizer.py 2006-07-11 12:39:43 UTC (rev 296) +++ pyplusplus_dev/pyplusplus/module_creator/class_organizer.py 2006-07-11 15:44:30 UTC (rev 297) @@ -59,7 +59,10 @@ if not isinstance( base_type, declarations.declarated_t ): continue top_class_inst = self.__get_top_class_inst( base_type.declaration ) - i_depend_on_them.add( full_name( top_class_inst ) ) + i_depend_on_them.add( full_name( top_class_inst ) ) + + i_depend_on_them = list( i_depend_on_them ) + i_depend_on_them.sort() return i_depend_on_them def __get_top_class_inst( self, decl ): @@ -71,8 +74,8 @@ def _topological_sort(self): self._dfs() - def _dfs( self ): - for class_ in self.__dependencies_graph: + def _dfs( self ): + for class_ in sorted( self.__dependencies_graph.keys() ): if self.__colors[class_] == COLOR.WHITE: self._dfs_visit(class_) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-11 12:39:58
|
Revision: 296 Author: roman_yakovenko Date: 2006-07-11 05:39:43 -0700 (Tue, 11 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=296&view=rev Log Message: ----------- improving generated code stability( order of generated code should not change from one generation to another ) Modified Paths: -------------- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py pyplusplus_dev/pyplusplus/module_creator/class_organizer.py pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pyplusplus_dev/pyplusplus/file_writers/multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-07-11 09:05:55 UTC (rev 295) +++ pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-07-11 12:39:43 UTC (rev 296) @@ -293,7 +293,8 @@ self.split_global_variables() self.split_free_functions() - if write_main: + if write_main: + self.__include_creators.sort( cmp=lambda ic1, ic2: cmp( ic1.header, ic2.header ) ) map( lambda creator: self.extmodule.adopt_include( creator ) , self.__include_creators ) main_cpp = os.path.join( self.directory_path, self.extmodule.body.name + '.main.cpp' ) Modified: pyplusplus_dev/pyplusplus/module_creator/class_organizer.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/class_organizer.py 2006-07-11 09:05:55 UTC (rev 295) +++ pyplusplus_dev/pyplusplus/module_creator/class_organizer.py 2006-07-11 12:39:43 UTC (rev 296) @@ -10,12 +10,15 @@ WHITE = 0 GRAY = 1 BLACK = 2 + class class_organizer_t(object): def __init__( self, decls ): - object.__init__( self ) + object.__init__( self ) + self.__classes = filter( lambda x: isinstance( x, declarations.class_t ) - , decls ) + , decls ) + self.__classes.sort( lambda cls1, cls2: cmp( cls1.decl_string, cls2.decl_string ) ) self.__dependencies_graph = self._build_graph() self.__time = 0 self.__colors = dict( zip( self.__dependencies_graph.keys() Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-11 09:05:55 UTC (rev 295) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-11 12:39:43 UTC (rev 296) @@ -113,7 +113,7 @@ decls = filter( lambda x: not x.ignore, decls ) return decls - def _reorder_decls(self, decls ): + def _reorder_decls(self, decls ): classes = filter( lambda x: isinstance( x, declarations.class_t ) , decls ) @@ -126,15 +126,33 @@ #type should be exported before it can be used. variables = [] enums = [] - others = [] + others = [] + classes = [] + constructors = [] for inst in ordered: if isinstance( inst, declarations.variable_t ): variables.append( inst ) elif isinstance( inst, declarations.enumeration_t ): - enums.append( inst ) + enums.append( inst ) + elif isinstance( inst, ( declarations.class_t, declarations.class_declaration_t ) ): + classes.append( inst ) + elif isinstance( inst, declarations.constructor_t ): + constructors.append( inst ) else: - others.append( inst ) - new_ordered = enums + others.append( inst ) + #this will prevent from py++ to change the order of generated code + cmp_by_name = lambda d1, d2: cmp( d1.name, d2.name ) + cmp_by_line = lambda d1, d2: cmp( d1.location.line, d2.location.line ) + + enums.sort( cmp=cmp_by_name ) + others.sort( cmp=cmp_by_name ) + variables.sort( cmp=cmp_by_name ) + constructors.sort( cmp=cmp_by_line ) + + new_ordered = [] + new_ordered.extend( enums ) + new_ordered.extend( classes ) + new_ordered.extend( constructors ) new_ordered.extend( others ) new_ordered.extend( variables ) return new_ordered # @@ -168,7 +186,7 @@ return ordered_members def _does_class_have_smth_to_export(self, exportable_members ): - return bool( self._filter_decls( self._reorder_decls( exportable_members ) ) ) + return bool( self._filter_decls( exportable_members ) ) def _is_constructor_of_abstract_class( self, decl ): assert isinstance( decl, declarations.constructor_t ) @@ -242,8 +260,11 @@ if self.__is_same_func( f, f_defined ): break else: - not_reimplemented_funcs.add( f ) - return not_reimplemented_funcs + not_reimplemented_funcs.add( f ) + functions = list( not_reimplemented_funcs ) + functions.sort( cmp=lambda f1, f2: cmp( ( f1.name, f1.location.as_tuple() ) + , ( f2.name, f2.location.as_tuple() ) ) ) + return functions def _is_wrapper_needed(self, class_inst, exportable_members): if isinstance( self.curr_decl, declarations.class_t ) \ @@ -657,7 +678,7 @@ self.curr_code_creator.adopt_creator( class_inst ) self.curr_code_creator = class_inst - for decl in self._filter_decls( self._reorder_decls( exportable_members ) ): + for decl in exportable_members: self.curr_decl = decl declarations.apply_visitor( self, decl ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-11 09:06:13
|
Revision: 295 Author: roman_yakovenko Date: 2006-07-11 02:05:55 -0700 (Tue, 11 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=295&view=rev Log Message: ----------- improving py++ messages usability Modified Paths: -------------- pygccxml_dev/pygccxml/utils/__init__.py pyplusplus_dev/pyplusplus/_logging_/__init__.py pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py pyplusplus_dev/pyplusplus/module_builder/__init__.py pyplusplus_dev/pyplusplus/module_creator/types_database.py Modified: pygccxml_dev/pygccxml/utils/__init__.py =================================================================== --- pygccxml_dev/pygccxml/utils/__init__.py 2006-07-11 08:45:33 UTC (rev 294) +++ pygccxml_dev/pygccxml/utils/__init__.py 2006-07-11 09:05:55 UTC (rev 295) @@ -11,7 +11,7 @@ def _create_logger_( name ): logger = logging.getLogger(name) __handler = logging.StreamHandler(sys.stdout) - __handler.setFormatter( logging.Formatter( '%(levelname)s %(message)s' ) ) + __handler.setFormatter( logging.Formatter( os.linesep + '%(levelname)s %(message)s' ) ) logger.addHandler(__handler) logger.setLevel(logging.INFO) return logger Modified: pyplusplus_dev/pyplusplus/_logging_/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/_logging_/__init__.py 2006-07-11 08:45:33 UTC (rev 294) +++ pyplusplus_dev/pyplusplus/_logging_/__init__.py 2006-07-11 09:05:55 UTC (rev 295) @@ -8,14 +8,15 @@ This package contains logging configuration for pyplusplus. Default log level is DEBUG. Default log messages destination is sys.stdout. """ - + +import os import sys import logging def _create_logger_( name ): logger = logging.getLogger(name) __handler = logging.StreamHandler(sys.stdout) - __handler.setFormatter( logging.Formatter( '%(levelname)s %(message)s' ) ) + __handler.setFormatter( logging.Formatter( os.linesep + '%(levelname)s %(message)s' ) ) logger.addHandler(__handler) logger.setLevel(logging.INFO) return logger Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-11 08:45:33 UTC (rev 294) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-11 09:05:55 UTC (rev 295) @@ -197,8 +197,9 @@ if isinstance( oper, declarations.member_operator_t ) and oper.symbol in ( '()', '[]' ): return '' if not operators_helper.is_supported( oper ): - #see http://www.boost.org/libs/python/doc/v2/operators.html#introduction - return 'operator %s is not supported. Please take a look on http://www.boost.org/libs/python/doc/v2/operators.html#introduction.' + msg = [ '"operator%s" is not supported. ' % oper.symbol ] + msg.append( 'See Boost.Python documentation: http://www.boost.org/libs/python/doc/v2/operators.html#introduction.' ) + return os.linesep.join( msg ) return '' exportable = staticmethod( exportable ) Modified: pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-07-11 08:45:33 UTC (rev 294) +++ pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-07-11 09:05:55 UTC (rev 295) @@ -2,7 +2,8 @@ # Distributed under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) - + +import os import sys import algorithm from pyplusplus import _logging_ @@ -10,13 +11,6 @@ -__REPOTED_REPLACES = [] -def report_msg_once( msg ): - global __REPOTED_REPLACES - if msg not in __REPOTED_REPLACES: - print 'pyplusplus: ', msg - __REPOTED_REPLACES.append( msg ) - class ERROR_BEHAVIOR: PRINT = 'print' RAISE = 'raise' @@ -29,7 +23,11 @@ information about how the binding is to be created. Instances of this class are never created by the user, instead they are returned by the API. - """ + """ + + DO_NOT_REPORT_MSGS = [ "pyplusplus does not exports compiler generated constructors" ] + ALREADY_REPORTED_MSGS = set() + def __init__(self): object.__init__(self) self._alias = None @@ -67,8 +65,21 @@ def rename( self, new_name ): self.alias = new_name + + def __report_warning( self, reason ): + if reason in decl_wrapper_t.DO_NOT_REPORT_MSGS: + return + if reason in decl_wrapper_t.ALREADY_REPORTED_MSGS: + return + decl_wrapper_t.ALREADY_REPORTED_MSGS.add( reason ) + msg = [ 'Declaration "%s" could not be exported.' % declarations.full_name( self ) ] + reason = reason.replace( os.linesep, os.linesep + '\t' ) + msg.append( '\tReason: %s' % reason ) + self.logger.warn( os.linesep.join( msg ) ) - def _get_ignore( self ): + def _get_ignore( self ): + if False == self._ignore and not self.exportable: + self.__report_warning( self.why_not_exportable() ) return self._ignore or not self.exportable def _set_ignore( self, value ): Modified: pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py 2006-07-11 08:45:33 UTC (rev 294) +++ pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py 2006-07-11 09:05:55 UTC (rev 295) @@ -48,9 +48,9 @@ type_ = declarations.remove_const( type_ ) if declarations.is_pointer( type_ ): if self.type_qualifiers.has_static: - return "pyplusplus, right now, can not expose static pointer member variables. This could be changed in future." + return "pyplusplus can not expose static pointer member variables. This could be changed in future." if declarations.is_fundamental( type_.base ): - return "pyplusplus, right now, can not expose pointer to fundamental member variables. This could be changed in future." + return "pyplusplus can not expose pointer to fundamental member variables. This could be changed in future." units = declarations.decompose_type( type_ ) ptr2functions = filter( lambda unit: isinstance( unit, declarations.calldef_type_t ) @@ -62,6 +62,6 @@ if declarations.class_traits.is_my_case( type_ ): cls = declarations.class_traits.get_declaration( type_ ) if not cls.name: - return "pyplusplus, right now, can not expose variables of with unnamed type." + return "pyplusplus can not expose variables of with unnamed type." return '' \ No newline at end of file Modified: pyplusplus_dev/pyplusplus/module_builder/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/module_builder/__init__.py 2006-07-11 08:45:33 UTC (rev 294) +++ pyplusplus_dev/pyplusplus/module_builder/__init__.py 2006-07-11 09:05:55 UTC (rev 295) @@ -52,5 +52,6 @@ def set_logger_level( level ): for l in __pygccxml_utils.loggers.all: - l.setLevel( level ) - __pyplusplus_logging.logger.setLevel( level ) \ No newline at end of file + l.setLevel( level ) + for l in __pyplusplus_logging.loggers.all: + l.setLevel( level ) Modified: pyplusplus_dev/pyplusplus/module_creator/types_database.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/types_database.py 2006-07-11 08:45:33 UTC (rev 294) +++ pyplusplus_dev/pyplusplus/module_creator/types_database.py 2006-07-11 09:05:55 UTC (rev 295) @@ -73,7 +73,7 @@ try: check_extraction = container_cls.indexing_suite.element_type except RuntimeError, error: - msg = 'WARNING: pyplusplus found "%s" instantiation declaration, ' % container_cls.name + msg = 'pyplusplus found "%s" instantiation declaration, ' % container_cls.name msg = msg + 'but can not find out value type!' msg = msg + os.linesep + 'This class will not be exported!' _logging_.loggers.declarations.warn( msg ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-07-11 08:45:39
|
Revision: 294 Author: mbaas Date: 2006-07-11 01:45:33 -0700 (Tue, 11 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=294&view=rev Log Message: ----------- The warning message was still using the hardcoded number (10) instead of the variable. Modified Paths: -------------- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-11 08:26:11 UTC (rev 293) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-11 08:45:33 UTC (rev 294) @@ -100,10 +100,10 @@ #TODO: functions that takes as argument pointer to pointer to smth, could not be exported #see http://www.boost.org/libs/python/doc/v2/faq.html#funcptr if len( self.arguments ) > calldef_t.BOOST_PYTHON_MAX_ARITY: - msg = "Function '%s' has more than 10 arguments ( %d ). " + msg = "Function '%s' has more than %d arguments ( %d ). " msg = msg + " You should adjust BOOST_PYTHON_MAX_ARITY." msg = msg + " For more information see: http://mail.python.org/pipermail/c++-sig/2002-June/001554.html" - self.logger.info( msg % ( self.decl_string, len( self.arguments ) ) ) + self.logger.info( msg % ( self.decl_string, calldef_t.BOOST_PYTHON_MAX_ARITY, len( self.arguments ) ) ) all_types = [ arg.type for arg in self.arguments ] all_types.append( self.return_type ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-07-11 08:26:15
|
Revision: 293 Author: mbaas Date: 2006-07-11 01:26:11 -0700 (Tue, 11 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=293&view=rev Log Message: ----------- Oops, overlooked another typo... Modified Paths: -------------- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-11 08:23:53 UTC (rev 292) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-11 08:26:11 UTC (rev 293) @@ -100,7 +100,7 @@ #TODO: functions that takes as argument pointer to pointer to smth, could not be exported #see http://www.boost.org/libs/python/doc/v2/faq.html#funcptr if len( self.arguments ) > calldef_t.BOOST_PYTHON_MAX_ARITY: - msg = "Function '%s' has more then 10 arguments ( %d ). " + msg = "Function '%s' has more than 10 arguments ( %d ). " msg = msg + " You should adjust BOOST_PYTHON_MAX_ARITY." msg = msg + " For more information see: http://mail.python.org/pipermail/c++-sig/2002-June/001554.html" self.logger.info( msg % ( self.decl_string, len( self.arguments ) ) ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-07-11 08:23:57
|
Revision: 292 Author: mbaas Date: 2006-07-11 01:23:53 -0700 (Tue, 11 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=292&view=rev Log Message: ----------- Fixed a typo and 'unified' the newlines (there were a few DOS newlines in the file even though I've checked it out under Linux). Modified Paths: -------------- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-11 07:24:56 UTC (rev 291) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-11 08:23:53 UTC (rev 292) @@ -13,10 +13,10 @@ ##return False ##return self.declaration.virtuality != declarations.VIRTUALITY_TYPES.PURE_VIRTUAL -class calldef_t(decl_wrapper.decl_wrapper_t): - - BOOST_PYTHON_MAX_ARITY = 10 +class calldef_t(decl_wrapper.decl_wrapper_t): + BOOST_PYTHON_MAX_ARITY = 10 + def __init__(self, *arguments, **keywords): decl_wrapper.decl_wrapper_t.__init__( self, *arguments, **keywords ) @@ -96,12 +96,12 @@ def _exportable_impl_derived( self ): return '' - def _exportable_impl( self ): + def _exportable_impl( self ): #TODO: functions that takes as argument pointer to pointer to smth, could not be exported #see http://www.boost.org/libs/python/doc/v2/faq.html#funcptr if len( self.arguments ) > calldef_t.BOOST_PYTHON_MAX_ARITY: - msg = "Function '%s' with more then 10 arguments( %d ). " - msg = msg + " You should adjest BOOST_PYTHON_MAX_ARITY" + msg = "Function '%s' has more then 10 arguments ( %d ). " + msg = msg + " You should adjust BOOST_PYTHON_MAX_ARITY." msg = msg + " For more information see: http://mail.python.org/pipermail/c++-sig/2002-June/001554.html" self.logger.info( msg % ( self.decl_string, len( self.arguments ) ) ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |