[pygccxml-commit] SF.net SVN: pygccxml: [335] pyplusplus_dev/unittests
Brought to you by:
mbaas,
roman_yakovenko
From: <rom...@us...> - 2006-07-23 13:26:14
|
Revision: 335 Author: roman_yakovenko Date: 2006-07-23 06:25:56 -0700 (Sun, 23 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=335&view=rev Log Message: ----------- adding initial support for huge classes 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 Added Paths: ----------- pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py Modified: pyplusplus_dev/pyplusplus/file_writers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/__init__.py 2006-07-23 06:02:19 UTC (rev 334) +++ pyplusplus_dev/pyplusplus/file_writers/__init__.py 2006-07-23 13:25:56 UTC (rev 335) @@ -18,7 +18,8 @@ import types from writer import writer_t from single_file import single_file_t -from multiple_files import multiple_files_t +from multiple_files import multiple_files_t +from class_multiple_files import class_multiple_files_t def write_file( data, file_path ): if isinstance( data, types.StringTypes ): @@ -29,4 +30,8 @@ def write_multiple_files( extmodule, dir_path ): mfs = multiple_files_t( extmodule, dir_path ) - mfs.write() \ No newline at end of file + mfs.write() + +def write_class_multiple_files( extmodule, dir_path, huge_classes ): + mfs = class_multiple_files_t( extmodule, dir_path, huge_classes ) + mfs.write() \ No newline at end of file Added: pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py (rev 0) +++ pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-07-23 13:25:56 UTC (rev 335) @@ -0,0 +1,178 @@ +# 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 writer +import multiple_files +from sets import Set as set +from pygccxml import declarations +from pyplusplus import decl_wrappers +from pyplusplus import code_creators + +#TODO: to add namespace_alias_t classes +class class_multiple_files_t(multiple_files.multiple_files_t): + """ + 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 + 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): + multiple_files.multiple_files_t.__init__(self, extmodule, directory_path) + self.huge_classes = huge_classes + self.internal_splitters = [ + self.split_internal_enums + , self.split_internal_unnamed_enums + #, self.split_internal_member_functions + , self.split_internal_classes + #, self.split_internal_member_variables + ] + + def split_class_impl( self, class_creator): + function_name = 'register_%s_class' % class_creator.alias + file_path = os.path.join( self.directory_path, class_creator.alias ) + # Write the .h file... + header_name = file_path + self.HEADER_EXT + self.write_file( header_name + , self.create_header( class_creator.alias + , self.create_function_code( function_name ) ) ) + class_wrapper = None + decl_creators = None + if isinstance( class_creator, code_creators.class_t ) and class_creator.wrapper: + class_wrapper = class_creator.wrapper + decl_creators = [ class_creator.wrapper ] + # Write the .cpp file... + cpp_code = self.create_source( class_creator.alias + , function_name + , [class_creator] + , decl_creators ) + self.write_file( file_path + self.SOURCE_EXT, cpp_code ) + if class_wrapper: + # The wrapper has already been written above, so replace the create() + # method with a new 'method' that just returns an empty string because + # this method is later called again for the main source file. + class_wrapper.create = lambda: '' + # Replace the create() method so that only the register() method is called + # (this is called later for the main source file). + class_creator.create = lambda: function_name +'();' + self.__include_creators.append( code_creators.include_t( header_name ) ) + self.split_header_names.append(header_name) + self.split_method_names.append(function_name) + + def write_wrapper( self, class_creator ): + code = '' + if class_creator.wrapper: + code = class_creator.wrapper.create() + class_creator.wrapper.create = lambda: '' + + wrapper_code = self.create_header( class_creator.alias + '_wrapper', code ) + header_file = os.path.join( self.directory_path, class_creator.alias, 'wrapper' + self.HEADER_EXT ) + self.write_file( header_file, wrapper_code ) + + def split_internal_creators( self, class_creator, creators, pattern ): + file_path = os.path.join( self.directory_path + , class_creator.alias + , pattern ) + + function_name = 'register_%s_%s' % ( class_creator.alias, pattern ) + + self.write_file( file_path + self.HEADER_EXT + , self.create_header( pattern, self.create_function_code( function_name ) ) ) + + self.write_file( file_path + self.SOURCE_EXT + , self.create_source( pattern + , function_name + , creators )) + for index, creator in enumerate( creators ): + if 0 == index: + creator.create = lambda: function_name + '();' + else: + creator.create = lambda: '' + + def split_internal_enums( self, class_creator ): + """Write all enumerations into a separate .h/.cpp file. + """ + enums_creators = filter( lambda x: isinstance(x, code_creators.enum_t ) + , class_creator.creators ) + self.split_internal_creators( class_creator, enums_creators, 'enums' ) + return 'enums' + + def split_internal_unnamed_enums( self, class_creator ): + creators = filter( lambda x: isinstance(x, code_creators.unnamed_enum_t ) + , class_creator.creators ) + self.split_internal_creators( class_creator, creators, 'unnamed_enums' ) + return 'unnamed_enums' + + def split_internal_member_functions( self, class_creator ): + creators = filter( lambda x: isinstance(x, code_creators.mem_fun_t ) + , class_creator.creators ) + self.split_internal_creators( class_creator, creators, 'memfuns' ) + return 'memfuns' + + def split_internal_classes( self, class_creator ): + class_types = ( code_creators.class_t, code_creators.class_declaration_t ) + creators = filter( lambda x: isinstance(x, class_types ), class_creator.creators ) + self.split_internal_creators( class_creator, creators, 'classes' ) + return 'classes' + + def split_internal_member_variables( self, class_creator ): + creators = filter( lambda x: isinstance(x, code_creators.member_variable_base_t) + , 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 ) + + extmodule = class_creator.top_parent + + self.create_dir( os.path.join( self.directory_path, class_creator.alias ) ) + + function_name = 'register_%s_class' % class_creator.alias + file_path = os.path.join( self.directory_path, class_creator.alias ) + # Write the .h file... + header_name = file_path + self.HEADER_EXT + self.write_file( header_name + , self.create_header( class_creator.alias + , self.create_function_code( function_name ) ) ) + + self.write_wrapper( class_creator ) + wrapper_include = code_creators.include_t( os.path.join( class_creator.alias, 'wrapper' + self.HEADER_EXT ) ) + + extmodule.adopt_include( wrapper_include ) + + include_creators = [ wrapper_include ] + splitter_includes = [] + for splitter in self.internal_splitters: + pattern = splitter( class_creator ) + include_creator = code_creators.include_t( os.path.join( class_creator.alias, pattern + self.HEADER_EXT ) ) + splitter_includes.append( include_creator ) + + for creator in splitter_includes: + extmodule.adopt_include( creator ) + + # Write the .cpp file... + cpp_code = self.create_source( class_creator.alias + , function_name + , [class_creator] ) + + self.write_file( file_path + self.SOURCE_EXT, cpp_code ) + + extmodule.remove_creator( wrapper_include ) + for creator in splitter_includes: + extmodule.remove_creator( creator ) + # 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) Modified: pyplusplus_dev/pyplusplus/file_writers/multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-07-23 06:02:19 UTC (rev 334) +++ pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-07-23 13:25:56 UTC (rev 335) @@ -29,19 +29,19 @@ """ writer.writer_t.__init__(self, extmodule) self.__directory_path = directory_path - self._create_dir() - self.__include_creators = [] # List of include_t creators that contain the generated headers + self.create_dir( directory_path ) + self.include_creators = [] # List of include_t creators that contain the generated headers self.split_header_names = [] # List of include file names for split files self.split_method_names = [] # List of methods from the split files - def _create_dir( self ): + def create_dir( self, directory_path ): """Create the output directory if it doesn't already exist. """ - if os.path.exists( self.__directory_path ) and not os.path.isdir(self.__directory_path): + if os.path.exists( directory_path ) and not os.path.isdir(directory_path): raise RuntimeError( 'directory_path should contain path to directory.' ) - if not os.path.exists( self.__directory_path ): - os.makedirs( self.__directory_path ) + if not os.path.exists( directory_path ): + os.makedirs( directory_path ) def _get_directory_path(self): return self.__directory_path @@ -181,7 +181,7 @@ # 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.include_creators.append( code_creators.include_t( header_name ) ) self.split_header_names.append(header_name) self.split_method_names.append(function_name) @@ -246,7 +246,7 @@ 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) @@ -304,8 +304,8 @@ self.split_free_functions() if write_main: - self.__include_creators.sort( cmp=lambda ic1, ic2: cmp( ic1.header, ic2.header ) ) + self.include_creators.sort( cmp=lambda ic1, ic2: cmp( ic1.header, ic2.header ) ) map( lambda creator: self.extmodule.adopt_include( creator ) - , self.__include_creators ) + , 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 ) Modified: pyplusplus_dev/pyplusplus/module_builder/builder.py =================================================================== --- pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-07-23 06:02:19 UTC (rev 334) +++ pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-07-23 13:25:56 UTC (rev 335) @@ -235,14 +235,19 @@ """ file_writers.write_file( self.code_creator, file_name ) - def split_module(self, dir_name): + def split_module(self, dir_name, huge_classes=None): """ Writes module to multiple files @param dir_name: directory name - @type dir_name: string - """ - file_writers.write_multiple_files( self.code_creator, dir_name ) + @type dir_name: string + + @param huge_classes: list that contains reference to classes, that should be split + """ + if None is huge_classes: + file_writers.write_multiple_files( self.code_creator, dir_name ) + else: + file_writers.write_class_multiple_files( self.code_creator, dir_name, huge_classes ) #select decl(s) interfaces def decl( self, name=None, function=None, header_dir=None, header_file=None, recursive=None ): Modified: pyplusplus_dev/unittests/algorithms_tester.py =================================================================== --- pyplusplus_dev/unittests/algorithms_tester.py 2006-07-23 06:02:19 UTC (rev 334) +++ pyplusplus_dev/unittests/algorithms_tester.py 2006-07-23 13:25:56 UTC (rev 335) @@ -99,15 +99,44 @@ mem_funs = arr.calldefs( 'x', arg_types=[None,None] ) for x in mem_funs: self.failUnless( x.exportable == False ) + +class class_multiple_files_tester_t(unittest.TestCase): + CLASS_DEF = \ + """ + namespace tester{ + struct X{ + enum EColor{ red, blue }; + enum EFruit{ apple, orange }; + + X(){} + X( int ){} + + void do_nothing(){} + + int do_somghing(){ return 1; } + + int m_dummy; + }; + } + """ + def test(self): + mb = module_builder.module_builder_t( + [ module_builder.create_text_fc( self.CLASS_DEF ) ] + , gccxml_path=autoconfig.gccxml.executable ) + mb.namespace( name='::tester' ).include() + mb.build_code_creator('dummy') + mb.split_module( autoconfig.build_dir, [ mb.class_( '::tester::X' ) ] ) def create_suite(): 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)) - suite.addTest( unittest.makeSuite(creator_finder_tester_t)) - suite.addTest( unittest.makeSuite(exclude_function_with_array_arg_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)) + #~ suite.addTest( unittest.makeSuite(creator_finder_tester_t)) + #~ suite.addTest( unittest.makeSuite(exclude_function_with_array_arg_tester_t)) + suite.addTest( unittest.makeSuite(class_multiple_files_tester_t)) + return suite def run_suite(): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |