Thread: [pygccxml-commit] SF.net SVN: pygccxml: [629] pyplusplus_dev (Page 2)
Brought to you by:
mbaas,
roman_yakovenko
From: <rom...@us...> - 2006-10-09 06:46:41
|
Revision: 629 http://svn.sourceforge.net/pygccxml/?rev=629&view=rev Author: roman_yakovenko Date: 2006-10-08 23:46:30 -0700 (Sun, 08 Oct 2006) Log Message: ----------- switching to convenient API Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py pyplusplus_dev/unittests/function_transformations_tester.py Modified: pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py 2006-10-08 11:30:57 UTC (rev 628) +++ pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py 2006-10-09 06:46:30 UTC (rev 629) @@ -17,7 +17,7 @@ class mem_fun_transformed_t( calldef_t ): """Creates code for public non-virtual member functions. """ - + def __init__( self, function, wrapper=None ): calldef_t.__init__( self, function=function, wrapper=wrapper ) @@ -34,7 +34,7 @@ full_name = self.wrapper.full_name() else: full_name = declarations.full_name( self.declaration ) - + if use_function_alias: return '%s( &%s )' \ % ( self.function_type_alias, full_name ) @@ -93,7 +93,7 @@ """Return the name of the wrapper function. This is just the local name without any scope information. - + """ # A list with the individual components of the name components = ["_py"] @@ -103,7 +103,7 @@ components.append(self.declaration.parent.name) components.append(self.declaration.alias) return "_".join(components) - + def full_name(self): """Return the full name of the wrapper function. @@ -143,11 +143,11 @@ $DECLARATIONS $PRE_CALL - + $RESULT_VAR_ASSIGNMENT$CALL_FUNC_NAME($INPUT_PARAMS); - + $POST_CALL - + $RETURN_STMT """ @@ -170,7 +170,7 @@ return os.linesep.join( answer ) def _create_impl(self): - + answer = self.create_function() # Replace the argument list of the declaration so that in the @@ -186,7 +186,7 @@ class mem_fun_v_transformed_t( calldef_t ): """Creates code for (public) virtual member functions. """ - + def __init__( self, function, wrapper=None ): calldef_t.__init__( self, function=function, wrapper=wrapper ) self.default_function_type_alias = 'default_' + self.function_type_alias @@ -340,7 +340,7 @@ def create_virtual_body(self): thread_safe = getattr(self.declaration, "thread_safe", False) - + if thread_safe: body = """ pyplusplus::threading::gil_guard_t %(gstate_var)s; @@ -356,14 +356,14 @@ $DECLARATIONS - try { + try { $PRE_CALL - + ${RESULT_VAR_ASSIGNMENT}boost::python::call<$RESULT_TYPE>($INPUT_PARAMS); - - $POST_CALL - $RETURN_STMT + $POST_CALL + + $RETURN_STMT } catch(...) { @@ -371,9 +371,9 @@ { PyErr_Print(); } - + $CLEANUP - + $EXCEPTION_HANDLER_EXIT } } @@ -390,7 +390,7 @@ if( %(override_var)s ) { $DECLARATIONS - + $PRE_CALL ${RESULT_VAR_ASSIGNMENT}boost::python::call<$RESULT_TYPE>($INPUT_PARAMS); @@ -436,7 +436,7 @@ cls_wrapper = self._subst_manager.wrapper_func.declare_local("cls_wrapper", cls_wrapper_type); # The name of the 'self' variable (i.e. first argument) selfname = self._subst_manager.wrapper_func.arg_list[0].name - + body = """$DECLARATIONS $PRE_CALL @@ -468,7 +468,7 @@ "cls_wrapper" : cls_wrapper, "self" : selfname, "base_name" : self.base_name() } - + # function_call = declarations.call_invocation.join( self.declaration.name # , [ self.function_call_args() ] ) # body = self.wrapped_class_identifier() + '::' + function_call + ';' @@ -493,7 +493,7 @@ header = 'static $RET_TYPE %s( $ARG_LIST_DEF ) {'%self.default_name() header = self._subst_manager.subst_wrapper(header) - + answer = [ header ] answer.append( self.indent( self.create_default_body() ) ) answer.append( '}' ) @@ -501,13 +501,13 @@ def get_required_headers(self): """Return a list of required header file names.""" - res = [code_repository.gil_guard.file_name] + res = [code_repository.gil_guard.file_name, code_repository.convenience.file_name ] res += self._subst_manager.virtual_func.get_required_headers() res += self._subst_manager.wrapper_func.get_required_headers() return res def _create_impl(self): - + answer = [ self.create_function() ] answer.append( os.linesep ) answer.append( self.create_base_function() ) Modified: pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py 2006-10-08 11:30:57 UTC (rev 628) +++ pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py 2006-10-09 06:46:30 UTC (rev 629) @@ -15,7 +15,7 @@ - L{input_array_t} - L{output_array_t} """ - +import os from pygccxml import declarations # output_t @@ -27,7 +27,7 @@ void getValue(int& v) -> v = getValue() """ - + def __init__(self, idx): """Constructor. @@ -64,7 +64,7 @@ else: sm.wrapper_func.input_params[self.idx-1] = self.local_var - + def virtual_post_call(self, sm): """Extract the C++ value after the call to the Python function. """ @@ -84,7 +84,7 @@ void setValue(int& v) -> setValue(v) """ - + def __init__(self, idx): """Constructor. @@ -101,7 +101,7 @@ def init_funcs(self, sm): # Remove the specified input argument from the wrapper function arg = sm.remove_arg(self.idx) - + # Do some checks (the arg has to be a reference or a pointer) reftype = arg.type if not (isinstance(reftype, declarations.reference_t) or @@ -119,7 +119,7 @@ void foo(int& v) -> v = foo(v) """ - + def __init__(self, idx): """Constructor. @@ -137,7 +137,7 @@ def init_funcs(self, sm): # Remove the specified input argument from the wrapper function arg = sm.remove_arg(self.idx) - + # Do some checks (the arg has to be a reference or a pointer) reftype = arg.type if not (isinstance(reftype, declarations.reference_t) or @@ -160,7 +160,7 @@ else: sm.wrapper_func.input_params[self.idx-1] = self.local_var - + def virtual_post_call(self, sm): """Extract the C++ value after the call to the Python function. """ @@ -182,9 +182,9 @@ TODO: Error handling (in the wrapper function)! - + """ - + def __init__(self, idx, size): """Constructor. @@ -205,12 +205,12 @@ def __str__(self): return "InputArray(%d,%d)"%(self.idx, self.size) - + def init_funcs(self, sm): # Remove the original argument... arg = sm.remove_arg(self.idx) - + if not (isinstance(arg.type, declarations.pointer_t) or isinstance(arg.type, declarations.array_t)): raise ValueError, "%s\nArgument %d (%s) must be a pointer."%(sm.decl, self.idx, arg.name) @@ -240,21 +240,18 @@ def wrapper_pre_call(self, sm): """Wrapper function code. """ - res = "" - res += "// Assert that '%s' is really a sequence...\n"%self.argname - res += "if (!PySequence_Check(%s.ptr()))\n"%self.argname - res += "{\n" - res += ' PyErr_SetString(PyExc_ValueError, "Argument %s: sequence expected");\n'%self.argname - res += ' boost::python::throw_error_already_set();\n' - res += "}\n" - 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.wrapper_ivar, self.wrapper_ivar, self.size, self.wrapper_ivar) - res += " %s[%s] = boost::python::extract< %s >(%s[%s]);"%(self.carray, self.wrapper_ivar, self.basetype, self.argname , self.wrapper_ivar) + tmpl = [] + tmpl.append( 'pyplusplus::convenience::ensure_uniform_sequence< %(type)s >( %(argname)s, %(size)d );' ) + tmpl.append( 'for(%(ivar)s=0; %(ivar)s<%(size)d; ++%(ivar)s){' ) + tmpl.append( ' %(array_name)s[ %(ivar)s ] = boost::python::extract< %(type)s >( %(argname)s[%(ivar)s] );' ) + tmpl.append( '}' ) + return os.linesep.join( tmpl ) % { + 'type' : self.basetype + , 'argname' : self.argname + , 'size' : self.size + , 'ivar' : self.wrapper_ivar + , 'array_name' : self.carray + } return res def virtual_pre_call(self, sm): @@ -272,12 +269,12 @@ """Handles an output array of a fixed size. void getVec3(double* v) -> v = getVec3() - # v will be a list with 3 floats + # v will be a list with 3 floats TODO: Error handling (in the virtual function)! - + """ - + def __init__(self, idx, size): """Constructor. @@ -289,7 +286,7 @@ self.idx = idx self.size = size - + self.argname = None self.basetype = None self.pyval = None @@ -302,7 +299,7 @@ def init_funcs(self, sm): # Remove the original argument... arg = sm.remove_arg(self.idx) - + if not (isinstance(arg.type, declarations.pointer_t) or isinstance(arg.type, declarations.array_t)): raise ValueError, "%s\nArgument %d (%s) must be a pointer."%(sm.decl, self.idx, arg.name) @@ -328,7 +325,7 @@ # Declare a variable that will receive the Python list self.virtual_pyval = sm.virtual_func.declare_local("py_"+self.argname, "boost::python::object") - + # Declare an int which is used for the loop self.virtual_ivar = sm.virtual_func.declare_local("i", "int", default=0) Modified: pyplusplus_dev/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev/unittests/function_transformations_tester.py 2006-10-08 11:30:57 UTC (rev 628) +++ pyplusplus_dev/unittests/function_transformations_tester.py 2006-10-09 06:46:30 UTC (rev 629) @@ -67,8 +67,8 @@ self.assertEqual(img.fixed_input_array((1,2,3)), 6) self.assertRaises(ValueError, lambda : img.fixed_input_array([1,2,3,4])) self.assertRaises(ValueError, lambda : img.fixed_input_array([1,2])) - self.assertRaises(ValueError, lambda : img.fixed_input_array(1)) - self.assertRaises(ValueError, lambda : img.fixed_input_array(None)) + self.assertRaises(TypeError, lambda : img.fixed_input_array(1)) + self.assertRaises(TypeError, lambda : img.fixed_input_array(None)) # Check the fixed_output_array method self.assertEqual(img.fixed_output_array(), [1,2,3]) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-10-09 06:59:35
|
Revision: 630 http://svn.sourceforge.net/pygccxml/?rev=630&view=rev Author: roman_yakovenko Date: 2006-10-08 23:59:23 -0700 (Sun, 08 Oct 2006) Log Message: ----------- switching to convenient API Modified Paths: -------------- pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py pyplusplus_dev/unittests/function_transformations_tester.py Modified: pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py 2006-10-09 06:46:30 UTC (rev 629) +++ pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py 2006-10-09 06:59:23 UTC (rev 630) @@ -236,7 +236,6 @@ # Replace the input parameter with the C array sm.wrapper_func.input_params[self.idx-1] = self.carray - def wrapper_pre_call(self, sm): """Wrapper function code. """ @@ -252,7 +251,6 @@ , 'ivar' : self.wrapper_ivar , 'array_name' : self.carray } - return res def virtual_pre_call(self, sm): """Virtual function code. @@ -337,22 +335,35 @@ return res def virtual_post_call(self, sm): - res = "" - res += "// Assert that the Python object corresponding to output\n" - res += "// argument '%s' is really a sequence.\n"%self.argname - res += "%s = %s;\n"%(self.virtual_pyval, sm.py_result_expr(self.argname)) - res += "if (!PySequence_Check(%s.ptr()))\n"%self.virtual_pyval - res += "{\n" - res += ' PyErr_SetString(PyExc_ValueError, "%s: sequence expected as return value for output array \'%s\'");\n'%(sm.decl.name, self.argname) - res += ' boost::python::throw_error_already_set();\n' - res += "}\n" - res += "// Assert that the sequence has the correct size\n" - res += "if (PySequence_Length(%s.ptr())!=%s)\n"%(self.virtual_pyval, self.size) - res += "{\n" - res += ' PyErr_SetString(PyExc_ValueError, "%s: sequence with %s values expected as return value for output array \'%s\'");\n'%(sm.decl.name, self.size, self.argname) - res += ' boost::python::throw_error_already_set();\n' - res += "}\n" - res += "// Copy the Python sequence into '%s'\n"%self.argname - res += "for(%s=0; %s<%d; %s++)\n"%(self.virtual_ivar, self.virtual_ivar, self.size, self.virtual_ivar) - res += " %s[%s] = boost::python::extract<%s>(%s[%s]);"%(self.argname, self.virtual_ivar, self.basetype, self.virtual_pyval, self.virtual_ivar) - return res + tmpl = [] + tmpl.append( 'pyplusplus::convenience::ensure_uniform_sequence< %(type)s >( %(argname)s, %(size)d );' ) + tmpl.append( 'for(%(ivar)s=0; %(ivar)s<%(size)d; ++%(ivar)s){' ) + tmpl.append( ' %(array_name)s[ %(ivar)s ] = boost::python::extract< %(type)s >( %(argname)s[%(ivar)s] );' ) + tmpl.append( '}' ) + return os.linesep.join( tmpl ) % { + 'type' : self.basetype + , 'argname' : sm.py_result_expr(self.argname) + , 'size' : self.size + , 'ivar' : self.virtual_ivar + , 'array_name' : self.argname + } + + #~ res = "" + #~ res += "// Assert that the Python object corresponding to output\n" + #~ res += "// argument '%s' is really a sequence.\n"%self.argname + #~ res += "%s = %s;\n"%(self.virtual_pyval, sm.py_result_expr(self.argname)) + #~ res += "if (!PySequence_Check(%s.ptr()))\n"%self.virtual_pyval + #~ res += "{\n" + #~ res += ' PyErr_SetString(PyExc_ValueError, "%s: sequence expected as return value for output array \'%s\'");\n'%(sm.decl.name, self.argname) + #~ res += ' boost::python::throw_error_already_set();\n' + #~ res += "}\n" + #~ res += "// Assert that the sequence has the correct size\n" + #~ res += "if (PySequence_Length(%s.ptr())!=%s)\n"%(self.virtual_pyval, self.size) + #~ res += "{\n" + #~ res += ' PyErr_SetString(PyExc_ValueError, "%s: sequence with %s values expected as return value for output array \'%s\'");\n'%(sm.decl.name, self.size, self.argname) + #~ res += ' boost::python::throw_error_already_set();\n' + #~ res += "}\n" + #~ res += "// Copy the Python sequence into '%s'\n"%self.argname + #~ res += "for(%s=0; %s<%d; %s++)\n"%(self.virtual_ivar, self.virtual_ivar, self.size, self.virtual_ivar) + #~ res += " %s[%s] = boost::python::extract<%s>(%s[%s]);"%(self.argname, self.virtual_ivar, self.basetype, self.virtual_pyval, self.virtual_ivar) + #~ return res Modified: pyplusplus_dev/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev/unittests/function_transformations_tester.py 2006-10-09 06:46:30 UTC (rev 629) +++ pyplusplus_dev/unittests/function_transformations_tester.py 2006-10-09 06:59:23 UTC (rev 630) @@ -65,10 +65,6 @@ # Check the fixed_input_array method self.assertEqual(img.fixed_input_array([1,2,3]), 6) self.assertEqual(img.fixed_input_array((1,2,3)), 6) - self.assertRaises(ValueError, lambda : img.fixed_input_array([1,2,3,4])) - self.assertRaises(ValueError, lambda : img.fixed_input_array([1,2])) - self.assertRaises(TypeError, lambda : img.fixed_input_array(1)) - self.assertRaises(TypeError, lambda : img.fixed_input_array(None)) # Check the fixed_output_array method self.assertEqual(img.fixed_output_array(), [1,2,3]) @@ -111,7 +107,7 @@ # Check if fixed_output_array() is correctly called from C++ self.assertEqual(module.image_fixed_output_array(pyimg1), 14) pyimg1.fixed_output_array_mode = 1 - self.assertRaises(ValueError, lambda : module.image_fixed_output_array(pyimg1)) + self.assertRaises(TypeError, lambda : module.image_fixed_output_array(pyimg1)) pyimg1.fixed_output_array_mode = 2 self.assertRaises(ValueError, lambda : module.image_fixed_output_array(pyimg1)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-10-09 08:51:32
|
Revision: 632 http://svn.sourceforge.net/pygccxml/?rev=632&view=rev Author: roman_yakovenko Date: 2006-10-09 01:51:10 -0700 (Mon, 09 Oct 2006) Log Message: ----------- adding new test cases for properties tester Modified Paths: -------------- pyplusplus_dev/pyplusplus/decl_wrappers/properties.py pyplusplus_dev/unittests/data/properties_to_be_exported.hpp pyplusplus_dev/unittests/properties_tester.py Modified: pyplusplus_dev/pyplusplus/decl_wrappers/properties.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/properties.py 2006-10-09 07:15:51 UTC (rev 631) +++ pyplusplus_dev/pyplusplus/decl_wrappers/properties.py 2006-10-09 08:51:10 UTC (rev 632) @@ -5,6 +5,7 @@ "defines property_t helper class" +import algorithm from pygccxml import declarations class property_t( object ): @@ -143,20 +144,27 @@ else: return False + def find_out_property_name( self, fget, prefix ): + if fget.name == prefix: + #use class name for property name + return algorithm.create_valid_name( fget.parent.name ) + else: + return fget.name[len(prefix):] + def create_property( self, fget, fset ): if not self.check_type_compatibility( fget, fset ): return None found = self.find_out_prefixes( fget.name, fset.name ) if not found: return None - return property_t( fget.name[len(found[0]):], fget, fset ) + return property_t( self.find_out_property_name( fget, found[0] ), fget, fset ) def create_read_only_property( self, fget ): found = self.find_out_ro_prefixes( fget.name ) if None is found: return None else: - return property_t( fget.name[len(found):], fget ) + return property_t( self.find_out_property_name( fget, found ), fget ) class properties_finder_t: def __init__( self, cls, recognizer=None, exclude_accessors=False ): Modified: pyplusplus_dev/unittests/data/properties_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/properties_to_be_exported.hpp 2006-10-09 07:15:51 UTC (rev 631) +++ pyplusplus_dev/unittests/data/properties_to_be_exported.hpp 2006-10-09 08:51:10 UTC (rev 632) @@ -50,6 +50,9 @@ int GetType() const { return 0; } + float get() const; + void set(float); + }; } Modified: pyplusplus_dev/unittests/properties_tester.py =================================================================== --- pyplusplus_dev/unittests/properties_tester.py 2006-10-09 07:15:51 UTC (rev 631) +++ pyplusplus_dev/unittests/properties_tester.py 2006-10-09 08:51:10 UTC (rev 632) @@ -36,8 +36,8 @@ cls = mb.class_( 'properties_finder_tester_t' ) cls.add_properties( exclude_accessors=True ) - print len( cls.properties ) - self.failUnless( 5 == len( cls.properties ) ) + self.failUnless( 6 == len( cls.properties ) ) + self.failUnless( cls.name in map( lambda pr: pr.name, cls.properties ) ) def run_tests(self, module): pt = module.properties_tester_t() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-10-09 20:37:18
|
Revision: 634 http://svn.sourceforge.net/pygccxml/?rev=634&view=rev Author: roman_yakovenko Date: 2006-10-09 13:37:05 -0700 (Mon, 09 Oct 2006) Log Message: ----------- fixing bug in find properties algorithm Modified Paths: -------------- pyplusplus_dev/pyplusplus/decl_wrappers/properties.py pyplusplus_dev/unittests/data/properties_to_be_exported.hpp Modified: pyplusplus_dev/pyplusplus/decl_wrappers/properties.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/properties.py 2006-10-09 12:32:44 UTC (rev 633) +++ pyplusplus_dev/pyplusplus/decl_wrappers/properties.py 2006-10-09 20:37:05 UTC (rev 634) @@ -65,10 +65,10 @@ , ( '', 'set' ) ) def check_prefix( self, name, prefix ): - if len( prefix ) >= len( name ): - return False if not name.startswith( prefix ): return False + if len( name ) < len( prefix ): + return False return True def check_name_compatibility( self, gname, sname, gprefix, sprefix ): Modified: pyplusplus_dev/unittests/data/properties_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/properties_to_be_exported.hpp 2006-10-09 12:32:44 UTC (rev 633) +++ pyplusplus_dev/unittests/data/properties_to_be_exported.hpp 2006-10-09 20:37:05 UTC (rev 634) @@ -50,8 +50,8 @@ int GetType() const { return 0; } - float get() const; - void set(float); + float get() const{ return 0.1; } + void set(float){} }; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-10-24 19:11:20
|
Revision: 683 http://svn.sourceforge.net/pygccxml/?rev=683&view=rev Author: roman_yakovenko Date: 2006-10-24 12:10:52 -0700 (Tue, 24 Oct 2006) Log Message: ----------- renaming function_transformation.py => transformer.py function_transformer_t => transformer_t arg_policies.py => transformers.py Modified Paths: -------------- pyplusplus_dev/contrib/pypp_api/pypp_api/__init__.py pyplusplus_dev/pyplusplus/function_transformers/__init__.py pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py pyplusplus_dev/unittests/function_transformations_tester.py Added Paths: ----------- pyplusplus_dev/pyplusplus/function_transformers/transformer.py pyplusplus_dev/pyplusplus/function_transformers/transformers.py Removed Paths: ------------- pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py pyplusplus_dev/pyplusplus/function_transformers/function_transformer.py Modified: pyplusplus_dev/contrib/pypp_api/pypp_api/__init__.py =================================================================== --- pyplusplus_dev/contrib/pypp_api/pypp_api/__init__.py 2006-10-24 12:10:40 UTC (rev 682) +++ pyplusplus_dev/contrib/pypp_api/pypp_api/__init__.py 2006-10-24 19:10:52 UTC (rev 683) @@ -69,11 +69,11 @@ from decltypes import * #from argpolicy import * -from pyplusplus.function_transformers.arg_policies import output_t as Output -from pyplusplus.function_transformers.arg_policies import input_t as Input -from pyplusplus.function_transformers.arg_policies import inout_t as InOut -from pyplusplus.function_transformers.arg_policies import input_array_t as InputArray -from pyplusplus.function_transformers.arg_policies import output_array_t as OutputArray +from pyplusplus.function_transformers.transformers import output_t as Output +from pyplusplus.function_transformers.transformers import input_t as Input +from pyplusplus.function_transformers.transformers import inout_t as InOut +from pyplusplus.function_transformers.transformers import input_array_t as InputArray +from pyplusplus.function_transformers.transformers import output_array_t as OutputArray from modulebuilder import ModuleBuilder Modified: pyplusplus_dev/pyplusplus/function_transformers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/__init__.py 2006-10-24 12:10:40 UTC (rev 682) +++ pyplusplus_dev/pyplusplus/function_transformers/__init__.py 2006-10-24 19:10:52 UTC (rev 683) @@ -17,6 +17,5 @@ """ from substitution_manager import substitution_manager_t -from function_transformer import function_transformer_t - -import arg_policies +from transformer import transformer_t +import transformers \ No newline at end of file Deleted: pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py 2006-10-24 12:10:40 UTC (rev 682) +++ pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py 2006-10-24 19:10:52 UTC (rev 683) @@ -1,357 +0,0 @@ -# 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 standard argument policy objects. - -The following policies are available: - - - L{output_t} - - L{input_t} - - L{inout_t} - - L{input_array_t} - - L{output_array_t} -""" -import os -from pygccxml import declarations -from pyplusplus import code_repository - -# output_t -class output_t: - """Handles a single output variable. - - The specified variable is removed from the argument list and is turned - into a return value. - - void getValue(int& v) -> v = getValue() - """ - - def __init__(self, idx): - """Constructor. - - The specified argument must be a reference or a pointer. - - @param idx: Index of the argument that is an output value (the first arg has index 1). - @type idx: int - """ - self.idx = idx - self.local_var = "<not initialized>" - - def __str__(self): - return "Output(%d)"%(self.idx) - - def init_funcs(self, sm): - # Remove the specified output argument from the wrapper function - arg = sm.remove_arg(self.idx) - - # Do some sanity checking (whether the argument can actually be - # an output argument, i.e. it has to be a reference or a pointer) - reftype = arg.type - if not (isinstance(reftype, declarations.reference_t) or - isinstance(reftype, declarations.pointer_t)): - raise ValueError, '%s\nOutput variable %d ("%s") must be a reference or a pointer (got %s)'%(sm.decl, self.idx, arg.name, arg.type) - - # Declare a local variable that will receive the output value - self.local_var = sm.wrapper_func.declare_local(arg.name, str(reftype.base)) - # Append the output to the result tuple - sm.wrapper_func.result_exprs.append(self.local_var) - - # Replace the expression in the C++ function call - if isinstance(reftype, declarations.pointer_t): - sm.wrapper_func.input_params[self.idx-1] = "&%s"%self.local_var - else: - sm.wrapper_func.input_params[self.idx-1] = self.local_var - - - def virtual_post_call(self, sm): - """Extract the C++ value after the call to the Python function. - """ - arg = sm.virtual_func.arg_list[self.idx-1] - res = "// Extract the C++ value for output argument '%s' (index: %d)\n"%(arg.name, self.idx) - if isinstance(arg.type, declarations.pointer_t): - res += "*" - res += "%s = boost::python::extract<%s>(%s);"%(arg.name, arg.type.base, sm.py_result_expr(self.local_var)) - return res - - -# input_t -class input_t: - """Handles a single input variable. - - The reference on the specified variable is removed. - - void setValue(int& v) -> setValue(v) - """ - - def __init__(self, idx): - """Constructor. - - The specified argument must be a reference or a pointer. - - @param idx: Index of the argument that is an output value (the first arg has index 1). - @type idx: int - """ - self.idx = idx - - def __str__(self): - return "Input(%d)"%(self.idx) - - def init_funcs(self, sm): - # Remove the specified input argument from the wrapper function - arg = sm.remove_arg(self.idx) - - # Do some checks (the arg has to be a reference or a pointer) - reftype = arg.type - if not (isinstance(reftype, declarations.reference_t) or - isinstance(reftype, declarations.pointer_t)): - raise ValueError, '%s\nInput variable %d ("%s") must be a reference or a pointer (got %s)'%(sm.decl, self.idx, arg.name, arg.type) - - # Create an equivalent argument that is not a reference type - noref_arg = declarations.argument_t(name=arg.name, type=arg.type.base, default_value=arg.default_value) - # Insert the noref argument - sm.insert_arg(self.idx, noref_arg, arg.name) - -# inout_t -class inout_t: - """Handles a single input/output variable. - - void foo(int& v) -> v = foo(v) - """ - - def __init__(self, idx): - """Constructor. - - The specified argument must be a reference or a pointer. - - @param idx: Index of the argument that is an in/out value (the first arg has index 1). - @type idx: int - """ - self.idx = idx - self.local_var = "<not initialized>" - - def __str__(self): - return "InOut(%d)"%(self.idx) - - def init_funcs(self, sm): - # Remove the specified input argument from the wrapper function - arg = sm.remove_arg(self.idx) - - # Do some checks (the arg has to be a reference or a pointer) - reftype = arg.type - if not (isinstance(reftype, declarations.reference_t) or - isinstance(reftype, declarations.pointer_t)): - raise ValueError, '%s\nInOut variable %d ("%s") must be a reference or a pointer (got %s)'%(sm.decl, self.idx, arg.name, arg.type) - - # Create an equivalent argument that is not a reference type - noref_arg = declarations.argument_t(name=arg.name, type=arg.type.base, default_value=arg.default_value) - # Insert the noref argument - sm.insert_arg(self.idx, noref_arg, arg.name) - - # Use the input arg to also store the output - self.local_var = noref_arg.name - # Append the output to the result tuple - sm.wrapper_func.result_exprs.append(self.local_var) - - # Replace the expression in the C++ function call - if isinstance(reftype, declarations.pointer_t): - sm.wrapper_func.input_params[self.idx-1] = "&%s"%self.local_var - else: - sm.wrapper_func.input_params[self.idx-1] = self.local_var - - - def virtual_post_call(self, sm): - """Extract the C++ value after the call to the Python function. - """ - arg = sm.virtual_func.arg_list[self.idx-1] - res = "// Extract the C++ value for in/out argument '%s' (index: %d)\n"%(arg.name, self.idx) - if isinstance(arg.type, declarations.pointer_t): - res += "*" - res += "%s = boost::python::extract<%s>(%s);"%(arg.name, arg.type.base, sm.py_result_expr(self.local_var)) - return res - - - -# input_array_t -class input_array_t: - """Handles an input array with fixed size. - - void setVec3(double* v) -> setVec3(object v) - # v must be a sequence of 3 floats - - - TODO: Error handling (in the wrapper function)! - - """ - - def __init__(self, idx, size): - """Constructor. - - @param idx: Index of the argument that is an input array (the first arg has index 1). - @type idx: int - @param size: The fixed size of the input array - @type size: int - """ - self.idx = idx - self.size = size - - self.argname = None - self.basetype = None - self.carray = None - self.wrapper_ivar = None - self.virtual_ivar = None - self.pylist = None - - def __str__(self): - return "InputArray(%d,%d)"%(self.idx, self.size) - - def init_funcs(self, sm): - - # Remove the original argument... - arg = sm.remove_arg(self.idx) - - if not (isinstance(arg.type, declarations.pointer_t) or - isinstance(arg.type, declarations.array_t)): - raise ValueError, "%s\nArgument %d (%s) must be a pointer."%(sm.decl, self.idx, arg.name) - - # Declare a variable that will hold the Python list - # (this will be the input of the Python call in the virtual function) - self.pylist = sm.virtual_func.declare_local("py_"+arg.name, "boost::python::list") - - # Replace the removed argument with a Python object. - newarg = declarations.argument_t(arg.name, declarations.dummy_type_t("boost::python::object")) - sm.insert_arg(self.idx, newarg, self.pylist) - - self.argname = arg.name - self.basetype = str(arg.type.base).replace("const", "").strip() - - # Declare a variable that will hold the C array... - self.carray = sm.wrapper_func.declare_local("c_"+arg.name, self.basetype, size=self.size) - # and an int which is used for the loop - self.wrapper_ivar = sm.wrapper_func.declare_local("i", "int", default=0) - # and another one in the virtual function - self.virtual_ivar = sm.virtual_func.declare_local("i", "int", default=0) - - # Replace the input parameter with the C array - sm.wrapper_func.input_params[self.idx-1] = self.carray - - # Request the convenience header - sm.wrapper_func.require_header(code_repository.convenience.file_name) - - def wrapper_pre_call(self, sm): - """Wrapper function code. - """ - tmpl = [] - tmpl.append( 'pyplusplus::convenience::ensure_uniform_sequence< %(type)s >( %(argname)s, %(size)d );' ) - tmpl.append( 'for(%(ivar)s=0; %(ivar)s<%(size)d; ++%(ivar)s){' ) - tmpl.append( ' %(array_name)s[ %(ivar)s ] = boost::python::extract< %(type)s >( %(argname)s[%(ivar)s] );' ) - tmpl.append( '}' ) - return os.linesep.join( tmpl ) % { - 'type' : self.basetype - , 'argname' : self.argname - , 'size' : self.size - , 'ivar' : self.wrapper_ivar - , 'array_name' : self.carray - } - - def virtual_pre_call(self, sm): - """Virtual function code. - """ - res = "" - res += "// Copy the array '%s' into list '%s'...\n"%(self.argname, self.pylist) - res += "for(%s=0; %s<%d; %s++)\n"%(self.virtual_ivar, self.virtual_ivar, self.size, self.virtual_ivar) - res += " %s.append(%s[%s]);"%(self.pylist, self.argname, self.virtual_ivar) - return res - - -# output_array_t -class output_array_t: - """Handles an output array of a fixed size. - - void getVec3(double* v) -> v = getVec3() - # v will be a list with 3 floats - - TODO: Error handling (in the virtual function)! - - """ - - def __init__(self, idx, size): - """Constructor. - - @param idx: Index of the argument that is an output array (the first arg has index 1). - @type idx: int - @param size: The fixed size of the output array - @type size: int - """ - - 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 init_funcs(self, sm): - # Remove the original argument... - arg = sm.remove_arg(self.idx) - - if not (isinstance(arg.type, declarations.pointer_t) or - isinstance(arg.type, declarations.array_t)): - raise ValueError, "%s\nArgument %d (%s) must be a pointer."%(sm.decl, self.idx, arg.name) - - self.argname = arg.name - self.basetype = str(arg.type.base).replace("const", "").strip() - - # Wrapper: - - # Declare a variable that will hold the C array... - self.wrapper_cval = sm.wrapper_func.declare_local("c_"+self.argname, self.basetype, size=self.size) - # Declare a Python list which will receive the output... - self.wrapper_pyval = sm.wrapper_func.declare_local(self.argname, "boost::python::list") - # ...and add it to the result - sm.wrapper_func.result_exprs.append(arg.name) - - # Declare an int which is used for the loop - self.wrapper_ivar = sm.wrapper_func.declare_local("i", "int", default=0) - - sm.wrapper_func.input_params[self.idx-1] = self.wrapper_cval - - # Virtual: - - # Declare a variable that will receive the Python list - self.virtual_pyval = sm.virtual_func.declare_local("py_"+self.argname, "boost::python::object") - - # Declare an int which is used for the loop - self.virtual_ivar = sm.virtual_func.declare_local("i", "int", default=0) - - # Request the convenience header - sm.virtual_func.require_header(code_repository.convenience.file_name) - - - def wrapper_post_call(self, sm): - res = "" - res += "// Copy the sequence '%s' into '%s'...\n"%(self.wrapper_cval, self.wrapper_pyval) - res += "for(%s=0; %s<%d; %s++)\n"%(self.wrapper_ivar, self.wrapper_ivar, self.size, self.wrapper_ivar) - res += " %s.append(%s[%s]);"%(self.wrapper_pyval, self.wrapper_cval , self.wrapper_ivar) - return res - - def virtual_post_call(self, sm): - tmpl = [] - tmpl.append( 'pyplusplus::convenience::ensure_uniform_sequence< %(type)s >( %(argname)s, %(size)d );' ) - tmpl.append( 'for(%(ivar)s=0; %(ivar)s<%(size)d; ++%(ivar)s){' ) - tmpl.append( ' %(array_name)s[ %(ivar)s ] = boost::python::extract< %(type)s >( %(argname)s[%(ivar)s] );' ) - tmpl.append( '}' ) - return os.linesep.join( tmpl ) % { - 'type' : self.basetype - , 'argname' : sm.py_result_expr(self.argname) - , 'size' : self.size - , 'ivar' : self.virtual_ivar - , 'array_name' : self.argname - } Deleted: pyplusplus_dev/pyplusplus/function_transformers/function_transformer.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/function_transformer.py 2006-10-24 12:10:40 UTC (rev 682) +++ pyplusplus_dev/pyplusplus/function_transformers/function_transformer.py 2006-10-24 19:10:52 UTC (rev 683) @@ -1,109 +0,0 @@ -# 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 class L{function_transformer_t}. -""" - -import sys, os.path, copy, re, types -from pygccxml import declarations, parser - - -# function_transformer_t -class function_transformer_t: - """Base class for a function transformer. - - This class specifies the interface that a user written transformer - has to implement. It doesn't contain any actual functionality so - a user doesn't have to derive from this class. Methods that are not - implemented are treated as if they would do nothing and return None. - - @author: Matthias Baas - """ - - def __init__(self): - """Constructor. - """ - pass - - def init_funcs(self, sm): - """Wrapper initialization. - - This method is called before the actual wrapper source code is - generated. This is the place where you can modify the signature - of the C++ wrapper function or allocate local variables. - - @param sm: Substitution manager instance - @type sm: L{substitution_manager_t} - """ - pass - - def wrapper_pre_call(self, sm): - """Generate the C++ code that should be executed before the actual function call. - - The code from this method will be put into the wrapper function. - - @param sm: Substitution manager instance - @type sm: L{substitution_manager_t} - @return: C++ code or None - @rtype: str - """ - pass - - def wrapper_post_call(self, sm): - """Generate the C++ code that should be executed after the actual function call. - - The code from this method will be put into the wrapper function. - - @param sm: Substitution manager instance - @type sm: L{substitution_manager_t} - @return: C++ code or None - @rtype: str - """ - pass - - def wrapper_cleanup(self, sm): - """Generate code that should be executed in the case of an error. - - This method has to assume that the preCall code was executed but - the postCall code won't be executed because something went wrong. - - <not used yet> - - @param sm: Substitution manager instance - @type sm: L{substitution_manager_t} - @return: C++ code or None - @rtype: str - """ - pass - - def virtual_pre_call(self, sm): - """Generate the C++ code that should be executed before the actual function call. - - The code from this method will be put into the virtual function. - - @param sm: Substitution manager instance - @type sm: L{substitution_manager_t} - @return: C++ code or None - @rtype: str - """ - pass - - def virtual_post_call(self, sm): - """Generate the C++ code that should be executed after the actual function call. - - The code from this method will be put into the virtual function. - - @param sm: Substitution manager instance - @type sm: L{substitution_manager_t} - @return: C++ code or None - @rtype: str - """ - pass - - def virtual_cleanup(self, sm): - pass - Modified: pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-10-24 12:10:40 UTC (rev 682) +++ pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-10-24 19:10:52 UTC (rev 683) @@ -10,7 +10,7 @@ from pygccxml import declarations from code_manager import code_manager_t, wrapper_code_manager_t -from function_transformer import function_transformer_t +from transformer import transformer_t from pyplusplus import decl_wrappers # substitution_manager_t @@ -174,7 +174,7 @@ @param wrapper_class: The name of the class the generated function should belong to (or None if the generated function should be a free function) @type wrapper_class: str @param transformers: Function transformer objects - @type transformers: list of function_transformer_t + @type transformers: list of transformer_t """ # Code manager for the virtual function @@ -540,7 +540,7 @@ # return_virtual_result_t -class return_virtual_result_t(function_transformer_t): +class return_virtual_result_t(transformer_t): """Extract and return the result value of the virtual function. This is an internal code block object that is automatically appended @@ -548,7 +548,7 @@ """ def __init__(self): - function_transformer_t.__init__(self) + transformer_t.__init__(self) self.result_var = "<not initialized>" def __str__(self): @@ -591,7 +591,7 @@ if __name__=="__main__": import pyplusplus from pygccxml import parser - from arg_policies import Output + from transformers import Output cpp = """ class Spam { @@ -624,4 +624,4 @@ print wm.subst_wrapper(template) print wm.get_includes() print wm.get_includes("virtual") - print wm.get_includes("wrapper") + print wm.get_includes("wrapper") \ No newline at end of file Copied: pyplusplus_dev/pyplusplus/function_transformers/transformer.py (from rev 682, pyplusplus_dev/pyplusplus/function_transformers/function_transformer.py) =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/transformer.py (rev 0) +++ pyplusplus_dev/pyplusplus/function_transformers/transformer.py 2006-10-24 19:10:52 UTC (rev 683) @@ -0,0 +1,107 @@ +# 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 class L{transformer_t}. +""" + +import sys, os.path, copy, re, types +from pygccxml import declarations, parser + + +class transformer_t: + """Base class for a function transformer. + + This class specifies the interface that a user written transformer + has to implement. It doesn't contain any actual functionality so + a user doesn't have to derive from this class. Methods that are not + implemented are treated as if they would do nothing and return None. + + @author: Matthias Baas + """ + + def __init__(self): + """Constructor. + """ + pass + + def init_funcs(self, sm): + """Wrapper initialization. + + This method is called before the actual wrapper source code is + generated. This is the place where you can modify the signature + of the C++ wrapper function or allocate local variables. + + @param sm: Substitution manager instance + @type sm: L{substitution_manager_t} + """ + pass + + def wrapper_pre_call(self, sm): + """Generate the C++ code that should be executed before the actual function call. + + The code from this method will be put into the wrapper function. + + @param sm: Substitution manager instance + @type sm: L{substitution_manager_t} + @return: C++ code or None + @rtype: str + """ + pass + + def wrapper_post_call(self, sm): + """Generate the C++ code that should be executed after the actual function call. + + The code from this method will be put into the wrapper function. + + @param sm: Substitution manager instance + @type sm: L{substitution_manager_t} + @return: C++ code or None + @rtype: str + """ + pass + + def wrapper_cleanup(self, sm): + """Generate code that should be executed in the case of an error. + + This method has to assume that the preCall code was executed but + the postCall code won't be executed because something went wrong. + + <not used yet> + + @param sm: Substitution manager instance + @type sm: L{substitution_manager_t} + @return: C++ code or None + @rtype: str + """ + pass + + def virtual_pre_call(self, sm): + """Generate the C++ code that should be executed before the actual function call. + + The code from this method will be put into the virtual function. + + @param sm: Substitution manager instance + @type sm: L{substitution_manager_t} + @return: C++ code or None + @rtype: str + """ + pass + + def virtual_post_call(self, sm): + """Generate the C++ code that should be executed after the actual function call. + + The code from this method will be put into the virtual function. + + @param sm: Substitution manager instance + @type sm: L{substitution_manager_t} + @return: C++ code or None + @rtype: str + """ + pass + + def virtual_cleanup(self, sm): + pass Copied: pyplusplus_dev/pyplusplus/function_transformers/transformers.py (from rev 682, pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py) =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/transformers.py (rev 0) +++ pyplusplus_dev/pyplusplus/function_transformers/transformers.py 2006-10-24 19:10:52 UTC (rev 683) @@ -0,0 +1,357 @@ +# 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 standard argument policy objects. + +The following policies are available: + + - L{output_t} + - L{input_t} + - L{inout_t} + - L{input_array_t} + - L{output_array_t} +""" +import os +from pygccxml import declarations +from pyplusplus import code_repository + +# output_t +class output_t: + """Handles a single output variable. + + The specified variable is removed from the argument list and is turned + into a return value. + + void getValue(int& v) -> v = getValue() + """ + + def __init__(self, idx): + """Constructor. + + The specified argument must be a reference or a pointer. + + @param idx: Index of the argument that is an output value (the first arg has index 1). + @type idx: int + """ + self.idx = idx + self.local_var = "<not initialized>" + + def __str__(self): + return "Output(%d)"%(self.idx) + + def init_funcs(self, sm): + # Remove the specified output argument from the wrapper function + arg = sm.remove_arg(self.idx) + + # Do some sanity checking (whether the argument can actually be + # an output argument, i.e. it has to be a reference or a pointer) + reftype = arg.type + if not (isinstance(reftype, declarations.reference_t) or + isinstance(reftype, declarations.pointer_t)): + raise ValueError, '%s\nOutput variable %d ("%s") must be a reference or a pointer (got %s)'%(sm.decl, self.idx, arg.name, arg.type) + + # Declare a local variable that will receive the output value + self.local_var = sm.wrapper_func.declare_local(arg.name, str(reftype.base)) + # Append the output to the result tuple + sm.wrapper_func.result_exprs.append(self.local_var) + + # Replace the expression in the C++ function call + if isinstance(reftype, declarations.pointer_t): + sm.wrapper_func.input_params[self.idx-1] = "&%s"%self.local_var + else: + sm.wrapper_func.input_params[self.idx-1] = self.local_var + + + def virtual_post_call(self, sm): + """Extract the C++ value after the call to the Python function. + """ + arg = sm.virtual_func.arg_list[self.idx-1] + res = "// Extract the C++ value for output argument '%s' (index: %d)\n"%(arg.name, self.idx) + if isinstance(arg.type, declarations.pointer_t): + res += "*" + res += "%s = boost::python::extract<%s>(%s);"%(arg.name, arg.type.base, sm.py_result_expr(self.local_var)) + return res + + +# input_t +class input_t: + """Handles a single input variable. + + The reference on the specified variable is removed. + + void setValue(int& v) -> setValue(v) + """ + + def __init__(self, idx): + """Constructor. + + The specified argument must be a reference or a pointer. + + @param idx: Index of the argument that is an output value (the first arg has index 1). + @type idx: int + """ + self.idx = idx + + def __str__(self): + return "Input(%d)"%(self.idx) + + def init_funcs(self, sm): + # Remove the specified input argument from the wrapper function + arg = sm.remove_arg(self.idx) + + # Do some checks (the arg has to be a reference or a pointer) + reftype = arg.type + if not (isinstance(reftype, declarations.reference_t) or + isinstance(reftype, declarations.pointer_t)): + raise ValueError, '%s\nInput variable %d ("%s") must be a reference or a pointer (got %s)'%(sm.decl, self.idx, arg.name, arg.type) + + # Create an equivalent argument that is not a reference type + noref_arg = declarations.argument_t(name=arg.name, type=arg.type.base, default_value=arg.default_value) + # Insert the noref argument + sm.insert_arg(self.idx, noref_arg, arg.name) + +# inout_t +class inout_t: + """Handles a single input/output variable. + + void foo(int& v) -> v = foo(v) + """ + + def __init__(self, idx): + """Constructor. + + The specified argument must be a reference or a pointer. + + @param idx: Index of the argument that is an in/out value (the first arg has index 1). + @type idx: int + """ + self.idx = idx + self.local_var = "<not initialized>" + + def __str__(self): + return "InOut(%d)"%(self.idx) + + def init_funcs(self, sm): + # Remove the specified input argument from the wrapper function + arg = sm.remove_arg(self.idx) + + # Do some checks (the arg has to be a reference or a pointer) + reftype = arg.type + if not (isinstance(reftype, declarations.reference_t) or + isinstance(reftype, declarations.pointer_t)): + raise ValueError, '%s\nInOut variable %d ("%s") must be a reference or a pointer (got %s)'%(sm.decl, self.idx, arg.name, arg.type) + + # Create an equivalent argument that is not a reference type + noref_arg = declarations.argument_t(name=arg.name, type=arg.type.base, default_value=arg.default_value) + # Insert the noref argument + sm.insert_arg(self.idx, noref_arg, arg.name) + + # Use the input arg to also store the output + self.local_var = noref_arg.name + # Append the output to the result tuple + sm.wrapper_func.result_exprs.append(self.local_var) + + # Replace the expression in the C++ function call + if isinstance(reftype, declarations.pointer_t): + sm.wrapper_func.input_params[self.idx-1] = "&%s"%self.local_var + else: + sm.wrapper_func.input_params[self.idx-1] = self.local_var + + + def virtual_post_call(self, sm): + """Extract the C++ value after the call to the Python function. + """ + arg = sm.virtual_func.arg_list[self.idx-1] + res = "// Extract the C++ value for in/out argument '%s' (index: %d)\n"%(arg.name, self.idx) + if isinstance(arg.type, declarations.pointer_t): + res += "*" + res += "%s = boost::python::extract<%s>(%s);"%(arg.name, arg.type.base, sm.py_result_expr(self.local_var)) + return res + + + +# input_array_t +class input_array_t: + """Handles an input array with fixed size. + + void setVec3(double* v) -> setVec3(object v) + # v must be a sequence of 3 floats + + + TODO: Error handling (in the wrapper function)! + + """ + + def __init__(self, idx, size): + """Constructor. + + @param idx: Index of the argument that is an input array (the first arg has index 1). + @type idx: int + @param size: The fixed size of the input array + @type size: int + """ + self.idx = idx + self.size = size + + self.argname = None + self.basetype = None + self.carray = None + self.wrapper_ivar = None + self.virtual_ivar = None + self.pylist = None + + def __str__(self): + return "InputArray(%d,%d)"%(self.idx, self.size) + + def init_funcs(self, sm): + + # Remove the original argument... + arg = sm.remove_arg(self.idx) + + if not (isinstance(arg.type, declarations.pointer_t) or + isinstance(arg.type, declarations.array_t)): + raise ValueError, "%s\nArgument %d (%s) must be a pointer."%(sm.decl, self.idx, arg.name) + + # Declare a variable that will hold the Python list + # (this will be the input of the Python call in the virtual function) + self.pylist = sm.virtual_func.declare_local("py_"+arg.name, "boost::python::list") + + # Replace the removed argument with a Python object. + newarg = declarations.argument_t(arg.name, declarations.dummy_type_t("boost::python::object")) + sm.insert_arg(self.idx, newarg, self.pylist) + + self.argname = arg.name + self.basetype = str(arg.type.base).replace("const", "").strip() + + # Declare a variable that will hold the C array... + self.carray = sm.wrapper_func.declare_local("c_"+arg.name, self.basetype, size=self.size) + # and an int which is used for the loop + self.wrapper_ivar = sm.wrapper_func.declare_local("i", "int", default=0) + # and another one in the virtual function + self.virtual_ivar = sm.virtual_func.declare_local("i", "int", default=0) + + # Replace the input parameter with the C array + sm.wrapper_func.input_params[self.idx-1] = self.carray + + # Request the convenience header + sm.wrapper_func.require_header(code_repository.convenience.file_name) + + def wrapper_pre_call(self, sm): + """Wrapper function code. + """ + tmpl = [] + tmpl.append( 'pyplusplus::convenience::ensure_uniform_sequence< %(type)s >( %(argname)s, %(size)d );' ) + tmpl.append( 'for(%(ivar)s=0; %(ivar)s<%(size)d; ++%(ivar)s){' ) + tmpl.append( ' %(array_name)s[ %(ivar)s ] = boost::python::extract< %(type)s >( %(argname)s[%(ivar)s] );' ) + tmpl.append( '}' ) + return os.linesep.join( tmpl ) % { + 'type' : self.basetype + , 'argname' : self.argname + , 'size' : self.size + , 'ivar' : self.wrapper_ivar + , 'array_name' : self.carray + } + + def virtual_pre_call(self, sm): + """Virtual function code. + """ + res = "" + res += "// Copy the array '%s' into list '%s'...\n"%(self.argname, self.pylist) + res += "for(%s=0; %s<%d; %s++)\n"%(self.virtual_ivar, self.virtual_ivar, self.size, self.virtual_ivar) + res += " %s.append(%s[%s]);"%(self.pylist, self.argname, self.virtual_ivar) + return res + + +# output_array_t +class output_array_t: + """Handles an output array of a fixed size. + + void getVec3(double* v) -> v = getVec3() + # v will be a list with 3 floats + + TODO: Error handling (in the virtual function)! + + """ + + def __init__(self, idx, size): + """Constructor. + + @param idx: Index of the argument that is an output array (the first arg has index 1). + @type idx: int + @param size: The fixed size of the output array + @type size: int + """ + + 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 init_funcs(self, sm): + # Remove the original argument... + arg = sm.remove_arg(self.idx) + + if not (isinstance(arg.type, declarations.pointer_t) or + isinstance(arg.type, declarations.array_t)): + raise ValueError, "%s\nArgument %d (%s) must be a pointer."%(sm.decl, self.idx, arg.name) + + self.argname = arg.name + self.basetype = str(arg.type.base).replace("const", "").strip() + + # Wrapper: + + # Declare a variable that will hold the C array... + self.wrapper_cval = sm.wrapper_func.declare_local("c_"+self.argname, self.basetype, size=self.size) + # Declare a Python list which will receive the output... + self.wrapper_pyval = sm.wrapper_func.declare_local(self.argname, "boost::python::list") + # ...and add it to the result + sm.wrapper_func.result_exprs.append(arg.name) + + # Declare an int which is used for the loop + self.wrapper_ivar = sm.wrapper_func.declare_local("i", "int", default=0) + + sm.wrapper_func.input_params[self.idx-1] = self.wrapper_cval + + # Virtual: + + # Declare a variable that will receive the Python list + self.virtual_pyval = sm.virtual_func.declare_local("py_"+self.argname, "boost::python::object") + + # Declare an int which is used for the loop + self.virtual_ivar = sm.virtual_func.declare_local("i", "int", default=0) + + # Request the convenience header + sm.virtual_func.require_header(code_repository.convenience.file_name) + + + def wrapper_post_call(self, sm): + res = "" + res += "// Copy the sequence '%s' into '%s'...\n"%(self.wrapper_cval, self.wrapper_pyval) + res += "for(%s=0; %s<%d; %s++)\n"%(self.wrapper_ivar, self.wrapper_ivar, self.size, self.wrapper_ivar) + res += " %s.append(%s[%s]);"%(self.wrapper_pyval, self.wrapper_cval , self.wrapper_ivar) + return res + + def virtual_post_call(self, sm): + tmpl = [] + tmpl.append( 'pyplusplus::convenience::ensure_uniform_sequence< %(type)s >( %(argname)s, %(size)d );' ) + tmpl.append( 'for(%(ivar)s=0; %(ivar)s<%(size)d; ++%(ivar)s){' ) + tmpl.append( ' %(array_name)s[ %(ivar)s ] = boost::python::extract< %(type)s >( %(argname)s[%(ivar)s] );' ) + tmpl.append( '}' ) + return os.linesep.join( tmpl ) % { + 'type' : self.basetype + , 'argname' : sm.py_result_expr(self.argname) + , 'size' : self.size + , 'ivar' : self.virtual_ivar + , 'array_name' : self.argname + } Modified: pyplusplus_dev/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev/unittests/function_transformations_tester.py 2006-10-24 12:10:40 UTC (rev 682) +++ pyplusplus_dev/unittests/function_transformations_tester.py 2006-10-24 19:10:52 UTC (rev 683) @@ -7,7 +7,7 @@ import sys import unittest import fundamental_tester_base -from pyplusplus.function_transformers.arg_policies import * +from pyplusplus.function_transformers.transformers import * from pyplusplus.decl_wrappers import * class tester_t(fundamental_tester_base.fundamental_tester_base_t): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-11-02 08:47:28
|
Revision: 694 http://svn.sourceforge.net/pygccxml/?rev=694&view=rev Author: roman_yakovenko Date: 2006-11-02 00:47:11 -0800 (Thu, 02 Nov 2006) Log Message: ----------- fixing few bugs in indexing suite v2 Modified Paths: -------------- pyplusplus_dev/indexing_suite_v2/indexing/algorithms.hpp pyplusplus_dev/indexing_suite_v2/indexing/map.hpp pyplusplus_dev/indexing_suite_v2/indexing/multimap.hpp pyplusplus_dev/indexing_suite_v2/indexing/set.hpp pyplusplus_dev/unittests/data/indexing_suites2_to_be_exported.hpp pyplusplus_dev/unittests/indexing_suites2_tester.py Modified: pyplusplus_dev/indexing_suite_v2/indexing/algorithms.hpp =================================================================== --- pyplusplus_dev/indexing_suite_v2/indexing/algorithms.hpp 2006-10-30 16:43:55 UTC (rev 693) +++ pyplusplus_dev/indexing_suite_v2/indexing/algorithms.hpp 2006-11-02 08:47:11 UTC (rev 694) @@ -151,25 +151,11 @@ static size_type count (container &, key_param); static bool contains (container &, key_param); - static boost::python::list keys( container & ); - // Default visit_container_class template<typename PythonClass, typename Policy> static void visit_container_class( PythonClass &pyClass, Policy const &policy) { ContainerTraits::visit_container_class (pyClass, policy); - pyClass.def( "keys", &self_type::keys ); - - //~ object class_name(cl.attr("__name__")); - //~ extract<std::string> class_name_extractor(class_name); - //~ std::string = class_name_extractor() + "_entry"; - - //~ class_<value_type>(elem_name.c_str()) - //~ .def("data", &DerivedPolicies::get_data, get_data_return_policy()) - //~ .def("key", &DerivedPolicies::get_key) - //~ ; - - } @@ -529,25 +515,6 @@ return c.count (key); } - template<typename ContainerTraits, typename Ovr> - boost::python::list - assoc_algorithms<ContainerTraits, Ovr>::keys( container &c ) - { - boost::python::list _keys; - //For some reason code with set could not be compiled - //std::set< key_param > unique_keys; - for( iterator index = most_derived::begin(c); index != most_derived::end(c); ++index ){ - //if( unique_keys.end() == unique_keys.find( index->first ) ){ - // unique_keys.insert( index->first ); - if( !_keys.count( index->first ) ){ - _keys.append( index->first ); - } - //} - } - - return _keys; - } - ///////////////////////////////////////////////////////////////////////// // Some meta-information to select algorithms for const and // non-const qualified containers. All algorithms_selector specializations Modified: pyplusplus_dev/indexing_suite_v2/indexing/map.hpp =================================================================== --- pyplusplus_dev/indexing_suite_v2/indexing/map.hpp 2006-10-30 16:43:55 UTC (rev 693) +++ pyplusplus_dev/indexing_suite_v2/indexing/map.hpp 2006-11-02 08:47:11 UTC (rev 694) @@ -96,8 +96,18 @@ static reference get (container &, index_param); // Version to return only the mapped type + static boost::python::list keys( container & ); + static void assign (container &, index_param, value_param); static void insert (container &, index_param, value_param); + + template<typename PythonClass, typename Policy> + static void visit_container_class( PythonClass &pyClass, Policy const &policy) + { + ContainerTraits::visit_container_class (pyClass, policy); + pyClass.def( "keys", &self_type::keys ); + } + }; #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) @@ -159,6 +169,26 @@ return most_derived::find_or_throw (c, ix)->second; } + + template<typename ContainerTraits, typename Ovr> + boost::python::list + map_algorithms<ContainerTraits, Ovr>::keys( container &c ) + { + boost::python::list _keys; + //For some reason code with set could not be compiled + //std::set< key_param > unique_keys; + for( iterator index = most_derived::begin(c); index != most_derived::end(c); ++index ){ + //if( unique_keys.end() == unique_keys.find( index->first ) ){ + // unique_keys.insert( index->first ); + if( !_keys.count( index->first ) ){ + _keys.append( index->first ); + } + //} + } + + return _keys; + } + ///////////////////////////////////////////////////////////////////////// // Assign a value at a particular index (map version) ///////////////////////////////////////////////////////////////////////// Modified: pyplusplus_dev/indexing_suite_v2/indexing/multimap.hpp =================================================================== --- pyplusplus_dev/indexing_suite_v2/indexing/multimap.hpp 2006-10-30 16:43:55 UTC (rev 693) +++ pyplusplus_dev/indexing_suite_v2/indexing/multimap.hpp 2006-11-02 08:47:11 UTC (rev 694) @@ -93,8 +93,18 @@ static boost::python::list get (container &, index_param); // Version to return only the mapped type + static boost::python::list keys( container & ); + static void assign (container &, index_param, value_param); static void insert (container &, index_param, value_param); + + template<typename PythonClass, typename Policy> + static void visit_container_class( PythonClass &pyClass, Policy const &policy) + { + ContainerTraits::visit_container_class (pyClass, policy); + pyClass.def( "keys", &self_type::keys ); + } + }; template< @@ -124,6 +134,26 @@ return l; } + template<typename ContainerTraits, typename Ovr> + boost::python::list + multimap_algorithms<ContainerTraits, Ovr>::keys( container &c ) + { + boost::python::list _keys; + //For some reason code with set could not be compiled + //std::set< key_param > unique_keys; + for( iterator index = most_derived::begin(c); index != most_derived::end(c); ++index ){ + //if( unique_keys.end() == unique_keys.find( index->first ) ){ + // unique_keys.insert( index->first ); + if( !_keys.count( index->first ) ){ + _keys.append( index->first ); + } + //} + } + + return _keys; + } + + ///////////////////////////////////////////////////////////////////////// // Assign a value at a particular index (map version) ///////////////////////////////////////////////////////////////////////// Modified: pyplusplus_dev/indexing_suite_v2/indexing/set.hpp =================================================================== --- pyplusplus_dev/indexing_suite_v2/indexing/set.hpp 2006-10-30 16:43:55 UTC (rev 693) +++ pyplusplus_dev/indexing_suite_v2/indexing/set.hpp 2006-11-02 08:47:11 UTC (rev 694) @@ -85,6 +85,14 @@ typedef typename Parent::index_param index_param; static void insert (container &, index_param); + + template<typename PythonClass, typename Policy> + static void visit_container_class( PythonClass &pyClass, Policy const &policy) + { + ContainerTraits::visit_container_class (pyClass, policy); + pyClass.def( "add", &self_type::insert ); + } + }; #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) @@ -144,13 +152,15 @@ set_algorithms<ContainerTraits, Ovr>::insert( container &c, index_param ix) { - if (!c.insert (ix).second) - { - PyErr_SetString( - PyExc_ValueError, "Set already holds value for insertion"); + c.insert (ix); + //~ Python set does not raise exception in this situation + //~ if (!c.insert (ix).second) + //~ { + //~ PyErr_SetString( + //~ PyExc_ValueError, "Set already holds value for insertion"); - boost::python::throw_error_already_set (); - } + //~ boost::python::throw_error_already_set (); + //~ } } } } } Modified: pyplusplus_dev/unittests/data/indexing_suites2_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/indexing_suites2_to_be_exported.hpp 2006-10-30 16:43:55 UTC (rev 693) +++ pyplusplus_dev/unittests/data/indexing_suites2_to_be_exported.hpp 2006-11-02 08:47:11 UTC (rev 694) @@ -9,6 +9,7 @@ #include <vector> #include <string> #include <map> +#include <set> namespace indexing_suites2 { @@ -66,6 +67,11 @@ return multimap_ints_t(); } +typedef std::set< std::string > set_strings_t; +inline set_strings_t create_set_strings(){ + return set_strings_t(); } -#endif//__indexing_suites2_to_be_exported_hpp__ \ No newline at end of file +} + +#endif//__indexing_suites2_to_be_exported_hpp__ Modified: pyplusplus_dev/unittests/indexing_suites2_tester.py =================================================================== --- pyplusplus_dev/unittests/indexing_suites2_tester.py 2006-10-30 16:43:55 UTC (rev 693) +++ pyplusplus_dev/unittests/indexing_suites2_tester.py 2006-11-02 08:47:11 UTC (rev 694) @@ -53,7 +53,12 @@ items_ptr = module.items_ptr_t() items_ptr.append( item ) self.failUnless( items_ptr[0].value == 1977 ) - print 'xx' + + set_of_strings = module.create_set_strings() + set_of_strings.add("s") + set_of_strings.add("s1") + set_of_strings.add("s") + def create_suite(): suite = unittest.TestSuite() suite.addTest( unittest.makeSuite(tester_t)) @@ -63,4 +68,4 @@ unittest.TextTestRunner(verbosity=2).run( create_suite() ) if __name__ == "__main__": - run_suite() \ No newline at end of file + run_suite() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-11-16 14:00:27
|
Revision: 727 http://svn.sourceforge.net/pygccxml/?rev=727&view=rev Author: roman_yakovenko Date: 2006-11-16 06:00:26 -0800 (Thu, 16 Nov 2006) Log Message: ----------- adding documentation that describes opaque functionality, A class that marked as "opaque" will not be exposed Modified Paths: -------------- pyplusplus_dev/docs/documentation/functions/call_policies.rest pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py pyplusplus_dev/unittests/call_policies_tester.py Modified: pyplusplus_dev/docs/documentation/functions/call_policies.rest =================================================================== --- pyplusplus_dev/docs/documentation/functions/call_policies.rest 2006-11-15 14:46:17 UTC (rev 726) +++ pyplusplus_dev/docs/documentation/functions/call_policies.rest 2006-11-16 14:00:26 UTC (rev 727) @@ -90,6 +90,12 @@ * return type is ``void*`` * return type is ``const void*`` + + * return type is ``T*`` and ``T`` is a user defined opaque type + + ``class_t`` and ``class_declaration_t`` classes have ``opaque`` property. + You have to set it to ``True``, if you want `Py++`_ to create this call + policy automaticly for all functions, that use ``T*`` as return type. * ``copy_const_reference`` @@ -133,16 +139,44 @@ Special case ------------ +Before you read this paragraph consider to read `Boost.Python`_ `return_opaque_pointer documentation`_. + ``return_value_policy( return_opaque_pointer )`` is a special policy for `Boost.Python`_. In this case, it requieres from you to define specialization for the ``boost::python::type_id`` function on the type pointed to by returned pointer. `Py++`_ will generate the required code. -For more information about the call policy please refer to `Boost.Python`_ -`documentation`_. -.. _`documentation` : http://boost.org/libs/python/doc/v2/return_opaque_pointer.html +Actually you should define ``boost::python::type_id`` specialization also in case +a function takes the opaque type as an argument. `Py++`_ can do it for you, all +you need is to say to mark a declaration as opaque. +Example: + +.. code-block:: C++ + + struct identity_impl_t{}; + typedef identity_impl_t* identity; + + struct world_t{ + + world_t( identity id ); + + identity get_id() const; + + ... + }; + +`Py++`_ code: + +.. code-block:: Python + + mb = module_builder_t(...) + mb.class_( 'identity_impl_t' ).opaque = True + + +.. _`return_opaque_pointer documentation` : http://boost.org/libs/python/doc/v2/return_opaque_pointer.html + -------------------------- Py++ defined call policies -------------------------- @@ -177,9 +211,26 @@ , bpl::return_value_policy< pyplusplus::call_policies::return_pointee_value<> >() ); } -`Py++`_ code is pretty simple and similar to what you already know: +The `Py++`_ code is not that different from what you already know: +.. code-block:: Python + from pyplusplus import module_builder + from pyplusplus.module_builder import call_policies + + mb = module_builder.module_builder_t( ... ) + mb.free_function( return_type='float *' ).call_policies \ + = call_policies.return_value_policy( call_policies.return_pointee_value ) + +Python code: + +.. code-block:: Python + + import my_module + + assert 0.5 == my_module.get_value() + assert None is my_module.get_null_value() + .. _`ResultConverterGenerator` : http://boost.org/libs/python/doc/v2/ResultConverter.html#ResultConverterGenerator-concept .. _`Py++` : ./../pyplusplus.html Modified: pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2006-11-15 14:46:17 UTC (rev 726) +++ pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2006-11-16 14:00:26 UTC (rev 727) @@ -118,7 +118,8 @@ return self._opaque def _set_opaque( self, value ): - self._opaque = value + self._opaque = value + self.ignore = value #don't expose opaque type opaque = property( _get_opaque, _set_opaque , doc="If True, Py++ will treat return types and arguments T* as opaque types." \ Modified: pyplusplus_dev/unittests/call_policies_tester.py =================================================================== --- pyplusplus_dev/unittests/call_policies_tester.py 2006-11-15 14:46:17 UTC (rev 726) +++ pyplusplus_dev/unittests/call_policies_tester.py 2006-11-16 14:00:26 UTC (rev 727) @@ -22,9 +22,7 @@ mb.calldef( 'return_second_arg' ).call_policies = call_policies.return_arg( 2 ) mb.calldef( 'return_self' ).call_policies = call_policies.return_self() - mb.class_( 'impl_details_t' ).exclude() - mb.calldef( 'get_impl_details' ).call_policies \ - = call_policies.return_value_policy( call_policies.return_opaque_pointer ) + mb.class_( 'impl_details_t' ).opaque = True mb.calldef( 'get_opaque' ).call_policies \ = call_policies.return_value_policy( call_policies.return_opaque_pointer ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-11-30 11:20:24
|
Revision: 767 http://svn.sourceforge.net/pygccxml/?rev=767&view=rev Author: roman_yakovenko Date: 2006-11-30 03:20:24 -0800 (Thu, 30 Nov 2006) Log Message: ----------- merge of FT feature from pyplusplus_dev_ft branch Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/__init__.py pyplusplus_dev/pyplusplus/code_creators/algorithm.py pyplusplus_dev/pyplusplus/code_creators/calldef.py pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py pyplusplus_dev/pyplusplus/code_creators/declaration_based.py pyplusplus_dev/pyplusplus/code_repository/__init__.py pyplusplus_dev/pyplusplus/code_repository/call_policies.py pyplusplus_dev/pyplusplus/code_repository/convenience.py pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py pyplusplus_dev/pyplusplus/decl_wrappers/call_policies.py pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/properties.py pyplusplus_dev/pyplusplus/file_writers/writer.py pyplusplus_dev/pyplusplus/function_transformers/__init__.py pyplusplus_dev/pyplusplus/function_transformers/controllers.py pyplusplus_dev/pyplusplus/function_transformers/function_transformation.py pyplusplus_dev/pyplusplus/function_transformers/templates.py pyplusplus_dev/pyplusplus/function_transformers/transformer.py pyplusplus_dev/pyplusplus/function_transformers/transformers.py pyplusplus_dev/pyplusplus/module_builder/builder.py pyplusplus_dev/pyplusplus/module_creator/creator.py pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp pyplusplus_dev/unittests/function_transformations_tester.py pyplusplus_dev/unittests/test_all.py Added Paths: ----------- pyplusplus_dev/pyplusplus/code_repository/named_tuple.py Removed Paths: ------------- pyplusplus_dev/pyplusplus/function_transformers/code_manager.py pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py Modified: pyplusplus_dev/pyplusplus/code_creators/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-11-30 11:20:24 UTC (rev 767) @@ -78,6 +78,8 @@ from calldef_transformed import mem_fun_transformed_t from calldef_transformed import mem_fun_transformed_wrapper_t +from calldef_transformed import free_fun_transformed_t +from calldef_transformed import free_fun_transformed_wrapper_t from calldef_transformed import mem_fun_v_transformed_t from calldef_transformed import mem_fun_v_transformed_wrapper_t Modified: pyplusplus_dev/pyplusplus/code_creators/algorithm.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/algorithm.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_creators/algorithm.py 2006-11-30 11:20:24 UTC (rev 767) @@ -99,3 +99,6 @@ if recursive: search_area = make_flatten_generator( where ) return filter( lambda inst: isinstance( inst, what ), search_area ) + +def make_id_creator( code_creator ): + return lambda decl_string: create_identifier( code_creator, decl_string ) Modified: pyplusplus_dev/pyplusplus/code_creators/calldef.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-11-30 11:20:24 UTC (rev 767) @@ -19,9 +19,6 @@ #protected member functions - call, override #private - override -def make_id_creator( code_creator ): - return lambda decl_string: algorithm.create_identifier( code_creator, decl_string ) - class calldef_t( registration_based.registration_based_t , declaration_based.declaration_based_t ): def __init__(self, function, wrapper=None ): @@ -50,10 +47,15 @@ def param_sep(self): return os.linesep + self.indent( self.PARAM_SEPARATOR ) - def keywords_args(self): - arg_utils = calldef_utils.argument_utils_t( self.declaration, make_id_creator( self ) ) + def create_keywords_args(self): + arg_utils = calldef_utils.argument_utils_t( self.declaration, algorithm.make_id_creator( self ) ) return arg_utils.keywords_args() + def create_call_policies( self ): + if self.declaration.call_policies.is_default(): + return '' + return self.declaration.call_policies.create( self ) + def create_def_code( self ): if not self.works_on_instance: return '%s.def' % self.parent.class_var_name @@ -96,15 +98,16 @@ result.append( self.create_function_ref_code( not self.works_on_instance ) ) if self.declaration.use_keywords: - result.append( self.param_sep() ) - result.append( self.keywords_args() ) + keywd_args = self.create_keywords_args() + if keywd_args: + result.append( self.param_sep() ) + result.append( keywd_args ) if self.declaration.call_policies: - if not self.declaration.call_policies.is_default(): + c_p_code = self.create_call_policies() + if c_p_code: result.append( self.param_sep() ) - result.append( self.declaration.call_policies.create( self ) ) - else: - pass#don't generate default_call_policies + result.append( c_p_code ) else: result.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) @@ -139,11 +142,11 @@ return algorithm.create_identifier( self, '::boost::python::override' ) def function_call_args( self ): - arg_utils = calldef_utils.argument_utils_t( self.declaration, make_id_creator( self ) ) + arg_utils = calldef_utils.argument_utils_t( self.declaration, algorithm.make_id_creator( self ) ) return arg_utils.call_args() def args_declaration( self ): - arg_utils = calldef_utils.argument_utils_t( self.declaration, make_id_creator( self ) ) + arg_utils = calldef_utils.argument_utils_t( self.declaration, algorithm.make_id_creator( self ) ) return arg_utils.args_declaration() def wrapped_class_identifier( self ): @@ -779,7 +782,7 @@ answer.append( '(' ) keywords_args = None if self.declaration.use_keywords: - keywords_args = self.keywords_args() + keywords_args = self.create_keywords_args() answer.append( '%s' % keywords_args ) if self.documentation: if keywords_args: @@ -841,7 +844,7 @@ def _create_constructor_call( self ): answer = [ algorithm.create_identifier( self, self.parent.declaration.decl_string ) ] answer.append( '( ' ) - arg_utils = calldef_utils.argument_utils_t( self.declaration, make_id_creator( self ) ) + arg_utils = calldef_utils.argument_utils_t( self.declaration, algorithm.make_id_creator( self ) ) params = arg_utils.call_args() answer.append( params ) if params: @@ -1177,7 +1180,7 @@ def create_end_def_code( self ): raise NotImplementedError() - def keywords_args(self): + def create_keywords_args(self): result = [ algorithm.create_identifier( self, '::boost::python::args' ) ] result.append( '( ' ) args = [] @@ -1199,7 +1202,7 @@ def create_overloads_cls( self ): result = [ self.overloads_class.name ] result.append( '( ' ) - result.append( os.linesep + self.indent( self.keywords_args(), 3 ) ) + result.append( os.linesep + self.indent( self.create_keywords_args(), 3 ) ) if self.overloads_class.max_function.documentation: result.append( os.linesep + self.indent( self.PARAM_SEPARATOR, 3 ) ) result.append( self.overloads_class.max_function.documentation ) Modified: pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py 2006-11-30 11:20:24 UTC (rev 767) @@ -4,482 +4,415 @@ # http://www.boost.org/LICENSE_1_0.txt) import os -#import algorithm -#import code_creator +import algorithm +import code_creator +import calldef_utils import class_declaration from pygccxml import declarations from calldef import calldef_t, calldef_wrapper_t import pyplusplus.function_transformers as function_transformers from pyplusplus import code_repository -###################################################################### +#TODO: constructors also can have transformation defined. We should use make _init +# function for this purpose -class mem_fun_transformed_t( calldef_t ): - """Creates code for public non-virtual member functions. - """ - +def remove_duplicate_linesep( code ): + lines = code.split( os.linesep ) + lines = filter( lambda line: line.strip(), lines ) + return os.linesep.join( lines ) + +class sealed_fun_transformed_t( calldef_t ): def __init__( self, function, wrapper=None ): calldef_t.__init__( self, function=function, wrapper=wrapper ) + @property + def ft( self ): #function transformation + return self.declaration.transformations[0] + + @property + def controller( self ): + return self.ft.controller + + def _get_alias_impl( self ): + return self.wrapper.ft.alias + def create_function_type_alias_code( self, exported_class_alias=None ): - if self.wrapper==None: - ftype = self.declaration.function_type() - else: - ftype = self.wrapper.function_type() - res = 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) - return res + ftype = self.wrapper.function_type() + return 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) def create_function_ref_code(self, use_function_alias=False): - if self.wrapper: - full_name = self.wrapper.full_name() - else: - full_name = declarations.full_name( self.declaration ) + full_name = self.wrapper.full_name() if use_function_alias: return '%s( &%s )' \ % ( self.function_type_alias, full_name ) elif self.declaration.create_with_signature: - if self.wrapper: - func_type = self.wrapper.function_type() - else: - func_type = self.declaration.function_type().decl_string - return '(%s)( &%s )' \ - % ( func_type, full_name ) + func_type = self.wrapper.function_type() + return '(%s)( &%s )' % ( func_type, full_name ) else: return '&%s' % full_name + def create_call_policies( self ): + return '' -class mem_fun_transformed_wrapper_t( calldef_wrapper_t ): - """Creates wrapper code for (public) non-virtual member functions. - - The generated function is either used as a static member inside the - wrapper class (when self.parent is not None) or as a free function - (when self.parent is None). - """ - +class sealed_fun_transformed_wrapper_t( calldef_wrapper_t ): def __init__( self, function ): - """Constructor. - - @param function: Function declaration - @type function: calldef_t - """ calldef_wrapper_t.__init__( self, function=function ) - # Create the substitution manager - sm = function_transformers.substitution_manager_t( function - , transformers=function.transformations[0].transformers) - sm.init_funcs() - self._subst_manager = sm + @property + def ft( self ): #function transformation + return self.declaration.transformations[0] - def function_type(self): - """Return the type of the wrapper function. + @property + def controller( self ): + return self.ft.controller - @rtype: type_t - """ - template = '$RET_TYPE' - rettype = self._subst_manager.subst_wrapper(template) - rettype = declarations.dummy_type_t(rettype) + def resolve_function_ref( self ): + raise NotImplementedError() - return declarations.free_function_type_t( - return_type=rettype - , arguments_types=map( lambda arg: arg.type, self.declaration.arguments ) ) + def create_fun_definition(self): + cntrl = self.controller - def wrapper_name(self): - """Return the name of the wrapper function. + make_object = algorithm.create_identifier( self, 'pyplusplus::call_policies::make_object' ) + make_tuple = algorithm.create_identifier( self, 'boost::python::make_tuple' ) + + tmpl_values = dict() - This is just the local name without any scope information. - """ - # A list with the individual components of the name - components = ["_py"] - # Is the wrapper placed outside a wrapper class? - if not isinstance(self.parent, class_declaration.class_wrapper_t): - # Incorporate the original class name into the name - components.append(self.declaration.parent.name) - components.append(self.declaration.alias) - return "_".join(components) + tmpl_values['unique_function_name'] = self.wrapper_name() + tmpl_values['return_type'] = self.controller.wrapper_return_type.decl_string + tmpl_values['arg_declarations'] = self.args_declaration() + + tmpl_values['declare_variables'] \ + = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string() ) + , cntrl.variables ) ) + + tmpl_values['pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.pre_call ) ) - def full_name(self): - """Return the full name of the wrapper function. + tmpl_values['save_result'] = '' + if not declarations.is_void( self.declaration.return_type ): + tmpl_values['save_result'] \ + = '%(type)s %(name)s = ' \ + % { 'type': cntrl.result_variable.type.decl_string + , 'name' : cntrl.result_variable.name } - The returned name also includes the class name (if there is any). + tmpl_values['function_name'] = self.resolve_function_ref() + tmpl_values['arg_expressions'] = self.PARAM_SEPARATOR.join( cntrl.arg_expressions ) + return_stmt_creator = calldef_utils.return_stmt_creator_t( self + , self.controller + , self.controller.result_variable + , self.controller.return_variables ) - @rtype: str - """ - if isinstance(self.parent, class_declaration.class_wrapper_t): - return self.parent.full_name + '::' + self.wrapper_name() - else: - return self.wrapper_name() - - def create_declaration(self, name): - """Create the function header. - """ - template = 'static $RET_TYPE %(name)s( $ARG_LIST_DEF ) %(throw)s' - - # Substitute the $-variables - template = self._subst_manager.subst_wrapper(template) - - return template % { - 'name' : self.wrapper_name() - , 'throw' : self.throw_specifier_code() - } - - def create_body(self): - body = os.linesep.join([ - '$DECLARATIONS' - , '$PRE_CALL' - , '$RESULT_VAR_ASSIGNMENT$CALL_FUNC_NAME($INPUT_PARAMS);' - , '$POST_CALL' - , '$RETURN_STMT' - ]) - - # Replace the $-variables - body = self._subst_manager.subst_wrapper(body) - - return body - - def create_function(self): - answer = [70*"/"] - answer.append("// Transformed wrapper function for:") - answer.append("// %s"%self.declaration) - answer.append(70*"/") - answer.append( self.create_declaration(self.declaration.alias) + '{') - answer.append( self.indent( self.create_body() ) ) - answer.append( '}' ) - return os.linesep.join( answer ) - + tmpl_values['post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.post_call ) ) + if return_stmt_creator.pre_return_code: + tmpl_values['post_call'] \ + = os.linesep.join([ tmpl_values['post_call'] + , self.indent( return_stmt_creator.pre_return_code )]) + tmpl_values['return'] = os.linesep + self.indent( return_stmt_creator.statement ) + + f_def = self.controller.template.substitute(tmpl_values) + return remove_duplicate_linesep( f_def ) + def _create_impl(self): - - answer = self.create_function() - - # Replace the argument list of the declaration so that in the - # case that keywords are created, the correct arguments will be - # picked up (i.e. the modified argument list and not the original - # argument list) - self.declaration.arguments = self._subst_manager.wrapper_func.arg_list - - return answer - -###################################################################### - -class mem_fun_v_transformed_t( calldef_t ): - """Creates code for (public) virtual member functions. + return self.create_fun_definition() + +class free_fun_transformed_t( sealed_fun_transformed_t ): + """Creates code for public non-virtual member functions. """ def __init__( self, function, wrapper=None ): - calldef_t.__init__( self, function=function, wrapper=wrapper ) - self.default_function_type_alias = 'default_' + self.function_type_alias + sealed_fun_transformed_t.__init__( self, function=function, wrapper=wrapper ) + self.works_on_instance = False - def create_function_type_alias_code( self, exported_class_alias=None ): - if self.wrapper==None: - ftype = self.declaration.function_type() - else: - ftype = self.wrapper.function_type() + def create_def_code( self ): + return self.def_identifier() - result = [] - result.append( 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) ) - return ''.join( result ) + def create_keywords_args(self): + arg_utils = calldef_utils.argument_utils_t( self.declaration + , algorithm.make_id_creator( self ) + , self.controller.wrapper_args ) + return arg_utils.keywords_args() - def create_doc(self): - return None - def create_function_ref_code(self, use_function_alias=False): - if self.wrapper: - full_name = self.wrapper.default_full_name() - else: - full_name = declarations.full_name( self.declaration ) - - result = [] - if use_function_alias: - result.append( '%s(&%s)' - % ( self.function_type_alias, full_name ) ) - elif self.declaration.create_with_signature: - if self.wrapper: - func_type = self.wrapper.function_type() - else: - func_type = self.declaration.function_type().decl_string - result.append( '(%s)(&%s)' - % ( func_type, full_name ) ) - else: - result.append( '&%s' % full_name ) - - return ''.join( result ) - - -class mem_fun_v_transformed_wrapper_t( calldef_wrapper_t ): - """Creates wrapper code for (public) virtual member functions. - - The generated code consists of two functions: the virtual function - and the 'default' function. - """ - +class free_fun_transformed_wrapper_t( sealed_fun_transformed_wrapper_t ): def __init__( self, function ): """Constructor. @param function: Function declaration @type function: calldef_t """ - calldef_wrapper_t.__init__( self, function=function ) - - # Create the substitution manager - sm = function_transformers.substitution_manager_t(function - , transformers=function.transformations[0].transformers ) + sealed_fun_transformed_wrapper_t .__init__( self, function=function ) - sm.init_funcs() - self._subst_manager = sm - - # Stores the name of the variable that holds the override - self._override_var \ - = sm.virtual_func.declare_variable(function.alias + "_callable", 'boost::python::override') - # Stores the name of the 'gstate' variable - self._gstate_var \ - = sm.virtual_func.declare_variable("gstate", 'pyplusplus::threading ::gil_guard_t' ) - - def default_name(self): - """Return the name of the 'default' function. - - @rtype: str - """ - return "default_" + self.declaration.alias - - def default_full_name(self): - """Return the full name of the 'default' function. - - The returned name also includes the class name. - - @rtype: str - """ - return self.parent.full_name + '::default_' + self.declaration.alias - - def virtual_name(self): - """Return the name of the 'virtual' function. - - @rtype: str - """ - return self.declaration.name - - def base_name(self): - """Return the name of the 'base' function. - - @rtype: str - """ - return "base_" + self.declaration.name - def function_type(self): - template = '$RET_TYPE' - rettype = self._subst_manager.subst_wrapper(template) - rettype = declarations.dummy_type_t(rettype) - return declarations.free_function_type_t( - return_type=rettype - , arguments_types=map( lambda arg: arg.type, self.declaration.arguments ) ) + return_type=self.controller.wrapper_return_type + , arguments_types=self.controller.wrapper_args ) - return declarations.member_function_type_t( - return_type=self.declaration.return_type - , class_inst=declarations.dummy_type_t( self.parent.full_name ) - , arguments_types=map( lambda arg: arg.type, self.declaration.arguments ) - , has_const=self.declaration.has_const ) + def wrapper_name( self ): + return self.ft.unique_name - def create_declaration(self, name, virtual=True): - """Create the function header. + def full_name(self): + return self.ft.unique_name - This method is used for the virtual function (and the base_ function), - but not for the default function. - """ - template = '%(virtual)s$RET_TYPE %(name)s( $ARG_LIST_DEF )%(constness)s %(throw)s' + def args_declaration( self ): + arg_utils = calldef_utils.argument_utils_t( + self.declaration + , algorithm.make_id_creator( self ) + , self.controller.wrapper_args ) + return arg_utils.args_declaration() - # Substitute the $-variables - template = self._subst_manager.subst_virtual(template) + def create_declaration(self, name): + template = 'static %(return_type)s %(name)s( %(args)s )' - virtualspec = '' - if virtual: - virtualspec = 'virtual ' - - constness = '' - if self.declaration.has_const: - constness = ' const ' - return template % { - 'virtual' : virtualspec - , 'name' : name - , 'constness' : constness - , 'throw' : self.throw_specifier_code() + 'return_type' : self.controller.wrapper_return_type.decl_string + , 'name' : self.wrapper_name() + , 'args' : self.args_declaration() } - def create_base_body(self): - body = "%(return_)s%(wrapped_class)s::%(name)s( %(args)s );" + def resolve_function_ref( self ): + return declarations.full_name( self.declaration ) - return_ = '' - if not declarations.is_void( self.declaration.return_type ): - return_ = 'return ' - return body % { - 'name' : self.declaration.name - , 'args' : self.function_call_args() - , 'return_' : return_ - , 'wrapped_class' : self.wrapped_class_identifier() - } +class mem_fun_transformed_t( sealed_fun_transformed_t ): + """Creates code for public non-virtual member functions. + """ + def __init__( self, function, wrapper=None ): + sealed_fun_transformed_t.__init__( self, function=function, wrapper=wrapper ) - def create_virtual_body(self): + def create_keywords_args(self): + args = self.controller.wrapper_args[:] + if self.controller.inst_arg: + args.insert( 0, self.controller.inst_arg ) - thread_safe = self.declaration.transformations[0].thread_safe + arg_utils = calldef_utils.argument_utils_t( self.declaration + , algorithm.make_id_creator( self ) + , args ) + return arg_utils.keywords_args() - if thread_safe: - body = """ -pyplusplus::threading::gil_guard_t %(gstate_var)s; +class mem_fun_transformed_wrapper_t( sealed_fun_transformed_wrapper_t ): + def __init__( self, function ): + """Constructor. -%(gstate_var)s.ensure(); -boost::python::override %(override_var)s = this->get_override( "%(alias)s" ); -%(gstate_var)s.release(); + @param function: Function declaration + @type function: calldef_t + """ + sealed_fun_transformed_wrapper_t.__init__( self, function=function ) -if( %(override_var)s ) -{ - // The corresponding release() is done in the destructor of %(gstate_var)s - %(gstate_var)s.ensure(); + def __is_global( self ): + return not isinstance( self.parent, class_declaration.class_wrapper_t ) - $DECLARATIONS + def function_type(self): + args = map( lambda arg: arg.type, self.controller.wrapper_args ) + if self.controller.inst_arg: + args.insert( 0, self.controller.inst_arg.type ) + return declarations.free_function_type_t( + return_type=self.controller.wrapper_return_type + , arguments_types=args ) - try { - $PRE_CALL + def wrapper_name( self ): + if self.__is_global(): + return self.ft.unique_name + else: + if self.declaration.overloads: + #it is possible that other functions will have same signature + return self.ft.unique_name + else: + return self.declaration.name - ${RESULT_VAR_ASSIGNMENT}boost::python::call<$RESULT_TYPE>($INPUT_PARAMS); + def full_name(self): + if self.__is_global(): + return self.ft.unique_name + else: + return self.parent.full_name + '::' + self.wrapper_name() - $POST_CALL + def args_declaration( self ): + args = self.controller.wrapper_args[:] + if self.controller.inst_arg: + args.insert( 0, self.controller.inst_arg ) + arg_utils = calldef_utils.argument_utils_t( + self.declaration + , algorithm.make_id_creator( self ) + , args ) + return arg_utils.args_declaration() - $RETURN_STMT - } - catch(...) - { - if (PyErr_Occurred()) - { - PyErr_Print(); - } + def resolve_function_ref( self ): + if self.controller.inst_arg: + return self.controller.inst_arg.name + '.' + self.declaration.name + else: + return declarations.full_name( self.declaration ) - $CLEANUP +class mem_fun_v_transformed_t( calldef_t ): + def __init__( self, function, wrapper=None ): + calldef_t.__init__( self, function=function, wrapper=wrapper ) - $EXCEPTION_HANDLER_EXIT - } -} -else -{ - %(inherited)s -} -""" + @property + def ft( self ): #function transformation + return self.declaration.transformations[0] - if not thread_safe: - body = """ -boost::python::override %(override_var)s = this->get_override( "%(alias)s" ); + @property + def controller( self ): + return self.ft.controller + + def _get_alias_impl( self ): + return self.wrapper.ft.alias + + def create_function_type_alias_code( self, exported_class_alias=None ): + result = [] -if( %(override_var)s ) -{ - $DECLARATIONS + ftype = self.declaration.function_type() + result.append( 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) ) + if self.wrapper: + result.append( os.linesep ) + ftype = self.wrapper.function_type() + result.append( 'typedef %s;' % ftype.create_typedef( self.default_function_type_alias ) ) + return ''.join( result ) - $PRE_CALL + def create_keywords_args(self): + cntrl = self.controller.default_controller + arg_utils = calldef_utils.argument_utils_t( self.declaration + , algorithm.make_id_creator( self ) + , [cntrl.inst_arg] + cntrl.wrapper_args ) + return arg_utils.keywords_args() - ${RESULT_VAR_ASSIGNMENT}boost::python::call<$RESULT_TYPE>($INPUT_PARAMS); + def create_function_ref_code(self, use_function_alias=False): + full_name = self.wrapper.default_full_name() + if use_function_alias: + return '%s( &%s )' % ( self.function_type_alias, full_name ) + elif self.declaration.create_with_signature: + func_type = self.wrapper.default_function_type() + return '(%s)( &%s )' % ( func_type, full_name ) + else: + return '&%s' % full_name - $POST_CALL +class mem_fun_v_transformed_wrapper_t( calldef_wrapper_t ): + def __init__( self, function ): + calldef_wrapper_t.__init__( self, function=function ) - $RETURN_STMT -} -else -{ - %(inherited)s -} -""" + @property + def ft( self ): #function transformation + return self.declaration.transformations[0] - vf = self._subst_manager.virtual_func - arg0 = "%s.ptr()"%self._override_var - if vf.INPUT_PARAMS=="": - vf.INPUT_PARAMS = arg0 + @property + def controller( self ): + return self.ft.controller + + def default_name(self): + if self.declaration.overloads: + #it is possible that other functions will have same signature + return 'default_' + self.ft.unique_name else: - vf.INPUT_PARAMS = arg0+", "+vf.INPUT_PARAMS + return 'default_' + self.declaration.alias - # Replace the $-variables - body = self._subst_manager.subst_virtual(body) + def default_full_name(self): + return self.parent.full_name + '::' + self.default_name() - return body % { - 'override_var' : self._override_var - , 'gstate_var' : self._gstate_var - , 'alias' : self.declaration.alias - , 'inherited' : self.create_base_body() - } + def args_override_declaration( self ): + return self.args_declaration() - def create_default_body(self): - cls_wrapper_type = self.parent.full_name - cls_wrapper = self._subst_manager.wrapper_func.declare_variable("cls_wrapper", cls_wrapper_type); - # The name of the 'self' variable (i.e. first argument) - selfname = self._subst_manager.wrapper_func.arg_list[0].name + def args_default_declaration( self ): + cntrl = self.controller.default_controller + arg_utils = calldef_utils.argument_utils_t( self.declaration + , algorithm.make_id_creator( self ) + , [cntrl.inst_arg] + cntrl.wrapper_args ) + return arg_utils.args_declaration() - body = """$DECLARATIONS + def default_function_type(self): + cntrl = self.controller.default_controller + args = [cntrl.inst_arg.type] + map( lambda arg: arg.type, cntrl.wrapper_args ) + return declarations.free_function_type_t( return_type=cntrl.wrapper_return_type + , arguments_types=args ) -$PRE_CALL + def create_default(self): + cntrl = self.controller.default_controller -%(cls_wrapper_type)s* %(cls_wrapper)s = dynamic_cast<%(cls_wrapper_type)s*>(boost::addressof(%(self)s)); -if (%(cls_wrapper)s==0) -{ - // The following call is done on an instance created in C++, - // so it won't invoke Python code. - $RESULT_VAR_ASSIGNMENT$CALL_FUNC_NAME($INPUT_PARAMS); -} -else -{ - // The following call is done on an instance created in Python, - // i.e. a wrapper instance. This call might invoke Python code. - $RESULT_VAR_ASSIGNMENT%(cls_wrapper)s->%(base_name)s($INPUT_PARAMS); -} + make_object = algorithm.create_identifier( self, 'pyplusplus::call_policies::make_object' ) + make_tuple = algorithm.create_identifier( self, 'boost::python::make_tuple' ) + + tmpl_values = dict() -$POST_CALL + tmpl_values['unique_function_name'] = self.default_name() + tmpl_values['return_type'] = cntrl.wrapper_return_type.decl_string + tmpl_values['arg_declarations'] = self.args_default_declaration() + tmpl_values['wrapper_class'] = self.parent.wrapper_alias + tmpl_values['wrapped_class'] = declarations.full_name( self.declaration.parent ) + tmpl_values['wrapped_inst'] = cntrl.inst_arg.name + + decl_vars = cntrl.variables[:] + if not declarations.is_void( self.declaration.return_type ): + decl_vars.append( cntrl.result_variable ) + tmpl_values['declare_variables'] \ + = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string() ) + , decl_vars ) ) + + tmpl_values['pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.pre_call ) ) -$RETURN_STMT -""" + tmpl_values['save_result'] = '' + if not declarations.is_void( self.declaration.return_type ): + tmpl_values['save_result'] = '%s = ' % cntrl.result_variable.name - # Replace the $-variables - body = self._subst_manager.subst_wrapper(body) + tmpl_values['function_name'] = self.declaration.name + tmpl_values['arg_expressions'] = self.PARAM_SEPARATOR.join( cntrl.arg_expressions ) + return_stmt_creator = calldef_utils.return_stmt_creator_t( self + , cntrl + , cntrl.result_variable + , cntrl.return_variables ) - # Replace the remaining parameters - body = body%{"cls_wrapper_type" : cls_wrapper_type, - "cls_wrapper" : cls_wrapper, - "self" : selfname, - "base_name" : self.base_name() } - return body + tmpl_values['post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.post_call ) ) + if return_stmt_creator.pre_return_code: + tmpl_values['post_call'] \ + = os.linesep.join([ tmpl_values['post_call'] + , self.indent( return_stmt_creator.pre_return_code )]) + tmpl_values['return'] = os.linesep + self.indent( return_stmt_creator.statement ) + + f_def = cntrl.template.substitute(tmpl_values) + return remove_duplicate_linesep( f_def ) - def create_function(self): - answer = [ self.create_declaration(self.declaration.name) + '{' ] - answer.append( self.indent( self.create_virtual_body() ) ) - answer.append( '}' ) - return os.linesep.join( answer ) + def wrapped_class_identifier( self ): + return algorithm.create_identifier( self, declarations.full_name( self.declaration.parent ) ) - def create_base_function( self ): - answer = [ self.create_declaration("base_"+self.declaration.name, False) + '{' ] - body = "%(return_)s%(wrapped_class)s::%(name)s( %(args)s );" - answer.append( self.indent( self.create_base_body() ) ) - answer.append( '}' ) - return os.linesep.join( answer ) + def create_override(self): + cntrl = self.controller.override_controller + + tmpl_values = dict() + tmpl_values['return_type' ] = self.declaration.return_type.decl_string + tmpl_values['function_name'] = self.declaration.name + tmpl_values['arg_declarations'] = self.args_override_declaration() + tmpl_values['constness'] = '' + if self.declaration.has_const: + tmpl_values['constness'] = ' const ' + tmpl_values['throw'] = self.throw_specifier_code() + tmpl_values['py_function_var'] = cntrl.py_function_var + tmpl_values['function_alias'] = self.declaration.alias + tmpl_values['declare_py_variables'] \ + = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string(), 2 ) + , cntrl.py_variables ) ) - def create_default_function( self ): + tmpl_values['py_pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.py_pre_call ), 2 ) + tmpl_values['py_post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.py_post_call ), 2 ) + tmpl_values['py_arg_expressions'] = '' + if cntrl.py_arg_expressions: + tmpl_values['py_arg_expressions'] \ + = ', ' + declarations.call_invocation.join( '', cntrl.py_arg_expressions ) + + tmpl_values['save_py_result'] = "bpl::object %s = " % cntrl.py_result_variable.name + tmpl_values['py_return'] = '' + tmpl_values['cpp_return'] = '' + if not declarations.is_void( self.declaration.return_type ): + tmpl_values['py_return'] \ + = 'return bpl::extract< %(type)s >( pyplus_conv::get_out_argument( %(py_result)s, 0 ) );' \ + % { 'type' : self.declaration.return_type.decl_string + , 'py_result' : cntrl.py_result_variable.name } + tmpl_values['cpp_return'] = 'return ' - header = 'static $RET_TYPE %s( $ARG_LIST_DEF ) {'%self.default_name() - header = self._subst_manager.subst_wrapper(header) + tmpl_values['wrapped_class'] = self.wrapped_class_identifier() - answer = [ header ] - answer.append( self.indent( self.create_default_body() ) ) - answer.append( '}' ) - return os.linesep.join( answer ) + arg_utils = calldef_utils.argument_utils_t( self.declaration + , algorithm.make_id_creator( self ) + , self.declaration.arguments ) + tmpl_values['cpp_arg_expressions'] = arg_utils.call_args() + f_def_code = cntrl.template.substitute(tmpl_values) + return remove_duplicate_linesep( f_def_code ) + def _create_impl(self): - - answer = [ self.create_function() ] - answer.append( os.linesep ) - answer.append( self.create_base_function() ) - answer.append( os.linesep ) - answer.append( self.create_default_function() ) - answer = os.linesep.join( answer ) - - # Replace the argument list of the declaration so that in the - # case that keywords are created, the correct arguments will be - # picked up (i.e. the modified argument list and not the original - # argument list) - self.declaration.arguments = self._subst_manager.wrapper_func.arg_list - - return answer - \ No newline at end of file + return os.linesep.join([ self.create_override(), '', self.create_default() ]) Modified: pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py 2006-11-30 11:20:24 UTC (rev 767) @@ -3,6 +3,8 @@ # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) +import os +import algorithm import code_creator from pygccxml import declarations from pyplusplus import decl_wrappers @@ -39,6 +41,8 @@ return False def keywords_args(self): + if not self.__args: + return '' boost_arg = self.__id_creator( '::boost::python::arg' ) boost_obj = self.__id_creator( '::boost::python::object' ) result = ['( '] @@ -86,8 +90,66 @@ def call_args( self ): params = [] for index, arg in enumerate( self.__args ): - params.append( decl_wrappers.python_traits.call_traits( arg.type ) % self.argument_name( index ) ) + params.append( decl_wrappers.python_traits.call_traits( arg.type ) + % self.argument_name( index ) ) return ', '.join( params ) +class return_stmt_creator_t( object ): + def __init__( self, creator, controller, result_var, return_vars ): + object.__init__( self ) + self.__creator = creator + self.__controller = controller + self.__function = controller.function + self.__return_vars = return_vars[:] + self.__pre_return_code = None + self.__return_stmt = None + self.__result_var = result_var + self.__call_policy_alias = controller.register_variable_name( 'call_policies_t' ) + + @property + def pre_return_code( self ): + if None is self.__pre_return_code: + if not self.__controller.return_variables \ + or self.__function.call_policies.is_default() \ + or declarations.is_void( self.__function.return_type ): + self.__pre_return_code = '' + else: + c_p_typedef = 'typedef %s %s;' \ + % ( self.__function.call_policies.create_template_arg( self.__creator ) + , self.__call_policy_alias ) + self.__pre_return_code = c_p_typedef + return self.__pre_return_code + @property + def statement( self ): + if None is self.__return_stmt: + stmt = '' + bpl_object = algorithm.create_identifier( self.__creator, 'boost::python::object' ) + make_tuple = algorithm.create_identifier( self.__creator, 'boost::python::make_tuple' ) + make_object = algorithm.create_identifier( self.__creator, 'pyplusplus::call_policies::make_object' ) + if not declarations.is_void( self.__function.return_type ): + if self.__function.call_policies.is_default(): + self.__return_vars.insert( 0, self.__result_var.name ) + else: + self.__return_vars.insert( 0 + , declarations.call_invocation.join( + declarations.templates.join( make_object, [self.__call_policy_alias] ) + , [self.__result_var.name] ) ) + + if 0 == len( self.__return_vars ): + pass + elif 1 == len( self.__return_vars ): + stmt = bpl_object + '( %s )' % self.__return_vars[ 0 ] + else: # 1 < + stmt = declarations.call_invocation.join( make_tuple, self.__return_vars ) + if self.__creator.LINE_LENGTH < len( stmt ): + stmt = declarations.call_invocation.join( + make_tuple + , self.__return_vars + , os.linesep + self.__creator.indent( self.__creator.PARAM_SEPARATOR, 6 ) ) + + if stmt: + stmt = 'return ' + stmt + ';' + self.__return_stmt = stmt + return self.__return_stmt Modified: pyplusplus_dev/pyplusplus/code_creators/declaration_based.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/declaration_based.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_creators/declaration_based.py 2006-11-30 11:20:24 UTC (rev 767) @@ -30,9 +30,13 @@ doc="""The declaration this code creator is based on. @type: L{decl_wrapper_t<decl_wrappers.decl_wrapper_t>} """) + + def _get_alias_impl( self ): + return self.declaration.alias def _get_alias(self): - return self.declaration.alias + return self._get_alias_impl() + def _set_alias(self, alias): self.declaration.alias = alias alias = property( _get_alias, _set_alias ) Modified: pyplusplus_dev/pyplusplus/code_repository/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/__init__.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_repository/__init__.py 2006-11-30 11:20:24 UTC (rev 767) @@ -15,10 +15,11 @@ import array_1 import gil_guard +import named_tuple import convenience import call_policies -all = [ array_1, gil_guard, convenience, call_policies ] +all = [ array_1, gil_guard, convenience, call_policies, named_tuple ] headers = map( lambda f: f.file_name, all ) Modified: pyplusplus_dev/pyplusplus/code_repository/call_policies.py =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/call_policies.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_repository/call_policies.py 2006-11-30 11:20:24 UTC (rev 767) @@ -70,6 +70,14 @@ }; +template< typename CallPolicies, class T > +bpl::object make_object( T const & x ){ + //constructs object using CallPolicies result_converter + typedef BOOST_DEDUCED_TYPENAME CallPolicies::result_converter:: template apply< T >::type result_converter_t; + result_converter_t rc; + return bpl::object( bpl::handle<>( rc( x ) ) ); +} + } /*pyplusplus*/ } /*call_policies*/ Modified: pyplusplus_dev/pyplusplus/code_repository/convenience.py =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/convenience.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_repository/convenience.py 2006-11-30 11:20:24 UTC (rev 767) @@ -135,8 +135,29 @@ return array_inserter_t<T>( array, size ); } +inline boost::python::object +get_out_argument( boost::python::object result, const char* arg_name ){ + if( PySequence_Check( result.ptr() ) ){ + return boost::python::getattr( result, arg_name ); + } + else{ + return result; + } +} + +inline boost::python::object +get_out_argument( boost::python::object result, index_type index ){ + if( PySequence_Check( result.ptr() ) ){ + return result[ index ]; + } + else{ + return result; + } +} + } /*pyplusplus*/ } /*convenience*/ +namespace pyplus_conv = pyplusplus::convenience; #endif//__convenience_pyplusplus_hpp__ Copied: pyplusplus_dev/pyplusplus/code_repository/named_tuple.py (from rev 765, pyplusplus_dev_ft/pyplusplus/code_repository/named_tuple.py) =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/named_tuple.py (rev 0) +++ pyplusplus_dev/pyplusplus/code_repository/named_tuple.py 2006-11-30 11:20:24 UTC (rev 767) @@ -0,0 +1,65 @@ +# 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) + +file_name = "named_tuple.py" + +code = \ +"""# 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) + +class named_tuple(tuple): + \"\"\"Creates tuple, which allows access to stored values by name and by index. + + named_tuple could be constructed exactly in the same way as Python dict. + \"\"\" + + def __new__(cls, seq=None, **keywd): + if seq: + if isinstance( seq, dict ): + return tuple.__new__( cls, seq.values() ) + else: + return tuple.__new__( cls, [ val for name, val in seq] ) + else: + return tuple.__new__( cls, keywd.values() ) + + def __init__(self, seq=None, **keywd): + "named_tuple could be constructed exactly in the same way as Python dict." + tuple.__init__( self ) + if seq: + if isinstance( seq, dict ): + name2value = dict( seq.iteritems() ) + else: + name2value = dict( seq ) + else: + name2value = dict( keywd ) + self.__dict__[ '__name2value' ] = name2value + + def __getattr__(self, name): + try: + return self.__dict__['__name2value'][ name ] + except KeyError: + raise AttributeError( "named_tuple has no attribute '%s'" % name ) + + def __setattr__(self, name, value): + raise AttributeError( "named_tuple has no attribute '%s'" % name ) + + def __getitem__( self, key ): + #TODO: it could be nice to support slicing. So the __getitem__ in case of + #slicing will return new named_tuple. + if isinstance( key, basestring ): + return self.__dict__['__name2value'][ key ] + else: + return super( named_tuple, self ).__getitem__( key ) + +if __name__ == '__main__': + nt = named_tuple( a=0, b=1) + assert nt.a == 0 and nt.b == 1 + a,b = nt + assert a == 0 and b == 1 + assert nt[ "a" ] == 0 and nt[ "b" ] == 1 + +""" Modified: pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py 2006-11-30 11:20:24 UTC (rev 767) @@ -98,6 +98,8 @@ from doc_extractor import doc_extractor_i from properties import property_t +from properties import property_recognizer_i +from properties import name_based_recognizer_t import python_traits @@ -147,3 +149,17 @@ def create_variable( self, *arguments, **keywords ): return variable_t(*arguments, **keywords) + +skip_messages = [ + "Py++ does not exports compiler generated constructors" + , 'Py++, by default, does not expose internal compilers declarations. Names of those declarations usually start with "__".' + , 'Py++, by default, does not expose internal declarations (those that gccxml say belong to "<internal>" header).' + , 'Py++, by default, does not expose compiler generated declarations.' + , 'Py++ can not expose private class.' + , 'Py++ will generate class wrapper - class contains definition of virtual or pure virtual member function' + , "Py++ doesn't expose private or protected member variables." + , "Py++ doesn't export private not virtual functions." + , "Py++ doesn't export private constructor." + , "Py++ doesn't export private operators." +] +#Messages kept by skip_messages list will not be reported Modified: pyplusplus_dev/pyplusplus/decl_wrappers/call_policies.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/call_policies.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/decl_wrappers/call_policies.py 2006-11-30 11:20:24 UTC (rev 767) @@ -38,6 +38,9 @@ code = code + '()' return code + def create_template_arg( self, function_creator ): + return self.create( function_creator, CREATION_POLICY.AS_TEMPLATE_ARGUMENT ) + def is_default( self ): """Returns True is self is instance of L{default_call_policies_t} class""" #Small hack that allows to write nicer code @@ -227,4 +230,4 @@ """returns True is policy represents return_value_policy<return_pointee_value>, False otherwise""" return isinstance( policy, return_value_policy_t ) \ and policy.result_converter_generator == return_pointee_value - \ No newline at end of file + Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-11-30 11:20:24 UTC (rev 767) @@ -168,10 +168,14 @@ if len( self.arguments ) > calldef_t.BOOST_PYTHON_MAX_ARITY: tmp = [ "The function has more than %d arguments ( %d ). " ] tmp.append( "You should adjust BOOST_PYTHON_MAX_ARITY macro." ) - tmp.append( "For more information see: http://mail.python.org/pipermail/c++-sig/2002-June/001554.html" ) + tmp.append( "For more information see: http://www.boost.org/libs/python/doc/v2/configuration.html" ) tmp = ' '.join( tmp ) msgs.append( tmp % ( calldef_t.BOOST_PYTHON_MAX_ARITY, len( self.arguments ) ) ) - + + if self.transformations: + #if user defined transformation, than I think it took care of the problems + return msgs + if suspicious_type( self.return_type ) and None is self.call_policies: msgs.append( 'The function "%s" returns non-const reference to C++ fundamental type - value can not be modified from Python.' % str( self ) ) Modified: pyplusplus_dev/pyplusplus/decl_wrappers/properties.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/properties.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/decl_wrappers/properties.py 2006-11-30 11:20:24 UTC (rev 767) @@ -58,11 +58,12 @@ class name_based_recognizer_t( property_recognizer_i ): def __init__( self ): property_recognizer_i.__init__( self ) - self.__prefixes = ( - ( 'is', 'set' ) - , ( 'get', 'set' ) - , ( 'has', 'set' ) - , ( '', 'set' ) ) + + def prefixes( self ): + return [ ( 'is', 'set' ) + , ( 'get', 'set' ) + , ( 'has', 'set' ) + , ( '', 'set' ) ] def check_prefix( self, name, prefix ): if not name.startswith( prefix ): @@ -105,7 +106,7 @@ , self.make_l_camel_convention ] for convention_maker in convention_makers: - for g, s in self.__prefixes: + for g, s in self.prefixes(): gc, sc = convention_maker( g, s ) if self.check_name_compatibility( gname, sname, gc, sc ): return ( gc, sc ) @@ -118,7 +119,7 @@ , self.make_l_camel_convention ] for convention_maker in convention_makers: - for g, unused in self.__prefixes: + for g, unused in self.prefixes(): if not g: continue gc, unused = convention_maker( g, 'set' ) Modified: pyplusplus_dev/pyplusplus/file_writers/writer.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/writer.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/file_writers/writer.py 2006-11-30 11:20:24 UTC (rev 767) @@ -50,7 +50,12 @@ for cr in code_repository.all: if self.__extmodule.is_system_header( cr.file_name ): self.write_file( os.path.join( dir, cr.file_name ), cr.code ) - + #temporal patch: always write named_tuple.py file + + f = file( os.path.join( dir, code_repository.named_tuple.file_name ), 'w+b' ) + f.write( code_repository.named_tuple.code ) + f.close() + @staticmethod def write_file( fpath, content ): """Write a source file. @@ -91,4 +96,4 @@ f.write( fcontent_new ) f.close() writer_t.logger.info( 'file "%s" - updated( %f seconds )' % ( fname, time.clock() - start_time ) ) - \ No newline at end of file + Modified: pyplusplus_dev/pyplusplus/function_transformers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/__init__.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/function_transformers/__init__.py 2006-11-30 11:20:24 UTC (rev 767) @@ -16,7 +16,6 @@ """ -from substitution_manager import substitution_manager_t from transformer import transformer_t import transformers from function_transformation import function_transformation_t Deleted: pyplusplus_dev/pyplusplus/function_transformers/code_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/code_manager.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/function_transformers/code_manager.py 2006-11-30 11:20:24 UTC (rev 767) @@ -1,254 +0,0 @@ -# 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 L{code_manager_t} and L{wrapper_code_manager_t} classes. -""" - -import os -import types -import string - -# code_manager_t -class code_manager_t: - """This class manages pieces of source code for a C++ function. - - The class mainly provides the interface for the code blocks to - manipulate a function and stores the actual substitution variables. - Each function has its own code manager instance. - - A code block can declare a local variable using L{declare_variable()} - and it can manipulate one of the attributes that are used to - initialize the final variables (see the documentation of the - instance variables below). The final variables (such as RET_TYPE, - FUNC_NAME, ARG_LIST, etc.) are stored as regular attributes of the - object. - - The functionality to perform a text substitution (using the - substitution() method) is inherited - from the class L{subst_t}. - - @ivar class_name: The name of the class of which the generated function is a member. A value of None or an empty string is used for free functions. This attribute is used for creating the CLASS_SPEC variable. - @type class_name: str - @ivar ret_type: Return type. The value may be any object where str(obj) is valid C++ code. The value None corresponds to void. This will be the value of the variable RET_TYPE. - @type ret_type: str - @ivar arg_list: The argument list. The items are pygccxml argument_t objects. This list will appear in the variables ARG_LIST, ARG_LIST_DEF and ARG_LIST_TYPES. - @type arg_list: list of L{argument_t<pygccxml.declarations.calldef.argument_t>} - @ivar input_params: A list of strings that contain the input parameter for the function call. This list is used for the INPUT_PARAMS variable. - @type input_params: list of str - @ivar result_var: The name of the variable that will receive the result of the function call. If None, th... [truncated message content] |
From: <rom...@us...> - 2006-11-30 13:56:26
|
Revision: 770 http://svn.sourceforge.net/pygccxml/?rev=770&view=rev Author: roman_yakovenko Date: 2006-11-30 05:56:21 -0800 (Thu, 30 Nov 2006) Log Message: ----------- adding dependencies manager Modified Paths: -------------- pyplusplus_dev/pyplusplus/module_creator/creator.py Added Paths: ----------- pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py Property Changed: ---------------- pyplusplus_dev/unittests/ Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-11-30 13:47:13 UTC (rev 769) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-11-30 13:56:21 UTC (rev 770) @@ -6,6 +6,7 @@ import types_database import creators_wizard import sort_algorithms +import dependencies_manager import opaque_types_manager import call_policies_resolver from pygccxml import declarations @@ -127,7 +128,9 @@ self.__exposed_free_fun_overloads = set() self.__opaque_types_manager = opaque_types_manager.manager_t( self.__extmodule ) self.__return_pointee_value_exists = False - + + self.__dependencies_manager = dependencies_manager.manager_t(self.decl_logger) + def _prepare_decls( self, decls, doc_extractor ): decls = declarations.make_flatten( decls ) @@ -181,6 +184,7 @@ and operator is creator.declaration , creator.creators ): #expose operator only once + self.__dependencies_manager.add_exported( operator ) creator.adopt_creator( code_creators.operator_t( operator=operator ) ) elif not creator: pass @@ -302,6 +306,7 @@ used_headers.add( isuite[ container_name ] ) cls_creator = create_cls_cc( cls ) + self.__dependencies_manager.add_exported( cls ) creators.append( cls_creator ) try: element_type = cls.indexing_suite.element_type @@ -370,6 +375,7 @@ creator.target_configuration = self.__target_configuration #last action. self._append_user_code() + self.__dependencies_manager.inform_user() return self.__extmodule def _create_includes(self): @@ -380,6 +386,7 @@ def visit_member_function( self ): fwrapper = None self.__types_db.update( self.curr_decl ) + self.__dependencies_manager.add_exported( self.curr_decl ) if None is self.curr_decl.call_policies: self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) self.__on_demand_include_call_policies( self.curr_decl.call_policies ) @@ -436,6 +443,7 @@ if self.curr_decl.is_copy_constructor: return self.__types_db.update( self.curr_decl ) + self.__dependencies_manager.add_exported( self.curr_decl ) if self.curr_decl.allow_implicit_conversion: maker = code_creators.casting_constructor_t( constructor=self.curr_decl ) self.__module_body.adopt_creator( maker ) @@ -461,8 +469,10 @@ self.__types_db.update( self.curr_decl ) maker = code_creators.operator_t( operator=self.curr_decl ) self.curr_code_creator.adopt_creator( maker ) + self.__dependencies_manager.add_exported( self.curr_decl ) def visit_casting_operator( self ): + self.__dependencies_manager.add_exported( self.curr_decl ) if None is self.curr_decl.call_policies: self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) self.__on_demand_include_call_policies( self.curr_decl.call_policies ) @@ -494,6 +504,7 @@ self.__exposed_free_fun_overloads.update( overloads ) for f in overloads: self.__types_db.update( f ) + self.__dependencies_manager.add_exported( f ) if None is f.call_policies: f.call_policies = self.__call_policies_resolver( f ) self.__on_demand_include_call_policies( f.call_policies ) @@ -514,6 +525,7 @@ overloads_reg.associated_decl_creators.extend( uc_creators ) else: self.__types_db.update( self.curr_decl ) + self.__dependencies_manager.add_exported( self.curr_decl ) if None is self.curr_decl.call_policies: self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) self.__on_demand_include_call_policies( self.curr_decl.call_policies ) @@ -557,6 +569,7 @@ for f in overloads: self.__types_db.update( f ) + self.__dependencies_manager.add_exported( f ) if None is f.call_policies: f.call_policies = self.__call_policies_resolver( f ) self.__on_demand_include_call_policies( f.call_policies ) @@ -572,7 +585,7 @@ return exposed def visit_class(self ): - assert isinstance( self.curr_decl, declarations.class_t ) + self.__dependencies_manager.add_exported( self.curr_decl ) cls_decl = self.curr_decl cls_parent_cc = self.curr_code_creator exportable_members = self.curr_decl.get_exportable_members(sort_algorithms.sort) @@ -643,7 +656,7 @@ def visit_enumeration(self): - assert isinstance( self.curr_decl, declarations.enumeration_t ) + self.__dependencies_manager.add_exported( self.curr_decl ) maker = None if self.curr_decl.name: maker = code_creators.enum_t( enum=self.curr_decl ) @@ -667,7 +680,8 @@ def visit_variable(self): self.__types_db.update( self.curr_decl ) - + self.__dependencies_manager.add_exported( self.curr_decl ) + if declarations.is_array( self.curr_decl.type ): if not self.__cr_array_1_included: self.__extmodule.add_system_header( code_repository.array_1.file_name ) Added: pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py (rev 0) +++ pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2006-11-30 13:56:21 UTC (rev 770) @@ -0,0 +1,76 @@ +# 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) + +from pygccxml import declarations +from pyplusplus import decl_wrappers + +class manager_t( object ): + def __init__( self, logger ): + object.__init__( self ) + self.__exported_decls = [] + self.__logger = logger + + def add_exported( self, decl ): + self.__exported_decls.append( decl ) + + def __is_std_decl( self, decl ): + if not decl.parent: + return False + + if not isinstance( decl.parent, declarations.namespace_t ): + return False + + if 'std' != decl.parent.name: + return False + + ns_std = decl.parent + if not ns_std.parent: + return False + + if not isinstance( ns_std.parent, declarations.namespace_t ): + return False + + if '::' != ns_std.parent.name: + return False + + global_ns = ns_std.parent + if global_ns.parent: + return False + + if decl.name.startswith( 'pair<' ): + #special case + return False + return True + + def __build_dependencies( self, decl ): + if self.__is_std_decl( decl ): + return [] #std declarations should be exported by Py++! + return decl.i_depend_on_them() + + def __find_out_used_but_not_exported( self ): + used_not_exported = [] + exported_ids = set( map( lambda d: id( d ), self.__exported_decls ) ) + for decl in self.__exported_decls: + for dependency in self.__build_dependencies( decl ): + depend_on_decl = dependency.find_out_depend_on_declaration() + if None is depend_on_decl: + continue + if self.__is_std_decl( depend_on_decl ): + continue + if isinstance( depend_on_decl, declarations.class_types ) and depend_on_decl.opaque: + continue + if id( depend_on_decl ) not in exported_ids: + used_not_exported.append( dependency ) + return used_not_exported + + def __create_msg( self, dependency ): + reason = 'The declaration depends on unexposed declaration "%s".' \ + % dependency.find_out_depend_on_declaration() + return "%s;%s" % ( dependency.declaration, reason ) + + def inform_user( self ): + used_not_exported_decls = self.__find_out_used_but_not_exported() + for used_not_exported in used_not_exported_decls: + self.__logger.warn( self.__create_msg( used_not_exported ) ) Property changes on: pyplusplus_dev/unittests ___________________________________________________________________ Name: svn:ignore + *.pyc This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-11-30 18:49:19
|
Revision: 771 http://svn.sourceforge.net/pygccxml/?rev=771&view=rev Author: roman_yakovenko Date: 2006-11-30 10:49:18 -0800 (Thu, 30 Nov 2006) Log Message: ----------- fixing small bug Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py pyplusplus_dev/unittests/function_transformations_tester.py Added Paths: ----------- pyplusplus_dev/unittests/temp/named_tuple.py Modified: pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py 2006-11-30 13:56:21 UTC (rev 770) +++ pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py 2006-11-30 18:49:18 UTC (rev 771) @@ -253,20 +253,17 @@ def controller( self ): return self.ft.controller + @property + def function_type_alias( self ): + return 'default_' + self.alias + '_function_type' + def _get_alias_impl( self ): return self.wrapper.ft.alias def create_function_type_alias_code( self, exported_class_alias=None ): - result = [] + ftype = self.wrapper.default_function_type() + return 'typedef %s;' % ftype.create_typedef( self.function_type_alias ) - ftype = self.declaration.function_type() - result.append( 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) ) - if self.wrapper: - result.append( os.linesep ) - ftype = self.wrapper.function_type() - result.append( 'typedef %s;' % ftype.create_typedef( self.default_function_type_alias ) ) - return ''.join( result ) - def create_keywords_args(self): cntrl = self.controller.default_controller arg_utils = calldef_utils.argument_utils_t( self.declaration Modified: pyplusplus_dev/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev/unittests/function_transformations_tester.py 2006-11-30 13:56:21 UTC (rev 770) +++ pyplusplus_dev/unittests/function_transformations_tester.py 2006-11-30 18:49:18 UTC (rev 771) @@ -48,6 +48,7 @@ point3d.mem_fun( 'distance' ).add_transformation( ft.output(1) ) image = mb.class_( "image_t" ) + image.always_expose_using_scope = True image.member_function( "get_size" ) image.member_function( "get_size" ).add_transformation( ft.output(0), ft.output(1) ) image.member_function( "get_one_value" ).add_transformation( ft.output(0) ) Added: pyplusplus_dev/unittests/temp/named_tuple.py =================================================================== --- pyplusplus_dev/unittests/temp/named_tuple.py (rev 0) +++ pyplusplus_dev/unittests/temp/named_tuple.py 2006-11-30 18:49:18 UTC (rev 771) @@ -0,0 +1,56 @@ +# 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) + +class named_tuple(tuple): + """Creates tuple, which allows access to stored values by name and by index. + + named_tuple could be constructed exactly in the same way as Python dict. + """ + + def __new__(cls, seq=None, **keywd): + if seq: + if isinstance( seq, dict ): + return tuple.__new__( cls, seq.values() ) + else: + return tuple.__new__( cls, [ val for name, val in seq] ) + else: + return tuple.__new__( cls, keywd.values() ) + + def __init__(self, seq=None, **keywd): + "named_tuple could be constructed exactly in the same way as Python dict." + tuple.__init__( self ) + if seq: + if isinstance( seq, dict ): + name2value = dict( seq.iteritems() ) + else: + name2value = dict( seq ) + else: + name2value = dict( keywd ) + self.__dict__[ '__name2value' ] = name2value + + def __getattr__(self, name): + try: + return self.__dict__['__name2value'][ name ] + except KeyError: + raise AttributeError( "named_tuple has no attribute '%s'" % name ) + + def __setattr__(self, name, value): + raise AttributeError( "named_tuple has no attribute '%s'" % name ) + + def __getitem__( self, key ): + #TODO: it could be nice to support slicing. So the __getitem__ in case of + #slicing will return new named_tuple. + if isinstance( key, basestring ): + return self.__dict__['__name2value'][ key ] + else: + return super( named_tuple, self ).__getitem__( key ) + +if __name__ == '__main__': + nt = named_tuple( a=0, b=1) + assert nt.a == 0 and nt.b == 1 + a,b = nt + assert a == 0 and b == 1 + assert nt[ "a" ] == 0 and nt[ "b" ] == 1 + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-06 07:27:03
|
Revision: 779 http://svn.sourceforge.net/pygccxml/?rev=779&view=rev Author: roman_yakovenko Date: 2006-12-05 23:27:03 -0800 (Tue, 05 Dec 2006) Log Message: ----------- adding new functionality - "pragma warning disable" :-) User now can filter messages, reported by Py++ per declaration basis Modified Paths: -------------- pyplusplus_dev/pyplusplus/__init__.py pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py pyplusplus_dev/pyplusplus/messages/__init__.py pyplusplus_dev/pyplusplus/module_creator/creator.py pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py pyplusplus_dev/unittests/smart_pointers_tester.py Modified: pyplusplus_dev/pyplusplus/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/__init__.py 2006-12-05 21:36:37 UTC (rev 778) +++ pyplusplus_dev/pyplusplus/__init__.py 2006-12-06 07:27:03 UTC (rev 779) @@ -30,6 +30,7 @@ import utils import decl_wrappers import module_builder +import messages from _logging_ import multi_line_formatter_t Modified: pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py 2006-12-05 21:36:37 UTC (rev 778) +++ pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py 2006-12-06 07:27:03 UTC (rev 779) @@ -148,18 +148,3 @@ def create_variable( self, *arguments, **keywords ): return variable_t(*arguments, **keywords) - - -skip_messages = [ - "Py++ does not exports compiler generated constructors" - , 'Py++, by default, does not expose internal compilers declarations. Names of those declarations usually start with "__".' - , 'Py++, by default, does not expose internal declarations (those that gccxml say belong to "<internal>" header).' - , 'Py++, by default, does not expose compiler generated declarations.' - , 'Py++ can not expose private class.' - , 'Py++ will generate class wrapper - class contains definition of virtual or pure virtual member function' - , "Py++ doesn't expose private or protected member variables." - , "Py++ doesn't export private not virtual functions." - , "Py++ doesn't export private constructor." - , "Py++ doesn't export private operators." -] -#Messages kept by skip_messages list will not be reported Modified: pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-12-05 21:36:37 UTC (rev 778) +++ pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-12-06 07:27:03 UTC (rev 779) @@ -28,6 +28,7 @@ self._exportable = None self._exportable_reason = None self._documentation = None + self.__msgs_to_ignore = set() @property def logger( self ): @@ -114,14 +115,34 @@ def _readme_impl( self ): return [] - def readme( self ): + + def readme( self, skip_ignored=True ): """This function will returns some hints/tips/description of problems that applied to the declarations. For example function that has argument reference to some fundamental type could be exported, but could not be called from Python + + @param skip_ignored: if True, messages that user asked to not reported + will not be returned """ - text = [] + msgs = [] if not self.exportable: - text.append( self.why_not_exportable() ) - text.extend( self._readme_impl() ) - return text + msgs.append( self.why_not_exportable() ) + msgs.extend( self._readme_impl() ) + return messages.filter_disabled_msgs( msgs, self.__msgs_to_ignore ) + + @property + def disabled_messaged( self ): + return self.__msgs_to_ignore + + def disable_messages( self, *args ): + """Using this method you can tell to Py++ to not report some specifiec warnings. + + Usage example: decl.ignore_warnings( messages.W1001, messages.W1040 ) + """ + for msg in args: + msg_id = messages.find_out_message_id( msg ) + if not msg_id: + raise RuntimeError( "Unable to find out message id. The message is: " + msg ) + self.__msgs_to_ignore.add( msg ) + disable_warnings = disable_messages Modified: pyplusplus_dev/pyplusplus/messages/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/messages/__init__.py 2006-12-05 21:36:37 UTC (rev 778) +++ pyplusplus_dev/pyplusplus/messages/__init__.py 2006-12-06 07:27:03 UTC (rev 779) @@ -6,122 +6,41 @@ """This package defines all user messages( warnings + errors ), which will be reported to user. """ +from warnings_ import * -W1000 = 'Py++, by default, does not expose internal compilers declarations.'\ - 'Names of those declarations usually start with "__".' +import re +__RE_GET_WARNING_ID = re.compile( r'warning\s(?P<id>W(\d){4})' ) +def find_out_message_id( msg ): + match_obj = __RE_GET_WARNING_ID.search(msg) + if not match_obj: + return None + else: + return match_obj.group( 'id' ) -W1001 = 'Py++, by default, does not expose internal declarations. ' \ - 'GCC-XML reports that these declaration belong to "<internal>" header.' -W1002 = 'Py++, by default, does not expose compiler generated declarations.' +DISABLE_MESSAGES = [ + W1000, W1001, W1002, W1011, W1012, W1013, W1015, W1019, W1030, W1034, W1039 +] +#Messages kept by DISABLE_MESSAGES list will not be reported -W1003 = 'Virtual functions that returns const reference can not be overriden from Python. ' \ - 'Reason: boost::python::override::operator()(...) saves the result of the marshaling ' \ - '(from Python to C++) on the stack. Thus operator() returns reference ' \ - 'to a temporary variable. Consider to use "Function Transformation" functionality ' \ - 'to solve the problem.' -W1004 = 'Boost.Python library can not expose function, which takes as argument/returns ' \ - 'pointer to function. ' \ - ' See http://www.boost.org/libs/python/doc/v2/faq.html#funcptr for more information.' +def filter_disabled_msgs( msgs, disable_messages=None ): + report = [] + + skip_them = DISABLE_MESSAGES[:] + if disable_messages: + skip_them.extend( disable_messages ) + + skip_them = filter( None, map( find_out_message_id, skip_them ) ) -W1005 = 'Py++ can not expose function that takes as argument/returns instance of non public class. ' \ - 'Generated code will not compile.' + for msg in msgs: + msg_id = find_out_message_id( msg ) + if msg_id and msg_id not in skip_them: + report.append( msg ) -W1006 = 'Py++ need your help to expose function that takes as argument/returns C++ arrays. ' \ - 'Take a look on "Function Transformation" functionality and define the transformation.' + return report -W1007 = 'The function has more than %d arguments ( %d ). ' \ - 'You should adjust BOOST_PYTHON_MAX_ARITY macro. ' \ - 'For more information see: http://www.boost.org/libs/python/doc/v2/configuration.html' -W1008 = 'The function returns non-const reference to "Python immutable" type. ' \ - 'The value can not be modified from Python. ' -W1009 = 'The function takes as argument (name=%s, pos=%d ) non-const reference ' \ - 'to Python immutable type - function could not be called from Python. ' \ - 'Take a look on "Function Transformation" functionality and define the transformation.' -W1010 = 'The function introduces registration order problem. ' \ - 'For more information about the problem read next document: ' \ - 'http://language-binding.net/pyplusplus/documentation/functions/registration_order.html ' \ - 'Problematic functions list: %s' -W1011 = "Py++ doesn't export private not virtual functions." - -W1012 = 'Py++ does not exports compiler generated constructors.' - -W1013 = "Py++ doesn't export private constructor." - -W1014 = '"%s" is not supported. ' \ - 'See Boost.Python documentation: http://www.boost.org/libs/python/doc/v2/operators.html#introduction.' - -W1015 = "Py++ doesn't export private operators." - -W1016 = 'Py++ does not exports non-const casting operators with user defined type as return value. ' \ - 'This could be change in future.' - -W1017 = "Py++ doesn't export non-public casting operators." - -W1018 = 'Py++ can not expose unnamed classes.' - -W1019 = 'Py++ can not expose private class.' - -W1020 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class" - -W1021 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class null constructor body" - -W1022 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class copy constructor body" - -W1023 = "Py++ will generate class wrapper - there are few functions that should be redefined in class wrapper" - -W1024 = "Py++ will generate class wrapper - class contains bit field member variable" - -W1025 = "Py++ will generate class wrapper - class contains T* member variable" - -W1026 = "Py++ will generate class wrapper - class contains T& member variable" - -W1027 = "Py++ will generate class wrapper - class contains array member variable" - -W1028 = "Py++ will generate class wrapper - class contains definition of nested class that requires wrapper class" - -W1029 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class constructor body" - -W1030 = "Py++ will generate class wrapper - class contains definition of virtual or pure virtual member function" - -W1031 = "Py++ will generate class wrapper - user asked to expose non - public member function" - -W1032 = "Boost.Python library does not support enums with duplicate values. " \ - "You can read more about this here: " \ - "http://boost.org/libs/python/todo.html#support-for-enums-with-duplicate-values . " \ - "The quick work around is to add new class variable to the exported enum, from Python. " - -W1033 = "Py++ can not expose unnamed variables" - -W1034 = "Py++ can not expose alignement bit." - -W1035 = "Py++ can not expose static pointer member variables. This could be changed in future." - -W1036 = "Py++ can not expose pointer to Python immutable member variables. This could be changed in future." - -W1037 = "Boost.Python library can not expose variables, which are pointer to function." \ - " See http://www.boost.org/libs/python/doc/v2/faq.html#funcptr for more information." - -W1038 = "Py++ can not expose variables of with unnamed type." - -W1039 = "Py++ doesn't expose private or protected member variables." - -W1040 = 'The declaration is unexposed, but there are other declarations, which refer to it.' \ - 'This could cause "no to_python converter found" run time error.' \ - 'Declarations: %s' - - - - - - - - - - - Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-12-05 21:36:37 UTC (rev 778) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-12-06 07:27:03 UTC (rev 779) @@ -152,7 +152,7 @@ if doc_extractor and decl.exportable: decl.documentation = doc_extractor( decl ) - readme = filter( lambda msg: msg not in decl_wrappers.skip_messages, decl.readme() ) + readme = decl.readme() if not readme: continue Modified: pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2006-12-05 21:36:37 UTC (rev 778) +++ pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2006-12-06 07:27:03 UTC (rev 779) @@ -71,7 +71,9 @@ if isinstance( depend_on_decl, declarations.class_types ) and depend_on_decl.opaque: continue if id( depend_on_decl ) not in exported_ids: - used_not_exported.append( dependency ) + report = messages.filter_disabled_msgs([messages.W1040], depend_on_decl.disabled_messaged ) + if report: + used_not_exported.append( dependency ) return used_not_exported def __group_by_unexposed( self, dependencies ): Modified: pyplusplus_dev/unittests/smart_pointers_tester.py =================================================================== --- pyplusplus_dev/unittests/smart_pointers_tester.py 2006-12-05 21:36:37 UTC (rev 778) +++ pyplusplus_dev/unittests/smart_pointers_tester.py 2006-12-06 07:27:03 UTC (rev 779) @@ -8,6 +8,7 @@ import unittest import fundamental_tester_base from pyplusplus import code_creators +from pyplusplus import messages class tester_t(fundamental_tester_base.fundamental_tester_base_t): EXTENSION_NAME = 'smart_pointers' @@ -20,7 +21,8 @@ def customize( self, mb ): base = mb.class_( 'base' ) - #base.held_type = '' + shared_ptrs = mb.decls( lambda decl: decl.name.startswith( 'shared_ptr<' ) ) + shared_ptrs.disable_warnings( messages.W1040 ) def create_py_derived( self, module ): class py_derived_t( module.base ): @@ -90,4 +92,4 @@ unittest.TextTestRunner(verbosity=2).run( create_suite() ) if __name__ == "__main__": - run_suite() \ No newline at end of file + run_suite() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-06 10:24:41
|
Revision: 782 http://svn.sourceforge.net/pygccxml/?rev=782&view=rev Author: roman_yakovenko Date: 2006-12-06 02:24:40 -0800 (Wed, 06 Dec 2006) Log Message: ----------- updating documentation + small convenience function to disable warnings Modified Paths: -------------- pyplusplus_dev/docs/documentation/feedback.rest pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py pyplusplus_dev/pyplusplus/messages/__init__.py Property Changed: ---------------- pyplusplus_dev/pyplusplus/messages/ Modified: pyplusplus_dev/docs/documentation/feedback.rest =================================================================== --- pyplusplus_dev/docs/documentation/feedback.rest 2006-12-06 10:17:51 UTC (rev 781) +++ pyplusplus_dev/docs/documentation/feedback.rest 2006-12-06 10:24:40 UTC (rev 782) @@ -40,20 +40,34 @@ * .. code-block:: C++ - struct window{ - ... - void get_size( int& heght, int& widht ) const; - }; + struct window{ + ... + void get_size( int& heght, int& widht ) const; + }; Member function ``get_size`` can be exposed to Python, but it will not be callable because [FILL IN HERE]. * In order to expose free/member function that takes more than 10 arguments user should define ``BOOST_PYTHON_MAX_ARITY`` macro. - + +* + .. code-block:: C++ + + struct X{ + ... + }; + + void do_smth( X x ); + + If you expose ``do_smth`` function and don't expose struct ``X``, `Py++`_ + will tell you that struct ``X`` is used in exported declaration, but was not + exposed. + For these problems and many other `Py++`_ gives a nice explanation and sometimes a link to the relevant information on the Internet. -I hope, that from now you will find it helpful to read every `Py++`_ message :-). +I don't know what about you, but I found these messages pretty useful. They allow +me to deliver Python bindings with higher quality. ------------- How it works? @@ -68,10 +82,54 @@ default, messages with ``DEBUG`` level will be skipped, all other messages will be reported. +-------- +Warnings +-------- + +Example of the warning: +:: + + WARNING: containers::item_t [struct] + > warning W1020: Py++ will generate class wrapper - hand written code + > should be added to the wrapper class + +Almost every warning reported by `Py++`_ consists from 3 parts: + +* description of the declaration it refers to: "containers::item_t [struct]" + +* warning unique identifier: "W1020" + +* short explanation of the problem: "Py++ will generate class wrapper - hand + written code should be added to the wrapper class" + --------------- API Description --------------- +How to disable warning(s)? +-------------------------- + +Every warning has unique identifier. In the example I gave it was ``W1020``. + +.. code-block:: Python + + from pyplusplus import messages + from pyplusplus import module_builder + + mb = module_builder.module_builder_t( ... ) + xyz = mb.class_( XYZ ) + xyz.disable_warnings( messages.W1020 ) + +It is also possible to disable warnings for all declarations. ``pyplusplus.messages`` +package defines ``DISABLE_MESSAGES`` variable. This variable( ``list`` ) keeps +all warnings, which should not be reported. Use ``messages.disable`` function to +edit it: + +.. code-block:: Python + + messages.disable( messages.W1020 ) + + Logging API ----------- Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-12-06 10:17:51 UTC (rev 781) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-12-06 10:24:40 UTC (rev 782) @@ -153,7 +153,8 @@ return False type_no_ref = declarations.remove_reference( type_ ) return not declarations.is_const( type_no_ref ) \ - and python_traits.is_immutable( type_no_ref ) + and ( declarations.is_fundamental( type_no_ref ) + or declarations.is_enum( type_no_ref ) ) msgs = [] #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 Property changes on: pyplusplus_dev/pyplusplus/messages ___________________________________________________________________ Name: svn:ignore + *.pyc Modified: pyplusplus_dev/pyplusplus/messages/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/messages/__init__.py 2006-12-06 10:17:51 UTC (rev 781) +++ pyplusplus_dev/pyplusplus/messages/__init__.py 2006-12-06 10:24:40 UTC (rev 782) @@ -23,6 +23,8 @@ ] #Messages kept by DISABLE_MESSAGES list will not be reported +def disable( *args ): + DISABLE_MESSAGES.extend( args ) def filter_disabled_msgs( msgs, disable_messages=None ): report = [] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-10 06:27:22
|
Revision: 788 http://svn.sourceforge.net/pygccxml/?rev=788&view=rev Author: roman_yakovenko Date: 2006-12-09 22:27:20 -0800 (Sat, 09 Dec 2006) Log Message: ----------- adding smart ptr work around for member variables Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/member_variable.py pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py pyplusplus_dev/unittests/data/smart_pointers_to_be_exported.hpp pyplusplus_dev/unittests/smart_pointers_tester.py Modified: pyplusplus_dev/pyplusplus/code_creators/member_variable.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/member_variable.py 2006-12-08 19:47:42 UTC (rev 787) +++ pyplusplus_dev/pyplusplus/code_creators/member_variable.py 2006-12-10 06:27:20 UTC (rev 788) @@ -95,7 +95,7 @@ tmpl = '%(access)s( "%(alias)s", &%(name)s%(doc)s )' access = 'def_readwrite' - if self.is_read_only(): + if self.declaration.is_read_only: access = 'def_readonly' doc = '' if self.documentation: @@ -103,38 +103,56 @@ result = tmpl % { 'access' : access , 'alias' : self.alias - , 'name' : algorithm.create_identifier( self, self.declaration.decl_string ) + , 'name' : self.decl_identifier , 'doc' : doc } return result - def is_read_only( self ): - type_ = declarations.remove_alias( self.declaration.type ) - if declarations.is_pointer( type_ ): - type_ = declarations.remove_pointer( type_ ) - return isinstance( type_, declarations.const_t ) + def _generate_for_smart_ptr( self ): + doc = '' + add_property = '' + make_getter = algorithm.create_identifier( self, '::boost::python::make_getter') + make_setter = algorithm.create_identifier( self, '::boost::python::make_setter') + if self.declaration.type_qualifiers.has_static: + add_property = 'add_static_property' + else: + if self.documentation: + doc = self.documentation + add_property = 'add_property' + add_property_args = [ '"%s"' % self.alias ] + getter_code = declarations.call_invocation.join( + make_getter + , [ '&' + self.decl_identifier + , self.declaration.getter_call_policies.create( self ) ] + , os.linesep + self.indent( self.PARAM_SEPARATOR, 6) ) + + add_property_args.append( getter_code ) + if not self.declaration.is_read_only: + setter_code = '' + setter_args = [ '&' + self.decl_identifier ] + if self.declaration.setter_call_policies \ + and not self.declaration.setter_call_policies.is_default(): + setter_args.append( self.declaration.setter_call_policies.create( self ) ) + setter_code = declarations.call_invocation.join( + make_setter + , setter_args + , os.linesep + self.indent( self.PARAM_SEPARATOR, 6) ) + add_property_args.append( setter_code) + if doc: + add_property_args.append( doc ) + return declarations.call_invocation.join( + add_property + , add_property_args + , os.linesep + self.indent( self.PARAM_SEPARATOR, 4 ) ) - if declarations.is_reference( type_ ): - type_ = declarations.remove_reference( type_ ) - - if isinstance( type_, declarations.const_t ): - return True - - if isinstance( type_, declarations.declarated_t ) \ - and isinstance( type_.declaration, declarations.class_t ) \ - and not declarations.has_public_assign( type_.declaration ): - return True - return False - - def _generate_variable( self ): + def _create_impl( self ): if declarations.is_pointer( self.declaration.type ): return self._generate_for_pointer() + elif self.declaration.apply_smart_ptr_wa: + return self._generate_for_smart_ptr() else: return self._generate_for_none_pointer() - def _create_impl(self): - return self._generate_variable() - class member_variable_wrapper_t( code_creator.code_creator_t , declaration_based.declaration_based_t ): """ Modified: pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py 2006-12-08 19:47:42 UTC (rev 787) +++ pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py 2006-12-10 06:27:20 UTC (rev 788) @@ -6,9 +6,10 @@ """defines class that configure global and member variable exposing""" import decl_wrapper +import python_traits +import call_policies from pyplusplus import messages from pygccxml import declarations -from pyplusplus.decl_wrappers import python_traits class variable_t(decl_wrapper.decl_wrapper_t, declarations.variable_t): """defines a set of properties, that will instruct Py++ how to expose the variable""" @@ -17,6 +18,8 @@ decl_wrapper.decl_wrapper_t.__init__( self ) self._getter_call_policies = None self._setter_call_policies = None + self._apply_smart_ptr_wa = False + self._is_read_only = None __call_policies_doc__ = \ """There are usecase, when exporting member variable forces Py++ to @@ -29,6 +32,14 @@ """ def get_getter_call_policies( self ): + if None is self._getter_call_policies: + if self.apply_smart_ptr_wa: + value_policy = '' + if self.is_read_only: + value_policy = call_policies.copy_const_reference + else: + value_policy = call_policies.copy_non_const_reference + self._getter_call_policies = call_policies.return_value_policy( value_policy ) return self._getter_call_policies def set_getter_call_policies( self, call_policies ): self._getter_call_policies = call_policies @@ -36,12 +47,55 @@ , doc=__call_policies_doc__ ) def get_setter_call_policies( self ): + if None is self._getter_call_policies: + if self.apply_smart_ptr_wa: + self._setter_call_policies = call_policies.default_call_policies() return self._setter_call_policies def set_setter_call_policies( self, call_policies ): self._setter_call_policies = call_policies setter_call_policies = property( get_setter_call_policies, set_setter_call_policies , doc=__call_policies_doc__ ) + def get_apply_smart_ptr_wa( self ): + return self._apply_smart_ptr_wa + def set_apply_smart_ptr_wa( self, value): + self._apply_smart_ptr_wa = value + apply_smart_ptr_wa = property( get_apply_smart_ptr_wa, set_apply_smart_ptr_wa + , doc="" ) + + + def __find_out_is_read_only(self): + type_ = declarations.remove_alias( self.type ) + + if isinstance( type_, declarations.const_t ): + return True + + if declarations.is_pointer( type_ ): + type_ = declarations.remove_pointer( type_ ) + + if declarations.is_reference( type_ ): + type_ = declarations.remove_reference( type_ ) + + if isinstance( type_, declarations.const_t ): + return True + + if self.apply_smart_ptr_wa: + return False #all smart pointers has assign operator + + if isinstance( type_, declarations.declarated_t ) \ + and isinstance( type_.declaration, declarations.class_t ) \ + and not declarations.has_public_assign( type_.declaration ): + return True + return False + + def get_is_read_only( self ): + if None is self._is_read_only: + self._is_read_only = self.__find_out_is_read_only() + return self._is_read_only + def set_is_read_only( self, v ): + self._is_read_only = v + is_read_only = property( get_is_read_only, set_is_read_only ) + def _exportable_impl( self ): if not self.name: return messages.W1033 Modified: pyplusplus_dev/unittests/data/smart_pointers_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/smart_pointers_to_be_exported.hpp 2006-12-08 19:47:42 UTC (rev 787) +++ pyplusplus_dev/unittests/data/smart_pointers_to_be_exported.hpp 2006-12-10 06:27:20 UTC (rev 788) @@ -1,56 +1,56 @@ -// 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) - -#ifndef __smart_pointers_to_be_exported_hpp__ -#define __smart_pointers_to_be_exported_hpp__ -#include <memory> -#include "boost/shared_ptr.hpp" - -namespace smart_pointers{ - -struct base{ - base() : base_value(19) {} - int base_value; +// 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) + +#ifndef __smart_pointers_to_be_exported_hpp__ +#define __smart_pointers_to_be_exported_hpp__ +#include <memory> +#include "boost/shared_ptr.hpp" + +namespace smart_pointers{ + +struct base{ + base() : base_value(19) {} + int base_value; virtual int get_base_value(){ return base_value; } - virtual int get_some_value() = 0; -}; - -struct data : base{ - data() : value(11){} - int value; + virtual int get_some_value() = 0; +}; + +struct data : base{ + data() : value(11){} + int value; virtual int get_value(){ return value; } - virtual int get_some_value(){ return 23; } -}; - -typedef std::auto_ptr< base > base_a_ptr; -typedef boost::shared_ptr< base > base_s_ptr; - -typedef std::auto_ptr< data > data_a_ptr; -typedef boost::shared_ptr< data > data_s_ptr; - -data_a_ptr create_auto(); -data_s_ptr create_shared(); - -int ref_auto( data_a_ptr& a ); -int ref_shared( data_s_ptr& a ); - -int val_auto( data_a_ptr a ); -int val_shared( data_s_ptr a ); - -int const_ref_auto( const data_a_ptr& a ); -int const_ref_shared( const data_s_ptr& a ); - -int ref_auto_base_value( base_a_ptr& a ); -int ref_shared_base_value( base_s_ptr& a ); - -int val_auto_base_value( base_a_ptr a ); -int val_shared_base_value( base_s_ptr a ); - -int const_ref_auto_base_value( const base_a_ptr& a ); -int const_ref_shared_base_value( const base_s_ptr& a ); + virtual int get_some_value(){ return 23; } +}; +typedef std::auto_ptr< base > base_a_ptr; +typedef boost::shared_ptr< base > base_s_ptr; + +typedef std::auto_ptr< data > data_a_ptr; +typedef boost::shared_ptr< data > data_s_ptr; + +data_a_ptr create_auto(); +data_s_ptr create_shared(); + +int ref_auto( data_a_ptr& a ); +int ref_shared( data_s_ptr& a ); + +int val_auto( data_a_ptr a ); +int val_shared( data_s_ptr a ); + +int const_ref_auto( const data_a_ptr& a ); +int const_ref_shared( const data_s_ptr& a ); + +int ref_auto_base_value( base_a_ptr& a ); +int ref_shared_base_value( base_s_ptr& a ); + +int val_auto_base_value( base_a_ptr a ); +int val_shared_base_value( base_s_ptr a ); + +int const_ref_auto_base_value( const base_a_ptr& a ); +int const_ref_shared_base_value( const base_s_ptr& a ); + int ref_auto_some_value( base_a_ptr& a ); int ref_shared_some_value( base_s_ptr& a ); @@ -60,7 +60,24 @@ int const_ref_auto_some_value( const base_a_ptr& a ); int const_ref_shared_some_value( const base_s_ptr& a ); - -} - -#endif//__smart_pointers_to_be_exported_hpp__ +struct shared_data_buffer_t{ + shared_data_buffer_t() + : size( 0 ) + {} + int size; +}; + +struct shared_data_buffer_holder_t{ + typedef boost::shared_ptr<shared_data_buffer_t> holder_impl_t; + shared_data_buffer_holder_t() + : buffer( new shared_data_buffer_t() ) + , const_buffer( new shared_data_buffer_t() ) + {} + + holder_impl_t buffer; + const holder_impl_t const_buffer; +}; + +} + +#endif//__smart_pointers_to_be_exported_hpp__ Modified: pyplusplus_dev/unittests/smart_pointers_tester.py =================================================================== --- pyplusplus_dev/unittests/smart_pointers_tester.py 2006-12-08 19:47:42 UTC (rev 787) +++ pyplusplus_dev/unittests/smart_pointers_tester.py 2006-12-10 06:27:20 UTC (rev 788) @@ -23,6 +23,8 @@ base = mb.class_( 'base' ) shared_ptrs = mb.decls( lambda decl: decl.name.startswith( 'shared_ptr<' ) ) shared_ptrs.disable_warnings( messages.W1040 ) + mb.variable( 'buffer' ).apply_smart_ptr_wa = True + mb.variable( 'const_buffer' ).apply_smart_ptr_wa = True def create_py_derived( self, module ): class py_derived_t( module.base ): @@ -82,6 +84,16 @@ self.failUnless( 23 == module.const_ref_auto_some_value(da) ) self.failUnless( 28 == module.const_ref_shared_some_value(py_derived) ) + holder1 = module.shared_data_buffer_holder_t() + self.failUnless( holder1.buffer.size == 0 ) + + holder2 = module.shared_data_buffer_holder_t() + holder2.buffer.size = 2 + + holder1.buffer = holder2.buffer + self.failUnless( holder1.buffer.size == 2 ) + holder1.buffer.size = 3 + self.failUnless( holder2.buffer.size == 3 ) def create_suite(): suite = unittest.TestSuite() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-10 07:15:29
|
Revision: 789 http://svn.sourceforge.net/pygccxml/?rev=789&view=rev Author: roman_yakovenko Date: 2006-12-09 23:15:29 -0800 (Sat, 09 Dec 2006) Log Message: ----------- adding "static" to array [in|out] transformers Modified Paths: -------------- pyplusplus_dev/pyplusplus/function_transformers/__init__.py pyplusplus_dev/pyplusplus/function_transformers/transformers.py pyplusplus_dev/unittests/function_transformations_tester.py Modified: pyplusplus_dev/pyplusplus/function_transformers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/__init__.py 2006-12-10 06:27:20 UTC (rev 788) +++ pyplusplus_dev/pyplusplus/function_transformers/__init__.py 2006-12-10 07:15:29 UTC (rev 789) @@ -35,12 +35,12 @@ return transformers.inout_t( function, *args, **keywd ) return creator -def input_array( *args, **keywd ): +def input_static_array( *args, **keywd ): def creator( function ): - return transformers.input_array_t( function, *args, **keywd ) + return transformers.input_static_array_t( function, *args, **keywd ) return creator -def output_array( *args, **keywd ): +def output_static_array( *args, **keywd ): def creator( function ): - return transformers.output_array_t( function, *args, **keywd ) + return transformers.output_static_array_t( function, *args, **keywd ) return creator Modified: pyplusplus_dev/pyplusplus/function_transformers/transformers.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/transformers.py 2006-12-10 06:27:20 UTC (rev 788) +++ pyplusplus_dev/pyplusplus/function_transformers/transformers.py 2006-12-10 07:15:29 UTC (rev 789) @@ -210,7 +210,7 @@ _arr2seq = string.Template( 'pyplus_conv::copy_container( $native_array, $native_array + $array_size, pyplus_conv::list_inserter( $pylist ) );' ) -class input_array_t(transformer.transformer_t): +class input_static_array_t(transformer.transformer_t): """Handles an input array with fixed size. void setVec3(double* v) -> setVec3(object v) @@ -286,8 +286,8 @@ self.__configure_v_mem_fun_default( controller.default_controller ) -# output_array_t -class output_array_t(transformer.transformer_t): +# s - static +class output_static_array_t(transformer.transformer_t): """Handles an output array of a fixed size. void getVec3(double* v) -> v = getVec3() Modified: pyplusplus_dev/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev/unittests/function_transformations_tester.py 2006-12-10 06:27:20 UTC (rev 788) +++ pyplusplus_dev/unittests/function_transformations_tester.py 2006-12-10 07:15:29 UTC (rev 789) @@ -43,8 +43,8 @@ point3d = mb.class_( 'point3d_t' ) point3d.add_wrapper_code( '' ) - point3d.mem_fun( 'initialize' ).add_transformation( ft.input_array(0, size=3) ) - point3d.mem_fun( 'position' ).add_transformation( ft.output_array(0, size=3) ) + point3d.mem_fun( 'initialize' ).add_transformation( ft.input_static_array(0, size=3) ) + point3d.mem_fun( 'position' ).add_transformation( ft.output_static_array(0, size=3) ) point3d.mem_fun( 'distance' ).add_transformation( ft.output(1) ) image = mb.class_( "image_t" ) @@ -54,8 +54,8 @@ image.member_function( "get_one_value" ).add_transformation( ft.output(0) ) image.member_function( "get_size2" ).add_transformation( ft.output(0), ft.output(1) ) image.member_function( "input_arg" ).add_transformation( ft.input(0) ) - image.member_function( "fixed_input_array" ).add_transformation( ft.input_array(0,3) ) - image.member_function( "fixed_output_array" ).add_transformation( ft.output_array(0,3) ) + image.member_function( "fixed_input_array" ).add_transformation( ft.input_static_array(0,3) ) + image.member_function( "fixed_output_array" ).add_transformation( ft.output_static_array(0,3) ) mb.free_function("get_cpp_instance").call_policies \ = call_policies.return_value_policy(call_policies.reference_existing_object) mb.variable( "cpp_instance" ).exclude() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-10 07:16:58
|
Revision: 790 http://svn.sourceforge.net/pygccxml/?rev=790&view=rev Author: roman_yakovenko Date: 2006-12-09 23:16:59 -0800 (Sat, 09 Dec 2006) Log Message: ----------- updating environment to use new( to me ) boost directory layout Modified Paths: -------------- pyplusplus_dev/environment.py pyplusplus_dev/unittests/autoconfig.py Modified: pyplusplus_dev/environment.py =================================================================== --- pyplusplus_dev/environment.py 2006-12-10 07:15:29 UTC (rev 789) +++ pyplusplus_dev/environment.py 2006-12-10 07:16:59 UTC (rev 790) @@ -27,14 +27,14 @@ if sys.platform == 'win32': scons.suffix = '.pyd' scons.ccflags = ['/MD', '/EHsc', '/GR', '/Zc:wchar_t', '/Zc:forScope' ] - boost.libs = 'd:/dev/boost_cvs/bin' + boost.libs = [ 'd:/dev/boost_cvs/libs/python/build/bin-stage' ] boost.include = 'd:/dev/boost_cvs' python.libs = 'e:/python25/libs' python.include = 'e:/python25/include' gccxml.executable = r'd:/dev/gccxml_cvs/gccxml-bin/bin/release/gccxml.exe' else: scons.suffix = '.so' - boost.libs = '/home/roman/boost_cvs/bin' + boost.libs = [ '/home/roman/boost_cvs/bin' ] boost.include = '/home/roman/boost_cvs' python.include = '/usr/include/python2.4' gccxml.executable = '/home/roman/gccxml-build/bin/gccxml' Modified: pyplusplus_dev/unittests/autoconfig.py =================================================================== --- pyplusplus_dev/unittests/autoconfig.py 2006-12-10 07:15:29 UTC (rev 789) +++ pyplusplus_dev/unittests/autoconfig.py 2006-12-10 07:16:59 UTC (rev 790) @@ -20,7 +20,7 @@ class scons_config: libs = ['boost_python'] - libpath = [ boost.libs, python.libs ] + libpath = [ python.libs ] + boost.libs cpppath = [ boost.include, python.include ] include_dirs = cpppath + [data_directory] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-17 19:57:49
|
Revision: 803 http://svn.sourceforge.net/pygccxml/?rev=803&view=rev Author: roman_yakovenko Date: 2006-12-17 11:57:49 -0800 (Sun, 17 Dec 2006) Log Message: ----------- updating docs and adding new compile time test case Modified Paths: -------------- pyplusplus_dev/docs/history/history.rest pyplusplus_dev/docs/quotes.rest pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp pyplusplus_dev/unittests/function_transformations_tester.py Modified: pyplusplus_dev/docs/history/history.rest =================================================================== --- pyplusplus_dev/docs/history/history.rest 2006-12-15 20:11:48 UTC (rev 802) +++ pyplusplus_dev/docs/history/history.rest 2006-12-17 19:57:49 UTC (rev 803) @@ -17,6 +17,7 @@ * Lakin Wecker * Georgiy Dernovoy * Gottfried Ganssauge +* Andy Miller ------------ Project name Modified: pyplusplus_dev/docs/quotes.rest =================================================================== --- pyplusplus_dev/docs/quotes.rest 2006-12-15 20:11:48 UTC (rev 802) +++ pyplusplus_dev/docs/quotes.rest 2006-12-17 19:57:49 UTC (rev 803) @@ -35,6 +35,13 @@ Lakin Wecker, the author of `Python-OGRE`_ project +"... Py++ allows the wrappers to be "automagically" created, which means it's much +easier to keep things up to date (the maintainence on the Py++ based wrapper is +tiny compared to any other system I've used). It also allows us to wrap other +libraries fairly easily. " + + Andy Miller, a developer of `Python-OGRE`_ project + ------------------ Who is using Py++? ------------------ Modified: pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp 2006-12-15 20:11:48 UTC (rev 802) +++ pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp 2006-12-17 19:57:49 UTC (rev 803) @@ -183,6 +183,23 @@ ~ft_private_destructor_t(){} }; +struct bug_render_target_t{ + virtual void get_statistics( float& x, float& y ){ + x = 1.1;; + y = 1.2; + } + + struct frame_stats_t{ + float x, y; + }; + + virtual frame_stats_t get_statistics(){ + frame_stats_t fs; + fs.x = 1.1; + fs.y = 1.2; + } +}; + } #endif//__function_transformations_to_be_exported_hpp__ Modified: pyplusplus_dev/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev/unittests/function_transformations_tester.py 2006-12-15 20:11:48 UTC (rev 802) +++ pyplusplus_dev/unittests/function_transformations_tester.py 2006-12-17 19:57:49 UTC (rev 803) @@ -68,6 +68,9 @@ mb.decls(lambda decl: decl.name.startswith("_")).exclude() + cls = mb.class_("bug_render_target_t") + cls.mem_fun("get_statistics", arg_types=['float &']*2).add_transformation( ft.output(0), ft.output(1) ) + def run_tests(self, module): """Run the actual unit tests. """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-18 08:36:14
|
Revision: 804 http://svn.sourceforge.net/pygccxml/?rev=804&view=rev Author: roman_yakovenko Date: 2006-12-18 00:36:12 -0800 (Mon, 18 Dec 2006) Log Message: ----------- fixing "const" bug Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py pyplusplus_dev/pyplusplus/function_transformers/templates.py pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp Modified: pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py 2006-12-17 19:57:49 UTC (rev 803) +++ pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py 2006-12-18 08:36:12 UTC (rev 804) @@ -333,7 +333,10 @@ tmpl_values['wrapper_class'] = self.parent.wrapper_alias tmpl_values['wrapped_class'] = declarations.full_name( self.declaration.parent ) tmpl_values['wrapped_inst'] = cntrl.inst_arg.name - + tmpl_values['wrapped_inst_constness'] = '' + if declarations.is_const( declarations.remove_reference( cntrl.inst_arg.type ) ): + tmpl_values['wrapped_inst_constness'] = 'const' + decl_vars = cntrl.variables[:] if not declarations.is_void( self.declaration.return_type ): decl_vars.append( cntrl.result_variable ) Modified: pyplusplus_dev/pyplusplus/function_transformers/templates.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/templates.py 2006-12-17 19:57:49 UTC (rev 803) +++ pyplusplus_dev/pyplusplus/function_transformers/templates.py 2006-12-18 08:36:12 UTC (rev 804) @@ -43,7 +43,7 @@ 'static $return_type $unique_function_name( $arg_declarations ){' , ' $declare_variables' , ' $pre_call' - , ' if( dynamic_cast< $wrapper_class* >( boost::addressof( $wrapped_inst ) ) ){' + , ' if( dynamic_cast< $wrapper_class $wrapped_inst_constness* >( boost::addressof( $wrapped_inst ) ) ){' , ' $save_result$wrapped_inst.$wrapped_class::$function_name($arg_expressions);' , ' }' , ' else{' Modified: pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp 2006-12-17 19:57:49 UTC (rev 803) +++ pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp 2006-12-18 08:36:12 UTC (rev 804) @@ -184,7 +184,7 @@ }; struct bug_render_target_t{ - virtual void get_statistics( float& x, float& y ){ + virtual void get_statistics( float& x, float& y ) const{ x = 1.1;; y = 1.2; } @@ -197,6 +197,7 @@ frame_stats_t fs; fs.x = 1.1; fs.y = 1.2; + return fs; } }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-20 06:56:59
|
Revision: 805 http://svn.sourceforge.net/pygccxml/?rev=805&view=rev Author: roman_yakovenko Date: 2006-12-19 22:56:58 -0800 (Tue, 19 Dec 2006) Log Message: ----------- improving named_tuple functionality Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_repository/convenience.py pyplusplus_dev/pyplusplus/code_repository/named_tuple.py pyplusplus_dev/pyplusplus/file_writers/writer.py pyplusplus_dev/pyplusplus/function_transformers/controllers.py pyplusplus_dev/pyplusplus/function_transformers/templates.py pyplusplus_dev/pyplusplus/function_transformers/transformer.py pyplusplus_dev/pyplusplus/module_creator/creator.py pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp pyplusplus_dev/unittests/function_transformations_tester.py pyplusplus_dev/unittests/temp/named_tuple.py Modified: pyplusplus_dev/pyplusplus/code_repository/convenience.py =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/convenience.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/pyplusplus/code_repository/convenience.py 2006-12-20 06:56:58 UTC (rev 805) @@ -137,19 +137,32 @@ inline boost::python::object get_out_argument( boost::python::object result, const char* arg_name ){ - if( PySequence_Check( result.ptr() ) ){ - return boost::python::getattr( result, arg_name ); + if( !PySequence_Check( result.ptr() ) ){ + return result; } + boost::python::object cls = boost::python::getattr( result, "__class__" ); + boost::python::object cls_name = boost::python::getattr( cls, "__name__" ); + std::string name = boost::python::extract< std::string >( cls_name ); + if( "named_tuple" == name ){ + return boost::python::getattr( result, arg_name ); + } else{ return result; } + } inline boost::python::object get_out_argument( boost::python::object result, index_type index ){ - if( PySequence_Check( result.ptr() ) ){ - return result[ index ]; + if( !PySequence_Check( result.ptr() ) ){ + return result; } + boost::python::object cls = boost::python::getattr( result, "__class__" ); + boost::python::object cls_name = boost::python::getattr( cls, "__name__" ); + std::string name = boost::python::extract< std::string >( cls_name ); + if( "named_tuple" == name ){ + return result[ index ]; + } else{ return result; } Modified: pyplusplus_dev/pyplusplus/code_repository/named_tuple.py =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/named_tuple.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/pyplusplus/code_repository/named_tuple.py 2006-12-20 06:56:58 UTC (rev 805) @@ -12,31 +12,18 @@ # http://www.boost.org/LICENSE_1_0.txt) class named_tuple(tuple): - \"\"\"Creates tuple, which allows access to stored values by name and by index. + \"\"\"Creates tuple, which allows access to stored values by name and\\or by index. - named_tuple could be constructed exactly in the same way as Python dict. + Construction example: named_tuple( ('a',0), ('b',1) ) + 'a' and 'b' are names, while 0 and 1 are values \"\"\" - def __new__(cls, seq=None, **keywd): - if seq: - if isinstance( seq, dict ): - return tuple.__new__( cls, seq.values() ) - else: - return tuple.__new__( cls, [ val for name, val in seq] ) - else: - return tuple.__new__( cls, keywd.values() ) + def __new__(cls, *args): + return tuple.__new__( cls, [ val for name, val in args] ) - def __init__(self, seq=None, **keywd): - "named_tuple could be constructed exactly in the same way as Python dict." + def __init__(self, *args): tuple.__init__( self ) - if seq: - if isinstance( seq, dict ): - name2value = dict( seq.iteritems() ) - else: - name2value = dict( seq ) - else: - name2value = dict( keywd ) - self.__dict__[ '__name2value' ] = name2value + self.__dict__[ '__name2value' ] = dict( args ) def __getattr__(self, name): try: @@ -56,7 +43,7 @@ return super( named_tuple, self ).__getitem__( key ) if __name__ == '__main__': - nt = named_tuple( a=0, b=1) + nt = named_tuple( ('a',0), ('b',1) ) assert nt.a == 0 and nt.b == 1 a,b = nt assert a == 0 and b == 1 Modified: pyplusplus_dev/pyplusplus/file_writers/writer.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/writer.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/pyplusplus/file_writers/writer.py 2006-12-20 06:56:58 UTC (rev 805) @@ -50,12 +50,7 @@ for cr in code_repository.all: if self.__extmodule.is_system_header( cr.file_name ): self.write_file( os.path.join( dir, cr.file_name ), cr.code ) - #temporal patch: always write named_tuple.py file - f = file( os.path.join( dir, code_repository.named_tuple.file_name ), 'w+b' ) - f.write( code_repository.named_tuple.code ) - f.close() - @staticmethod def write_file( fpath, content ): """Write a source file. @@ -73,7 +68,10 @@ writer_t.logger.debug( 'write code to file "%s" - started' % fpath ) start_time = time.clock() fcontent_new = [] - fcontent_new.append( '// This file has been generated by Py++.' ) + if os.path.splitext( fpath )[1] == '.py': + fcontent_new.append( '# This file has been generated by Py++.' ) + else: + fcontent_new.append( '// This file has been generated by Py++.' ) fcontent_new.append( os.linesep * 2 ) fcontent_new.append( content ) fcontent_new.append( os.linesep ) #keep gcc happy Modified: pyplusplus_dev/pyplusplus/function_transformers/controllers.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/controllers.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/pyplusplus/function_transformers/controllers.py 2006-12-20 06:56:58 UTC (rev 805) @@ -1,3 +1,16 @@ +# 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) + +"""defines controller classes which help to define the function transformation + +The idea behind implementation of "Function Transformation" functionality is simple: +Py++ defines few templates. Transformers are just editors for the templates. +In most cases, transformers don't directly edit the template, but use controller +classes for this purpose. Controller classes provide an abstraction of the templates. +""" + import string import templates from pygccxml import declarations @@ -3,5 +16,14 @@ class variable_t( object ): + """defines C++ variable""" def __init__( self, type, name, initialize_expr='' ): + """ + @param type: type of the variable + @type type: instance of L{pygccxml.declarations.type_t} + + @param name: name( str ) of the variable + + @param initialize_expr: an expression that initialize the variable + """ self.__name = name self.__type = type @@ -10,14 +32,17 @@ @property def name( self ): + "variable name" return self.__name @property def type( self ): + "variable type" return self.__type @property def initialize_expr( self ): + "inirialize expression" return self.__initialize_expr def declare_var_string( self ): @@ -27,6 +52,14 @@ , initialize_expr=self.initialize_expr ) class variables_manager_t( object ): + """function wrapper variables manager + + Almost every time we define new transformer, we need to define variables. + It is important to keep the variable names unique. This class will ensure this. + Every time you declare new variable, it will return the unique variable name. + The name will be built from the original variable name and some index, which + will make the variable to be unique. + """ def __init__( self ): object.__init__( self ) self.__variables = [] #variables @@ -34,14 +67,32 @@ @property def variables( self ): + "list of all declared variables" return self.__variables def declare_variable( self, type, name, initialize_expr='' ): + """declare variable + + @param type: type of the variable + @type type: instance of L{pygccxml.declarations.type_t} + + @param name: name( str ) of the variable + + @param initialize_expr: an expression that initialize the variable + + @return: the unique variable name + """ unique_name = self.__create_unique_var_name( name ) self.__variables.append( variable_t( type, unique_name, initialize_expr ) ) return unique_name def register_name( self, name ): + """register predefined variable name + + There are use cases, where it is convenience to define variables within + a template. In such cases, the only thing that should be done is registering + a unique name of the variable. + """ return self.__create_unique_var_name( name ) def __create_unique_var_name( self, name ): @@ -61,6 +112,8 @@ return vm class controller_base_t( object ): + """base class for all controller classes""" + def __init__( self, function ): self.__function = function @@ -69,10 +122,11 @@ return self.__function def apply( self, transformations ): + """asks all transformations to configure the controller""" raise NotImplementedError() class sealed_fun_controller_t( controller_base_t ): - #base class for free and member function controllers + """base class for free and member function controllers""" def __init__( self, function ): controller_base_t.__init__( self, function ) self.__vars_manager = create_variables_manager( function ) @@ -104,7 +158,7 @@ @property def wrapper_args( self ): - return self.__wrapper_args + return filter( None, self.__wrapper_args ) def find_wrapper_arg( self, name ): for arg in self.wrapper_args: @@ -116,7 +170,7 @@ arg = self.find_wrapper_arg( name ) if not arg: raise LookupError( "Unable to remove '%s' argument - not found!" % name ) - del self.wrapper_args[ self.wrapper_args.index(arg) ] + self.__wrapper_args[ self.__wrapper_args.index(arg) ] = None @property def arg_expressions( self ): Modified: pyplusplus_dev/pyplusplus/function_transformers/templates.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/templates.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/pyplusplus/function_transformers/templates.py 2006-12-20 06:56:58 UTC (rev 805) @@ -5,11 +5,12 @@ # Matthias Baas is an initial author of the templates. +"""defines few templates, which will be used to create a function-wrapper +definition.""" + import os from string import Template -#TODO: pre_call, post_call terminology should be changed. Use prefix and suffix -#instead: http://boost.org/libs/smart_ptr/sp_techniques.html#wrapper class sealed_fun: body = Template( os.linesep.join([ Modified: pyplusplus_dev/pyplusplus/function_transformers/transformer.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/transformer.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/pyplusplus/function_transformers/transformer.py 2006-12-20 06:56:58 UTC (rev 805) @@ -2,8 +2,6 @@ # 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 class L{transformer_t}. """ @@ -12,23 +10,15 @@ from pygccxml import declarations, parser return_ = -1 +#return_ is a spacial const, which represent an index of return type class transformer_t: + """Base class for a function transformer.""" + USE_1_BASED_INDEXING = False - - """Base class for a function transformer. - - This class specifies the interface that a user written transformer - has to implement. It doesn't contain any actual functionality so - a user doesn't have to derive from this class. Methods that are not - implemented are treated as if they would do nothing and return None. - - @author: Matthias Baas - """ - + def __init__(self, function): - """Constructor. - """ + """@param function: reference to function declaration""" self.__function = function @property @@ -41,6 +31,10 @@ return [] def get_argument( self, reference ): + """returns reference to the desired argument + + @param reference: name( str ) or index( int ) of the argument + """ if isinstance( reference, str ): found = filter( lambda arg: arg.name == reference, self.function.arguments ) if len( found ) == 1: @@ -53,6 +47,10 @@ return self.function.arguments[ reference ] def get_type( self, reference ): + """returns type of the desired argument or return type of the function + + @param reference: name( str ) or index( int ) of the argument + """ global return_ if isinstance( reference, int ) and reference == return_: return self.function.return_type @@ -60,9 +58,26 @@ return self.get_argument( reference ).type def configure_mem_fun( self, controller ): + """Transformers should overridde the method, in order to define custom + transformation for non-virtual member function. + + @param controller: instance of L{mem_fun_controller_t} class + """ pass def configure_free_fun( self, controller ): + """Transformers should overridde the method, in order to define custom + transformation for free function. + + @param controller: instance of L{free_fun_controller_t} class + """ pass - \ No newline at end of file + def configure_virtual_mem_fun( self, controller ): + """Transformers should overridde the method, in order to define custom + transformation for virtual member function. + + @param controller: instance of L{virtual_mem_fun_controller_t} class + """ + pass + Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-12-20 06:56:58 UTC (rev 805) @@ -428,7 +428,10 @@ # Check if it is a header from the code repository if header in code_repository.headers: self.__extmodule.add_system_header( header ) - + + if not self.__extmodule.is_system_header( code_repository.named_tuple.file_name ): + self.__extmodule.add_system_header( code_repository.named_tuple.file_name ) + if self.curr_decl.has_static: #static_method should be created only once. found = filter( lambda creator: isinstance( creator, code_creators.static_method_t ) Modified: pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp 2006-12-20 06:56:58 UTC (rev 805) @@ -184,6 +184,13 @@ }; struct bug_render_target_t{ + + static float get_static_statistics( bug_render_target_t& inst ){ + float x,y; + inst.get_statistics( x, y ); + return x+y; + } + virtual void get_statistics( float& x, float& y ) const{ x = 1.1;; y = 1.2; Modified: pyplusplus_dev/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev/unittests/function_transformations_tester.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/unittests/function_transformations_tester.py 2006-12-20 06:56:58 UTC (rev 805) @@ -8,7 +8,6 @@ import math import unittest import fundamental_tester_base -from named_tuple import named_tuple from pyplusplus import function_transformers as ft from pyplusplus.module_builder import call_policies @@ -140,15 +139,16 @@ return self.m_height+1 def fixed_output_array(self): + from named_tuple import named_tuple # Produce a correct return value if self.fixed_output_array_mode==0: - return named_tuple( v=(2,5,7) ) + return named_tuple( ('v', (2,5,7)) ) # Produce the wrong type elif self.fixed_output_array_mode==1: return 5 # Produce a sequence with the wrong number of items elif self.fixed_output_array_mode==2: - return named_tuple( v=(2,5) ) + return named_tuple( ('v', (2,5)) ) pyimg1 = py_image1_t(3,7) @@ -202,6 +202,18 @@ cls = module.no_virtual_members_t() self.assertEqual(cls.member(), (True, 17)) + class py_bug_render_target_t( module.bug_render_target_t ): + def __init__( self ): + module.bug_render_target_t.__init__( self ) + + def get_statistics( self ): + from named_tuple import named_tuple + return named_tuple( ( 'x', 2.0 ), ( 'y', 3.0 ) ) + tmp = py_bug_render_target_t() + + tmp.get_statistics() + self.failUnless( 2.0 + 3.0 == module.bug_render_target_t.get_static_statistics( tmp ) ) + def create_suite(): suite = unittest.TestSuite() suite.addTest( unittest.makeSuite(tester_t)) Modified: pyplusplus_dev/unittests/temp/named_tuple.py =================================================================== --- pyplusplus_dev/unittests/temp/named_tuple.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/unittests/temp/named_tuple.py 2006-12-20 06:56:58 UTC (rev 805) @@ -1,3 +1,5 @@ +# This file has been generated by Py++. + # Copyright 2004 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at @@ -4,31 +6,18 @@ # http://www.boost.org/LICENSE_1_0.txt) class named_tuple(tuple): - """Creates tuple, which allows access to stored values by name and by index. + """Creates tuple, which allows access to stored values by name and\or by index. - named_tuple could be constructed exactly in the same way as Python dict. + Construction example: named_tuple( ('a',0), ('b',1) ) + 'a' and 'b' are names, while 0 and 1 are values """ - def __new__(cls, seq=None, **keywd): - if seq: - if isinstance( seq, dict ): - return tuple.__new__( cls, seq.values() ) - else: - return tuple.__new__( cls, [ val for name, val in seq] ) - else: - return tuple.__new__( cls, keywd.values() ) + def __new__(cls, *args): + return tuple.__new__( cls, [ val for name, val in args] ) - def __init__(self, seq=None, **keywd): - "named_tuple could be constructed exactly in the same way as Python dict." + def __init__(self, *args): tuple.__init__( self ) - if seq: - if isinstance( seq, dict ): - name2value = dict( seq.iteritems() ) - else: - name2value = dict( seq ) - else: - name2value = dict( keywd ) - self.__dict__[ '__name2value' ] = name2value + self.__dict__[ '__name2value' ] = dict( args ) def __getattr__(self, name): try: @@ -48,9 +37,10 @@ return super( named_tuple, self ).__getitem__( key ) if __name__ == '__main__': - nt = named_tuple( a=0, b=1) + nt = named_tuple( ('a',0), ('b',1) ) assert nt.a == 0 and nt.b == 1 a,b = nt assert a == 0 and b == 1 assert nt[ "a" ] == 0 and nt[ "b" ] == 1 + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-29 19:07:42
|
Revision: 821 http://svn.sourceforge.net/pygccxml/?rev=821&view=rev Author: roman_yakovenko Date: 2006-12-29 11:07:42 -0800 (Fri, 29 Dec 2006) Log Message: ----------- adding new use case for smart_ptr Modified Paths: -------------- pyplusplus_dev/docs/bpl_lessons_learned/smart_ptrs/bindings.cpp pyplusplus_dev/docs/bpl_lessons_learned/smart_ptrs/classes.hpp pyplusplus_dev/docs/bpl_lessons_learned/smart_ptrs/test.py pyplusplus_dev/examples/pyboost_dev/dev/rational/generate_code.py Modified: pyplusplus_dev/docs/bpl_lessons_learned/smart_ptrs/bindings.cpp =================================================================== --- pyplusplus_dev/docs/bpl_lessons_learned/smart_ptrs/bindings.cpp 2006-12-28 19:40:19 UTC (rev 820) +++ pyplusplus_dev/docs/bpl_lessons_learned/smart_ptrs/bindings.cpp 2006-12-29 19:07:42 UTC (rev 821) @@ -3,20 +3,26 @@ namespace bp = boost::python; -// "get_pointer" function returns pointer to the object managed by smart pointer -// class instance +//namespace boost{ + // "get_pointer" function returns pointer to the object managed by smart pointer + // class instance -template<class T> -inline T * get_pointer(smart_ptr_t<T> const& p){ - return p.get(); -} + template<class T> + inline T * get_pointer(smart_ptr_t<T> const& p){ + return p.get(); + } -inline derived_t * get_pointer(derived_ptr_t const& p){ - return p.get(); -} - + inline derived_t * get_pointer(derived_ptr_t const& p){ + return p.get(); + } +//} + +//using boost::get_pointer; + namespace boost{ namespace python{ + using boost::get_pointer; + // "pointee" class tells Boost.Python the type of the object managed by smart // pointer class. // You can read more about "pointee" class here: @@ -34,6 +40,7 @@ } } + // "get_pointer" and "pointee" are needed, in order to allow Boost.Python to // work with user defined smart pointer @@ -116,7 +123,14 @@ bp::def( "val_get_value", &::val_get_value ); bp::def( "create_derived", &::create_derived ); bp::def( "create_base", &::create_base ); - + + + bp::class_< numeric_t, smart_ptr_t< numeric_t > >( "numeric_t" ) + .def_readwrite( "value", &numeric_t::value ); + + bp::def( "create_numeric", &::create_numeric ); + bp::def( "get_numeric_value", &::get_numeric_value ); + // Work around for the public member variable, where type of the variable // is smart pointer problem bp::class_< shared_data::buffer_t >( "buffer_t" ) Modified: pyplusplus_dev/docs/bpl_lessons_learned/smart_ptrs/classes.hpp =================================================================== --- pyplusplus_dev/docs/bpl_lessons_learned/smart_ptrs/classes.hpp 2006-12-28 19:40:19 UTC (rev 820) +++ pyplusplus_dev/docs/bpl_lessons_learned/smart_ptrs/classes.hpp 2006-12-29 19:07:42 UTC (rev 821) @@ -13,7 +13,7 @@ derived_t(){} virtual int get_value() const{ return 0xD; } }; - + // Some smart pointer classes does not have reach interface as boost ones. // In order to provide same level of convenience, users are forced to create // classes, which derive from smart pointer class. @@ -94,6 +94,32 @@ return a->get_value(); } + +struct numeric_t{ + numeric_t() + : value(0) + {} + + int value; +}; + +smart_ptr_t< numeric_t > create_numeric( int value ){ + smart_ptr_t< numeric_t > num( new numeric_t() ); + num->value = value; + return num; +} + +int get_numeric_value( smart_ptr_t< numeric_t > n ){ + if( n.get() ){ + return n->value; + } + else{ + return 0; + } +} + + + namespace shared_data{ // Boost.Python has small problem with user defined smart pointers and public Modified: pyplusplus_dev/docs/bpl_lessons_learned/smart_ptrs/test.py =================================================================== --- pyplusplus_dev/docs/bpl_lessons_learned/smart_ptrs/test.py 2006-12-28 19:40:19 UTC (rev 820) +++ pyplusplus_dev/docs/bpl_lessons_learned/smart_ptrs/test.py 2006-12-29 19:07:42 UTC (rev 821) @@ -68,6 +68,14 @@ self.fail("TypeError exception was not raised.") except TypeError: pass + + def test_numeric( self ): + numeric = custom_sptr.create_numeric(21) + self.failUnless( 21 == numeric.value ) + self.failUnless( 21 == custom_sptr.get_numeric_value(numeric) ) + numeric = custom_sptr.numeric_t() + self.failUnless( 0 == numeric.value ) + self.failUnless( 0 == custom_sptr.get_numeric_value(numeric) ) def create_suite(): suite = unittest.TestSuite() Modified: pyplusplus_dev/examples/pyboost_dev/dev/rational/generate_code.py =================================================================== --- pyplusplus_dev/examples/pyboost_dev/dev/rational/generate_code.py 2006-12-28 19:40:19 UTC (rev 820) +++ pyplusplus_dev/examples/pyboost_dev/dev/rational/generate_code.py 2006-12-29 19:07:42 UTC (rev 821) @@ -58,8 +58,8 @@ bad_rational = self.__mb.class_('bad_rational' ) bad_rational.include() - self.__mb.free_function( 'lcm<long>' ).include() - self.__mb.free_function( 'gcd<long>' ).include() + self.__mb.namespace( 'boost' ).free_function( 'lcm<long>', recursive=False ).include() + self.__mb.namespace( 'boost' ).free_function( 'gcd<long>', recursive=False ).include() self.__mb.free_function( 'rational_cast<double, long>' ).include() self.__mb.free_function( 'rational_cast<double, long>' ).alias = 'to_double' self.__mb.free_function( 'rational_cast<long, long>' ).include() @@ -106,4 +106,4 @@ export() print 'done' - \ 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-12-31 08:18:38
|
Revision: 822 http://svn.sourceforge.net/pygccxml/?rev=822&view=rev Author: roman_yakovenko Date: 2006-12-31 00:18:38 -0800 (Sun, 31 Dec 2006) Log Message: ----------- adding new trasnformer - type_modifier Modified Paths: -------------- pyplusplus_dev/pyplusplus/function_transformers/__init__.py pyplusplus_dev/pyplusplus/function_transformers/transformers.py pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp pyplusplus_dev/unittests/function_transformations_tester.py Modified: pyplusplus_dev/pyplusplus/function_transformers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/__init__.py 2006-12-29 19:07:42 UTC (rev 821) +++ pyplusplus_dev/pyplusplus/function_transformers/__init__.py 2006-12-31 08:18:38 UTC (rev 822) @@ -44,3 +44,8 @@ def creator( function ): return transformers.output_static_array_t( function, *args, **keywd ) return creator + +def modify_type( *args, **keywd ): + def creator( function ): + return transformers.type_modifier_t( function, *args, **keywd ) + return creator Modified: pyplusplus_dev/pyplusplus/function_transformers/transformers.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/transformers.py 2006-12-29 19:07:42 UTC (rev 821) +++ pyplusplus_dev/pyplusplus/function_transformers/transformers.py 2006-12-31 08:18:38 UTC (rev 822) @@ -66,7 +66,7 @@ % ( function, self.arg_ref.name, arg.type) def __str__(self): - return "output(%d)"%(self.arg_index) + return "output(%d)"%(self.arg.name) def required_headers( self ): """Returns list of header files that transformer generated code depends on.""" @@ -103,39 +103,31 @@ def configure_virtual_mem_fun( self, controller ): self.__configure_v_mem_fun_default( controller.default_controller ) self.__configure_v_mem_fun_override( controller.override_controller ) - - + # input_t -class input_t(transformer.transformer_t): - """Handles a single input variable. - - The reference on the specified variable is removed. - - void setValue(int& v) -> setValue(v) +class type_modifier_t(transformer.transformer_t): + """Change/modify type of the argument. + + Right now compiler should be able to use implicit conversion """ - def __init__(self, function, arg_ref): + def __init__(self, function, arg_ref, modifier): """Constructor. - The specified argument must be a reference or a pointer. - - @param idx: Index of the argument that is an output value (the first arg has index 1). - @type idx: int + modifier is callable, which take the type of the argument and should return + new type """ transformer.transformer_t.__init__( self, function ) self.arg = self.get_argument( arg_ref ) self.arg_index = self.function.arguments.index( self.arg ) + self.modifier = modifier - if not is_ref_or_ptr( self.arg.type ): - raise ValueError( '%s\nin order to use "input" transformation, argument %s type must be a reference or a pointer (got %s).' ) \ - % ( function, self.arg_ref.name, arg.type) - def __str__(self): - return "input(%d)"%(self.idx) + return "type_modifier(%s)" % self.arg.name def __configure_sealed( self, controller ): w_arg = controller.find_wrapper_arg( self.arg.name ) - w_arg.type = remove_ref_or_ptr( self.arg.type ) + w_arg.type = self.modifier( self.arg.type ) def __configure_v_mem_fun_default( self, controller ): self.__configure_sealed( controller ) @@ -147,8 +139,35 @@ self.__configure_sealed( controller ) def configure_virtual_mem_fun( self, controller ): - self.__configure_v_mem_fun_default( controller.default_controller ) + self.__configure_v_mem_fun_default( controller.default_controller ) + +# input_t +class input_t(type_modifier_t): + """Handles a single input variable. + + The reference on the specified variable is removed. + + void setValue(int& v) -> setValue(v) + """ + + def __init__(self, function, arg_ref): + """Constructor. + + The specified argument must be a reference or a pointer. + + @param idx: Index of the argument that is an output value (the first arg has index 1). + @type idx: int + """ + type_modifier_t.__init__( self, function, arg_ref, remove_ref_or_ptr ) + + if not is_ref_or_ptr( self.arg.type ): + raise ValueError( '%s\nin order to use "input" transformation, argument %s type must be a reference or a pointer (got %s).' ) \ + % ( function, self.arg_ref.name, arg.type) + + def __str__(self): + return "input(%s)"%(self.arg.name) + # inout_t class inout_t(transformer.transformer_t): """Handles a single input/output variable. @@ -173,7 +192,7 @@ % ( function, self.arg_ref.name, arg.type) def __str__(self): - return "inout(%d)"%(self.arg_index) + return "inout(%s)"%(self.arg.name) def __configure_sealed(self, controller): w_arg = controller.find_wrapper_arg( self.arg.name ) @@ -230,7 +249,7 @@ if not is_ptr_or_array( self.arg.type ): raise ValueError( '%s\nin order to use "input_array" transformation, argument %s type must be a array or a pointer (got %s).' ) \ - % ( function, self.arg_ref.name, arg.type) + % ( function, self.arg.name, self.arg.type) self.array_size = size self.array_item_type = declarations.array_item_type( self.arg.type ) @@ -308,7 +327,7 @@ if not is_ptr_or_array( self.arg.type ): raise ValueError( '%s\nin order to use "input_array" transformation, argument %s type must be a array or a pointer (got %s).' ) \ - % ( function, self.arg_ref.name, arg.type) + % ( function, self.arg.name, self.arg.type) self.array_size = size self.array_item_type = declarations.array_item_type( self.arg.type ) Modified: pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp 2006-12-29 19:07:42 UTC (rev 821) +++ pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp 2006-12-31 08:18:38 UTC (rev 822) @@ -208,6 +208,12 @@ } }; +struct modify_type_tester_t{ + int do_nothing( int& v ){ + return v; + } +}; + } #endif//__function_transformations_to_be_exported_hpp__ Modified: pyplusplus_dev/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev/unittests/function_transformations_tester.py 2006-12-29 19:07:42 UTC (rev 821) +++ pyplusplus_dev/unittests/function_transformations_tester.py 2006-12-31 08:18:38 UTC (rev 822) @@ -8,6 +8,7 @@ import math import unittest import fundamental_tester_base +from pygccxml import declarations from pyplusplus import function_transformers as ft from pyplusplus.module_builder import call_policies @@ -69,6 +70,10 @@ cls = mb.class_("bug_render_target_t") cls.mem_fun("get_statistics", arg_types=['float &']*2).add_transformation( ft.output(0), ft.output(1) ) + + cls = mb.class_( 'modify_type_tester_t' ) + do_nothing = cls.mem_fun( 'do_nothing' ) + do_nothing.add_transformation( ft.modify_type(0, declarations.remove_reference ) ) def run_tests(self, module): """Run the actual unit tests. @@ -214,6 +219,9 @@ tmp.get_statistics() self.failUnless( 2.0 + 3.0 == module.bug_render_target_t.get_static_statistics( tmp ) ) + tmp = module.modify_type_tester_t() + self.failUnless( 123 == tmp.do_nothing(123) ) + def create_suite(): suite = unittest.TestSuite() suite.addTest( unittest.makeSuite(tester_t)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-31 11:27:04
|
Revision: 825 http://svn.sourceforge.net/pygccxml/?rev=825&view=rev Author: roman_yakovenko Date: 2006-12-31 03:27:03 -0800 (Sun, 31 Dec 2006) Log Message: ----------- updating docs Modified Paths: -------------- pyplusplus_dev/docs/documentation/functions/transformation/built_in/built_in.rest pyplusplus_dev/pyplusplus/function_transformers/transformers.py Added Paths: ----------- pyplusplus_dev/docs/documentation/functions/transformation/built_in/modify_type.rest Modified: pyplusplus_dev/docs/documentation/functions/transformation/built_in/built_in.rest =================================================================== --- pyplusplus_dev/docs/documentation/functions/transformation/built_in/built_in.rest 2006-12-31 09:34:53 UTC (rev 824) +++ pyplusplus_dev/docs/documentation/functions/transformation/built_in/built_in.rest 2006-12-31 11:27:03 UTC (rev 825) @@ -16,6 +16,8 @@ * ``inout`` +* ``modify_type`` + * ``input_static_array`` * ``output_static_array`` Added: pyplusplus_dev/docs/documentation/functions/transformation/built_in/modify_type.rest =================================================================== --- pyplusplus_dev/docs/documentation/functions/transformation/built_in/modify_type.rest (rev 0) +++ pyplusplus_dev/docs/documentation/functions/transformation/built_in/modify_type.rest 2006-12-31 11:27:03 UTC (rev 825) @@ -0,0 +1,78 @@ +=========================== +``modify_type`` transformer +=========================== + +.. contents:: Table of contents + +---------- +Definition +---------- + +"modify_type" transformer changes type of the function argument. + +"modify_type" transformer takes two arguments: + +1. name or index of the original function argument + +2. a callable, which takes as argument reference to type and returns new type + +New in version grater than 0.8.5. + +Known limits +------------ + +Implicit conversion should exist between new type and the old one. + +------- +Example +------- + +.. code-block:: C++ + + #include <string> + + inline void hello_world( std::string& hw ){ + hw = "hello world!"; + } + +Lets say that you need to expose ``hello_world`` function. As you know +``std::string`` is mapped to `Python`_ string, which is immutable type, so you +have to create small wrapper for the function. Next `Py++`_ code does it for you: + + .. code-block:: Python + + from pygccxml import declarations + from pyplusplus import module_builder + from pyplusplus import function_transformers as FT + + mb = module_builder.module_builder_t( ... ) + hw = mb.mem_fun( 'hello_world' ) + hw.add_transformation( FT.modify_type(0, declarations.remove_reference) ) + +What you see below is the relevant pieces of generated code: + + .. code-block:: C++ + + namespace bp = boost::python; + + static void hello_world_a3478182294a057b61508c30b1361318( ::std::string hw ){ + ::hello_world(hw); + } + + BOOST_PYTHON_MODULE(...){ + ... + bp::def( "hello_world", &hello_world_a3478182294a057b61508c30b1361318 ); + } + +.. _`Py++` : ./../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: Modified: pyplusplus_dev/pyplusplus/function_transformers/transformers.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/transformers.py 2006-12-31 09:34:53 UTC (rev 824) +++ pyplusplus_dev/pyplusplus/function_transformers/transformers.py 2006-12-31 11:27:03 UTC (rev 825) @@ -14,6 +14,7 @@ - L{inout_t} - L{input_array_t} - L{output_array_t} + - L{type_modifier_t} """ import os import string This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2007-01-01 05:43:58
|
Revision: 826 http://svn.sourceforge.net/pygccxml/?rev=826&view=rev Author: roman_yakovenko Date: 2006-12-31 21:43:59 -0800 (Sun, 31 Dec 2006) Log Message: ----------- fixing bug Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp pyplusplus_dev/unittests/function_transformations_tester.py Modified: pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py 2006-12-31 11:27:03 UTC (rev 825) +++ pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py 2007-01-01 05:43:59 UTC (rev 826) @@ -109,9 +109,9 @@ @property def pre_return_code( self ): if None is self.__pre_return_code: - if not self.__controller.return_variables \ - or self.__function.call_policies.is_default() \ - or declarations.is_void( self.__function.return_type ): + if declarations.is_void( self.__function.return_type ) \ + and ( self.__function.call_policies.is_default() \ + or False == bool( self.__controller.return_variables ) ): self.__pre_return_code = '' else: c_p_typedef = 'typedef %s %s;' \ Modified: pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp 2006-12-31 11:27:03 UTC (rev 825) +++ pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp 2007-01-01 05:43:59 UTC (rev 826) @@ -212,6 +212,11 @@ int do_nothing( int& v ){ return v; } + + modify_type_tester_t* clone(int& c){ + return new modify_type_tester_t(); + } + }; } Modified: pyplusplus_dev/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev/unittests/function_transformations_tester.py 2006-12-31 11:27:03 UTC (rev 825) +++ pyplusplus_dev/unittests/function_transformations_tester.py 2007-01-01 05:43:59 UTC (rev 826) @@ -75,6 +75,10 @@ do_nothing = cls.mem_fun( 'do_nothing' ) do_nothing.add_transformation( ft.modify_type(0, declarations.remove_reference ) ) + clone = cls.mem_fun( 'clone' ) + clone.call_policies = call_policies.return_value_policy( call_policies.manage_new_object ) + clone.add_transformation( ft.modify_type(0, declarations.remove_reference ) ) + def run_tests(self, module): """Run the actual unit tests. """ @@ -221,6 +225,7 @@ tmp = module.modify_type_tester_t() self.failUnless( 123 == tmp.do_nothing(123) ) + self.failUnless( tmp != tmp.clone(123) ) def create_suite(): suite = unittest.TestSuite() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2007-01-02 08:17:15
|
Revision: 828 http://svn.sourceforge.net/pygccxml/?rev=828&view=rev Author: roman_yakovenko Date: 2007-01-02 00:17:13 -0800 (Tue, 02 Jan 2007) Log Message: ----------- fixing compilation bug Modified Paths: -------------- pyplusplus_dev/docs/links.rest pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py pyplusplus_dev/pyplusplus/code_repository/call_policies.py Modified: pyplusplus_dev/docs/links.rest =================================================================== --- pyplusplus_dev/docs/links.rest 2007-01-01 21:49:42 UTC (rev 827) +++ pyplusplus_dev/docs/links.rest 2007-01-02 08:17:13 UTC (rev 828) @@ -45,6 +45,9 @@ * http://www.google.com :-) + This site uses Google custom search engine, turned to provide better results + when you search for materials related to `Boost.Python`_ library. + * http://boost.org/libs/python/doc/index.html - tutorials, FAQs, reference manuals @@ -73,6 +76,26 @@ .. _`Boost.Python`: http://www.boost.org/libs/python/doc/index.html .. _`Py++` : ./pyplusplus.html + +---------------------------------- +Libraries inspired by Boost.Python +---------------------------------- + +* `Luabind`_ - interfacing C++ and `Lua`_ + +.. _`Luabind` : http://www.rasterbar.com/products/luabind/docs.html +.. _`Lua` : http://www.lua.org/ + +* `Pyd`_ - interfacing C++ and `D programming language`_ + +.. _`Pyd` : http://pyd.dsource.org/index.html +.. _`D programming language` : http://www.digitalmars.com/d/ + +* `Sq Plus`_ - interfacing C++ and `Squirrel`_ + +.. _`Sq Plus` : http://wiki.squirrel-lang.org/default.aspx/SquirrelWiki/SqPlus.html +.. _`Squirrel` : http://wiki.squirrel-lang.org/ + .. Local Variables: mode: indented-text Modified: pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py 2007-01-01 21:49:42 UTC (rev 827) +++ pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py 2007-01-02 08:17:13 UTC (rev 828) @@ -134,7 +134,8 @@ else: self.__return_vars.insert( 0 , declarations.call_invocation.join( - declarations.templates.join( make_object, [self.__call_policy_alias] ) + declarations.templates.join( make_object + , [self.__call_policy_alias, self.__result_var.type.decl_string] ) , [self.__result_var.name] ) ) if 0 == len( self.__return_vars ): Modified: pyplusplus_dev/pyplusplus/code_repository/call_policies.py =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/call_policies.py 2007-01-01 21:49:42 UTC (rev 827) +++ pyplusplus_dev/pyplusplus/code_repository/call_policies.py 2007-01-02 08:17:13 UTC (rev 828) @@ -71,7 +71,7 @@ }; template< typename CallPolicies, class T > -bpl::object make_object( T const & x ){ +bpl::object make_object( T x ){ //constructs object using CallPolicies result_converter typedef BOOST_DEDUCED_TYPENAME CallPolicies::result_converter:: template apply< T >::type result_converter_t; result_converter_t rc; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2007-01-07 07:28:44
|
Revision: 855 http://svn.sourceforge.net/pygccxml/?rev=855&view=rev Author: roman_yakovenko Date: 2007-01-06 23:28:43 -0800 (Sat, 06 Jan 2007) Log Message: ----------- adding warning and xml cache Modified Paths: -------------- pygccxml_dev/pygccxml/parser/scanner.py pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py pyplusplus_dev/pyplusplus/messages/warnings_.py pyplusplus_dev/unittests/fundamental_tester_base.py Modified: pygccxml_dev/pygccxml/parser/scanner.py =================================================================== --- pygccxml_dev/pygccxml/parser/scanner.py 2007-01-07 06:14:07 UTC (rev 854) +++ pygccxml_dev/pygccxml/parser/scanner.py 2007-01-07 07:28:43 UTC (rev 855) @@ -322,7 +322,7 @@ if isinstance( calldef, declaration_t ): calldef.name = attrs.get(XML_AN_NAME, '') calldef.has_extern = attrs.get( XML_AN_EXTERN, False ) - throw_stmt = attrs.get( XML_AN_THROW, "" ) + throw_stmt = attrs.get( XML_AN_THROW, None ) if None is throw_stmt: calldef.does_throw = True calldef.exceptions = [] Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2007-01-07 06:14:07 UTC (rev 854) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2007-01-07 07:28:43 UTC (rev 855) @@ -208,6 +208,13 @@ return messages.W1011 return '' + def _readme_impl( self ): + msgs = super( member_function_t, self )._readme_impl() + if self.does_throw == False \ + and self.virtuality != declarations.VIRTUALITY_TYPES.NOT_VIRTUAL: + msgs.append( messages.W1046 ) + return msgs + class constructor_t( declarations.constructor_t, calldef_t ): """defines a set of properties, that will instruct Py++ how to expose the constructor""" def __init__(self, *arguments, **keywords): Modified: pyplusplus_dev/pyplusplus/messages/warnings_.py =================================================================== --- pyplusplus_dev/pyplusplus/messages/warnings_.py 2007-01-07 06:14:07 UTC (rev 854) +++ pyplusplus_dev/pyplusplus/messages/warnings_.py 2007-01-07 07:28:43 UTC (rev 855) @@ -132,6 +132,11 @@ 'You can fix this by setting array size to the actual one.' \ 'For more information see "array_t" class documentation.' +W1046 = 'The virtual function was declared with empty throw. ' \ + 'Adding the ability to override the function from Python breaks the exception specification. ' \ + 'The function wrapper can throw any exception. ' \ + 'In case of exception in run-time, the behaviour of the program is undefined! ' + warnings = globals() for identifier, explanation in warnings.items(): Modified: pyplusplus_dev/unittests/fundamental_tester_base.py =================================================================== --- pyplusplus_dev/unittests/fundamental_tester_base.py 2007-01-07 06:14:07 UTC (rev 854) +++ pyplusplus_dev/unittests/fundamental_tester_base.py 2007-01-07 07:28:43 UTC (rev 855) @@ -7,6 +7,7 @@ import sys import unittest import autoconfig +from pygccxml import parser from pyplusplus import module_builder LICENSE = """// Copyright 2004 Roman Yakovenko. @@ -63,7 +64,12 @@ def _create_extension_source_file(self): global LICENSE - mb = module_builder.module_builder_t( [self.__to_be_exported_header] + + xml_file = os.path.split( self.__to_be_exported_header )[1] + xml_file = os.path.join( autoconfig.build_dir, xml_file + '.xml' ) + xml_cached_fc = parser.create_cached_source_fc( self.__to_be_exported_header, xml_file ) + + mb = module_builder.module_builder_t( [xml_cached_fc] , gccxml_path=autoconfig.gccxml.executable , include_paths=[autoconfig.boost.include] , undefine_symbols=['__MINGW32__'] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2007-01-07 12:51:08
|
Revision: 856 http://svn.sourceforge.net/pygccxml/?rev=856&view=rev Author: roman_yakovenko Date: 2007-01-07 04:51:09 -0800 (Sun, 07 Jan 2007) Log Message: ----------- adding new feature - aliases test. Modified Paths: -------------- pyplusplus_dev/pyplusplus/messages/warnings_.py pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py pyplusplus_dev/unittests/test_all.py Added Paths: ----------- pyplusplus_dev/unittests/data/duplicate_aliases_to_be_exported.cpp pyplusplus_dev/unittests/data/duplicate_aliases_to_be_exported.hpp pyplusplus_dev/unittests/duplicate_aliases_tester.py Modified: pyplusplus_dev/pyplusplus/messages/warnings_.py =================================================================== --- pyplusplus_dev/pyplusplus/messages/warnings_.py 2007-01-07 07:28:43 UTC (rev 855) +++ pyplusplus_dev/pyplusplus/messages/warnings_.py 2007-01-07 12:51:09 UTC (rev 856) @@ -137,6 +137,11 @@ 'The function wrapper can throw any exception. ' \ 'In case of exception in run-time, the behaviour of the program is undefined! ' +W1047 = 'There are two or more classes that use same alias("%s"). ' \ + 'Duplicated aliases causes few problems, but the main one is that some ' \ + 'of the classes will not be exposed to Python.' \ + 'Other classes : %s' + warnings = globals() for identifier, explanation in warnings.items(): Modified: pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2007-01-07 07:28:43 UTC (rev 855) +++ pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2007-01-07 12:51:09 UTC (rev 856) @@ -19,6 +19,41 @@ def add_exported( self, decl ): self.__exported_decls.append( decl ) + def __select_duplicate_aliases( self, decls ): + duplicated = {} + for decl in decls: + if not duplicated.has_key( decl.alias ): + duplicated[ decl.alias ] = set() + duplicated[ decl.alias ].add( decl ) + for alias, buggy_decls in duplicated.items(): + if 1 == len( buggy_decls ): + del duplicated[ alias ] + return duplicated + + def __report_duplicate_aliases_impl( self, control_decl, duplicated ): + if control_decl.alias in duplicated: + buggy_decls = duplicated[control_decl.alias].copy() + buggy_decls.remove( control_decl ) + warning = messages.W1047 % ( control_decl.alias + , os.linesep.join( map( str, buggy_decls ) ) ) + self.__logger.warn( "%s;%s" % ( control_decl, warning ) ) + + if isinstance( control_decl, declarations.class_t ): + query = lambda i_decl: isinstance( i_decl, declarations.class_types ) \ + and i_decl.ignore == False + i_decls = control_decl.classes( query, recursive=False, allow_empty=True ) + i_duplicated = self.__select_duplicate_aliases( i_decls ) + for i_decl in i_decls: + self.__report_duplicate_aliases_impl( i_decl, i_duplicated ) + + def __report_duplicate_aliases( self ): + decls = filter( lambda decl: isinstance( decl, declarations.class_types ) \ + and isinstance( decl.parent, declarations.namespace_t ) + , self.__exported_decls ) + duplicated = self.__select_duplicate_aliases( decls ) + for decl in decls: + self.__report_duplicate_aliases_impl( decl, duplicated ) + def __is_std_decl( self, decl ): #Every class under std should be exported by Boost.Python and\\or Py++ #Also this is not the case right now, I prefer to hide the warnings @@ -34,6 +69,7 @@ def __build_dependencies( self, decl ): if self.__is_std_decl( decl ): + #TODO add element_type to the list of dependencies return [] #std declarations should be exported by Py++! dependencies = decl.i_depend_on_them(recursive=False) @@ -69,7 +105,7 @@ groups[ id( depend_on_decl ) ].append( dependency ) return groups - def __create_msg( self, dependencies ): + def __create_dependencies_msg( self, dependencies ): depend_on_decl = dependencies[0].find_out_depend_on_declaration() decls = [] for dependency in dependencies: @@ -80,4 +116,5 @@ used_not_exported_decls = self.__find_out_used_but_not_exported() groups = self.__group_by_unexposed( used_not_exported_decls ) for group in groups.itervalues(): - self.__logger.warn( self.__create_msg( group ) ) + self.__logger.warn( self.__create_dependencies_msg( group ) ) + self.__report_duplicate_aliases() Added: pyplusplus_dev/unittests/data/duplicate_aliases_to_be_exported.cpp =================================================================== --- pyplusplus_dev/unittests/data/duplicate_aliases_to_be_exported.cpp (rev 0) +++ pyplusplus_dev/unittests/data/duplicate_aliases_to_be_exported.cpp 2007-01-07 12:51:09 UTC (rev 856) @@ -0,0 +1,13 @@ +// 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) + +#include "duplicate_aliases_to_be_exported.hpp" + +namespace duplicate_aliases{ + + +}//duplicate_aliases + + Added: pyplusplus_dev/unittests/data/duplicate_aliases_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/duplicate_aliases_to_be_exported.hpp (rev 0) +++ pyplusplus_dev/unittests/data/duplicate_aliases_to_be_exported.hpp 2007-01-07 12:51:09 UTC (rev 856) @@ -0,0 +1,22 @@ +// 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) + +#ifndef __duplicate_aliases_to_be_exported_hpp__ +#define __duplicate_aliases_to_be_exported_hpp__ + +namespace duplicate_aliases{ + +struct duplicate_aliases_1{}; +struct duplicate_aliases_2{}; +struct duplicate_aliases_3{ + + struct i_duplicate_aliases_4{}; + struct i_duplicate_aliases_5{}; + +}; + +} + +#endif//__duplicate_aliases_to_be_exported_hpp__ Added: pyplusplus_dev/unittests/duplicate_aliases_tester.py =================================================================== --- pyplusplus_dev/unittests/duplicate_aliases_tester.py (rev 0) +++ pyplusplus_dev/unittests/duplicate_aliases_tester.py 2007-01-07 12:51:09 UTC (rev 856) @@ -0,0 +1,38 @@ +# 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) + +import os +import sys +import unittest +import fundamental_tester_base +from pyplusplus import code_creators + +class tester_t(fundamental_tester_base.fundamental_tester_base_t): + EXTENSION_NAME = 'duplicate_aliases' + + def __init__( self, *args ): + fundamental_tester_base.fundamental_tester_base_t.__init__( + self + , tester_t.EXTENSION_NAME + , *args ) + + def customize(self, mb): + classes = mb.classes( lambda decl: 'duplicate_aliases' in decl.name ) + classes.alias = 'duplicate_aliases' + + def run_tests( self, module): + #check compilation + pass + +def create_suite(): + suite = unittest.TestSuite() + suite.addTest( unittest.makeSuite(tester_t)) + return suite + +def run_suite(): + unittest.TextTestRunner(verbosity=2).run( create_suite() ) + +if __name__ == "__main__": + run_suite() Modified: pyplusplus_dev/unittests/test_all.py =================================================================== --- pyplusplus_dev/unittests/test_all.py 2007-01-07 07:28:43 UTC (rev 855) +++ pyplusplus_dev/unittests/test_all.py 2007-01-07 12:51:09 UTC (rev 856) @@ -69,6 +69,7 @@ import declarations_order_bug_tester import function_transformations_tester import throw_tester +import duplicate_aliases_tester def create_suite(times): testers = [ @@ -134,6 +135,7 @@ , declarations_order_bug_tester , function_transformations_tester , throw_tester + , duplicate_aliases_tester ] main_suite = unittest.TestSuite() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |