[pygccxml-commit] SF.net SVN: pygccxml: [1203] pyplusplus_dev
Brought to you by:
mbaas,
roman_yakovenko
From: <rom...@us...> - 2007-12-12 09:10:23
|
Revision: 1203 http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1203&view=rev Author: roman_yakovenko Date: 2007-12-12 01:10:21 -0800 (Wed, 12 Dec 2007) Log Message: ----------- adding new file writer balanced_files.py 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/pyplusplus/utils/__init__.py pyplusplus_dev/unittests/test_all.py Added Paths: ----------- pyplusplus_dev/pyplusplus/file_writers/balanced_files.py pyplusplus_dev/unittests/balanced_files_tester.py pyplusplus_dev/unittests/data/balanced_files_to_be_exported.hpp Modified: pyplusplus_dev/pyplusplus/file_writers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/__init__.py 2007-12-11 10:21:11 UTC (rev 1202) +++ pyplusplus_dev/pyplusplus/file_writers/__init__.py 2007-12-12 09:10:21 UTC (rev 1203) @@ -20,6 +20,7 @@ from writer import writer_t from single_file import single_file_t from multiple_files import multiple_files_t +from balanced_files import balanced_files_t from class_multiple_files import class_multiple_files_t from md5sum_repository import repository_t from md5sum_repository import cached_repository_t @@ -45,6 +46,12 @@ mfs.write() return mfs.written_files +def write_balanced_files( extmodule, dir_path, number_of_buckets, files_sum_repository=None, encoding='ascii' ): + """writes extmodule to fixed number of multiple cpp files""" + mfs = balanced_files_t( extmodule, dir_path, number_of_buckets, files_sum_repository=files_sum_repository, encoding=encoding ) + mfs.write() + return mfs.written_files + def write_class_multiple_files( extmodule, dir_path, huge_classes, files_sum_repository, encoding='ascii' ): """writes extmodule to multiple files and splits huge classes to few source files""" mfs = class_multiple_files_t( extmodule, dir_path, huge_classes, files_sum_repository=files_sum_repository, encoding=encoding ) Added: pyplusplus_dev/pyplusplus/file_writers/balanced_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/balanced_files.py (rev 0) +++ pyplusplus_dev/pyplusplus/file_writers/balanced_files.py 2007-12-12 09:10:21 UTC (rev 1203) @@ -0,0 +1,64 @@ +# Copyright 2004 Giovanni Beltrame +# 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 a class that writes L{code_creators.module_t} to multiple files""" + +import os +import math +import multiple_files +from pyplusplus import messages +from pyplusplus import _logging_ +from pygccxml import declarations +from pyplusplus import decl_wrappers +from pyplusplus import code_creators +from pyplusplus.utils import split_sequence + +#TODO: to add namespace_alias_t classes +class balanced_files_t(multiple_files.multiple_files_t): + """ + 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' + + def __init__( self + , extmodule + , directory_path + , number_of_buckets + , write_main=True + , files_sum_repository=None + , encoding='ascii'): + """Constructor. + + @param extmodule: The root of a code creator tree + @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. + @type write_main: boolean + """ + multiple_files.multiple_files_t.__init__( self, extmodule, directory_path, write_main, files_sum_repository, encoding) + self.number_of_buckets = number_of_buckets + + def split_classes( self ): + class_creators = filter( lambda x: isinstance(x, ( code_creators.class_t, code_creators.class_declaration_t ) ) + , self.extmodule.body.creators ) + + class_creators = filter( lambda cc: not cc.declaration.already_exposed + , class_creators ) + + buckets = split_sequence(class_creators, len(class_creators)/self.number_of_buckets ) + if len(buckets) > self.number_of_buckets: + buckets[len(buckets)-2] += buckets[len(buckets)-1] + buckets = buckets[:len(buckets)-1] + + for index, bucket in enumerate( buckets ): + self.split_creators( bucket + , '_classes_%d' % (index+1) + , 'register_classes_%d' % (index+1) + , -1 ) Modified: pyplusplus_dev/pyplusplus/file_writers/multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2007-12-11 10:21:11 UTC (rev 1202) +++ pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2007-12-12 09:10:21 UTC (rev 1203) @@ -290,6 +290,13 @@ self.logger.error( os.linesep.join( msg ) ) raise + def split_classes( self ): + # 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 ) + def create_value_traits_header_name( self, value_class ): return "_" + value_class.alias + "__value_traits" + self.HEADER_EXT @@ -308,6 +315,9 @@ , value_traits.create() ) ) value_traits.create = lambda: '' + def split_values_traits( self ): + map( self.split_value_traits, self.__value_traits ) + def split_creators( self, creators, pattern, function_name, registrator_pos ): """Write non-class creators into a particular .h/.cpp file. @@ -379,14 +389,8 @@ self.extmodule.do_include_dirs_optimization() - map( self.split_value_traits, self.__value_traits ) - - # 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_values_traits() + self.split_classes() self.split_enums() self.split_global_variables() self.split_free_functions() Modified: pyplusplus_dev/pyplusplus/module_builder/builder.py =================================================================== --- pyplusplus_dev/pyplusplus/module_builder/builder.py 2007-12-11 10:21:11 UTC (rev 1202) +++ pyplusplus_dev/pyplusplus/module_builder/builder.py 2007-12-12 09:10:21 UTC (rev 1203) @@ -317,6 +317,20 @@ self.__merge_user_code() file_writers.write_file( self.code_creator, file_name, encoding=self.encoding ) + def __work_on_unused_files( self, dir_name, written_files, on_unused_file_found ): + all_files = os.listdir( dir_name ) + all_files = map( lambda fname: os.path.join( dir_name, fname ), 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: + 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." ) + def split_module( self , dir_name , huge_classes=None @@ -358,22 +372,49 @@ , huge_classes , files_sum_repository=files_sum_repository , encoding=self.encoding) + self.__work_on_unused_files( dir_name, written_files, on_unused_file_found ) - all_files = os.listdir( dir_name ) - all_files = map( lambda fname: os.path.join( dir_name, fname ), all_files ) - all_files = filter( file_writers.has_pypp_extenstion, all_files ) + return written_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." ) + def balanced_split_module( self + , dir_name + , number_of_files + , on_unused_file_found=os.remove + , use_files_sum_repository=True): + """ + Writes module to fixed number of multiple cpp files + @param number_of_files: the desired number of generated cpp files + @type number_of_files: int + + @param dir_name: directory name + @type dir_name: string + + @param on_unused_file_found: callable object that represents the action that should be taken on + file, which is no more in use + + @use_files_sum_repository: Py++ can generate file, which will contain md5 sum of every generated file. + Next time you generate code, md5sum will be loaded from the file and compared. + This could speed-up code generation process by 10-15%. + """ + self.__merge_user_code() + + files_sum_repository = None + if use_files_sum_repository: + cache_file = os.path.join( dir_name, self.code_creator.body.name + '.md5.sum' ) + files_sum_repository = file_writers.cached_repository_t( cache_file ) + + written_files = file_writers.write_balanced_files( self.code_creator + , dir_name + , number_of_buckets=number_of_files + , files_sum_repository=files_sum_repository + , encoding=self.encoding) + + self.__work_on_unused_files( dir_name, written_files, on_unused_file_found ) + 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""" Modified: pyplusplus_dev/pyplusplus/utils/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/utils/__init__.py 2007-12-11 10:21:11 UTC (rev 1202) +++ pyplusplus_dev/pyplusplus/utils/__init__.py 2007-12-12 09:10:21 UTC (rev 1203) @@ -40,7 +40,7 @@ creator.parent.remove_creator( creator ) def split_sequence(seq, bucket_size): - #split sequence to buclets, where every will contain maximum bucket_size items + #split sequence to buckets, where every will contain maximum bucket_size items seq_len = len( seq ) if seq_len <= bucket_size: return [ seq ] Added: pyplusplus_dev/unittests/balanced_files_tester.py =================================================================== --- pyplusplus_dev/unittests/balanced_files_tester.py (rev 0) +++ pyplusplus_dev/unittests/balanced_files_tester.py 2007-12-12 09:10:21 UTC (rev 1203) @@ -0,0 +1,88 @@ +# 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 autoconfig +from pyplusplus import utils +import fundamental_tester_base +from pygccxml import declarations +from pyplusplus import module_builder +from pyplusplus.module_builder import call_policies + +class tester_t(fundamental_tester_base.fundamental_tester_base_t): + EXTENSION_NAME = 'balanced_files' + + def __init__( self, *args ): + fundamental_tester_base.fundamental_tester_base_t.__init__( + self + , tester_t.EXTENSION_NAME + , indexing_suite_version=1 + , *args ) + self.files = [] + + def customize( self, mb ): + mb.global_ns.exclude() + + nm_t = declarations.remove_declarated( mb.global_ns.typedef( 'naive_matrix_t' ).type ) + nm_t.include() + + exposed_db = utils.exposed_decls_db_t() + + exposed_db.register_decls( mb.global_ns ) + exposed_db.save( autoconfig.build_dir ) + mb.register_module_dependency( autoconfig.build_dir ) + + sm = mb.global_ns.namespace( name='split_module' ) + sm.include() + sm.class_( 'op_struct' ).exclude() + + mb.free_function( 'check_overload' ).add_declaration_code( '//hello check_overload' ) + mb.free_function( 'get_opaque' ).add_declaration_code( '//hello get_opaque' ) + + mb.calldefs( 'check_overload' ).use_overload_macro = True + mb.calldefs( 'get_opaque' ).call_policies \ + = call_policies.return_value_policy( call_policies.return_opaque_pointer ) + + mb.class_( 'op_struct' ).exclude() + item = mb.class_( 'item_t' ) + item.add_declaration_code( '//hello world' ) + nested = item.class_( 'nested_t' ) + nested.add_declaration_code( '//hello nested decl' ) + nested.add_registration_code( '//hello nested reg', False ) + mb.free_fun( 'create_empty_mapping' ).include() + + def generate_source_files( self, mb ): + files = mb.balanced_split_module( autoconfig.build_dir, 2, on_unused_file_found=lambda fpath: fpath ) + self.files = filter( lambda fname: fname.endswith( 'cpp' ), files ) + + def get_source_files( self ): + return self.files + + def run_tests(self, module): + module.get_opaque() + item = module.item_t() + item.get_opaque() + module.check_overload() + item.check_overload() + item = module.TestClass1() + if item.func() != 1: raise Exception + item = module.TestClass2() + if item.func() != 2: raise Exception + item = module.TestClass3() + if item.func() != 3: raise Exception + + +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() Added: pyplusplus_dev/unittests/data/balanced_files_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/balanced_files_to_be_exported.hpp (rev 0) +++ pyplusplus_dev/unittests/data/balanced_files_to_be_exported.hpp 2007-12-12 09:10:21 UTC (rev 1203) @@ -0,0 +1,90 @@ +// 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 __split_module_to_be_exported_hpp__ +#define __split_module_to_be_exported_hpp__ + +#include "boost/shared_ptr.hpp" +//#include BOOST_HASH_MAP_HEADER +#include <map> +#include <vector> +#include <string> + +namespace split_module{ + +typedef std::vector< std::vector< int > > naive_matrix_t; + +class TestClass1 { + +public: + int func() { + return 1; + } + +}; + +class TestClass2 { + +public: + int func() { + return 2; + } + +}; + +class TestClass3 { + +public: + int func() { + return 3; + } +}; + + +inline naive_matrix_t create_zero_matrix( unsigned int x ){ + return naive_matrix_t(); +}; + + +struct op_struct{}; + +inline op_struct* get_opaque(){ + return 0; +} + +inline void check_overload( int i=0, int j=1, int k=2 ){ +} + + +struct item_t{ + + enum EColor{ red, blue }; + enum EFruit{ apple, orange }; + + item_t(){} + item_t( int ){} + + void do_nothing(){} + int do_something(){ return 1; } + + op_struct* get_opaque(){ return 0; } + + void check_overload( int i=0, int j=1, int k=2 ){} + + int m_dummy; + + struct nested_t{}; +}; + +//typedef BOOST_STD_EXTENSION_NAMESPACE::hash_map< std::string, boost::shared_ptr< item_t > > str2item_t; +typedef std::map< std::string, boost::shared_ptr< item_t > > str2item_t; +inline str2item_t create_empty_mapping(){ + return str2item_t(); +} + +} + + +#endif//__split_module_to_be_exported_hpp__ Modified: pyplusplus_dev/unittests/test_all.py =================================================================== --- pyplusplus_dev/unittests/test_all.py 2007-12-11 10:21:11 UTC (rev 1202) +++ pyplusplus_dev/unittests/test_all.py 2007-12-12 09:10:21 UTC (rev 1203) @@ -97,6 +97,7 @@ import vector_with_shared_data_tester import constructors_bug_tester import precompiled_header_tester +import balanced_files_tester testers = [ @@ -182,6 +183,7 @@ , templates_tester , constructors_bug_tester , precompiled_header_tester + , balanced_files_tester ] class module_runner_t( object ): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |