Package pyplusplus :: Package file_writers :: Module class_multiple_files

Source Code for Module pyplusplus.file_writers.class_multiple_files

  1  # Copyright 2004-2008 Roman Yakovenko. 
  2  # Distributed under the Boost Software License, Version 1.0. (See 
  3  # accompanying file LICENSE_1_0.txt or copy at 
  4  # http://www.boost.org/LICENSE_1_0.txt) 
  5   
  6  """defines a class that writes L{code_creators.module_t} to multiple files, the class 
  7  also splits huge C++ classes to few source files 
  8  """ 
  9   
 10  import os 
 11  import writer 
 12  import multiple_files 
 13  from pygccxml import declarations 
 14  from pyplusplus import decl_wrappers 
 15  from pyplusplus import code_creators 
 16  from pyplusplus import utils as pypp_utils 
 17   
 18  #TODO: to add namespace_alias_t classes 
19 -class class_multiple_files_t(multiple_files.multiple_files_t):
20 """ 21 This class will split code, generated for huge classes, to few files. 22 Next strategy will be used: 23 1. New directory with class alias name will be created. 24 2. pyplusplus will generate 25 wrapper header - header that will contain code generated for class wrappers 26 classes h/cpp - will contain registration code for internal classes 27 memfun h/cpp - will contain registration code for member functions 28 29 alias + _main h/cpp this class will contain main registration function. 30 """ 31
32 - def __init__( self 33 , extmodule 34 , directory_path 35 , huge_classes 36 , num_of_functions_per_file=20 37 , files_sum_repository=None 38 , encoding='ascii'):
39 multiple_files.multiple_files_t.__init__(self 40 , extmodule 41 , directory_path 42 , files_sum_repository=files_sum_repository 43 , encoding=encoding) 44 self.huge_classes = huge_classes 45 self.num_of_functions_per_file = num_of_functions_per_file 46 self.internal_splitters = [ 47 self.split_internal_enums 48 , self.split_internal_unnamed_enums 49 , self.split_internal_classes 50 , self.split_internal_memfuns 51 , self.split_internal_v_memfuns 52 , self.split_internal_pv_memfuns 53 , self.split_internal_protected_memfuns 54 #not supported yet 55 #, self.split_internal_member_variables 56 ]
57
58 - def create_base_fname( self, class_creator, pattern ):
59 return "_%s__%s" % ( class_creator.alias, pattern )
60
61 - def wrapper_header( self, class_creator ):
62 return self.create_base_fname( class_creator, 'wrapper' + self.HEADER_EXT )
63
64 - def write_wrapper( self, class_creator ):
65 answer = [] 66 if self.extmodule.license: 67 answer.append( self.extmodule.license.create() ) 68 69 creators = [class_creator] 70 if class_creator.wrapper: 71 creators.append( class_creator.wrapper ) 72 73 answer.append( self.create_include_code( creators ) ) 74 answer.append( '' ) 75 answer.append( self.create_namespaces_code( creators ) ) 76 77 if class_creator.wrapper: 78 answer.append( class_creator.wrapper.create() ) 79 class_creator.wrapper.create = lambda: '' 80 81 answer.append( '' ) 82 answer.append( class_creator.create_typedef_code() ) 83 84 code = os.linesep.join( answer ) 85 wrapper_code = self.create_header( self.create_base_fname(class_creator, 'wrapper'), code ) 86 header_file = os.path.join( self.directory_path, self.wrapper_header(class_creator) ) 87 self.write_file( header_file, wrapper_code )
88
89 - def split_internal_creators( self, class_creator, creators, pattern ):
90 file_path = os.path.join( self.directory_path 91 , self.create_base_fname( class_creator, pattern ) ) 92 93 function_name = 'register_%(cls_alias)s_%(pattern)s' \ 94 % { 'cls_alias' : class_creator.alias, 'pattern' : pattern } 95 96 function_decl = 'void %(fname)s( %(exposer_type)s& %(var_name)s )' \ 97 % { 'fname' : function_name 98 , 'exposer_type' : class_creator.typedef_name 99 , 'var_name' : class_creator.class_var_name } 100 101 #writting header file 102 header_code = [ '#include "%s"' % self.wrapper_header( class_creator ) ] 103 header_code.append( '' ) 104 header_code.append( function_decl + ';' ) 105 self.write_file( file_path + self.HEADER_EXT 106 , self.create_header( class_creator.alias + '_' + pattern 107 , os.linesep.join(header_code) ) ) 108 109 #writting source file 110 source_code = [] 111 if self.extmodule.license: 112 source_code.append( self.extmodule.license.create() ) 113 114 #relevant header file 115 head_headers = [ self.create_base_fname( class_creator, pattern + self.HEADER_EXT ) ] 116 source_code.append( self.create_include_code( creators, tail_headers=head_headers ) ) 117 118 source_code.append( '' ) 119 source_code.append( self.create_namespaces_code( creators ) ) 120 121 for creator in creators: 122 for decl_creator in self.associated_decl_creators( creator ): 123 source_code.append( '' ) 124 source_code.append( decl_creator.create() ) 125 if not isinstance( decl_creator, self.ref_count_creators ): 126 decl_creator.create = lambda: '' 127 128 # Write the register() function... 129 source_code.append( '' ) 130 source_code.append( '%s{' % function_decl ) 131 source_code.append( '' ) 132 for index, creator in enumerate( creators ): 133 source_code.append( code_creators.code_creator_t.indent( creator.create() ) ) 134 source_code.append( '' ) 135 if 0 == index: 136 creator.create = lambda: function_name + '(%s);' % class_creator.class_var_name 137 else: 138 creator.create = lambda: '' 139 source_code.append( '}' ) 140 self.write_file( file_path + self.SOURCE_EXT, os.linesep.join( source_code ) )
141
142 - def split_internal_enums( self, class_creator ):
143 """Write all enumerations into a separate .h/.cpp file. 144 """ 145 enums_creators = filter( lambda x: isinstance(x, code_creators.enum_t ) 146 , class_creator.creators ) 147 self.split_internal_creators( class_creator, enums_creators, 'enums' ) 148 return 'enums'
149
150 - def split_internal_unnamed_enums( self, class_creator ):
151 creators = filter( lambda x: isinstance(x, code_creators.unnamed_enum_t ) 152 , class_creator.creators ) 153 self.split_internal_creators( class_creator, creators, 'unnamed_enums' ) 154 return 'unnamed_enums'
155
156 - def split_internal_calldefs( self, class_creator, calldef_types, pattern ):
157 creators = filter( lambda x: isinstance(x, calldef_types ), class_creator.creators ) 158 grouped_creators = pypp_utils.split_sequence( creators, self.num_of_functions_per_file ) 159 if len( grouped_creators ) == 1: 160 for creator in creators: 161 creator.works_on_instance = False 162 self.split_internal_creators( class_creator, creators, pattern ) 163 return pattern 164 else: 165 patterns = [] 166 for index, group in enumerate( grouped_creators ): 167 pattern_tmp = pattern + str( index ) 168 patterns.append( pattern_tmp ) 169 for creator in group: 170 creator.works_on_instance = False 171 self.split_internal_creators( class_creator, group, pattern_tmp ) 172 return patterns
173
174 - def split_internal_memfuns( self, class_creator ):
175 calldef_types = ( code_creators.mem_fun_t, code_creators.mem_fun_overloads_t ) 176 return self.split_internal_calldefs( class_creator, calldef_types, 'memfuns' )
177
178 - def split_internal_v_memfuns( self, class_creator ):
179 calldef_types = ( code_creators.mem_fun_v_t ) 180 return self.split_internal_calldefs( class_creator, calldef_types, 'memfuns_virtual' )
181
182 - def split_internal_pv_memfuns( self, class_creator ):
183 calldef_types = ( code_creators.mem_fun_pv_t ) 184 return self.split_internal_calldefs( class_creator, calldef_types, 'memfuns_pvirtual' )
185
186 - def split_internal_protected_memfuns( self, class_creator ):
193
194 - def split_internal_classes( self, class_creator ):
195 class_types = ( code_creators.class_t, code_creators.class_declaration_t ) 196 creators = filter( lambda x: isinstance(x, class_types ), class_creator.creators ) 197 self.split_internal_creators( class_creator, creators, 'classes' ) 198 return 'classes'
199
200 - def split_internal_member_variables( self, class_creator ):
201 creators = filter( lambda x: isinstance(x, code_creators.member_variable_base_t) 202 , class_creator.creators ) 203 self.split_internal_creators( class_creator, creators, 'memvars' ) 204 return 'memvars'
205
206 - def split_class_impl( self, class_creator):
207 if not class_creator.declaration in self.huge_classes: 208 return super( class_multiple_files_t, self ).split_class_impl( class_creator ) 209 210 class_creator.declaration.always_expose_using_scope = True 211 212 function_name = 'register_%s_class' % class_creator.alias 213 file_path = os.path.join( self.directory_path, class_creator.alias ) 214 # Write the .h file... 215 header_name = file_path + self.HEADER_EXT 216 self.write_file( header_name 217 , self.create_header( class_creator.alias 218 , self.create_function_code( function_name ) ) ) 219 220 self.write_wrapper( class_creator ) 221 222 tail_headers = [] 223 for splitter in self.internal_splitters: 224 pattern = splitter( class_creator ) 225 if not pattern: 226 continue 227 if isinstance( pattern, str ): 228 tail_headers.append( self.create_base_fname( class_creator, pattern + self.HEADER_EXT ) ) 229 else: 230 assert( isinstance( pattern, list ) ) 231 for p in pattern: 232 tail_headers.append( self.create_base_fname( class_creator, p + self.HEADER_EXT ) ) 233 #writting source file 234 source_code = [] 235 if self.extmodule.license: 236 source_code.append( self.extmodule.license.create() ) 237 238 source_code.append( self.create_include_code( [class_creator], tail_headers=tail_headers ) ) 239 240 source_code.append( '' ) 241 source_code.append( self.create_namespaces_code( [class_creator] ) ) 242 243 for creator in class_creator.associated_decl_creators: 244 source_code.append( '' ) 245 source_code.append( creator.create() ) 246 if not isinstance( creator, self.ref_count_creators ): 247 creator.create = lambda: '' 248 249 # Write the register() function... 250 source_code.append( '' ) 251 source_code.append( 'void %s(){' % function_name ) 252 source_code.append( '' ) 253 source_code.append( class_creator.create() ) 254 source_code.append( '' ) 255 source_code.append( '}' ) 256 self.write_file( file_path + self.SOURCE_EXT, os.linesep.join( source_code ) ) 257 258 # Replace the create() method so that only the register() method is called 259 # (this is called later for the main source file). 260 class_creator.create = lambda: function_name +'();' 261 self.include_creators.append( code_creators.include_t( header_name ) ) 262 self.split_header_names.append(header_name) 263 self.split_method_names.append(function_name)
264