pygccxml-commit Mailing List for C++ Python language bindings (Page 54)
Brought to you by:
mbaas,
roman_yakovenko
You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
(190) |
Apr
(166) |
May
(170) |
Jun
(75) |
Jul
(105) |
Aug
(131) |
Sep
(99) |
Oct
(84) |
Nov
(67) |
Dec
(54) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(66) |
Feb
(49) |
Mar
(25) |
Apr
(62) |
May
(21) |
Jun
(34) |
Jul
(9) |
Aug
(21) |
Sep
(5) |
Oct
|
Nov
(63) |
Dec
(34) |
2008 |
Jan
(10) |
Feb
(42) |
Mar
(26) |
Apr
(25) |
May
(6) |
Jun
(40) |
Jul
(18) |
Aug
(29) |
Sep
(6) |
Oct
(32) |
Nov
(14) |
Dec
(56) |
2009 |
Jan
(127) |
Feb
(52) |
Mar
(2) |
Apr
(10) |
May
(29) |
Jun
(3) |
Jul
|
Aug
(16) |
Sep
(4) |
Oct
(11) |
Nov
(8) |
Dec
(14) |
2010 |
Jan
(31) |
Feb
(1) |
Mar
(7) |
Apr
(9) |
May
(1) |
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2011 |
Jan
|
Feb
(8) |
Mar
(4) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2014 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <rom...@us...> - 2006-09-04 06:49:44
|
Revision: 516 http://svn.sourceforge.net/pygccxml/?rev=516&view=rev Author: roman_yakovenko Date: 2006-09-03 23:49:35 -0700 (Sun, 03 Sep 2006) Log Message: ----------- small refactoring before introducing "function transformation" functionality Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/__init__.py pyplusplus_dev/pyplusplus/code_creators/calldef.py pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pyplusplus_dev/pyplusplus/code_creators/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-09-04 06:17:49 UTC (rev 515) +++ pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-09-04 06:49:35 UTC (rev 516) @@ -74,6 +74,9 @@ from calldef import copy_constructor_wrapper_t from calldef import null_constructor_wrapper_t +from calldef import mem_fun_v_transformed_t +from calldef import mem_fun_v_transformed_wrapper_t + from global_variable import global_variable_base_t from global_variable import global_variable_t from global_variable import array_gv_t @@ -116,3 +119,49 @@ from exception_translator import exception_translator_t from exception_translator import exception_translator_register_t +from pygccxml import declarations + +ACCESS_TYPES = declarations.ACCESS_TYPES +VIRTUALITY_TYPES = declarations.VIRTUALITY_TYPES + + +def guess_mem_fun_creator_classes( decl ): + """return tuple of ( registration, declaration ) code creator classes""" + maker_cls = None + fwrapper_cls = None + access_level = decl.parent.find_out_member_access_type( decl ) + if access_level == ACCESS_TYPES.PUBLIC: + if decl.virtuality == VIRTUALITY_TYPES.NOT_VIRTUAL: + maker_cls = mem_fun_t + elif decl.virtuality == VIRTUALITY_TYPES.PURE_VIRTUAL: + fwrapper_cls = mem_fun_pv_wrapper_t + maker_cls = mem_fun_pv_t + else: + if decl.overridable: + fwrapper_cls = mem_fun_v_wrapper_t + maker_cls = mem_fun_v_t + elif access_level == ACCESS_TYPES.PROTECTED: + if decl.virtuality == VIRTUALITY_TYPES.NOT_VIRTUAL: + if decl.has_static: + fwrapper_cls = mem_fun_protected_s_wrapper_t + maker_cls = mem_fun_protected_s_t + else: + fwrapper_cls = mem_fun_protected_wrapper_t + maker_cls = mem_fun_protected_t + elif decl.virtuality == VIRTUALITY_TYPES.VIRTUAL: + if decl.overridable: + fwrapper_cls = mem_fun_protected_v_wrapper_t + maker_cls = mem_fun_protected_v_t + else: + fwrapper_cls = mem_fun_protected_pv_wrapper_t + maker_cls = mem_fun_protected_pv_t + else: #private + if decl.virtuality == VIRTUALITY_TYPES.NOT_VIRTUAL: + pass#in general we should not come here + elif decl.virtuality == VIRTUALITY_TYPES.PURE_VIRTUAL: + fwrapper_cls = mem_fun_private_pv_wrapper_t + else: + if decl.overridable: + fwrapper_cls = mem_fun_v_wrapper_t + maker_cls = mem_fun_v_t + return ( maker_cls, fwrapper_cls ) Modified: pyplusplus_dev/pyplusplus/code_creators/calldef.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-09-04 06:17:49 UTC (rev 515) +++ pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-09-04 06:49:35 UTC (rev 516) @@ -439,7 +439,130 @@ answer.append( self.create_default_function() ) return os.linesep.join( answer ) +class mem_fun_v_transformed_t( calldef_t ): + def __init__( self, function, wrapper=None ): + calldef_t.__init__( self, function=function, wrapper=wrapper ) + self.default_function_type_alias = 'default_' + self.function_type_alias + def create_function_type_alias_code( self, exported_class_alias=None ): + result = [] + + 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_doc(self): + return None + + def create_function_ref_code(self, use_function_alias=False): + result = [] + if use_function_alias: + result.append( '%s(&%s)' + % ( self.function_type_alias, declarations.full_name( self.declaration ) ) ) + if self.wrapper: + result.append( self.param_sep() ) + result.append( '%s(&%s)' + % ( self.default_function_type_alias, self.wrapper.default_full_name() ) ) + elif self.declaration.create_with_signature: + result.append( '(%s)(&%s)' + % ( self.declaration.function_type().decl_string + , declarations.full_name( self.declaration ) ) ) + if self.wrapper: + result.append( self.param_sep() ) + result.append( '(%s)(&%s)' + % ( self.wrapper.function_type().decl_string, self.wrapper.default_full_name() ) ) + else: + result.append( '&%s'% declarations.full_name( self.declaration ) ) + if self.wrapper: + result.append( self.param_sep() ) + result.append( '&%s' % self.wrapper.default_full_name() ) + return ''.join( result ) + +class mem_fun_v_transformed_wrapper_t( calldef_wrapper_t ): + def __init__( self, function ): + calldef_wrapper_t.__init__( self, function=function ) + + def default_full_name(self): + return self.parent.full_name + '::default_' + self.declaration.alias + + def function_type(self): + 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 create_declaration(self, name, has_virtual=True): + template = '%(virtual)s%(return_type)s %(name)s( %(args)s )%(constness)s %(throw)s' + + virtual = 'virtual ' + if not has_virtual: + virtual = '' + + constness = '' + if self.declaration.has_const: + constness = ' const ' + + return template % { + 'virtual' : virtual + , 'return_type' : self.declaration.return_type.decl_string + , 'name' : name + , 'args' : self.args_declaration() + , 'constness' : constness + , 'throw' : self.throw_specifier_code() + } + + def create_virtual_body(self): + template = [] + template.append( 'if( %(override)s func_%(alias)s = this->get_override( "%(alias)s" ) )' ) + template.append( self.indent('%(return_)sfunc_%(alias)s( %(args)s );') ) + template.append( 'else' ) + template.append( self.indent('%(return_)s%(wrapped_class)s::%(name)s( %(args)s );') ) + template = os.linesep.join( template ) + + return_ = '' + if not declarations.is_void( self.declaration.return_type ): + return_ = 'return ' + + return template % { + 'override' : self.override_identifier() + , 'name' : self.declaration.name + , 'alias' : self.declaration.alias + , 'return_' : return_ + , 'args' : self.function_call_args() + , 'wrapped_class' : self.wrapped_class_identifier() + } + + def create_default_body(self): + function_call = declarations.call_invocation.join( self.declaration.name + , [ self.function_call_args() ] ) + body = self.wrapped_class_identifier() + '::' + function_call + ';' + if not declarations.is_void( self.declaration.return_type ): + body = 'return ' + body + return body + + 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 create_default_function( self ): + answer = [ self.create_declaration('default_' + self.declaration.alias, False) + '{' ] + answer.append( self.indent( self.create_default_body() ) ) + answer.append( '}' ) + return os.linesep.join( answer ) + + def _create_impl(self): + answer = [ self.create_function() ] + answer.append( os.linesep ) + answer.append( self.create_default_function() ) + return os.linesep.join( answer ) + class mem_fun_protected_t( calldef_t ): def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-09-04 06:17:49 UTC (rev 515) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-09-04 06:49:35 UTC (rev 516) @@ -568,53 +568,13 @@ include = code_creators.include_t( header=fn ) self.__extmodule.adopt_include(include) - def guess_functions_code_creators( self ): - maker_cls = None - fwrapper_cls = None - access_level = self.curr_decl.parent.find_out_member_access_type( self.curr_decl ) - if access_level == ACCESS_TYPES.PUBLIC: - if self.curr_decl.virtuality == VIRTUALITY_TYPES.NOT_VIRTUAL: - maker_cls = code_creators.mem_fun_t - elif self.curr_decl.virtuality == VIRTUALITY_TYPES.PURE_VIRTUAL: - fwrapper_cls = code_creators.mem_fun_pv_wrapper_t - maker_cls = code_creators.mem_fun_pv_t - else: - if self.curr_decl.overridable: - fwrapper_cls = code_creators.mem_fun_v_wrapper_t - maker_cls = code_creators.mem_fun_v_t - elif access_level == ACCESS_TYPES.PROTECTED: - if self.curr_decl.virtuality == VIRTUALITY_TYPES.NOT_VIRTUAL: - if self.curr_decl.has_static: - fwrapper_cls = code_creators.mem_fun_protected_s_wrapper_t - maker_cls = code_creators.mem_fun_protected_s_t - else: - fwrapper_cls = code_creators.mem_fun_protected_wrapper_t - maker_cls = code_creators.mem_fun_protected_t - elif self.curr_decl.virtuality == VIRTUALITY_TYPES.VIRTUAL: - if self.curr_decl.overridable: - fwrapper_cls = code_creators.mem_fun_protected_v_wrapper_t - maker_cls = code_creators.mem_fun_protected_v_t - else: - fwrapper_cls = code_creators.mem_fun_protected_pv_wrapper_t - maker_cls = code_creators.mem_fun_protected_pv_t - else: #private - if self.curr_decl.virtuality == VIRTUALITY_TYPES.NOT_VIRTUAL: - pass#in general we should not come here - elif self.curr_decl.virtuality == VIRTUALITY_TYPES.PURE_VIRTUAL: - fwrapper_cls = code_creators.mem_fun_private_pv_wrapper_t - else: - if self.curr_decl.overridable: - fwrapper_cls = code_creators.mem_fun_v_wrapper_t - maker_cls = code_creators.mem_fun_v_t - return ( maker_cls, fwrapper_cls ) - def visit_member_function( self ): fwrapper = None self.__types_db.update( self.curr_decl ) if None is self.curr_decl.call_policies: self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) - maker_cls, fwrapper_cls = self.guess_functions_code_creators() + maker_cls, fwrapper_cls = code_creators.guess_mem_fun_creator_classes( self.curr_decl ) maker = None fwrapper = None @@ -678,7 +638,7 @@ and not self.curr_decl.has_const: #TODO: move this code to decl_wrappers return #only const casting operators can generate implicitly_convertible - + if None is self.curr_decl.call_policies: self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-04 06:18:05
|
Revision: 515 http://svn.sourceforge.net/pygccxml/?rev=515&view=rev Author: roman_yakovenko Date: 2006-09-03 23:17:49 -0700 (Sun, 03 Sep 2006) Log Message: ----------- adding documentation extractor interface to decl_wrappers package Modified Paths: -------------- pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py pyplusplus_dev/pyplusplus/module_builder/__init__.py pyplusplus_dev/unittests/algorithms_tester.py Added Paths: ----------- pyplusplus_dev/pyplusplus/decl_wrappers/doc_extractor.py Modified: pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py 2006-09-04 06:16:26 UTC (rev 514) +++ pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py 2006-09-04 06:17:49 UTC (rev 515) @@ -89,48 +89,51 @@ from indexing_suite1 import indexing_suite1_t from indexing_suite2 import indexing_suite2_t +from doc_extractor import doc_extractor_i + class dwfactory_t( declarations.decl_factory_t ): """ declarations factory class """ def __init__(self): declarations.decl_factory_t.__init__(self) - + def create_member_function( self, *arguments, **keywords ): return member_function_t(*arguments, **keywords) - + def create_constructor( self, *arguments, **keywords ): return constructor_t(*arguments, **keywords) - + def create_destructor( self, *arguments, **keywords ): return destructor_t(*arguments, **keywords) - + def create_member_operator( self, *arguments, **keywords ): return member_operator_t(*arguments, **keywords) - + def create_casting_operator( self, *arguments, **keywords ): return casting_operator_t(*arguments, **keywords) - + def create_free_function( self, *arguments, **keywords ): return free_function_t(*arguments, **keywords) - + def create_free_operator( self, *arguments, **keywords ): return free_operator_t(*arguments, **keywords) def create_class_declaration(self, *arguments, **keywords ): return class_declaration_t(*arguments, **keywords) - + def create_class( self, *arguments, **keywords ): return class_t(*arguments, **keywords) - + def create_enumeration( self, *arguments, **keywords ): return enumeration_t(*arguments, **keywords) - + def create_namespace( self, *arguments, **keywords ): return namespace_t(*arguments, **keywords) - + def create_typedef( self, *arguments, **keywords ): return typedef_t(*arguments, **keywords) - + def create_variable( self, *arguments, **keywords ): return variable_t(*arguments, **keywords) + Added: pyplusplus_dev/pyplusplus/decl_wrappers/doc_extractor.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/doc_extractor.py (rev 0) +++ pyplusplus_dev/pyplusplus/decl_wrappers/doc_extractor.py 2006-09-04 06:17:49 UTC (rev 515) @@ -0,0 +1,45 @@ +# 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) + +"""defines documentation extractor class interface""" + +import re + +class doc_extractor_i(object): + """defines documentation extractor interface""" + + __escape_re = re.compile (r'((\\x[a-f0-9][a-f0-9])|(\\*"))', re.I) + + def __init__( self, encoding='ascii' ): + object.__init__( self ) + self.encoding = encoding + + def extract( self, decl ): + """returns documentation text for the declaration + + This function should be implemented in derived class. + + Using decl.location.file_name and decl.location.line variables you can + find out the location of declaration within source file + """ + raise NotImplementedError() + + def __call__( self, decl ): + decl_doc = self.extract( decl ) + return self.escape_doc( decl_doc ) + + @staticmethod + def escape_doc( doc ): + """converts a text to be valid C++ string literals""" + def replace_escape(m): + g = m.group(1) + if g.startswith ('\\x'): + return g + '""' + elif g == '"': + return '\\"' + else: + return g + return '"%s"' % doc_extractor_i.__escape_re.sub( replace_escape, repr(doc)[1:-1] ) + Modified: pyplusplus_dev/pyplusplus/module_builder/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/module_builder/__init__.py 2006-09-04 06:16:26 UTC (rev 514) +++ pyplusplus_dev/pyplusplus/module_builder/__init__.py 2006-09-04 06:17:49 UTC (rev 515) @@ -8,7 +8,7 @@ functionality. L{module_builder_t} class is the main class. Please read it's documentation first. -Also take a look on tutorials. You can find them on Py++ +Also take a look on tutorials. You can find them on Py++ U{web site<http://www.language-binding.net>} """ @@ -45,6 +45,8 @@ from pyplusplus.decl_wrappers import print_declarations +from pyplusplus.decl_wrappers import doc_extractor_i + import call_policies from pygccxml import utils as __pygccxml_utils @@ -54,4 +56,4 @@ for l in __pygccxml_utils.loggers.all: l.setLevel( level ) for l in __pyplusplus_logging.loggers.all: - l.setLevel( level ) \ No newline at end of file + l.setLevel( level ) Modified: pyplusplus_dev/unittests/algorithms_tester.py =================================================================== --- pyplusplus_dev/unittests/algorithms_tester.py 2006-09-04 06:16:26 UTC (rev 514) +++ pyplusplus_dev/unittests/algorithms_tester.py 2006-09-04 06:17:49 UTC (rev 515) @@ -162,8 +162,14 @@ self.failUnless( [[1,2,3]] == split( seq, 3 ) ) self.failUnless( [[1,2,3]] == split( seq, 4 ) ) +class doc_extractor_tester_t( unittest.TestCase ): + def test( self ): + escaped_doc = module_builder.doc_extractor_i.escape_doc('Hello "Py++"') + self.failUnless( escaped_doc == '"Hello \\"Py++\\""' ) + def create_suite(): suite = unittest.TestSuite() + suite.addTest( unittest.makeSuite(doc_extractor_tester_t)) suite.addTest( unittest.makeSuite(class_organizer_tester_t)) suite.addTest( unittest.makeSuite(indent_tester_t)) suite.addTest( unittest.makeSuite(make_flatten_tester_t)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-04 06:16:31
|
Revision: 514 http://svn.sourceforge.net/pygccxml/?rev=514&view=rev Author: roman_yakovenko Date: 2006-09-03 23:16:26 -0700 (Sun, 03 Sep 2006) Log Message: ----------- updating history Modified Paths: -------------- pyplusplus_dev/docs/history/history.rest Modified: pyplusplus_dev/docs/history/history.rest =================================================================== --- pyplusplus_dev/docs/history/history.rest 2006-09-04 06:14:47 UTC (rev 513) +++ pyplusplus_dev/docs/history/history.rest 2006-09-04 06:16:26 UTC (rev 514) @@ -15,8 +15,8 @@ * Matthias Baas * Allen Bierbaum * Lakin Wecker - * Georgiy Dernovoy + * Gottfried Ganssauge ------------ Project name @@ -33,6 +33,22 @@ ------------- +Version 0.8.* +------------- + +1. Performance improvments. In some cases you can get x10 performance boost. + Many thanks to Allen Bierbaum! + +2. Convinience API for registering exception translator was introduced. + +3. `Py++`_ can generate code that uses ``BOOST_PYTHON_FUNCTION_OVERLOADS`` and + ``BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS`` macros. + +4. Treatment to previously generated and no more in-use files was added. By + default `Py++`_ will delete these files, but of course you can redefine this + behaviour. + +------------- Version 0.8.1 ------------- This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-04 06:14:53
|
Revision: 513 http://svn.sourceforge.net/pygccxml/?rev=513&view=rev Author: roman_yakovenko Date: 2006-09-03 23:14:47 -0700 (Sun, 03 Sep 2006) Log Message: ----------- updating history Modified Paths: -------------- pygccxml_dev/docs/history/history.rest Modified: pygccxml_dev/docs/history/history.rest =================================================================== --- pygccxml_dev/docs/history/history.rest 2006-09-03 19:19:45 UTC (rev 512) +++ pygccxml_dev/docs/history/history.rest 2006-09-04 06:14:47 UTC (rev 513) @@ -16,8 +16,18 @@ * Allen Bierbaum * Georgiy Dernovoy * Darren Garnier + * Gottfried Ganssauge ------------- +Version 0.8.* +------------- + +1. Few small bug fix and unit tests have been introduced on 64 Bit platform. + Many thanks to Gottfried Ganssauge! He also help me to discover and fix + some important bug in ``type_traits.__remove_alias`` function, by introducing + small example that reproduced the error. + +------------- Version 0.8.1 ------------- This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-03 19:19:53
|
Revision: 512 http://svn.sourceforge.net/pygccxml/?rev=512&view=rev Author: roman_yakovenko Date: 2006-09-03 12:19:45 -0700 (Sun, 03 Sep 2006) Log Message: ----------- adding unicode todo item Modified Paths: -------------- pyplusplus_dev/docs/peps/peps_index.rest Modified: pyplusplus_dev/docs/peps/peps_index.rest =================================================================== --- pyplusplus_dev/docs/peps/peps_index.rest 2006-09-03 18:41:14 UTC (rev 511) +++ pyplusplus_dev/docs/peps/peps_index.rest 2006-09-03 19:19:45 UTC (rev 512) @@ -62,7 +62,22 @@ .. _`DSL challenge` : ./dsl_challenge.html +--------------- +Unicode support +--------------- +In version 0.8.1 `Py++`_ introduced nice feature: automatic extraction and +integration of documentation strings. I estimated wrong the influence of the +feature on the project. First user, who actually tried it, was Gottfried Ganssauge. +He asked me to add support for documentation string that contains unicode characters. +These days I understand the influence. I should convert all strings in the whole +project to be unicode strings, with encoding specified by the user. This is a +lot of work, but I think this is really important. So this is high priority "TODO". + +http://www.joelonsoftware.com/articles/Unicode.html - a nice article, which +explains what is unicode, encoding and character sets. + + .. _`Py++` : ./../pyplusplus.html .. _`Boost.Python`: http://www.boost.org/libs/python/doc/index.html .. _`Python`: http://www.python.org This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-03 18:41:21
|
Revision: 511 http://svn.sourceforge.net/pygccxml/?rev=511&view=rev Author: roman_yakovenko Date: 2006-09-03 11:41:14 -0700 (Sun, 03 Sep 2006) Log Message: ----------- improving treatment of unrelevant files. Only files with ext .pypp.[h|c]pp will be removed Modified Paths: -------------- pyplusplus_dev/pyplusplus/file_writers/__init__.py pyplusplus_dev/pyplusplus/module_builder/builder.py Modified: pyplusplus_dev/pyplusplus/file_writers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/__init__.py 2006-09-03 11:37:31 UTC (rev 510) +++ pyplusplus_dev/pyplusplus/file_writers/__init__.py 2006-09-03 18:41:14 UTC (rev 511) @@ -22,6 +22,13 @@ from multiple_files import multiple_files_t from class_multiple_files import class_multiple_files_t +def has_pypp_extenstion( fname ): + """returns True if file has Py++ specific extension, otherwise False""" + for ext in ( multiple_files_t.HEADER_EXT, multiple_files_t.SOURCE_EXT ): + if fname.endswith( ext ): + return True + return False + def write_file( data, file_path ): """writes data to file""" if isinstance( data, types.StringTypes ): Modified: pyplusplus_dev/pyplusplus/module_builder/builder.py =================================================================== --- pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-09-03 11:37:31 UTC (rev 510) +++ pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-09-03 18:41:14 UTC (rev 511) @@ -313,9 +313,7 @@ all_files = os.listdir( dir_name ) all_files = map( lambda fname: os.path.join( dir_name, fname ), all_files ) - all_files = filter( lambda fname: os.path.isfile( fname ) \ - and os.path.splitext( fname )[1] in ( '.cpp', '.hpp' ) - , all_files ) + all_files = filter( file_writers.has_pypp_extenstion, all_files ) unused_files = set( all_files ).difference( set( written_files ) ) for fpath in unused_files: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-03 11:37:42
|
Revision: 510 http://svn.sourceforge.net/pygccxml/?rev=510&view=rev Author: roman_yakovenko Date: 2006-09-03 04:37:31 -0700 (Sun, 03 Sep 2006) Log Message: ----------- adding reference to simple installer for Boost Libraries Modified Paths: -------------- pyplusplus_dev/docs/download.rest Modified: pyplusplus_dev/docs/download.rest =================================================================== --- pyplusplus_dev/docs/download.rest 2006-09-03 10:55:07 UTC (rev 509) +++ pyplusplus_dev/docs/download.rest 2006-09-03 11:37:31 UTC (rev 510) @@ -32,12 +32,21 @@ ------------ In command prompt or shell change current directory to be "pyplusplus-X.Y.Z". -"X.Y.Z" is version of `Py++`_. Type next command: +"X.Y.Z" is version of `Py++`_. Type next command: | ``python setup.py install`` -After this command complete, you should have installed `Py++`_ package. +After this command complete, you should have installed `Py++`_ package. +Boost.Python installation +------------------------- + +Users of Microsoft Windows can enjoy from simple `installer for Boost Libraries`_. +You can find it `here`_. + +.. _`here` : http://www.boost-consulting.com/download.html +.. _`installer for Boost Libraries` : http://www.boost-consulting.com/download.html + ------------ Dependencies ------------ @@ -54,4 +63,4 @@ indent-tabs-mode: nil sentence-end-double-space: t fill-column: 70 - End: \ No newline at end of file + End: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-03 10:55:20
|
Revision: 509 http://svn.sourceforge.net/pygccxml/?rev=509&view=rev Author: roman_yakovenko Date: 2006-09-03 03:55:07 -0700 (Sun, 03 Sep 2006) Log Message: ----------- adding basic unit test for FT functionality Added Paths: ----------- pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp pyplusplus_dev/unittests/function_transformations_tester.py Added: pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp (rev 0) +++ pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp 2006-09-03 10:55:07 UTC (rev 509) @@ -0,0 +1,35 @@ +// 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 __function_transformations_to_be_exported_hpp__ +#define __function_transformations_to_be_exported_hpp__ + +namespace ft{ + +struct image_t{ + + image_t( unsigned int& h, unsigned int& w ) + : m_height( h ) + , m_width( w ) + {} + + void get_size( unsigned int& h, unsigned int& w ){ + h = m_height; + w = m_width; + } + + unsigned int m_width; + unsigned int m_height; + +}; + +inline void +get_image_size( image_t& img, unsigned int& h, unsigned int& w ){ + img.get_size( h, w ); +} + +} + +#endif//__function_transformations_to_be_exported_hpp__ Added: pyplusplus_dev/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev/unittests/function_transformations_tester.py (rev 0) +++ pyplusplus_dev/unittests/function_transformations_tester.py 2006-09-03 10:55:07 UTC (rev 509) @@ -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 + +class tester_t(fundamental_tester_base.fundamental_tester_base_t): + EXTENSION_NAME = 'function_transformations' + + def __init__( self, *args ): + fundamental_tester_base.fundamental_tester_base_t.__init__( + self + , tester_t.EXTENSION_NAME + , *args ) + + def customize( self, mb ): + image = mb.class_( "image_t" ) + pass + + def run_tests(self, module): + img = module.image_t( 2, 6) + h,w = img.get_size() + self.failUnless( h == 2 and w == 6 ) + +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() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-09-03 09:39:14
|
Revision: 508 http://svn.sourceforge.net/pygccxml/?rev=508&view=rev Author: mbaas Date: 2006-09-03 02:39:10 -0700 (Sun, 03 Sep 2006) Log Message: ----------- Added a property 'function_transformers' that is a list of function transformer objects that should be applied to the calldef. Modified Paths: -------------- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-09-03 09:31:45 UTC (rev 507) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-09-03 09:39:10 UTC (rev 508) @@ -28,6 +28,7 @@ self._use_default_arguments = True self._create_with_signature = False self._overridable = None + self._function_transformers = [] def get_call_policies(self): return self._call_policies @@ -114,6 +115,24 @@ overridable = property( get_overridable, set_overridable , doc = get_overridable.__doc__ ) + + def _get_function_transformers(self): + """Get method for property 'function_transformers'. + + Returns a reference to the internal list (which may be modified). + """ + return self._function_transformers + + def _set_function_transformers(self, function_transformers): + """Set method for property 'function_transformers'.""" + self._function_transformers = function_transformers + + function_transformers = property( _get_function_transformers, _set_function_transformers, + doc = """A list of function transformer objects that should be applied to the generated C++ code (default: []). + The returned list is the internal list (not a copy) which may be modified. + @type: list""") + + def _exportable_impl_derived( self ): return '' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-09-03 09:32:00
|
Revision: 507 http://svn.sourceforge.net/pygccxml/?rev=507&view=rev Author: mbaas Date: 2006-09-03 02:31:45 -0700 (Sun, 03 Sep 2006) Log Message: ----------- Added the 'function_transformers' sub-package. Modified Paths: -------------- pyplusplus_dev/setup.py Added Paths: ----------- pyplusplus_dev/pyplusplus/function_transformers/ pyplusplus_dev/pyplusplus/function_transformers/__init__.py pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py pyplusplus_dev/pyplusplus/function_transformers/code_manager.py pyplusplus_dev/pyplusplus/function_transformers/function_transformer.py pyplusplus_dev/pyplusplus/function_transformers/subst.py pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py Added: pyplusplus_dev/pyplusplus/function_transformers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/__init__.py (rev 0) +++ pyplusplus_dev/pyplusplus/function_transformers/__init__.py 2006-09-03 09:31:45 UTC (rev 507) @@ -0,0 +1,21 @@ +# Helper classes for wrapper function creation + +"""This sub-package provides text substitution services for creating C++ functions. + +The helper classes in this package are meant to be used by the actual +calldef code creators (that are not part of this sub-package). They +implement the core of the "arg policy" mechanism which can be used by +a user to modify the source code for a function. + +The main class of this sub-package is the class L{substitution_manager_t}. This +class maintains two sets of special variables, one for the wrapper function +and one for the virtual function, and provides text substitution services. +The variables contain parts of source code that can be inserted into the +function source code template which is generated by the user of the class. + + +""" + +from substitution_manager import substitution_manager_t +from function_transformer import function_transformer_t + Property changes on: pyplusplus_dev/pyplusplus/function_transformers/__init__.py ___________________________________________________________________ Name: svn:eol-style + native Added: pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py (rev 0) +++ pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py 2006-09-03 09:31:45 UTC (rev 507) @@ -0,0 +1,70 @@ +# 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 standard argument policy objects. +""" + +from pygccxml import declarations + +# Output +class Output: + """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.localvar = "<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, 'Output variable %d ("%s") must be a reference or a pointer (got %s)'%(self.idx, arg.name, arg.type) + + # Declare a local variable that will receive the output value + self.localvar = sm.wrapperfunc.declare_local(arg.name, str(reftype.base)) + # Append the output to the result tuple + sm.wrapperfunc.resultexprs.append(self.localvar) + + # Replace the expression in the C++ function call + if isinstance(reftype, declarations.pointer_t): + sm.wrapperfunc.inputparams[self.idx-1] = "&%s"%self.localvar + else: + sm.wrapperfunc.inputparams[self.idx-1] = self.localvar + + + def virtual_post_call(self, sm): + """Extract the C++ value after the call to the Python function. + """ + arg = sm.virtualfunc.arglist[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[%d]);"%(arg.name, arg.type.base, sm.virtualfunc.resultvar, sm.wrapperfunc.resultexprs.index(self.localvar)) + return res + + Property changes on: pyplusplus_dev/pyplusplus/function_transformers/arg_policies.py ___________________________________________________________________ Name: svn:eol-style + native Added: pyplusplus_dev/pyplusplus/function_transformers/code_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/code_manager.py (rev 0) +++ pyplusplus_dev/pyplusplus/function_transformers/code_manager.py 2006-09-03 09:31:45 UTC (rev 507) @@ -0,0 +1,267 @@ +# 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 types +from subst import subst_t + +# code_manager_t +class code_manager_t(subst_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_local()} + 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 RETTYPE, + FUNCNAME, ARGLIST, 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 classname: 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 CLASSSPEC variable. + @type classname: str + @ivar rettype: 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 RETTYPE. + @type rettype: str + @ivar arglist: The argument list. The items are pygccxml argument_t objects. This list will appear in the variables ARGLIST, ARGLISTDEF and ARGLISTTYPES. + @type arglist: list of argument_t + @ivar inputparams: A list of strings that contain the input parameter for the function call. This list is used for the INPUTPARAMS variable. + @type inputparams: list of str + @ivar resultvar: The name of the variable that will receive the result of the function call. If None, the return value is ignored. This attribute will be used for the variable RESULTVARASSIGNMENT. + @type resultvar: str + @ivar resultexpr: A string containing the expression that will be put after the "return" statement. This expression is used for the variable RETURNSTMT. + @type resultexpr: str + + @author: Matthias Baas + """ + + def __init__(self): + """Constructor. + """ + subst_t.__init__(self, blockvars=["DECLARATIONS", + "PRECALL", + "POSTCALL"]) + + # The name of the class of which the generated function is a member + # (pass None or an empty string if the function is a free function) + self.classname = None + + # Return type (the value may be any object where str(obj) is valid + # C++ code. The value None corresponds to "void"). + self.rettype = None + # The argument list. The items are argument_t objects. + self.arglist = [] + + # A list of strings that contain the input parameter for the + # function call + self.inputparams = [] + + # The name of the variable that will receive the result of the + # function call. If None, the return value is ignored. + self.resultvar = None + + # A string containing the expression that will be put after + # the "return" statement. + self.resultexpr = None + + # Key:Variable name / Value:(type,size,default) + self._declared_vars = {} + # A list with variable tuples: (name, type, size, default) + self._local_var_list = [] + + # declare_local + def declare_local(self, name, type, size=None, default=None): + """Declare a local variable and return its final name. + + @param name: The desired variable name + @type name: str + @param type: The type of the variable (must be valid C++ code) + @type type: str + @param size: The array length or None + @type size: int + @param default: The default value (must be valid C++ code) or None + @type default: str + @return: The assigned variable name (which is guaranteed to be unique) + @rtype: str + """ + name = self._make_name_unique(name) + self._declared_vars[name] = (type,size,default) + self._local_var_list.append((name, type, size, default)) + return name + + def is_defined(self, name): + """Check if a variable name is already in use. + + The method returns True if name is the name of an argument or of + a local variable. + + @rtype: bool + """ + if name in self._declared_vars: + return True + if filter(lambda a: a.name==name, self.arglist): + return True + return False + + def local_type_str(self, name): + """Return the type of a local variable. + + An exception is raised if a variable called name does not exist. + + @return: Returns the type of the specified local variable. + @rtype: str + """ + if name not in self._declared_vars: + raise ValueError, 'Local variable "%s" not found.'%name + + type,size,default = self._declared_vars[name] + + if size==None: + return type + else: + return "*%s"%type + + def init_variables(self): + """Initialize the substitution variables. + + Based on the (lowercase) attributes, the final (uppercase) + variables are created. Those variables are regular string + attributes. + """ + + # CLASSSPEC + if (self.classname in [None, ""]): + self.CLASSSPEC = "" + else: + self.CLASSSPEC = "%s::"%self.classname + + # RETTYPE + if self.rettype==None: + self.RETTYPE = "void" + else: + self.RETTYPE = str(self.rettype) + + # ARGLISTDEF + args = map(lambda a: str(a), self.arglist) + self.ARGLISTDEF = ", ".join(args) + + # ARGLIST + args = map(lambda s: s.split("=")[0], args) + self.ARGLIST = ", ".join(args) + + # ARGLISTTYPES + args = map(lambda a: str(a.type), self.arglist) + self.ARGLISTTYPES = ", ".join(args) + + # Create the declaration block -> DECLARATIONS + vardecls = [] + for varname,type,size,default in self._local_var_list: + if default==None: + vd = "%s %s"%(type, varname) + else: + vd = "%s %s = %s"%(type, varname, default) + if size!=None: + vd += "[%d]"%size + vardecls.append(vd+";") + self.DECLARATIONS = "\n".join(vardecls) + + # RESULTVARASSIGNMENT + if self.resultvar!=None: + self.RESULTVARASSIGNMENT = "%s = "%self.resultvar + + # INPUTPARAMS + self.INPUTPARAMS = ", ".join(self.inputparams) + + # RETURNSTMT + if self.resultexpr!=None: + self.RETURNSTMT = "return %s;"%self.resultexpr + + # _make_name_unique + def _make_name_unique(self, name): + """Make a variable name unique so that there's no clash with other names. + + @param name: The variable name that should be unique + @type name: str + @return: A unique name based on the input name + @rtype: str + """ + if not self.is_defined(name): + return name + + n = 2 + while 1: + newname = "%s_%d"%(name, n) + if not self.is_defined(newname): + return newname + n += 1 + + +# wrapper_code_manager_t +class wrapper_code_manager_t(code_manager_t): + """The CodeManager class for the wrapper function. + + In contrast to a regular C++ function a Python function can return + several values, so this class provides the extra attribute "resultexprs" + which is a list of individual expressions. Apart from that this + class is identical to L{code_manager_t}. + + @ivar resultexprs: Similar to resultexpr but this list variable can contain more than just one result. The items can be either strings containing the variable names (or expressions) that should be returned or it can be an argument_t object (usually from the argument list of the virtual function) whose name attribute will be used. This attribute only exists on the code manager for the wrapper function (the virtual function cannot return several values, use resultexpr instead). + @type resultexprs: list of str or argument_t + """ + + def __init__(self): + """Constructor. + """ + code_manager_t.__init__(self) + + # Similar to resultexpr but now there can be more than just one result + # The items can be either strings containing the variable names (or + # expressions) that should be returned or it can be an argument_t + # object (usually from the argument list of the virtual function) + # whose name attribute will be used. + self.resultexprs = [] + + def init_variables(self): + """Initialize the substitution variables. + """ + + # Prepare the variables for RETTYPE and RETURNSTMT... + + # Convert all items into strings + resultexprs = [] + for re in self.resultexprs: + # String? + if isinstance(re, types.StringTypes): + resultexprs.append(re) + # argument_t + else: + resultexprs.append(re.name) + + # No output values? + if len(resultexprs)==0: + self.rettype = None + self.resultexpr = None + # Exactly one output value? + elif len(resultexprs)==1: + self.rettype = "boost::python::object" + self.resultexpr = "boost::python::object(%s)"%resultexprs[0] + # More than one output value... + else: + self.rettype = "boost::python::object" + self.resultexpr = "boost::python::make_tuple(%s)"%(", ".join(resultexprs)) + + # Invoke the inherited method that sets the actual variables + code_manager_t.init_variables(self) + + Property changes on: pyplusplus_dev/pyplusplus/function_transformers/code_manager.py ___________________________________________________________________ Name: svn:eol-style + native Added: pyplusplus_dev/pyplusplus/function_transformers/function_transformer.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/function_transformer.py (rev 0) +++ pyplusplus_dev/pyplusplus/function_transformers/function_transformer.py 2006-09-03 09:31:45 UTC (rev 507) @@ -0,0 +1,109 @@ +# 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: 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: 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: 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: 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: 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: substitution_manager_t + @return: C++ code or None + @rtype: str + """ + pass + + def virtual_cleanup(self, sm): + pass + Property changes on: pyplusplus_dev/pyplusplus/function_transformers/function_transformer.py ___________________________________________________________________ Name: svn:eol-style + native Added: pyplusplus_dev/pyplusplus/function_transformers/subst.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/subst.py (rev 0) +++ pyplusplus_dev/pyplusplus/function_transformers/subst.py 2006-09-03 09:31:45 UTC (rev 507) @@ -0,0 +1,149 @@ +# 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 base class L{subst_t}. +""" + +import re + +# subst_t +class subst_t: + """Perform text substitutions. + + This class performs text substitutions on a template string. The + variables are simply stored as attributes inside the class and may + be of any type that can be converted to a string. An empty string + is used if a template string references a variable that does not + exist. + + Example:: + + sm = subst_t(blockvars=['BODY']) + sm.RETURNTYPE = 'int' + sm.FUNCNAME = 'foo' + sm.ARGLIST = 'int n' + sm.BODY = '''int res=0; + for(int i=0; i<n; i++) + { + res += n; + } + return res;''' + + template = ''' + $RETURNTYPE $FUNCNAME($ARGLIST) + { + $BODY + } + ''' + + print sm.substitute(template) + + The result of the substitution will be:: + + int foo(int n) + { + int res=0; + for(int i=0; i<n; i++) + { + res += n; + } + return res; + } + + The variable BODY is a block variable which means it may contain + an entire block of text where each line should be indented with + the same depth as the variable in the template string. The value + of BODY should not contain an already indented block. + + @author: Matthias Baas + """ + + def __init__(self, blockvars): + """Constructor. + + The argument blockvars is used to declare the names of those + variables that may contain a block of code (i.e. multiple lines). + + @param blockvars: A list of block variable names. + @type blockvars: list of str + """ + self._blockvars = dict(map(lambda x: (x,0), blockvars)) + + def substitute(self, template): + """Substitute the variables in template and return the result. + + All variables of the form "$<varname>" are replaced with the + corresponding attribute <varname>. Block variables must appear + in one single line. The indendation of the variable determines + the indendation of the entire block. + Unknown variables will be substituted with an empty string. + + @param template: The template string + @type template: str + @return: Returns the input string where all variables have been substituted. + @rtype: str + """ + + lines = [] + # Replace the block variables... + for line in template.split("\n"): + s = line.lstrip() + # Determine the indendation depth + depth = len(line)-len(s) + key = s.rstrip() + if key!="" and key[0]=="$" and key[1:] in self._blockvars: + block = getattr(self, key[1:], None) + if block==None or block=="": + line = None + else: + line = self._indent(depth, block) + else: + line = line.rstrip() + if line!=None and (line!="" or (lines!=[] and lines[-1]!="")): + lines.append(line) + code = "\n".join(lines) + + # Replace the non-block variables... + varexpr = re.compile("\$[a-zA-Z_]+") + while 1: + m = varexpr.search(code) + if m==None: + break + s = m.start() + e = m.end() + key = code[s+1:e] + code = "%s%s%s"%(code[:s], getattr(self, key, ""), code[e:]) + + # Replace trailing blanks on each line... + expr = re.compile("[ ]+$", re.MULTILINE) + code = expr.sub("", code) + + # Replace two subsequent empty lines with one single line... + expr = re.compile("^\n^\n", re.MULTILINE) + n1 = len(code) + while 1: + code = expr.sub("\n", code) + n2 = len(code) + if n2==n1: + break + n1 = n2 + + # Remove blank lines right after '{' or before '}' + code = code.replace("{\n\n", "{\n") + code = code.replace("\n\n}", "\n}") + + return code + + # _indent + def _indent(self, n, code): + """Indent source code. + """ + if code=="": + return "" + return "\n".join(map(lambda s: ((n*" ")+s).rstrip(), code.split("\n"))) + + Property changes on: pyplusplus_dev/pyplusplus/function_transformers/subst.py ___________________________________________________________________ Name: svn:eol-style + native Added: pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py (rev 0) +++ pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py 2006-09-03 09:31:45 UTC (rev 507) @@ -0,0 +1,554 @@ +# 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{substitution_manager_t} class. +""" + +from pygccxml import declarations +from code_manager import code_manager_t, wrapper_code_manager_t +from function_transformer import function_transformer_t + +# substitution_manager_t +class substitution_manager_t: + """Helper class for creating C++ source code for wrapper functions. + + The class does not create the entire function source code itself + but it maintains the individual parts that can be composed by the + user of the class. Those individual parts are stored inside + variables which can be used to perform text substitutions. + + Doing substitutions + =================== + + Here is an example that demonstrates the usage of the class. The + user creates a template string that contains the layout of the + entire wrapper function. Such a template string may look like + this:: + + $RETTYPE $CLASSSPEC$FUNCNAME($ARGLIST) + { + $DECLARATIONS + + $PRECALL + + $RESULTVARASSIGNMENT$CALLFUNCNAME($INPUTPARAMS); + + $POSTCALL + + $RETURNSTMT + } + + Any part of the function that is not fixed, i.e. that can be + modified by argument policies, is specified via a variable. The + substitution manager can now be used to substitute the variables with + their actual value. There are actually two sets of identical + variables, one for the wrapper function and one for the virtual + function. You choose a set either by using the L{subst_wrapper()} or + L{subst_virtual()} method for doing the substitution. For example, + performing a "wrapper" substitution on the above template string + might result in the following code:: + + boost::python::object Spam_wrapper::foo_wrapper(Spam& self, int mode) + { + int result; + int w; + int h; + + result = self.foo(w, &h, mode); + + return boost::python::make_tuple(result, w, h); + } + + In this example, the individual variables have the following values: + + - RETTYPE = C{boost::python::object} + - CLASSSPEC = C{Spam_wrapper::} + - FUNCNAME = C{foo_wrapper} + - ARGLIST = C{Spam& self, int mode} + - DECLARATIONS = C{int result;\\nint w;\\nint h;} + - PRECALL = <empty> + - RESULTVARASSIGNMENT = C{result =} + - CALLFUNCNAME = C{self.foo} + - INPUTPARAMS = C{w, &h, mode} + - POSTCALL = <empty> + - RETURNSTMT = C{return boost::python::make_tuple(result, w, h);} + + + Modifying the variables + ======================= + + In addition to the actual user of the class (who wants to do text + substitutions), the class is also used by the arg policies (code blocks) + to modify the variables. + There are two attributes L{wrapperfunc} and L{virtualfunc} that are + used to modify either the wrapper or the virtual function. If the + signature of the wrapper needs modification this should be done via + the methods L{remove_arg()} and L{insert_arg()} and not via the + wrapperfunc or virtualfunc attributes because this affects the + virtual function as well (because the virtual function makes a call + to the Python function). + + Variables + ========= + + + - RETTYPE: The return type (e.g. "void", "int", "boost::python::object") + + - CLASSSPEC: "<classname>::" or empty + + - FUNCNAME: The name of the wrapper or virtual function. + + - ARGLIST: The parameters for $FUNCNAME (including self if required) + + - ARGLISTDEF: Like ARGLIST, but including default values (if there are any) + + - ARGLISTTYPES: Like ARGLIST but the variable names are left out and only the types are listed (this can identify a particular signature). + + - DECLARATIONS: The declaration block + + - PRECALL:: + + +--------------------------+ + | [try {] | + +--------------------------+ + | Pre-call code block 1 | + +--------------------------+ + | Pre-call code block 2 | + +--------------------------+ + | ... | + +--------------------------+ + | Pre-call code block n | + +--------------------------+ + + - RESULTVARASSIGNMENT: "<varname> = " or empty + + - CALLFUNCNAME: The name of the function that should be invoked (self?). + + - INPUTPARAMS: The values or variables that will be passed to $FUNCNAME, + e.g. "a, b" or "0.5, 1.5" etc + + - POSTCALL:: + + +--------------------------+ + | Post-call code block n | + +--------------------------+ + | ... | + +--------------------------+ + | Post-call code block 2 | + +--------------------------+ + | Post-call code block 1 | + +--------------------------+ + | [} catch(...) {...}] | + +--------------------------+ + + - RETURNSTMT: "return <varname>" or "return boost::python::make_tuple(...)" + + + @ivar wrapperfunc: The L{code manager<code_manager_t>} object that manages the wrapper function. This is used by the arg policies to modify the wrapper function. + @type wrapperfunc: L{wrapper_code_manager_t} + @ivar virtualfunc: The L{code manager<code_manager_t>} object that manages the virtual function. This is used by the arg policies to modify the virtual function. + @type virtualfunc: L{code_manager_t} + + @group Methods called by the user of the class: append_code_block, subst_wrapper, subst_virtual, get_includes + @group Methods called by the arg policies: remove_arg, insert_arg, require_include + + @author: Matthias Baas + """ + + def __init__(self, decl, wrapperclass=None, transformers=None): + """Constructor. + + @param decl: calldef declaration + @type decl: calldef_t + @param wrapperclass: The name of the class the generated function should belong to (or None if the generated function should be a free function) + @type wrapperclass: str + @param transformers: Function transformer objects + @type transformers: list of function_transformer_t + """ + + # Code manager for the virtual function + self.virtualfunc = code_manager_t() + # Code manager for the wrapper function + self.wrapperfunc = wrapper_code_manager_t() + + # The declaration that represents the original C++ function + self.decl = decl + + # The function transformers + if transformers==None: + transformers = [] + self.transformers = transformers + + self.wrapperclass = wrapperclass + + # A list of required include files + self._virtual_includes = [] + self._wrapper_includes = [] + + # Initialize the code managers... + + if str(decl.return_type)=="void": + rettype = None + else: + rettype = decl.return_type + self.wrapperfunc.resultvar = self.wrapperfunc.declare_local("result", str(rettype)) + self.wrapperfunc.resultexprs = [self.wrapperfunc.resultvar] + + self.virtualfunc.rettype = rettype + self.virtualfunc.arglist = decl.arguments[:] + self.virtualfunc.classname = wrapperclass + self.virtualfunc.FUNCNAME = decl.name + self.virtualfunc.CALLFUNCNAME = decl.name + self.virtualfunc.inputparams = map(lambda a: a.name, decl.arguments) + + self.wrapperfunc.rettype = rettype + self.wrapperfunc.arglist = decl.arguments[:] + self.wrapperfunc.classname = wrapperclass + self.wrapperfunc.FUNCNAME = "%s_wrapper"%decl.alias + self.wrapperfunc.CALLFUNCNAME = decl.name + self.wrapperfunc.inputparams = map(lambda a: a.name, decl.arguments) + + # Check if we're dealing with a member function... + clsdecl = self._classDecl(decl) + if clsdecl!=None: + selfname = self.wrapperfunc._make_name_unique("self") + selfarg = declarations.argument_t(selfname, "%s&"%clsdecl.name) + self.wrapperfunc.arglist.insert(0, selfarg) + self.wrapperfunc.CALLFUNCNAME = "%s.%s"%(selfname, self.wrapperfunc.CALLFUNCNAME) + + # Argument index map + # Original argument index ---> Input arg index (indices are 0-based!) + # Initial state is the identity: f(x) = x + # The argument index map represents a function that maps the argument + # index of the original C++ function to the index of the corresponding + # parameter in the input parameter list for the Python call. + self.argidxmap = range(len(decl.arguments)) + + + # Flag that is set after the functions were initialized + self._funcs_initialized = False + + + def append_transformer(self, transformer): + """not yet implemented""" + pass + + # init_funcs + def init_funcs(self): + """Initialize the virtual function and the wrapper function. + + After this method has been called, the substitution variables + are ready for usage. + + It is not necessary to call this method manually, it is + automatically called at the time a substitution is requested. + """ + + # Append the default return_virtual_result_t code modifier + transformers = self.transformers+[return_virtual_result_t()] + + for cb in transformers: + if hasattr(cb, "init_funcs"): + cb.init_funcs(self) + + # Create a variable that will hold the result of the Python call + # inside the virtual function. + if len(self.wrapperfunc.resultexprs)>0: + self.virtualfunc.resultvar = self.virtualfunc.declare_local("pyresult", "boost::python::object") +# self.virtualfunc.resultexpr = self.virtualfunc.resultvar + + self.wrapperfunc.init_variables() + self.virtualfunc.init_variables() + + self._funcs_initialized = True + + # The default method which is used when a particular method from + # the code_base_t interface is not implemented + defmeth = lambda x: None + # Create the wrapper function pre-call block... + src = map(lambda cb: getattr(cb, "wrapper_pre_call", defmeth)(self), transformers) + src = filter(lambda x: x!=None, src) + precall = "\n\n".join(src) + self.wrapperfunc.PRECALL = precall + + # Create the wrapper function post-call block... + src = map(lambda cb: getattr(cb, "wrapper_post_call", defmeth)(self), transformers) + src = filter(lambda x: x!=None, src) + src.reverse() + postcall = "\n\n".join(src) + self.wrapperfunc.POSTCALL = postcall + + # Create the virtual function pre-call block... + src = map(lambda cb: getattr(cb, "virtual_pre_call", defmeth)(self), transformers) + src = filter(lambda x: x!=None, src) + precall = "\n\n".join(src) + self.virtualfunc.PRECALL = precall + + # Create the virtual function post-call block... + src = map(lambda cb: getattr(cb, "virtual_post_call", defmeth)(self), transformers) + src = filter(lambda x: x!=None, src) + src.reverse() + postcall = "\n\n".join(src) + self.virtualfunc.POSTCALL = postcall + + + # remove_arg + def remove_arg(self, idx): + """Remove an argument from the wrapper function. + + This function can also be used to remove the original return value + (idx=0). + + The function is supposed to be called by function transformer + objects. + + @param idx: Argument index of the original function (may be negative) + @type idx: int + @returns: Returns the argument_t object that was removed (or None + if idx is 0 and the function has no return type). You must not + modify this object as it may still be in use on the virtual + function. + @rtype: argument_t + """ + if self._funcs_initialized: + raise ValueError, "remove_arg() may only be called before function initialization." + if idx<0: + idx += len(self.virtualfunc.arglist)+1 + if idx>=len(self.virtualfunc.arglist)+1: + raise IndexError, "Index (%d) out of range."%idx + + # Remove original return type? + if idx==0: + if id(self.wrapperfunc.rettype)==id(self.wrapperfunc.rettype): + self.wrapperfunc.rettype = None + else: + raise ValueError, 'Argument %d not found on the wrapper function'%(idx) + # Remove argument... + else: + # Get the original argument... + arg = self.virtualfunc.arglist[idx-1] + # ...and remove it from the wrapper + try: + self.wrapperfunc.arglist.remove(arg) + except ValueError: + raise ValueError, 'Argument %d ("%s") not found on the wrapper function'%(idx, arg.name) + + # Remove the input parameter on the Python call in the + # virtual function. + paramidx = self.argidxmap[idx-1] + if paramidx==None: + raise ValueError, "Argument was already removed" + del self.virtualfunc.inputparams[paramidx] + self.argidxmap[idx-1] = None + for i in range(idx,len(self.argidxmap)): + if self.argidxmap[i]!=None: + self.argidxmap[i] -= 1 + + return arg + + # insert_arg + def insert_arg(self, idx, arg): + """Insert a new argument into the argument list of the wrapper function. + + This function is supposed to be called by function transformer + objects. + + @param idx: New argument index (may be negative) + @type idx: int + @param arg: New argument object + @type arg: argument_t + """ + if self._funcs_initialized: + raise ValueError, "insert_arg() may only be called before function initialization." + if idx==0: + pass + else: + if idx<0: + idx += len(self.wrapperfunc.arglist)+2 + self.wrapperfunc.arglist.insert(idx-1, arg) + + # What to insert? + self.virtualfunc.inputparams.insert(idx-1, "???") + # Adjust the argument index map + for i in range(idx-1,len(self.argidxmap)): + if self.argidxmap[i]!=None: + self.argidxmap[i] += 1 + + # require_include + def require_include(self, include, where=None): + """Declare an include file that is required for the code to compile. + + This function is supposed to be called by function transformer + objects to tell the substitution manager that they create code + that requires a particular header file. + + include is the name of the include file which may contain <> or "" + characters around the name. + + @param include: The name of the include file (may contain <> or "") + @type include: str + @param where: "wrapper", "virtual" or None (for both) + @type where: str + """ + if where not in ["wrapper", "virtual", None]: + raise ValueError, "Invalid 'where' argument: %s"%where + + if include=="": + return + + # Add apostrophes if there aren't any already + if include[0] not in '"<': + include = '"%s"'%include + + if where=="wrapper" or where==None: + if include not in self._wrapper_includes: + self._wrapper_includes.append(include) + + if where=="virtual" or where==None: + if include not in self._virtual_includes: + self._virtual_includes.append(include) + + # get_includes + def get_includes(self, where=None): + """Return a list of include files required for the wrapper and/or the virtual function. + + @param where: "wrapper", "virtual" or None (for a combined list) + @type where: str + @return: A list of include file names (all names contain <> or "") + @rtype: list of str + """ + if where not in ["wrapper", "virtual", None]: + raise ValueError, "Invalid 'where' argument: %s"%where + + if where=="wrapper": + return self._wrapper_includes[:] + + if where=="virtual": + return self._virtual_includes[:] + + # Merge both lists (without duplicating names) + res = self._virtual_includes[:] + for inc in self._wrapper_includes: + if inc not in res: + res.append(inc) + + return res + + # subst_virtual + def subst_virtual(self, template): + """Perform a text substitution using the "virtual" variable set. + + @return: Returns the input string that has all variables substituted. + @rtype: str + """ + if not self._funcs_initialized: + self.init_funcs() + return self.virtualfunc.substitute(template) + + # subst_wrapper + def subst_wrapper(self, template): + """Perform a text substitution using the "wrapper" variable set. + + @return: Returns the input string that has all variables substituted. + @rtype: str + """ + if not self._funcs_initialized: + self.init_funcs() + return self.wrapperfunc.substitute(template) + + # _classDecl + def _classDecl(self, decl): + """Return the class declaration that belongs to a member declaration. + """ + while decl.parent!=None: + parent = decl.parent + if isinstance(parent, declarations.class_t): + return parent + decl = parent + return None + + +# return_virtual_result_t +class return_virtual_result_t(function_transformer_t): + """Extract and return the result value of the virtual function. + + This is an internal code block object that is automatically appended + to the list of code blocks inside the substitution_manager_t class. + """ + + def __init__(self): + function_transformer_t.__init__(self) + self.resultvar = "<not initialized>" + + def __str__(self): + return "ReturnVirtualResult()"%(self.idx) + + def init_funcs(self, sm): + if sm.virtualfunc.rettype==None: + return + + # Declare the local variable that will hold the return value + # for the virtual function + self.resultvar = sm.virtualfunc.declare_local("result", sm.virtualfunc.rettype) + # Replace the result expression if there is still the default + # result expression (which will not work anyway) + if sm.virtualfunc.resultexpr==sm.virtualfunc.resultvar: + sm.virtualfunc.resultexpr = self.resultvar + + def virtual_post_call(self, sm): + # Search the result tuple of the wrapper function for the return + # value of the C++ function call. If the value exists it is extracted + # from the Python result tuple, converted to C++ and returned from + # the virtual function. If it does not exist, do nothing. + try: + resultidx = sm.wrapperfunc.resultexprs.index(sm.wrapperfunc.resultvar) + except ValueError: + return + + res = "// Extract the C++ return value\n" + res += "%s = boost::python::extract<%s>(%s[%d]);"%(self.resultvar, sm.virtualfunc.rettype, sm.virtualfunc.resultvar, resultidx) + return res + + +###################################################################### +if __name__=="__main__": + import pyplusplus + from pygccxml import parser + from arg_policies import Output + cpp = """ + class Spam + { + public: + int foo(int& w, int* h, int mode=0); + }; + """ + parser = parser.project_reader_t(parser.config.config_t(), + decl_factory=pyplusplus.decl_wrappers.dwfactory_t()) + root = parser.read_string(cpp) + spam = root[0].class_("Spam") + foo = spam.member_function("foo") + + wm = substitution_manager_t(foo, transformers=[Output(1), Output(2)], wrapperclass="Spam_wrapper") + + template = '''$RETTYPE $CLASSSPEC$FUNCNAME($ARGLIST) +{ + $DECLARATIONS + + $PRECALL + + $RESULTVARASSIGNMENT$CALLFUNCNAME($INPUTPARAMS); + + $POSTCALL + + $RETURNSTMT +} +''' + print wm.subst_virtual(template) + print wm.subst_wrapper(template) + print wm.get_includes() + print wm.get_includes("virtual") + print wm.get_includes("wrapper") Property changes on: pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py ___________________________________________________________________ Name: svn:eol-style + native Modified: pyplusplus_dev/setup.py =================================================================== --- pyplusplus_dev/setup.py 2006-09-03 07:59:17 UTC (rev 506) +++ pyplusplus_dev/setup.py 2006-09-03 09:31:45 UTC (rev 507) @@ -107,6 +107,7 @@ 'pyplusplus.decl_wrappers', 'pyplusplus.module_builder', 'pyplusplus.utils', + 'pyplusplus.function_transformers', 'pyplusplus._logging_'], cmdclass = {"doc" : doc_cmd} ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-09-03 07:59:30
|
Revision: 506 http://svn.sourceforge.net/pygccxml/?rev=506&view=rev Author: roman_yakovenko Date: 2006-09-03 00:59:17 -0700 (Sun, 03 Sep 2006) Log Message: ----------- adding treatment to unused files Modified Paths: -------------- pyplusplus_dev/pyplusplus/file_writers/__init__.py pyplusplus_dev/pyplusplus/file_writers/multiple_files.py pyplusplus_dev/pyplusplus/module_builder/builder.py pyplusplus_dev/unittests/algorithms_tester.py Modified: pyplusplus_dev/pyplusplus/file_writers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/__init__.py 2006-09-01 14:32:52 UTC (rev 505) +++ pyplusplus_dev/pyplusplus/file_writers/__init__.py 2006-09-03 07:59:17 UTC (rev 506) @@ -9,9 +9,9 @@ Right now 3 strategies were implemented: 1. All code is written in one file - + 2. Classic strategy of deviding classes to files: one class in one header + source files. - + 2.1 Huge classes are splitten to few source files. """ @@ -29,13 +29,15 @@ else: sf = single_file_t( data, file_path ) sf.write() - + def write_multiple_files( extmodule, dir_path ): """writes extmodule to multiple files""" mfs = multiple_files_t( extmodule, dir_path ) mfs.write() - + return mfs.written_files + def write_class_multiple_files( extmodule, dir_path, huge_classes ): """writes extmodule to multiple files and splits huge classes to few source files""" mfs = class_multiple_files_t( extmodule, dir_path, huge_classes ) - mfs.write() + mfs.write() + return mfs.written_files Modified: pyplusplus_dev/pyplusplus/file_writers/multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-09-01 14:32:52 UTC (rev 505) +++ pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-09-03 07:59:17 UTC (rev 506) @@ -16,7 +16,7 @@ """ This class implements classic strategy of deviding classes to files one class in one header + source files. - """ + """ HEADER_EXT = '.pypp.hpp' SOURCE_EXT = '.pypp.cpp' @@ -27,9 +27,9 @@ @type extmodule: module_t @param directory_path: The output directory where the source files are written @type directory_path: str - - @param write_main: if it is True, the class will write out a main file - that calls all the registration methods. + + @param write_main: if it is True, the class will write out a main file + that calls all the registration methods. @type write_main: boolean """ writer.writer_t.__init__(self, extmodule) @@ -39,8 +39,13 @@ self.split_header_names = [] # List of include file names for split files self.split_method_names = [] # List of methods from the split files self.write_main = write_main + self.written_files = [] - + + def write_file( self, fpath, content ): + self.written_files.append( fpath ) + writer.writer_t.write_file( fpath, content ) + def create_dir( self, directory_path ): """Create the output directory if it doesn't already exist. """ @@ -76,7 +81,7 @@ , "%(code)s" , '' , "#endif//__%(file_name)s_hpp__pyplusplus_wrapper__" ]) - + content = '' if self.extmodule.license: content = self.extmodule.license.create() + os.linesep @@ -117,19 +122,19 @@ includes = filter( lambda creator: isinstance( creator, code_creators.include_t ) , self.extmodule.creators ) answer.extend( map( lambda creator: creator.create(), includes ) ) - + for creator in creators: header = self.find_out_value_traits_header( creator ) if header: answer.append( '#include "%s"' % header ) - + if tail_headers: answer.extend( map( lambda header: '#include "%s"' % normalize( header ) , tail_headers ) ) - + return os.linesep.join( answer ) - - def create_namespaces_code( self, creators ): + + def create_namespaces_code( self, creators ): # Write all 'global' namespace_alias_t and namespace_using_t creators first... ns_types = ( code_creators.namespace_alias_t, code_creators.namespace_using_t ) ns_creators = filter( lambda x: isinstance( x, ns_types ), self.extmodule.creators ) @@ -152,15 +157,15 @@ @returns: The content for a cpp file @rtype: str """ - + if None is declaration_creators: declaration_creators = [] creators = registration_creators + declaration_creators - + answer = [] if self.extmodule.license: answer.append( self.extmodule.license.create() ) - + head_headers = [ file_name + self.HEADER_EXT ] answer.append( self.create_include_code( creators, head_headers ) ) @@ -182,7 +187,7 @@ answer.append( '' ) answer.append( '}' ) return os.linesep.join( answer ) - + def split_class_impl( self, class_creator): function_name = 'register_%s_class' % class_creator.alias file_path = os.path.join( self.directory_path, class_creator.alias ) @@ -198,7 +203,7 @@ if class_creator.wrapper: class_wrapper = class_creator.wrapper decl_creators.append( class_creator.wrapper ) - + # Write the .cpp file... cpp_code = self.create_source( class_creator.alias , function_name @@ -239,7 +244,7 @@ Write the value_traits class to header file, that will be included from files, that uses indexing suite 2 """ - header_name = self.create_value_traits_header_name( value_traits.declaration ) + header_name = self.create_value_traits_header_name( value_traits.declaration ) file_path = os.path.join( self.directory_path, header_name ) self.write_file( file_path , self.create_header( header_name.replace( '.', '_' ) @@ -271,10 +276,10 @@ , creators )) for creator in creators: creator.create = lambda: '' - self.extmodule.body.adopt_creator( + self.extmodule.body.adopt_creator( code_creators.custom_text_t( function_name + '();' ) , registrator_pos) - self.include_creators.append( code_creators.include_t( header_name ) ) + self.include_creators.append( code_creators.include_t( header_name ) ) self.split_header_names.append(header_name) self.split_method_names.append(function_name) @@ -320,20 +325,20 @@ value_traits_classes = filter( lambda x: isinstance(x, code_creators.value_traits_t ) , self.extmodule.creators ) map( self.split_value_traits, value_traits_classes ) - + # Obtain a list of all class creators... class_creators = filter( lambda x: isinstance(x, ( code_creators.class_t, code_creators.class_declaration_t ) ) , self.extmodule.body.creators ) # ...and write a .h/.cpp file for each class map( self.split_class, class_creators ) - + self.split_enums() self.split_global_variables() self.split_free_functions() - + if self.write_main: self.include_creators.sort( cmp=lambda ic1, ic2: cmp( ic1.header, ic2.header ) ) map( lambda creator: self.extmodule.adopt_include( creator ) , self.include_creators ) main_cpp = os.path.join( self.directory_path, self.extmodule.body.name + '.main.cpp' ) - self.write_file( main_cpp, self.extmodule.create() + os.linesep ) \ No newline at end of file + self.write_file( main_cpp, self.extmodule.create() + os.linesep ) Modified: pyplusplus_dev/pyplusplus/module_builder/builder.py =================================================================== --- pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-09-01 14:32:52 UTC (rev 505) +++ pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-09-03 07:59:17 UTC (rev 506) @@ -292,7 +292,7 @@ self.__merge_user_code() file_writers.write_file( self.code_creator, file_name ) - def split_module(self, dir_name, huge_classes=None): + def split_module(self, dir_name, huge_classes=None, on_unused_file_found=os.remove): """ Writes module to multiple files @@ -300,13 +300,34 @@ @type dir_name: string @param huge_classes: list that contains reference to classes, that should be split + + @param on_unused_file_found: callable object that represents the action that should be taken on + file, which is no more in use """ self.__merge_user_code() + written_files = [] if None is huge_classes: - file_writers.write_multiple_files( self.code_creator, dir_name ) + written_files = file_writers.write_multiple_files( self.code_creator, dir_name ) else: - file_writers.write_class_multiple_files( self.code_creator, dir_name, huge_classes ) + written_files = file_writers.write_class_multiple_files( self.code_creator, dir_name, huge_classes ) + all_files = os.listdir( dir_name ) + all_files = map( lambda fname: os.path.join( dir_name, fname ), all_files ) + all_files = filter( lambda fname: os.path.isfile( fname ) \ + and os.path.splitext( fname )[1] in ( '.cpp', '.hpp' ) + , all_files ) + + unused_files = set( all_files ).difference( set( written_files ) ) + for fpath in unused_files: + try: + if on_unused_file_found is os.remove: + self.logger.info( 'removing file "%s"' % fpath ) + on_unused_file_found( fpath ) + except Exception, error: + self.logger.exception( "Exception was catched, while executing 'on_unused_file_found' function." ) + + return written_files + #select decl(s) interfaces def decl( self, name=None, function=None, header_dir=None, header_file=None, recursive=None ): """Please see L{decl_wrappers.scopedef_t} class documentation""" @@ -561,4 +582,4 @@ return decl_wrappers.calldef_t.BOOST_PYTHON_MAX_ARITY def _set_BOOST_PYTHON_MAX_ARITY( self, value ): decl_wrappers.calldef_t.BOOST_PYTHON_MAX_ARITY = value - BOOST_PYTHON_MAX_ARITY = property( _get_BOOST_PYTHON_MAX_ARITY, _set_BOOST_PYTHON_MAX_ARITY ) \ No newline at end of file + BOOST_PYTHON_MAX_ARITY = property( _get_BOOST_PYTHON_MAX_ARITY, _set_BOOST_PYTHON_MAX_ARITY ) Modified: pyplusplus_dev/unittests/algorithms_tester.py =================================================================== --- pyplusplus_dev/unittests/algorithms_tester.py 2006-09-01 14:32:52 UTC (rev 505) +++ pyplusplus_dev/unittests/algorithms_tester.py 2006-09-03 07:59:17 UTC (rev 506) @@ -9,7 +9,7 @@ import autoconfig from pygccxml import parser from pygccxml import declarations -from pyplusplus import code_creators +from pyplusplus import code_creators from pyplusplus import module_creator from pyplusplus import module_builder from pyplusplus import utils as pypp_utils @@ -21,7 +21,7 @@ class make_flatten_tester_t(unittest.TestCase): def test(self): - mb = module_builder.module_builder_t( + mb = module_builder.module_builder_t( [ module_builder.create_text_fc( 'namespace enums{ enum { OK=1 }; }' ) ] , gccxml_path=autoconfig.gccxml.executable ) mb.namespace( name='::enums' ).include() @@ -31,24 +31,24 @@ class creator_finder_tester_t( unittest.TestCase ): def test_find_by_declaration(self): - mb = module_builder.module_builder_t( + mb = module_builder.module_builder_t( [ module_builder.create_text_fc( 'namespace enums{ enum color{ red = 1}; }' )] , gccxml_path=autoconfig.gccxml.executable ) mb.namespace( name='::enums' ).include() - enum_matcher = declarations.match_declaration_t( name='color' ) + enum_matcher = declarations.match_declaration_t( name='color' ) mb.build_code_creator( 'dummy' ) - enum_found = code_creators.creator_finder.find_by_declaration( + enum_found = code_creators.creator_finder.find_by_declaration( enum_matcher , mb.code_creator.creators ) self.failUnless( enum_found ) def test_find_by_class_instance(self): - mb = module_builder.module_builder_t( + mb = module_builder.module_builder_t( [ module_builder.create_text_fc( 'namespace enums{ enum color{ red = 1}; }' )] , gccxml_path=autoconfig.gccxml.executable ) mb.namespace( name='::enums' ).include() mb.build_code_creator('dummy') - enum_found = code_creators.creator_finder.find_by_class_instance( + enum_found = code_creators.creator_finder.find_by_class_instance( code_creators.enum_t , mb.code_creator.creators , recursive=True) @@ -64,14 +64,14 @@ answer.append( base.related_class ) answer.extend( self._findout_base_classes( base.related_class ) ) return answer - + def test(self): config = parser.config_t( gccxml_path=autoconfig.gccxml.executable ) code = [] code.append('struct a{};') code.append('struct b{};') code.append('struct c{};') - code.append('struct d : public a{};') + code.append('struct d : public a{};') code.append('struct e : public a, public b{};') code.append('struct f{};') code.append('struct g : public d, public f{};') @@ -92,7 +92,7 @@ class exclude_function_with_array_arg_tester_t( unittest.TestCase ): def test(self): - mb = module_builder.module_builder_t( + mb = module_builder.module_builder_t( [ module_builder.create_text_fc( 'namespace arr{ struct x{ x( int arr[3][3], int ){} x( const x arr[3][3], int ){} }; }' )] , gccxml_path=autoconfig.gccxml.executable ) arr = mb.namespace( name='arr' ) @@ -103,8 +103,8 @@ class readme_tester_t( unittest.TestCase ): CODE = \ """ - namespace xxx{ - int do_smth(int); + namespace xxx{ + int do_smth(int); typedef int Int; struct data_t{ data_t& operator--(int a); @@ -112,7 +112,7 @@ } """ def test(self): - mb = module_builder.module_builder_t( + mb = module_builder.module_builder_t( [ module_builder.create_text_fc( self.CODE )] , gccxml_path=autoconfig.gccxml.executable ) xxx = mb.namespace( name='xxx' ) @@ -128,27 +128,29 @@ struct X{ enum EColor{ red, blue }; enum EFruit{ apple, orange }; - + X(){} X( int ){} - + void do_nothing(){} - + int do_somghing(){ return 1; } - - int m_dummy; + + int m_dummy; }; } """ def test(self): - mb = module_builder.module_builder_t( + mb = module_builder.module_builder_t( [ module_builder.create_text_fc( self.CLASS_DEF ) ] , gccxml_path=autoconfig.gccxml.executable ) mb.namespace( name='::tester' ).include() X = mb.class_( 'X' ) X.add_declaration_code( '//hello world' ) mb.build_code_creator('dummy') - mb.split_module( autoconfig.build_dir, [ mb.class_( '::tester::X' ) ] ) + mb.split_module( autoconfig.build_dir + , [ mb.class_( '::tester::X' ) ] + , on_unused_file_found=lambda fpath: fpath ) class split_sequence_tester_t(unittest.TestCase): @@ -161,7 +163,7 @@ self.failUnless( [[1,2,3]] == split( seq, 4 ) ) def create_suite(): - suite = unittest.TestSuite() + suite = unittest.TestSuite() suite.addTest( unittest.makeSuite(class_organizer_tester_t)) suite.addTest( unittest.makeSuite(indent_tester_t)) suite.addTest( unittest.makeSuite(make_flatten_tester_t)) @@ -170,12 +172,12 @@ suite.addTest( unittest.makeSuite(class_multiple_files_tester_t)) suite.addTest( unittest.makeSuite(readme_tester_t)) suite.addTest( unittest.makeSuite(split_sequence_tester_t)) - - + + return suite def run_suite(): 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: <al...@us...> - 2006-09-01 14:32:54
|
Revision: 505 http://svn.sourceforge.net/pygccxml/?rev=505&view=rev Author: allenb Date: 2006-09-01 07:32:52 -0700 (Fri, 01 Sep 2006) Log Message: ----------- Add re import. Modified Paths: -------------- pyplusplus_dev/contrib/goodies/goodie_utils.py Modified: pyplusplus_dev/contrib/goodies/goodie_utils.py =================================================================== --- pyplusplus_dev/contrib/goodies/goodie_utils.py 2006-08-31 21:43:49 UTC (rev 504) +++ pyplusplus_dev/contrib/goodies/goodie_utils.py 2006-09-01 14:32:52 UTC (rev 505) @@ -14,6 +14,7 @@ import pyplusplus.code_creators as code_creators import pyplusplus.decl_wrappers as decl_wrappers import copy +import re def set_recursive_default(val): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <al...@us...> - 2006-08-31 21:43:52
|
Revision: 504 http://svn.sourceforge.net/pygccxml/?rev=504&view=rev Author: allenb Date: 2006-08-31 14:43:49 -0700 (Thu, 31 Aug 2006) Log Message: ----------- - Use new code inserting interfaces - Use a "better" template instantiation method so there are no compiler warnings - Fix a bug in const wrapper method. Modified Paths: -------------- pyplusplus_dev/contrib/goodies/goodie_utils.py Modified: pyplusplus_dev/contrib/goodies/goodie_utils.py =================================================================== --- pyplusplus_dev/contrib/goodies/goodie_utils.py 2006-08-31 10:05:20 UTC (rev 503) +++ pyplusplus_dev/contrib/goodies/goodie_utils.py 2006-08-31 21:43:49 UTC (rev 504) @@ -51,10 +51,7 @@ def add_method(moduleBuilder, methodName, method): """ Add a method to the module builder. """ code_text = 'boost::python::def("%s",%s);'%(methodName, method) - moduleBuilder.code_creator.body.adopt_creator( code_creators.custom_text_t( code_text ), 0 ) - #[Roman]moduleBuilder.add_registration_code( ... ), see relevant documentation - #This will add have exactly same effect as a previous line, also you don't - #have to build code creator first + moduleBuilder.add_registration_code(code_text) def is_const_ref(type): @@ -113,10 +110,13 @@ elif tt.is_const(old_arg): new_args[i].type = tt.remove_const(old_arg_type) - new_name = "%s_const_ref_wrapper"%c.name + wrapper_name = "%s_const_ref_wrapper"%c.name args_str = [str(a) for a in new_args] arg_names_str = [str(a.name) for a in new_args] - new_sig = "static %s %s(%s& self_arg, %s)"%(c.return_type,new_name,cls.name,",".join(args_str)) + new_sig = "static %s %s(%s& self_arg, %s)"%(c.return_type, + wrapper_name, + pd.full_name(cls), + ",".join(args_str)) new_method = """%s { return self_arg.%s(%s); } """%(new_sig,c.name,",".join(arg_names_str)) @@ -127,9 +127,10 @@ #[Roman] you can use cls.add_declaration_code, this could simplify the #wrapper you created, because it will generate the code within the source #file, the class is generated - cls.add_wrapper_code(new_method) + cls.add_declaration_code(new_method) - cls.add_code('def("%s", &%s::%s);'%(c.name, cls.wrapper_alias,new_name)) + cls.add_registration_code('def("%s", &%s)'%(c.name, wrapper_name), + works_on_instance=True) class TemplateWrapper: @@ -231,8 +232,8 @@ typedef_name = t.mTypedefName content += """ typedef %(template_type)s %(typedef_name)s; - inline void __instantiate_%(typedef_name)s() - { sizeof(%(typedef_name)s); } + inline unsigned __instantiate_%(typedef_name)s() + { return unsigned(sizeof(%(typedef_name)s)); } """ % vars() return content This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-08-31 10:05:23
|
Revision: 503 http://svn.sourceforge.net/pygccxml/?rev=503&view=rev Author: mbaas Date: 2006-08-31 03:05:20 -0700 (Thu, 31 Aug 2006) Log Message: ----------- Small fix to remove an epydoc error (because of that error the doc string was displayed verbatim) and to fix a typo. Modified Paths: -------------- pyplusplus_dev/pyplusplus/file_writers/__init__.py Modified: pyplusplus_dev/pyplusplus/file_writers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/__init__.py 2006-08-31 10:03:26 UTC (rev 502) +++ pyplusplus_dev/pyplusplus/file_writers/__init__.py 2006-08-31 10:05:20 UTC (rev 503) @@ -10,8 +10,7 @@ 1. All code is written in one file - 2. Classic strategy of deviding classes to files: one class in one header + source - files. + 2. Classic strategy of deviding classes to files: one class in one header + source files. 2.1 Huge classes are splitten to few source files. @@ -37,6 +36,6 @@ mfs.write() def write_class_multiple_files( extmodule, dir_path, huge_classes ): - """writes extmodue to multiple files and splits huge classes to few source files""" + """writes extmodule to multiple files and splits huge classes to few source files""" mfs = class_multiple_files_t( extmodule, dir_path, huge_classes ) - mfs.write() \ No newline at end of file + mfs.write() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-08-31 10:03:31
|
Revision: 502 http://svn.sourceforge.net/pygccxml/?rev=502&view=rev Author: mbaas Date: 2006-08-31 03:03:26 -0700 (Thu, 31 Aug 2006) Log Message: ----------- Small fix so that epydoc doesn't produce a warning (it was accidentally treating a comment as a special epydoc comment). Modified Paths: -------------- pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-08-31 10:01:30 UTC (rev 501) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-08-31 10:03:26 UTC (rev 502) @@ -24,7 +24,7 @@ # }; # float val[4]; # }; -#}; +# }; INDEXING_SUITE_1_CONTAINERS = { 'vector<' : "boost/python/suite/indexing/vector_indexing_suite.hpp" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-08-31 10:01:34
|
Revision: 501 http://svn.sourceforge.net/pygccxml/?rev=501&view=rev Author: mbaas Date: 2006-08-31 03:01:30 -0700 (Thu, 31 Aug 2006) Log Message: ----------- Added an epydoc logger so that epydoc warnings/errors are not ignored while the docs are generated. Modified Paths: -------------- pyplusplus_dev/setup.py Modified: pyplusplus_dev/setup.py =================================================================== --- pyplusplus_dev/setup.py 2006-08-31 02:21:55 UTC (rev 500) +++ pyplusplus_dev/setup.py 2006-08-31 10:01:30 UTC (rev 501) @@ -45,11 +45,15 @@ add_pygccxml_to_PYTHONPATH() + import epydoc from epydoc.docbuilder import build_doc_index from epydoc.docwriter.html import HTMLWriter print "Generating epydoc files..." + # Register a logger object so that warnings/errors are shown + epydoc.log.register_logger(epydoc.log.SimpleLogger()) + docindex = build_doc_index(['pyplusplus', 'pygccxml']) html_writer = HTMLWriter( docindex , prj_name='Py++' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <al...@us...> - 2006-08-31 02:21:58
|
Revision: 500 http://svn.sourceforge.net/pygccxml/?rev=500&view=rev Author: allenb Date: 2006-08-30 19:21:55 -0700 (Wed, 30 Aug 2006) Log Message: ----------- Add first pass at a more complete template helper class. This doesn't provide the full interface proposed on the wiki, but it is a start and can serve my needs for now. Modified Paths: -------------- pyplusplus_dev/contrib/goodies/__init__.py pyplusplus_dev/contrib/goodies/goodie_utils.py Modified: pyplusplus_dev/contrib/goodies/__init__.py =================================================================== --- pyplusplus_dev/contrib/goodies/__init__.py 2006-08-30 21:16:47 UTC (rev 499) +++ pyplusplus_dev/contrib/goodies/__init__.py 2006-08-31 02:21:55 UTC (rev 500) @@ -12,6 +12,7 @@ from goodie_utils import (set_recursive_default, set_allow_empty_mdecl_default, finalize, add_member_function, wrap_method, add_method, - is_const_ref, exclude_protected, wrap_const_ref_params) + is_const_ref, exclude_protected, wrap_const_ref_params, + TemplateBuilder) from dsl_interface import * Modified: pyplusplus_dev/contrib/goodies/goodie_utils.py =================================================================== --- pyplusplus_dev/contrib/goodies/goodie_utils.py 2006-08-30 21:16:47 UTC (rev 499) +++ pyplusplus_dev/contrib/goodies/goodie_utils.py 2006-08-31 02:21:55 UTC (rev 500) @@ -130,3 +130,111 @@ cls.add_wrapper_code(new_method) cls.add_code('def("%s", &%s::%s);'%(c.name, cls.wrapper_alias,new_name)) + + +class TemplateWrapper: + """ Proxy for a template instance. Returned from the TemplateBuilder + to allow access to the template at a later time. + + TODO: If used a form that allowed multiple templates to be specified + ex: TemplateWrapper("osg::vector", arguments=[["float","3"],["int","4"]] + then how would we handle naming? Automatic or must be specified? + """ + def __init__(self, templateType, finalName = None): #, arguments=None): + """ + templateType: Either a base type ("osg::vector") or a full template + type ("osg::vector<float>") + finalName: Name to rename the decl to after finding it. + """ + self.mTemplateType = templateType + self.mFinalName = finalName + if not finalName: + self.mTypedefName = self.cleanTemplateName(self.mTemplateType) + else: + self.mTypedefName = "alias_%s"%self.mFinalName + self.mDecl = None + + # Properties + decl = property(lambda x: x.mDecl) + + def process(self, templateBuilder): + """ Process the wrapper to make it ready for usage by user. + templateBuilder - The module builder used to parse the template. + """ + # Look up the decl from the alias db + # XXX: I don't know if this is the best way to look up the decl, but it seems to work + self.mDecl = templateBuilder.mAliasDB[self.mTypedefName].declaration.type.declaration + # Another method + # decl_name = templateBuilder.mAliasDB[self.mTypedefName].declaration.name + # decl = ns.decl(decl_name) + + if self.mFinalName: + self.mDecl.rename(self.mFinalName) + + + def cleanTemplateName(self, templateName): + """ Build a clean template name. """ + clean_re = re.compile('[:<>\s,]') + return clean_re.sub('_', templateName) + + +class TemplateBuilder: + """ Template builder helper class. + This class is meant to simplify the use of templates with py++. + + Usage: + + tb = TemplateBuilder() + vec3f_t = tb.Template("osg::vector<float,3>") + + # Add autogen code to a header that is included + mb = moduble_builder_t([myheaders]) + tb.process(mb) + + vec3f = vec3f_t.decl + vec3f.method("getSize").exclude() + + mb.create() + """ + + def __init__(self): + """ Initialize template builder. """ + # List of tuples: (templateTypename, typedefName) + # ex: ("MyClass<float>","myclass_float") + self.mTemplates = [] + + def Template(self, *args, **kw): + """Create and add a template wrapper. + """ + temp_wrapper = TemplateWrapper(*args, **kw) + self.mTemplates.append(temp_wrapper) + return temp_wrapper + + def processTemplates(self, mbuilder): + self.mAliasDB = {} + global_typedefs = mbuilder.global_ns.typedefs() + for td in global_typedefs: + self.mAliasDB[td.name] = td.type + + for t in self.mTemplates: + t.process(self) + + + def buildAutogenContents(self): + """ Build up the contents of a file to instantiate the needed templates. """ + if len(self.mTemplates) == 0: + return None + + content = "/** Autogenerated temporary file for template instantiation. */\n" + for t in self.mTemplates: + template_type = t.mTemplateType + typedef_name = t.mTypedefName + content += """ + typedef %(template_type)s %(typedef_name)s; + inline void __instantiate_%(typedef_name)s() + { sizeof(%(typedef_name)s); } + """ % vars() + + return content + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <al...@us...> - 2006-08-30 21:16:50
|
Revision: 499 http://svn.sourceforge.net/pygccxml/?rev=499&view=rev Author: allenb Date: 2006-08-30 14:16:47 -0700 (Wed, 30 Aug 2006) Log Message: ----------- - Import more methods and symbols into dsl interface. This brings all of type_traits and the types from cpptypes and calldef. It may not be a good idea to bring them "all" in with an "from X import *", but it was quick to do and I will just have to see if it has any side-effects in the future. For now I only have one import for my script "from goodies import *". That now brings in everything that I need to building a model and creating methods that do custom policies and a variety of other "advanced" things. Modified Paths: -------------- pyplusplus_dev/contrib/goodies/dsl_interface.py pyplusplus_dev/contrib/goodies/goodie_utils.py Modified: pyplusplus_dev/contrib/goodies/dsl_interface.py =================================================================== --- pyplusplus_dev/contrib/goodies/dsl_interface.py 2006-08-30 19:44:27 UTC (rev 498) +++ pyplusplus_dev/contrib/goodies/dsl_interface.py 2006-08-30 21:16:47 UTC (rev 499) @@ -22,7 +22,17 @@ # Type traits +# - just import them all. This isn't pretty, but it will work for now +from pygccxml.declarations.type_traits import * +# cpptypes +# - import them all and leave them named X_t because they are "types" and +# this seems like a good way to keep that in mind. +# This may end up being a bad idea. I don't know yet, so for now we will +# try it and see what happens. +from pygccxml.declarations.cpptypes import * +from pygccxml.declarations.calldef import * + # Matchers # - Bring in all matchers but rename then without the '_t' at the end import pygccxml.declarations.matchers Modified: pyplusplus_dev/contrib/goodies/goodie_utils.py =================================================================== --- pyplusplus_dev/contrib/goodies/goodie_utils.py 2006-08-30 19:44:27 UTC (rev 498) +++ pyplusplus_dev/contrib/goodies/goodie_utils.py 2006-08-30 21:16:47 UTC (rev 499) @@ -22,7 +22,6 @@ def set_allow_empty_mdecl_default(val): pd.scopedef_t.ALLOW_EMPTY_MDECL_WRAPPER = val - def finalize(cls): """ Attempt to finalize a class by not exposing virtual methods. Still exposes in the case of pure virtuals otherwise the class This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <al...@us...> - 2006-08-30 19:44:30
|
Revision: 498 http://svn.sourceforge.net/pygccxml/?rev=498&view=rev Author: allenb Date: 2006-08-30 12:44:27 -0700 (Wed, 30 Aug 2006) Log Message: ----------- - Split off the cache management for module builder to a separate class. This change doesn't same much code, but it does make it easier to see what is happening. Modified Paths: -------------- pyplusplus_dev/contrib/goodies/goodie_perf_overrides.py Modified: pyplusplus_dev/contrib/goodies/goodie_perf_overrides.py =================================================================== --- pyplusplus_dev/contrib/goodies/goodie_perf_overrides.py 2006-08-30 17:33:44 UTC (rev 497) +++ pyplusplus_dev/contrib/goodies/goodie_perf_overrides.py 2006-08-30 19:44:27 UTC (rev 498) @@ -8,7 +8,7 @@ # # This file defines overrides to the standard pyplusplus behavior # -import time +import time, os print "Using Goodie perf overrides:" @@ -65,7 +65,80 @@ import cPickle, md5, os.path, gzip from pygccxml.parser.declarations_cache import file_signature, configuration_signature +class ModuleBuilderCache(object): + """ Wrapper for handling the caching (loading and saving) of a cache + For a single decl tree. + + Cache content format: + - tuple: + - md5 hex of cfg sig and file_sigs for src files + - md5 hex sig of implicit includes + - list of implicit includes) + - decl tree + """ + def __init__(self, cacheFileName): + self.cacheFileName = cacheFileName + self.logger = _logging_.loggers.module_builder + + def computeSrcAndCfgDigest(self, srcFiles, configSig): + sig = md5.new() + sig.update(configSig) + for f in srcFiles: + sig.update(file_signature(f)) + return sig.hexdigest() + + + def getCachedTree(self, sourceFiles, configSig): + """ Attempt to read a cache decl tree from the cache. + + sourceFiles - A list of source files for the module builder + configuration - A pygccxml configuration object being used. + returns: None if failed sigs or none found. + """ + ret_val = None + + if os.path.exists(self.cacheFileName): + src_and_cfg_digest = self.computeSrcAndCfgDigest(sourceFiles, configSig) + + self.logger.info("Attempting to load module cache file: %s"%self.cacheFileName) + cache_file = file(self.cacheFileName, 'rb') + (cached_src_and_cfg_digest, includes_digest, includes) = cPickle.load(cache_file) + + if (cached_src_and_cfg_digest == src_and_cfg_digest): + inc_sig = md5.new() + for f in [ x for x in includes if os.path.isfile(x)]: + inc_sig.update(file_signature(f)) + if inc_sig.hexdigest() == includes_digest: + load_start_time = time.time() + self.logger.info(" Signatures matched, loading data.") + ret_val = cPickle.load(cache_file) + self._module_builder_t__code_creator = None + self.logger.info(" Loading complete. %ss"%(time.time()-load_start_time)) + else: + self.logger.info(" Sig mis-match: Implicit include files changes.") + else: + self.logger.info(" Sig mis-match: Source files or configuration changed.") + cache_file.close() + + return ret_val + def dumpCachedTree(self, sourceFiles, configSig, declTree): + self.logger.info("Writing module cache... ") + cache_file = file(self.cacheFileName,'wb') + + src_and_cfg_digest = self.computeSrcAndCfgDigest(sourceFiles, configSig) + decl_files = [ f for f in decls_package.declaration_files(declTree) if os.path.isfile(f)] + inc_sig = md5.new() + for f in decl_files: + inc_sig.update(file_signature(f)) + + cPickle.dump( (src_and_cfg_digest, inc_sig.hexdigest(), decl_files), + cache_file, cPickle.HIGHEST_PROTOCOL) + cPickle.dump(declTree, cache_file, cPickle.HIGHEST_PROTOCOL) + cache_file.close() + self.logger.info("Complete.") + + def mb_override__init__( self , files , gccxml_path='' @@ -107,32 +180,18 @@ self._module_builder_t__parsed_dirs = filter( None, tmp ) self._module_builder_t__global_ns = None + + # Have to do it here because the parser changes the config :( + config_sig = configuration_signature(gccxml_config) # If we have a cache filename # - Compute signature and check it against file # - If matches, load it - if cache: - sig = md5.new() - sig.update(configuration_signature(gccxml_config)) - for f in self._module_builder_t__parsed_files: # files: - sig.update(file_signature(f)) - for f in dependent_headers: - sig.update(file_signature(f)) - cur_digest = sig.hexdigest() - - if os.path.exists(cache): - self.logger.info("Attempting to loading module cache file: %s"%cache) - cache_file = file(cache,'rb') - cache_digest = cPickle.load(cache_file) - if (cur_digest == cache_digest): - load_start_time = time.time() - self.logger.info(" Signatures matched, loading data.") - self._module_builder_t__global_ns = cPickle.load(cache_file) - self._module_builder_t__code_creator = None - self.logger.info(" Loading complete. %ss"%(time.time()-load_start_time)) - else: - self.logger.info(" Signatures did not match. Ignoring cache.") - cache_file.close() + if cache and os.path.exists(cache): + mb_cache = ModuleBuilderCache(cache) + self._module_builder_t__global_ns = \ + mb_cache.getCachedTree(self._module_builder_t__parsed_files, config_sig) + self._module_builder_t__code_creator = None # If didn't load global_ns from cache # - Parse and optimize it @@ -150,12 +209,9 @@ self.run_query_optimizer() if cache: - self.logger.info("Writing module cache... ") - cache_file = file(cache,'wb') - cPickle.dump(cur_digest, cache_file, cPickle.HIGHEST_PROTOCOL) - cPickle.dump(self._module_builder_t__global_ns, cache_file, cPickle.HIGHEST_PROTOCOL) - cache_file.close() - self.logger.info("Complete.") + mb_cache = ModuleBuilderCache(cache) + mb_cache.dumpCachedTree(self._module_builder_t__parsed_files, + config_sig, self._module_builder_t__global_ns) self._module_builder_t__declarations_code_head = [] self._module_builder_t__declarations_code_tail = [] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-08-30 17:41:41
|
Revision: 497 http://svn.sourceforge.net/pygccxml/?rev=497&view=rev Author: roman_yakovenko Date: 2006-08-30 10:33:44 -0700 (Wed, 30 Aug 2006) Log Message: ----------- fixing bug: Py++ started to expose private declarations Modified Paths: -------------- pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-08-30 10:15:59 UTC (rev 496) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-08-30 17:33:44 UTC (rev 497) @@ -138,13 +138,16 @@ if decl.ignore: continue - if isinstance( decl, declarations.calldef_t ) and not isinstance( decl, declarations.destructor_t ): - self.__types_db.update( decl ) - if None is decl.call_policies: - decl.call_policies = self.__call_policies_resolver( decl ) + #Right now this functionality introduce a bug: declarations that should + #not be exported for some reason are not marked as such. I will need to + #find out. + #if isinstance( decl, declarations.calldef_t ) and not isinstance( decl, declarations.destructor_t ): + #self.__types_db.update( decl ) + #if None is decl.call_policies: + #decl.call_policies = self.__call_policies_resolver( decl ) - if isinstance( decl, declarations.variable_t ): - self.__types_db.update( decl ) + #if isinstance( decl, declarations.variable_t ): + #self.__types_db.update( decl ) if doc_extractor and decl.exportable: decl.documentation = doc_extractor( decl ) @@ -607,6 +610,9 @@ def visit_member_function( self ): fwrapper = None + self.__types_db.update( self.curr_decl ) + if None is self.curr_decl.call_policies: + self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) maker_cls, fwrapper_cls = self.guess_functions_code_creators() @@ -637,6 +643,7 @@ def visit_constructor( self ): if self.curr_decl.is_copy_constructor: return + self.__types_db.update( self.curr_decl ) if not self._is_constructor_of_abstract_class( self.curr_decl ) \ and 1 == len( self.curr_decl.arguments ) \ and self.__create_castinig_constructor \ @@ -662,6 +669,7 @@ if self.curr_decl.symbol in ( '()', '[]' ): self.visit_member_function() else: + self.__types_db.update( self.curr_decl ) maker = code_creators.operator_t( operator=self.curr_decl ) self.curr_code_creator.adopt_creator( maker ) @@ -670,7 +678,11 @@ and not self.curr_decl.has_const: #TODO: move this code to decl_wrappers return #only const casting operators can generate implicitly_convertible + + if None is self.curr_decl.call_policies: + self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) + self.__types_db.update( self.curr_decl ) if not self.curr_decl.parent.is_abstract \ and not declarations.is_reference( self.curr_decl.return_type ): maker = code_creators.casting_operator_t( operator=self.curr_decl ) @@ -694,6 +706,10 @@ continue else: self.__exposed_free_fun_overloads.update( overloads ) + for f in overloads: + self.__types_db.update( f ) + if None is f.call_policies: + f.call_policies = self.__call_policies_resolver( f ) overloads_cls_creator = code_creators.free_fun_overloads_class_t( overloads ) self.__extmodule.adopt_declaration_creator( overloads_cls_creator ) @@ -701,10 +717,14 @@ overloads_reg = code_creators.free_fun_overloads_t( overloads_cls_creator ) self.curr_code_creator.adopt_creator( overloads_reg ) else: + self.__types_db.update( self.curr_decl ) + if None is self.curr_decl.call_policies: + self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) maker = code_creators.free_function_t( function=self.curr_decl ) self.curr_code_creator.adopt_creator( maker ) def visit_free_operator( self ): + self.__types_db.update( self.curr_decl ) self.__free_operators.append( self.curr_decl ) def visit_class_declaration(self ): @@ -723,6 +743,11 @@ else: exposed.update( overloads ) + for f in overloads: + self.__types_db.update( f ) + if None is f.call_policies: + f.call_policies = self.__call_policies_resolver( f ) + overloads_cls_creator = code_creators.mem_fun_overloads_class_t( overloads ) self.__extmodule.adopt_declaration_creator( overloads_cls_creator ) cls_creator.associated_decl_creators.append( overloads_cls_creator ) @@ -822,6 +847,8 @@ return True def visit_variable(self): + self.__types_db.update( 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 ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-08-30 10:16:12
|
Revision: 496 Author: roman_yakovenko Date: 2006-08-30 03:15:59 -0700 (Wed, 30 Aug 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=496&view=rev Log Message: ----------- rename user_declarations to associated_decl_creators for better reflection of the variable meaning Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/class_declaration.py pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py pyplusplus_dev/pyplusplus/file_writers/multiple_files.py pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pyplusplus_dev/pyplusplus/code_creators/class_declaration.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-08-30 10:04:41 UTC (rev 495) +++ pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-08-30 10:15:59 UTC (rev 496) @@ -86,7 +86,7 @@ scoped.scoped_t.__init__( self, declaration=class_inst ) self._wrapper = wrapper self.works_on_instance = False - self._user_declarations = [] + self._associated_decl_creators = [] def _get_wrapper( self ): return self._wrapper @@ -95,9 +95,9 @@ wrapper = property( _get_wrapper, _set_wrapper ) @property - def user_declarations( self ): + def associated_decl_creators( self ): """ references to class declaration code creators. """ - return self._user_declarations + return self._associated_decl_creators def _get_held_type(self): return self.declaration.held_type Modified: pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-08-30 10:04:41 UTC (rev 495) +++ pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-08-30 10:15:59 UTC (rev 496) @@ -221,7 +221,7 @@ source_code.append( '' ) source_code.append( self.create_namespaces_code( [class_creator] ) ) - for creator in class_creator.user_declarations: + for creator in class_creator.associated_decl_creators: source_code.append( '' ) source_code.append( creator.create() ) creator.create = lambda: '' Modified: pyplusplus_dev/pyplusplus/file_writers/multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-08-30 10:04:41 UTC (rev 495) +++ pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-08-30 10:15:59 UTC (rev 496) @@ -194,7 +194,7 @@ class_wrapper = None decl_creators = [] if isinstance( class_creator, code_creators.class_t ): - decl_creators.extend( class_creator.user_declarations ) + decl_creators.extend( class_creator.associated_decl_creators ) if class_creator.wrapper: class_wrapper = class_creator.wrapper decl_creators.append( class_creator.wrapper ) Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-08-30 10:04:41 UTC (rev 495) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-08-30 10:15:59 UTC (rev 496) @@ -443,7 +443,7 @@ uc_creators = map( lambda uc: ctext_t( uc.text ), cls_decl.declaration_code ) insert_pos = self.__extmodule.creators.index( self.__module_body ) self.__extmodule.adopt_creators( uc_creators, insert_pos ) - cls_creator.user_declarations.extend( uc_creators ) + cls_creator.associated_decl_creators.extend( uc_creators ) def _treat_indexing_suite( self ): global INDEXING_SUITE_1_CONTAINERS @@ -725,7 +725,7 @@ overloads_cls_creator = code_creators.mem_fun_overloads_class_t( overloads ) self.__extmodule.adopt_declaration_creator( overloads_cls_creator ) - cls_creator.user_declarations.append( overloads_cls_creator ) + cls_creator.associated_decl_creators.append( overloads_cls_creator ) overloads_reg = code_creators.mem_fun_overloads_t( overloads_cls_creator ) cls_creator.adopt_creator( overloads_reg ) @@ -789,7 +789,7 @@ if cls_decl.exception_translation_code: translator = code_creators.exception_translator_t( cls_decl ) self.__extmodule.adopt_declaration_creator( translator ) - cls_cc.user_declarations.append( translator ) + cls_cc.associated_decl_creators.append( translator ) translator_register \ = code_creators.exception_translator_register_t( cls_decl, translator ) cls_cc.adopt_creator( translator_register ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-08-30 10:05:07
|
Revision: 495 Author: roman_yakovenko Date: 2006-08-30 03:04:41 -0700 (Wed, 30 Aug 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=495&view=rev Log Message: ----------- adding support for BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS and BOOST_PYTHON_FUNCTION_OVERLOADS macros Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/__init__.py pyplusplus_dev/pyplusplus/code_creators/calldef.py pyplusplus_dev/pyplusplus/code_creators/class_declaration.py pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py pyplusplus_dev/pyplusplus/module_creator/creator.py pyplusplus_dev/unittests/test_all.py Added Paths: ----------- pyplusplus_dev/unittests/data/overloads_macro_to_be_exported.hpp pyplusplus_dev/unittests/overloads_macro_tester.py Modified: pyplusplus_dev/pyplusplus/code_creators/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-08-30 06:32:44 UTC (rev 494) +++ pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-08-30 10:04:41 UTC (rev 495) @@ -64,9 +64,13 @@ from calldef import constructor_t from calldef import static_method_t from calldef import casting_operator_t +from calldef import mem_fun_overloads_t +from calldef import free_fun_overloads_t from calldef import casting_constructor_t from calldef import constructor_wrapper_t +from calldef import mem_fun_overloads_class_t from calldef import casting_member_operator_t +from calldef import free_fun_overloads_class_t from calldef import copy_constructor_wrapper_t from calldef import null_constructor_wrapper_t @@ -85,7 +89,7 @@ from member_variable import mem_var_ref_t from member_variable import mem_var_ref_wrapper_t -from class_declaration import class_t +from class_declaration import class_t from class_declaration import class_wrapper_t from class_declaration import class_declaration_t Modified: pyplusplus_dev/pyplusplus/code_creators/calldef.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-08-30 06:32:44 UTC (rev 494) +++ pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-08-30 10:04:41 UTC (rev 495) @@ -5,6 +5,7 @@ import os import algorithm +import code_creator import declaration_based import class_declaration from pygccxml import declarations @@ -84,7 +85,7 @@ raise NotImplementedError() def _get_function_type_alias( self ): - return 'function_ptr_t' + return self.alias + '_function_type' function_type_alias = property( _get_function_type_alias ) def _get_exported_class_alias( self ): @@ -1126,3 +1127,218 @@ + '();' + +class calldef_overloads_class_t( code_creator.code_creator_t ): + def __init__( self, functions ): + #precondition: all member functions belong to same class and + #they all have same alias, otherwise it does not makes sense + code_creator.code_creator_t.__init__( self ) + self._functions = functions + self._functions.sort() #I need this for "stabble" code generation + self._max_fun = None #function with maximal number of arguments + + @property + def functions( self ): + return self._functions + + def min_max_num_of_args( self ): + #returns tuple( minimal, maximal ) number of arguments + min_ = None + max_ = 0 + for f in self.functions: + args_ = len( f.arguments ) + if None is min_: + min_ = args_ + else: + min_ = min( min_, args_ ) + max_tmp = max( max_, args_ ) + if max_ < max_tmp: + max_ = max_tmp + self._max_fun = f + return ( min_, max_ ) + + @property + def max_function( self ): + if not self._max_fun: + initialize_max_fun_var = self.min_max_num_of_args() + return self._max_fun + + @property + def max_function_identifier( self ): + return algorithm.create_identifier( self, declarations.full_name( self.max_function ) ) + + @property + def alias( self ): + return self.functions[0].alias + + @property + def parent_decl( self ): + return self.functions[0].parent + + @property + def name( self ): + return '%s_%s_overloads' % ( self.parent_decl.alias, self.alias ) + +class mem_fun_overloads_class_t( calldef_overloads_class_t ): + def __init__( self, mem_funs ): + #precondition: all member functions belong to same class and + #they all have same alias, otherwise it does not makes sense + calldef_overloads_class_t.__init__( self, mem_funs ) + + def _create_impl(self): + min_, max_ = self.min_max_num_of_args() + return "BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( %(overloads_cls)s, %(fun)s, %(min)d, %(max)d )" \ + % { 'overloads_cls' : self.name + , 'fun' : self.max_function_identifier + , 'min' : min_ + , 'max' : max_ + } + +class free_fun_overloads_class_t( calldef_overloads_class_t ): + def __init__( self, free_funs ): + #precondition: all member functions belong to same class and + #they all have same alias, otherwise it does not makes sense + calldef_overloads_class_t.__init__( self, free_funs ) + + def _create_impl(self): + min_, max_ = self.min_max_num_of_args() + return "BOOST_PYTHON_FUNCTION_OVERLOADS( %(overloads_cls)s, %(fun)s, %(min)d, %(max)d )" \ + % { 'overloads_cls' : self.name + , 'fun' : self.max_function_identifier + , 'min' : min_ + , 'max' : max_ + } + +class calldef_overloads_t( code_creator.code_creator_t ): + def __init__( self, overloads_class ): + code_creator.code_creator_t.__init__( self ) + self._overloads_class = overloads_class + + @property + def overloads_class( self ): + return self._overloads_class + + def create_def_code( self ): + raise NotImplementedError() + + def create_end_def_code( self ): + raise NotImplementedError() + + def keywords_args(self): + result = [ algorithm.create_identifier( self, '::boost::python::args' ) ] + result.append( '( ' ) + args = [] + for arg in self.overloads_class.max_function.arguments: + if 0 < len( args ): + args.append( self.PARAM_SEPARATOR ) + args.append( '"%s"' % arg.name ) + result.extend( args ) + result.append( ' )' ) + return ''.join( result ) + + def _get_function_type_alias( self ): + return self.overloads_class.alias + '_function_type' + function_type_alias = property( _get_function_type_alias ) + + def create_function_type_alias_code( self, exported_class_alias=None ): + raise NotImplementedError() + + def create_overloads_cls( self ): + result = [ self.overloads_class.name ] + result.append( '( ' ) + result.append( os.linesep + self.indent( self.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 ) + result.append( ' )' ) + if self.overloads_class.max_function.call_policies: + result.append( os.linesep + self.indent('', 3) ) + result.append('[ %s ]' % self.overloads_class.max_function.call_policies.create( self ) ) + return ''.join( result ) + + def _create_impl(self): + result = [] + if not self.works_on_instance: + exported_class_alias = None + if declarations.templates.is_instantiation( self.overloads_class.max_function.parent.name ): + exported_class_alias = self.exported_class_alias + result.append( 'typedef %s %s;' % ( self.parent.decl_identifier, exported_class_alias ) ) + result.append( os.linesep ) + result.append( self.create_function_type_alias_code(exported_class_alias) ) + result.append( os.linesep * 2 ) + + result.append( self.create_def_code() + '( ' ) + result.append( os.linesep + self.indent( '"%s"' % self.overloads_class.alias ) ) + + result.append( os.linesep + self.indent( self.PARAM_SEPARATOR ) ) + result.append( self.create_function_ref_code( not self.works_on_instance ) ) + + result.append( os.linesep + self.indent( self.PARAM_SEPARATOR ) ) + result.append( self.create_overloads_cls() ) + + result.append( ' )' ) + result.append( self.create_end_def_code() ) + + if not self.works_on_instance: + #indenting and adding scope + code = ''.join( result ) + result = [ '{ //%s' % declarations.full_name( self.overloads_class.max_function ) ] + result.append( os.linesep * 2 ) + result.append( self.indent( code ) ) + result.append( os.linesep * 2 ) + result.append( '}' ) + + return ''.join( result ) + +class mem_fun_overloads_t( calldef_overloads_t ): + def __init__( self, overloads_class ): + calldef_overloads_t.__init__( self, overloads_class ) + + def create_def_code( self ): + if not self.works_on_instance: + return '%s.def' % self.parent.class_var_name + else: + return 'def' + + def create_end_def_code( self ): + if not self.works_on_instance: + return ';' + else: + return '' + + def create_function_type_alias_code( self, exported_class_alias=None ): + ftype = self.overloads_class.max_function.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): + fname = declarations.full_name( self.overloads_class.max_function ) + if use_function_alias: + return '%s( &%s )' % ( self.function_type_alias, fname ) + elif self.overloads_class.max_function.create_with_signature: + return '(%s)( &%s )' % ( self.overloads_class.max_function.function_type().decl_string, fname ) + else: + return '&%s' % fname + + +class free_fun_overloads_t( calldef_overloads_t ): + def __init__( self, overloads_class ): + calldef_overloads_t.__init__( self, overloads_class ) + + def create_def_code( self ): + return algorithm.create_identifier( self, '::boost::python::def' ) + + def create_end_def_code( self ): + return ';' + + def create_function_type_alias_code( self, exported_class_alias=None ): + ftype = self.overloads_class.max_function.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): + fname = declarations.full_name( self.overloads_class.max_function ) + if use_function_alias: + return '%s( &%s )' % ( self.function_type_alias, fname ) + elif self.overloads_class.max_function.create_with_signature: + return '(%s)( &%s )' % ( self.overloads_class.max_function.function_type().decl_string, fname ) + else: + return '&%s' % fname Modified: pyplusplus_dev/pyplusplus/code_creators/class_declaration.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-08-30 06:32:44 UTC (rev 494) +++ pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-08-30 10:04:41 UTC (rev 495) @@ -7,7 +7,7 @@ import types import scoped import calldef -import algorithm +import algorithm import smart_pointers import declaration_based from pygccxml import declarations @@ -36,26 +36,26 @@ def _get_class_var_name(self): return self.alias + '_exposer' class_var_name = property( _get_class_var_name ) - + def is_exposed_using_scope(self): if self.declaration.always_expose_using_scope: return True - return bool( filter( lambda cc: not cc.works_on_instance, self.creators ) ) + return bool( filter( lambda cc: not cc.works_on_instance, self.creators ) ) @property def typedef_name( self ): return self.class_var_name + '_t' - + def _generate_code_with_scope(self): result = [] scope_var_name = self.alias + '_scope' result.append( 'typedef ' + self._generate_class_definition() + ' ' + self.typedef_name + ';') result.append( self.typedef_name + ' ' + self.class_var_name ) result[-1] = result[-1] + ' = '+ self.typedef_name + '("%s");' % self.declaration.alias - + result.append( algorithm.create_identifier( self, '::boost::python::scope' ) ) result[-1] = result[-1] + ' ' + scope_var_name - result[-1] = result[-1] + '( %s );' % self.class_var_name + result[-1] = result[-1] + '( %s );' % self.class_var_name for x in self.creators: if not x.works_on_instance: @@ -64,13 +64,13 @@ result.append( '%s.%s;' % ( self.class_var_name, x.create() ) ) code = os.linesep.join( result ) - + result = [ '{ //scope begin' ] result.append( self.indent( code ) ) result.append( '} //scope end' ) - + return os.linesep.join( result ) - + def _create_impl(self): if self.is_exposed_using_scope(): return self._generate_code_with_scope() @@ -87,7 +87,7 @@ self._wrapper = wrapper self.works_on_instance = False self._user_declarations = [] - + def _get_wrapper( self ): return self._wrapper def _set_wrapper( self, new_wrapper ): @@ -109,17 +109,17 @@ assert held_type # should be non emptry string self.declaration.held_type = held_type held_type = property( _get_held_type, _set_held_type ) - + def _exported_base_classes(self): if not self.declaration.bases: - return {}, {} + return {}, {} base_classes = {} for hierarchy_info in self.declaration.recursive_bases: if hierarchy_info.access_type == declarations.ACCESS_TYPES.PRIVATE: - continue + continue base_classes[ id( hierarchy_info.related_class ) ] = hierarchy_info base_classes_size = len( base_classes ) - creators = {} + creators = {} for creator in algorithm.make_flatten_generator( self.top_parent.body.creators ): if not isinstance( creator, class_t ): continue @@ -128,7 +128,7 @@ if len( creators ) == base_classes_size: break #all classes has been found return base_classes, creators - + def _get_base_operators(self, base_classes, base_creators): #May be in future I will redefine operators on wrapper class #thus I will support [protected|private] [ [not|pure|] virtual] operators. @@ -137,20 +137,20 @@ hierarchy_info = base_classes[ id( base_creator.declaration )] if hierarchy_info.access_type != declarations.ACCESS_TYPES.PUBLIC: continue - base_operator_creators = filter( lambda creator: + base_operator_creators = filter( lambda creator: isinstance( creator, calldef.operator_t ) and isinstance( creator.declaration, declarations.member_operator_t ) - and creator.declaration.access_type + and creator.declaration.access_type == declarations.ACCESS_TYPES.PUBLIC , base_creator.creators ) operator_creators.extend( base_operator_creators ) return operator_creators - + def _generate_noncopyable(self): if self.declaration.noncopyable: return algorithm.create_identifier( self, '::boost::noncopyable' ) - def _generate_bases(self, base_creators): + def _generate_bases(self, base_creators): bases = [] assert isinstance( self.declaration, declarations.class_t ) for base_desc in self.declaration.bases: @@ -171,11 +171,11 @@ return self.held_type else: return None - + def _generate_class_definition(self, base_creators): class_identifier = algorithm.create_identifier( self, '::boost::python::class_' ) args = [] - + held_type = self._generated_held_type() if self.wrapper: if held_type and not self.target_configuration.boost_python_has_wrapper_held_type: @@ -185,8 +185,8 @@ args.append( algorithm.create_identifier( self, self.declaration.decl_string ) ) bases = self._generate_bases(base_creators) if bases: - args.append( bases ) - + args.append( bases ) + if held_type: args.append( held_type ) notcopyable = self._generate_noncopyable() @@ -205,7 +205,7 @@ if ( self.declaration.is_abstract \ or not declarations.has_any_non_copyconstructor(self.declaration) ) \ and not self.wrapper \ - or ( declarations.has_destructor( self.declaration ) + or ( declarations.has_destructor( self.declaration ) and not declarations.has_public_destructor( self.declaration ) ): #TODO: or self.declaration has public constructor and destructor result.append( ", " ) @@ -253,12 +253,12 @@ @property def typedef_name( self ): return self.class_var_name + '_t' - + def create_typedef_code( self ): base_classes, base_creators = self._exported_base_classes() return 'typedef ' + self._generate_class_definition(base_creators) + ' ' + self.typedef_name + ';' - - + + def _generate_code_with_scope(self): result = [] scope_var_name = self.alias + '_scope' @@ -269,19 +269,19 @@ class_constructor, used_init = self._generate_constructor() result[-1] = result[-1] + self.typedef_name + class_constructor result[-1] = result[-1] + ';' - + result.append( algorithm.create_identifier( self, '::boost::python::scope' ) ) result[-1] = result[-1] + ' ' + scope_var_name - result[-1] = result[-1] + '( %s );' % self.class_var_name + result[-1] = result[-1] + '( %s );' % self.class_var_name creators = self.creators if self.declaration.redefine_operators: creators = self.creators + self._get_base_operators(base_classes, base_creators) - + for x in creators: if x is used_init: continue - if isinstance( x, calldef.calldef_t ): + if isinstance( x, ( calldef.calldef_t, calldef.calldef_overloads_t ) ): x.works_on_instance = False code = x.create() if code: @@ -295,18 +295,18 @@ result.append( '%s.%s;' % ( self.class_var_name, x.create() ) ) code = os.linesep.join( result ) - + result = [ '{ //%s' % declarations.full_name( self.declaration ) ] result.append( self.indent( code ) ) result.append( '}' ) - + return os.linesep.join( result ) def is_exposed_using_scope(self): if self.declaration.always_expose_using_scope: return True - return bool( filter( lambda cc: not cc.works_on_instance, self.creators ) ) - + return bool( filter( lambda cc: not cc.works_on_instance, self.creators ) ) + def _create_impl(self): if self.is_exposed_using_scope(): return self._generate_code_with_scope() @@ -323,13 +323,13 @@ scoped.scoped_t.__init__( self, declaration=declaration ) self._class_creator = class_creator self._base_wrappers = [] - + def _get_wrapper_alias( self ): return self.declaration.wrapper_alias def _set_wrapper_alias( self, walias ): self.declaration.wrapper_alias = walias wrapper_alias = property( _get_wrapper_alias, _set_wrapper_alias ) - + def _get_base_wrappers( self ): if self.declaration.is_abstract and not self._base_wrappers: bases = [ hi.related_class for hi in self.declaration.bases ] @@ -366,15 +366,15 @@ def _get_held_type(self): return self._class_creator.held_type held_type = property( _get_held_type ) - + def _get_boost_wrapper_identifier(self): boost_wrapper = algorithm.create_identifier( self, '::boost::python::wrapper' ) - return declarations.templates.join( boost_wrapper, [self.exposed_identifier] ) + return declarations.templates.join( boost_wrapper, [self.exposed_identifier] ) boost_wrapper_identifier = property( _get_boost_wrapper_identifier ) - + def _create_bases(self): return ', '.join( [self.exposed_identifier, self.boost_wrapper_identifier] ) - + def _create_impl(self): answer = ['struct %s : %s {' % ( self.wrapper_alias, self._create_bases() )] answer.append( '' ) @@ -382,12 +382,11 @@ answer.append( '' ) answer.append( '};' ) return os.linesep.join( answer ) - - - - - - - - - \ No newline at end of file + + + + + + + + Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-08-30 06:32:44 UTC (rev 494) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-08-30 10:04:41 UTC (rev 495) @@ -11,10 +11,10 @@ class calldef_t(decl_wrapper.decl_wrapper_t): """base class for all decl_wrappers callable objects classes.""" - + BOOST_PYTHON_MAX_ARITY = 10 """Boost.Python configuration macro value. - + A function has more than BOOST_PYTHON_MAX_ARITY arguments, will not compile. You should adjust BOOST_PYTHON_MAX_ARITY macro. For more information see: http://mail.python.org/pipermail/c++-sig/2002-June/001554.html @@ -64,7 +64,7 @@ def has_wrapper( self ): """returns True, if function - wrapper is needed - + The functionality by this function is uncomplete. So please don't use it in your code. """ @@ -176,7 +176,17 @@ def __init__(self, *arguments, **keywords): declarations.member_function_t.__init__( self, *arguments, **keywords ) calldef_t.__init__( self ) + self._use_overload_macro = False + def get_use_overload_macro(self): + return self._use_overload_macro + def set_use_overload_macro(self, use_macro): + self._use_overload_macro = use_macro + use_overload_macro = property( get_use_overload_macro, set_use_overload_macro + , doc="boolean, if True, will use BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS macro to expose declarations" \ + +"Default value is False.") + + 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): @@ -330,7 +340,17 @@ def __init__(self, *arguments, **keywords): declarations.free_function_t.__init__( self, *arguments, **keywords ) calldef_t.__init__( self ) + self._use_overload_macro = False + def get_use_overload_macro(self): + return self._use_overload_macro + def set_use_overload_macro(self, use_macro): + self._use_overload_macro = use_macro + use_overload_macro = property( get_use_overload_macro, set_use_overload_macro + , doc="boolean, if True, will use BOOST_PYTHON_FUNCTION_OVERLOADS macro to expose declarations" \ + +"Default value is False.") + + class free_operator_t( declarations.free_operator_t, calldef_t ): """defines a set of properties, that will instruct Py++ how to expose the free operator""" def __init__(self, *arguments, **keywords): Modified: pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-08-30 06:32:44 UTC (rev 494) +++ pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-08-30 10:04:41 UTC (rev 495) @@ -21,15 +21,15 @@ This class will split code, generated for huge classes, to few files. Next strategy will be used: 1. New directory with class alias name will be created. - 2. pyplusplus will generate + 2. pyplusplus will generate wrapper header - header that will contain code generated for class wrappers classes h/cpp - will contain registration code for internal classes memfun h/cpp - will contain registration code for member functions alias + _main h/cpp this class will contain main registration function. - """ + """ - def __init__(self, extmodule, directory_path, huge_classes, num_of_functions_per_file=25): + def __init__(self, extmodule, directory_path, huge_classes, num_of_functions_per_file=20): multiple_files.multiple_files_t.__init__(self, extmodule, directory_path) self.huge_classes = huge_classes self.num_of_functions_per_file = num_of_functions_per_file @@ -44,7 +44,7 @@ #not supported yet #, self.split_internal_member_variables ] - + def create_base_fname( self, class_creator, pattern ): return "_%s__%s" % ( class_creator.alias, pattern ) @@ -55,7 +55,7 @@ answer = [] if self.extmodule.license: answer.append( self.extmodule.license.create() ) - + answer.append( self.create_include_code( [class_creator] ) ) answer.append( '' ) answer.append( self.create_namespaces_code( [class_creator] ) ) @@ -63,27 +63,27 @@ if class_creator.wrapper: answer.append( class_creator.wrapper.create() ) class_creator.wrapper.create = lambda: '' - + answer.append( '' ) answer.append( class_creator.create_typedef_code() ) - + code = os.linesep.join( answer ) wrapper_code = self.create_header( self.create_base_fname(class_creator, 'wrapper'), code ) header_file = os.path.join( self.directory_path, self.wrapper_header(class_creator) ) self.write_file( header_file, wrapper_code ) - + def split_internal_creators( self, class_creator, creators, pattern ): file_path = os.path.join( self.directory_path , self.create_base_fname( class_creator, pattern ) ) - + function_name = 'register_%(cls_alias)s_%(pattern)s' \ % { 'cls_alias' : class_creator.alias, 'pattern' : pattern } - + function_decl = 'void %(fname)s( %(exposer_type)s& %(var_name)s )' \ % { 'fname' : function_name , 'exposer_type' : class_creator.typedef_name , 'var_name' : class_creator.class_var_name } - + #writting header file header_code = [ '#include "%s"' % self.wrapper_header( class_creator ) ] header_code.append( '' ) @@ -91,12 +91,12 @@ self.write_file( file_path + self.HEADER_EXT , self.create_header( class_creator.alias + '_' + pattern , os.linesep.join(header_code) ) ) - - #writting source file + + #writting source file source_code = [] if self.extmodule.license: source_code.append( self.extmodule.license.create() ) - + #relevant header file head_headers = [ self.create_base_fname( class_creator, pattern + self.HEADER_EXT ) ] source_code.append( self.create_include_code( creators, head_headers ) ) @@ -132,7 +132,7 @@ self.split_internal_creators( class_creator, creators, 'unnamed_enums' ) return 'unnamed_enums' - def split_internal_calldefs( self, class_creator, calldef_types, pattern ): + def split_internal_calldefs( self, class_creator, calldef_types, pattern ): creators = filter( lambda x: isinstance(x, calldef_types ), class_creator.creators ) grouped_creators = pypp_utils.split_sequence( creators, self.num_of_functions_per_file ) if len( grouped_creators ) == 1: @@ -140,8 +140,8 @@ creator.works_on_instance = False self.split_internal_creators( class_creator, creators, pattern ) return pattern - else: - patterns = [] + else: + patterns = [] for index, group in enumerate( grouped_creators ): pattern_tmp = pattern + str( index ) patterns.append( pattern_tmp ) @@ -151,24 +151,24 @@ return patterns def split_internal_memfuns( self, class_creator ): - calldef_types = ( code_creators.mem_fun_t ) + calldef_types = ( code_creators.mem_fun_t ) return self.split_internal_calldefs( class_creator, calldef_types, 'memfuns' ) def split_internal_v_memfuns( self, class_creator ): - calldef_types = ( code_creators.mem_fun_v_t ) + calldef_types = ( code_creators.mem_fun_v_t ) return self.split_internal_calldefs( class_creator, calldef_types, 'memfuns_virtual' ) def split_internal_pv_memfuns( self, class_creator ): - calldef_types = ( code_creators.mem_fun_pv_t ) + calldef_types = ( code_creators.mem_fun_pv_t ) return self.split_internal_calldefs( class_creator, calldef_types, 'memfuns_pvirtual' ) def split_internal_protected_memfuns( self, class_creator ): - calldef_types = ( + calldef_types = ( code_creators.mem_fun_protected_t , code_creators.mem_fun_protected_s_t , code_creators.mem_fun_protected_v_t , code_creators.mem_fun_protected_pv_t ) - + return self.split_internal_calldefs( class_creator, calldef_types, 'protected_memfuns' ) @@ -183,13 +183,13 @@ , class_creator.creators ) self.split_internal_creators( class_creator, creators, 'memvars' ) return 'memvars' - + def split_class_impl( self, class_creator): if not class_creator.declaration in self.huge_classes: return super( class_multiple_files_t, self ).split_class_impl( class_creator ) - + class_creator.declaration.always_expose_using_scope = True - + function_name = 'register_%s_class' % class_creator.alias file_path = os.path.join( self.directory_path, class_creator.alias ) # Write the .h file... @@ -197,9 +197,9 @@ self.write_file( header_name , self.create_header( class_creator.alias , self.create_function_code( function_name ) ) ) - + self.write_wrapper( class_creator ) - + tail_headers = [] for splitter in self.internal_splitters: pattern = splitter( class_creator ) @@ -211,16 +211,16 @@ assert( isinstance( pattern, list ) ) for p in pattern: tail_headers.append( self.create_base_fname( class_creator, p + self.HEADER_EXT ) ) - #writting source file + #writting source file source_code = [] if self.extmodule.license: source_code.append( self.extmodule.license.create() ) - + source_code.append( self.create_include_code( [class_creator], tail_headers=tail_headers ) ) source_code.append( '' ) source_code.append( self.create_namespaces_code( [class_creator] ) ) - + for creator in class_creator.user_declarations: source_code.append( '' ) source_code.append( creator.create() ) @@ -234,10 +234,10 @@ source_code.append( '' ) source_code.append( '}' ) self.write_file( file_path + self.SOURCE_EXT, os.linesep.join( source_code ) ) - + # Replace the create() method so that only the register() method is called # (this is called later for the main source file). class_creator.create = lambda: function_name +'();' self.include_creators.append( code_creators.include_t( header_name ) ) self.split_header_names.append(header_name) - self.split_method_names.append(function_name) \ No newline at end of file + self.split_method_names.append(function_name) Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-08-30 06:32:44 UTC (rev 494) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-08-30 10:04:41 UTC (rev 495) @@ -127,6 +127,7 @@ self.__cr_array_1_included = False self.__array_1_registered = set() #(type.decl_string,size) self.__free_operators = [] + self.__exposed_free_fun_overloads = set() def _prepare_decls( self, decls, doc_extractor ): global DO_NOT_REPORT_MSGS @@ -680,15 +681,56 @@ self.curr_code_creator.adopt_creator( maker ) def visit_free_function( self ): - maker = code_creators.free_function_t( function=self.curr_decl ) - self.curr_code_creator.adopt_creator( maker ) + if self.curr_decl in self.__exposed_free_fun_overloads: + return + elif self.curr_decl.use_overload_macro: + parent_decl = self.curr_decl.parent + names = set( map( lambda decl: decl.name + , parent_decl.free_functions( allow_empty=True, recursive=False ) ) ) + for name in names: + overloads = parent_decl.free_functions( name, allow_empty=True, recursive=False ) + overloads = filter( lambda decl: decl.use_overload_macro, overloads ) + if not overloads: + continue + else: + self.__exposed_free_fun_overloads.update( overloads ) + overloads_cls_creator = code_creators.free_fun_overloads_class_t( overloads ) + self.__extmodule.adopt_declaration_creator( overloads_cls_creator ) + + overloads_reg = code_creators.free_fun_overloads_t( overloads_cls_creator ) + self.curr_code_creator.adopt_creator( overloads_reg ) + else: + maker = code_creators.free_function_t( function=self.curr_decl ) + self.curr_code_creator.adopt_creator( maker ) + def visit_free_operator( self ): self.__free_operators.append( self.curr_decl ) def visit_class_declaration(self ): pass + def expose_overloaded_mem_fun_using_macro( self, cls, cls_creator ): + #returns set of exported member functions + exposed = set() + names = set( map( lambda decl: decl.name + , cls.member_functions( allow_empty=True, recursive=False ) ) ) + for name in names: + overloads = cls.member_functions( name, allow_empty=True, recursive=False ) + overloads = filter( lambda decl: decl.use_overload_macro, overloads ) + if not overloads: + continue + else: + exposed.update( overloads ) + + overloads_cls_creator = code_creators.mem_fun_overloads_class_t( overloads ) + self.__extmodule.adopt_declaration_creator( overloads_cls_creator ) + cls_creator.user_declarations.append( overloads_cls_creator ) + + overloads_reg = code_creators.mem_fun_overloads_t( overloads_cls_creator ) + cls_creator.adopt_creator( overloads_reg ) + return exposed + def visit_class(self ): assert isinstance( self.curr_decl, declarations.class_t ) cls_decl = self.curr_decl @@ -720,9 +762,13 @@ tcons = code_creators.null_constructor_wrapper_t( class_inst=self.curr_decl ) wrapper.adopt_creator( tcons ) + exposed = self.expose_overloaded_mem_fun_using_macro( cls_decl, cls_cc ) + cls_parent_cc.adopt_creator( cls_cc ) self.curr_code_creator = cls_cc for decl in exportable_members: + if decl in exposed: + continue self.curr_decl = decl declarations.apply_visitor( self, decl ) Added: pyplusplus_dev/unittests/data/overloads_macro_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/overloads_macro_to_be_exported.hpp (rev 0) +++ pyplusplus_dev/unittests/data/overloads_macro_to_be_exported.hpp 2006-08-30 10:04:41 UTC (rev 495) @@ -0,0 +1,45 @@ +// 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 __overloads_macro_to_be_exported_hpp__ +#define __overloads_macro_to_be_exported_hpp__ + +namespace overloads_macro{ + +struct calculator_t{ + + double add( int i, int j ){ + return i + j; + } + + double add( int i, int j, int k ){ + return i * j + k; + } + + double add( double i, double j ){ + return i + j; + } + + +}; + +double add( int i, int j ){ + return i + j; +} + +double add( int i, int j, int k ){ + return i * j + k; +} + +double add( double i, double j ){ + return i + j; +} + + + +} + + +#endif//__enums_to_be_exported_hpp__ Added: pyplusplus_dev/unittests/overloads_macro_tester.py =================================================================== --- pyplusplus_dev/unittests/overloads_macro_tester.py (rev 0) +++ pyplusplus_dev/unittests/overloads_macro_tester.py 2006-08-30 10:04:41 UTC (rev 495) @@ -0,0 +1,51 @@ +# 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 + +class tester_t(fundamental_tester_base.fundamental_tester_base_t): + EXTENSION_NAME = 'overloads_macro' + + def __init__( self, *args ): + fundamental_tester_base.fundamental_tester_base_t.__init__( + self + , tester_t.EXTENSION_NAME + , *args ) + + def customize(self, mb ): + calc = mb.class_( 'calculator_t' ) + calc.always_expose_using_scope = True + calc.member_functions( 'add' ).set_use_overload_macro( True ) + add_doubles = calc.member_function( 'add', arg_types=['double', 'double'] ) + add_doubles.set_use_overload_macro( False ) + + mb.free_functions( 'add' ).set_use_overload_macro( True ) + add_doubles = mb.free_function( 'add', arg_types=['double', 'double'] ) + add_doubles.set_use_overload_macro( False ) + + + def run_tests(self, module): + calc = module.calculator_t() + self.failUnless( 3 == calc.add( 1, 2 ) ) + self.failUnless( 9 == calc.add( 3, 2, 3 ) ) + self.failUnless( 3 == calc.add( 1.5, 1.5 ) ) + self.failUnless( 3 == module.add( 1, 2 ) ) + self.failUnless( 9 == module.add( 3, 2, 3 ) ) + self.failUnless( 3 == module.add( 1.5, 1.5 ) ) + + +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 2006-08-30 06:32:44 UTC (rev 494) +++ pyplusplus_dev/unittests/test_all.py 2006-08-30 10:04:41 UTC (rev 495) @@ -60,6 +60,7 @@ import unnamed_classes_tester import cppexceptions_tester import no_init_tester +import overloads_macro_tester def create_suite(times): testers = [ @@ -116,6 +117,7 @@ , unnamed_classes_tester , cppexceptions_tester , no_init_tester + , overloads_macro_tester ] main_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-08-30 06:32:51
|
Revision: 494 Author: roman_yakovenko Date: 2006-08-29 23:32:44 -0700 (Tue, 29 Aug 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=494&view=rev Log Message: ----------- make variable names clear Modified Paths: -------------- pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-08-30 06:18:25 UTC (rev 493) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-08-30 06:32:44 UTC (rev 494) @@ -691,17 +691,17 @@ def visit_class(self ): assert isinstance( self.curr_decl, declarations.class_t ) - temp_curr_decl = self.curr_decl - temp_curr_parent = self.curr_code_creator + cls_decl = self.curr_decl + cls_parent_cc = self.curr_code_creator exportable_members = self._exportable_class_members(self.curr_decl) wrapper = None - class_inst = code_creators.class_t( class_inst=self.curr_decl ) + cls_cc = code_creators.class_t( class_inst=self.curr_decl ) if self._is_wrapper_needed( self.curr_decl, exportable_members ): wrapper = code_creators.class_wrapper_t( declaration=self.curr_decl - , class_creator=class_inst ) - class_inst.wrapper = wrapper + , class_creator=cls_cc ) + cls_cc.wrapper = wrapper #insert wrapper before module body if isinstance( self.curr_decl.parent, declarations.class_t ): #we deal with internal class @@ -720,13 +720,13 @@ tcons = code_creators.null_constructor_wrapper_t( class_inst=self.curr_decl ) wrapper.adopt_creator( tcons ) - self.curr_code_creator.adopt_creator( class_inst ) - self.curr_code_creator = class_inst + cls_parent_cc.adopt_creator( cls_cc ) + self.curr_code_creator = cls_cc for decl in exportable_members: self.curr_decl = decl declarations.apply_visitor( self, decl ) - for redefined_func in self.redefined_funcs( temp_curr_decl ): + for redefined_func in self.redefined_funcs( cls_decl ): if isinstance( redefined_func, declarations.operator_t ): continue self.curr_decl = redefined_func @@ -735,22 +735,23 @@ #all static_methods_t should be moved to the end #better approach is to move them after last def of relevant function static_methods = filter( lambda creator: isinstance( creator, code_creators.static_method_t ) - , class_inst.creators ) + , cls_cc.creators ) for static_method in static_methods: - class_inst.remove_creator( static_method ) - class_inst.adopt_creator( static_method ) + cls_cc.remove_creator( static_method ) + cls_cc.adopt_creator( static_method ) - if temp_curr_decl.exception_translation_code: - translator = code_creators.exception_translator_t( temp_curr_decl ) + if cls_decl.exception_translation_code: + translator = code_creators.exception_translator_t( cls_decl ) self.__extmodule.adopt_declaration_creator( translator ) - class_inst.user_declarations.append( translator ) + cls_cc.user_declarations.append( translator ) translator_register \ - = code_creators.exception_translator_register_t( temp_curr_decl, translator ) - class_inst.adopt_creator( translator_register ) + = code_creators.exception_translator_register_t( cls_decl, translator ) + cls_cc.adopt_creator( translator_register ) - self.curr_decl = temp_curr_decl - self.curr_code_creator = temp_curr_parent + self.curr_decl = cls_decl + self.curr_code_creator = cls_parent_cc + def visit_enumeration(self): assert isinstance( self.curr_decl, declarations.enumeration_t ) maker = None This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-08-30 06:18:32
|
Revision: 493 Author: roman_yakovenko Date: 2006-08-29 23:18:25 -0700 (Tue, 29 Aug 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=493&view=rev Log Message: ----------- small refactoring before introducing BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS functionality Modified Paths: -------------- pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-08-30 05:18:13 UTC (rev 492) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-08-30 06:18:25 UTC (rev 493) @@ -137,6 +137,14 @@ if decl.ignore: continue + if isinstance( decl, declarations.calldef_t ) and not isinstance( decl, declarations.destructor_t ): + self.__types_db.update( decl ) + if None is decl.call_policies: + decl.call_policies = self.__call_policies_resolver( decl ) + + if isinstance( decl, declarations.variable_t ): + self.__types_db.update( decl ) + if doc_extractor and decl.exportable: decl.documentation = doc_extractor( decl ) @@ -154,6 +162,7 @@ for msg in readme: self.decl_logger.warn( "%s;%s" % ( decl, msg ) ) + #leave only declarations defined under namespace, but remove namespaces decls = filter( lambda x: not isinstance( x, declarations.namespace_t ) \ and isinstance( x.parent, declarations.namespace_t ) @@ -597,9 +606,6 @@ def visit_member_function( self ): fwrapper = None - self.__types_db.update( self.curr_decl ) - if None is self.curr_decl.call_policies: - self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) maker_cls, fwrapper_cls = self.guess_functions_code_creators() @@ -630,7 +636,6 @@ def visit_constructor( self ): if self.curr_decl.is_copy_constructor: return - self.__types_db.update( self.curr_decl ) if not self._is_constructor_of_abstract_class( self.curr_decl ) \ and 1 == len( self.curr_decl.arguments ) \ and self.__create_castinig_constructor \ @@ -656,19 +661,15 @@ if self.curr_decl.symbol in ( '()', '[]' ): self.visit_member_function() else: - self.__types_db.update( self.curr_decl ) maker = code_creators.operator_t( operator=self.curr_decl ) self.curr_code_creator.adopt_creator( maker ) def visit_casting_operator( self ): if not declarations.is_fundamental( self.curr_decl.return_type ) \ and not self.curr_decl.has_const: + #TODO: move this code to decl_wrappers return #only const casting operators can generate implicitly_convertible - if None is self.curr_decl.call_policies: - self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) - - self.__types_db.update( self.curr_decl ) if not self.curr_decl.parent.is_abstract \ and not declarations.is_reference( self.curr_decl.return_type ): maker = code_creators.casting_operator_t( operator=self.curr_decl ) @@ -679,14 +680,10 @@ self.curr_code_creator.adopt_creator( maker ) def visit_free_function( self ): - self.__types_db.update( self.curr_decl ) maker = code_creators.free_function_t( function=self.curr_decl ) - if None is self.curr_decl.call_policies: - self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) self.curr_code_creator.adopt_creator( maker ) def visit_free_operator( self ): - self.__types_db.update( self.curr_decl ) self.__free_operators.append( self.curr_decl ) def visit_class_declaration(self ): @@ -778,8 +775,6 @@ return True def visit_variable(self): - self.__types_db.update( 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 ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-08-30 05:18:22
|
Revision: 492 Author: roman_yakovenko Date: 2006-08-29 22:18:13 -0700 (Tue, 29 Aug 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=492&view=rev Log Message: ----------- small improvement for getting function overloads Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/calldef.py pygccxml_dev/unittests/core_tester.py Modified: pygccxml_dev/pygccxml/declarations/calldef.py =================================================================== --- pygccxml_dev/pygccxml/declarations/calldef.py 2006-08-29 14:07:44 UTC (rev 491) +++ pygccxml_dev/pygccxml/declarations/calldef.py 2006-08-30 05:18:13 UTC (rev 492) @@ -156,16 +156,12 @@ if not self.parent: return [] # finding all functions with the same name - overloaded_funcs \ - = algorithm.find_all_declarations( self.parent.declarations - , type=calldef_t - , name=self.name - , recursive=False ) - if not overloaded_funcs: - return overloaded_funcs - overloaded_funcs_ids = map( id, overloaded_funcs ) - index = overloaded_funcs_ids.index( id( self ) ) - return overloaded_funcs[:index] + overloaded_funcs[index+1:] + return self.parent.calldefs( + name=self.name + , function=lambda decl: not (decl is self ) + , allow_empty=True + , recursive=False ) + overloads = property( _get_overloads , doc="""A list of overloaded "callables" (i.e. other callables with the same name within the same scope. @type: list of L{calldef_t}""" ) Modified: pygccxml_dev/unittests/core_tester.py =================================================================== --- pygccxml_dev/unittests/core_tester.py 2006-08-29 14:07:44 UTC (rev 491) +++ pygccxml_dev/unittests/core_tester.py 2006-08-30 05:18:13 UTC (rev 492) @@ -36,9 +36,9 @@ , 'core_overloads_1.hpp' , 'core_overloads_2.hpp' , 'abstract_classes.hpp' - ] + ] self.global_ns = None - + def setUp(self): if not core_t.global_ns: decls = parse( self.test_files, self.config, self.COMPILATION_MODE ) @@ -50,7 +50,7 @@ def test_top_parent(self): enum = self.global_ns.enum( '::ns::ns32::E33' ) self.failUnless( self.global_ns is enum.top_parent ) - + #tests namespaces join functionality. described in gccxml.py def test_nss_join(self): #list of all namespaces @@ -114,7 +114,7 @@ self.failUnless( nested_enum1 is nested_enum2 , "enum accessed through access definition('%s') and through declarations('%s') are different enums or instances." \ %( nested_enum1.name, nested_enum2.name ) ) - + #check whether we meaning same class instance self.failUnless( class_inst is nested_enum1.parent is nested_enum2.parent , 'There are 2 or more instances of ns namespace.' ) @@ -124,7 +124,7 @@ core_membership = self.global_ns.namespace( 'membership' ) self._test_ns_membership( self.global_ns, 'EGlobal' ) self._test_ns_membership( core_membership.namespace('enums_ns'), 'EWithin' ) - self._test_ns_membership( core_membership.namespace( '' ), 'EWithinUnnamed' ) + self._test_ns_membership( core_membership.namespace( '' ), 'EWithinUnnamed' ) class_nested_enums = core_membership.class_( 'class_for_nested_enums_t' ) self._test_class_membership( class_nested_enums, 'ENestedPublic', ACCESS_TYPES.PUBLIC ) self._test_class_membership( class_nested_enums, 'ENestedProtected', ACCESS_TYPES.PROTECTED ) @@ -193,28 +193,28 @@ % (typedef.type.decl_string, fundamental_type.decl_string) ) def test_compound_types(self): - typedef_inst = self.global_ns.decl( decl_type=typedef_t, name='typedef_const_int' ) + typedef_inst = self.global_ns.decl( decl_type=typedef_t, name='typedef_const_int' ) self._test_type_composition( typedef_inst.type, const_t, int_t ) - typedef_inst = self.global_ns.decl( decl_type=typedef_t, name='typedef_pointer_int' ) + typedef_inst = self.global_ns.decl( decl_type=typedef_t, name='typedef_pointer_int' ) self._test_type_composition( typedef_inst.type, pointer_t, int_t ) - typedef_inst = self.global_ns.decl( decl_type=typedef_t, name='typedef_reference_int' ) + typedef_inst = self.global_ns.decl( decl_type=typedef_t, name='typedef_reference_int' ) self._test_type_composition( typedef_inst.type, reference_t, int_t ) - typedef_inst = self.global_ns.decl( decl_type=typedef_t, name='typedef_const_unsigned_int_const_pointer' ) + typedef_inst = self.global_ns.decl( decl_type=typedef_t, name='typedef_const_unsigned_int_const_pointer' ) self._test_type_composition( typedef_inst.type, const_t, pointer_t ) self._test_type_composition( typedef_inst.type.base, pointer_t, const_t ) self._test_type_composition( typedef_inst.type.base.base, const_t, unsigned_int_t ) - typedef_inst = self.global_ns.decl( decl_type=typedef_t, name='typedef_volatile_int' ) + typedef_inst = self.global_ns.decl( decl_type=typedef_t, name='typedef_volatile_int' ) self._test_type_composition( typedef_inst.type, volatile_t, int_t ) - var_inst = self.global_ns.variable( 'array255' ) + var_inst = self.global_ns.variable( 'array255' ) self._test_type_composition( var_inst.type, array_t, int_t ) - typedef_inst = self.global_ns.decl( decl_type=typedef_t, name='typedef_EFavoriteDrinks' ) + typedef_inst = self.global_ns.decl( decl_type=typedef_t, name='typedef_EFavoriteDrinks' ) self.failUnless( isinstance( typedef_inst.type, declarated_t ) , " typedef to enum should be 'declarated_t' instead of '%s'" % typedef_inst.type.__class__.__name__ ) enum_declaration = self.global_ns.enum( 'EFavoriteDrinks' ) @@ -223,7 +223,7 @@ % ( typedef_inst.type.declaration.name, enum_declaration.name ) ) def test_free_function_type(self): - function_ptr = self.global_ns.decl( decl_type=typedef_t, name='function_ptr' ) + function_ptr = self.global_ns.decl( decl_type=typedef_t, name='function_ptr' ) self._test_type_composition( function_ptr.type, pointer_t, free_function_type_t ) function_type = function_ptr.type.base self.failUnless( isinstance( function_type.return_type, int_t ) @@ -240,7 +240,7 @@ %( 'double_t', function_type.arguments_types[0].__class__.__name__ ) ) def test_member_function_type(self): - function_ptr = self.global_ns.decl( decl_type=typedef_t, name='member_function_ptr_t') + function_ptr = self.global_ns.decl( decl_type=typedef_t, name='member_function_ptr_t') self._test_type_composition( function_ptr.type, pointer_t, member_function_type_t ) function_type = function_ptr.type.base @@ -262,7 +262,7 @@ %( 'double_t', function_type.arguments_types[0].__class__.__name__ ) ) def test_member_variable_type(self): - mv = self.global_ns.decl( decl_type=typedef_t, name='member_variable_ptr_t') + mv = self.global_ns.decl( decl_type=typedef_t, name='member_variable_ptr_t') self._test_type_composition( mv.type, pointer_t, member_variable_type_t ) members_pointers = self.global_ns.class_( 'members_pointers_t' ) @@ -282,7 +282,7 @@ % ( 4, len(do_nothings) ) ) for index, do_nothing in enumerate(do_nothings): others = do_nothings[:index] + do_nothings[index+1:] - self.failUnless( do_nothing.overloads == others + self.failUnless( set( do_nothing.overloads ) == set( others ) , "there is a difference between expected function overloads and existing ones." ) def test_abstract_classes(self): @@ -320,7 +320,7 @@ core_t.__init__(self, *args) def create_suite(): - suite = unittest.TestSuite() + suite = unittest.TestSuite() suite.addTest( unittest.makeSuite(core_all_at_once_t)) suite.addTest( unittest.makeSuite(core_all_at_once_no_opt_t)) suite.addTest( unittest.makeSuite(core_file_by_file_t)) @@ -342,4 +342,4 @@ ##~ statistics = hotshot.stats.load( statistics_file ) ##~ statistics.strip_dirs() ##~ statistics.sort_stats( 'time', 'calls' ) -##~ statistics.print_stats( 678 ) \ No newline at end of file +##~ statistics.print_stats( 678 ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |