Package pyplusplus :: Package code_creators :: Module class_declaration

Source Code for Module pyplusplus.code_creators.class_declaration

  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  import os 
  7  import types 
  8  import scoped 
  9  import calldef 
 10  import algorithm 
 11  import smart_pointers 
 12  import declaration_based 
 13  import registration_based 
 14  from pygccxml import declarations 
15 16 -class class_declaration_t( scoped.scoped_t 17 , registration_based.registration_based_t ):
18 - def __init__(self, class_inst ):
22
24 class_identifier = algorithm.create_identifier( self, '::boost::python::class_' ) 25 return declarations.templates.join( class_identifier, [self.decl_identifier] )
26
27 - def _generate_code_no_scope(self):
28 result = [] 29 result.append( self._generate_class_definition() + '("%s")' % self.declaration.alias ) 30 for x in self.creators: 31 code = x.create() 32 tmpl = '%s.%s' 33 if self.is_comment( code ): 34 tmpl = '%s%s' 35 result.append( self.indent( tmpl % ( os.linesep, code ) ) ) 36 result.append( ';' ) 37 return ''.join( result )
38 39 @property
40 - def class_var_name(self):
41 return self.declaration.class_var_name
42
43 - def is_exposed_using_scope(self):
44 if self.declaration.always_expose_using_scope: 45 return True 46 return bool( filter( lambda cc: not cc.works_on_instance, self.creators ) )
47 48 @property
49 - def typedef_name( self ):
50 return self.class_var_name + '_t'
51
53 result = [] 54 scope_var_name = self.alias + '_scope' 55 result.append( 'typedef ' + self._generate_class_definition() + ' ' + self.typedef_name + ';') 56 result.append( self.typedef_name + ' ' + self.class_var_name ) 57 result[-1] = result[-1] + ' = '+ self.typedef_name + '("%s");' % self.declaration.alias 58 59 result.append( algorithm.create_identifier( self, '::boost::python::scope' ) ) 60 result[-1] = result[-1] + ' ' + scope_var_name 61 result[-1] = result[-1] + '( %s );' % self.class_var_name 62 63 for x in self.creators: 64 if not x.works_on_instance: 65 result.append( x.create() ) 66 else: 67 result.append( '%s.%s;' % ( self.class_var_name, x.create() ) ) 68 69 code = os.linesep.join( result ) 70 71 result = [ '{ //scope begin' ] 72 result.append( self.indent( code ) ) 73 result.append( '} //scope end' ) 74 75 return os.linesep.join( result )
76
77 - def _create_impl(self):
78 if self.declaration.already_exposed: 79 return '' 80 if self.is_exposed_using_scope(): 81 return self._generate_code_with_scope() 82 else: 83 return self._generate_code_no_scope()
84
85 - def _get_system_headers_impl( self ):
86 return []
87
88 -class class_t( scoped.scoped_t, registration_based.registration_based_t ):
89 """ 90 Creates boost.python code that needed to export a class 91 """
92 - def __init__(self, class_inst, wrapper=None ):
97
98 - def _get_wrapper( self ):
99 return self._wrapper
100 - def _set_wrapper( self, new_wrapper ):
101 self._wrapper = new_wrapper
102 wrapper = property( _get_wrapper, _set_wrapper ) 103
104 - def _get_held_type(self):
105 return self.declaration.held_type
106 - def _set_held_type(self, held_type):
107 assert isinstance( held_type, types.NoneType ) \ 108 or isinstance( held_type, smart_pointers.held_type_t ) \ 109 or isinstance( held_type, types.StringTypes ) 110 if isinstance( held_type, types.StringTypes ): 111 assert held_type # should be non emptry string 112 self.declaration.held_type = held_type
113 held_type = property( _get_held_type, _set_held_type ) 114
115 - def _exported_base_classes(self):
116 if not self.declaration.bases: 117 return {}, {} 118 base_classes = {} 119 for hierarchy_info in self.declaration.recursive_bases: 120 if hierarchy_info.access_type == declarations.ACCESS_TYPES.PRIVATE: 121 continue 122 base_classes[ id( hierarchy_info.related_class ) ] = hierarchy_info 123 base_classes_size = len( base_classes ) 124 creators = {} 125 creators_len = 0 126 for creator in algorithm.make_flatten_generator( self.top_parent.body.creators ): 127 if isinstance( creator, class_t ) and id(creator.declaration) in base_classes: 128 creators[ id(creator.declaration) ] = creator 129 if len( creators ) == base_classes_size: 130 break #all classes has been found 131 return base_classes, creators
132
133 - def _get_base_operators(self, base_classes, base_creators):
134 #May be in future I will redefine operators on wrapper class 135 #thus I will support [protected|private] [ [not|pure|] virtual] operators. 136 operator_creators = [] 137 for base_creator in base_creators.values(): 138 hierarchy_info = base_classes[ id( base_creator.declaration )] 139 if hierarchy_info.access_type != declarations.ACCESS_TYPES.PUBLIC: 140 continue 141 base_operator_creators = filter( lambda creator: 142 isinstance( creator, calldef.operator_t ) 143 and isinstance( creator.declaration, declarations.member_operator_t ) 144 and creator.declaration.access_type 145 == declarations.ACCESS_TYPES.PUBLIC 146 , base_creator.creators ) 147 operator_creators.extend( base_operator_creators ) 148 return operator_creators
149
150 - def _generate_noncopyable(self):
151 noncopyable_vars = self.declaration.find_noncopyable_vars() 152 copy_constr = self.declaration.find_copy_constructor() 153 154 if self.declaration.noncopyable \ 155 or copy_constr and copy_constr.is_artificial and noncopyable_vars: 156 return algorithm.create_identifier( self, '::boost::noncopyable' )
157
158 - def _generate_bases(self, base_creators):
159 bases = [] 160 assert isinstance( self.declaration, declarations.class_t ) 161 for base_desc in self.declaration.bases: 162 assert isinstance( base_desc, declarations.hierarchy_info_t ) 163 if base_desc.access != declarations.ACCESS_TYPES.PUBLIC: 164 continue 165 if base_creators.has_key( id(base_desc.related_class) ): 166 bases.append( algorithm.create_identifier( self, base_desc.related_class.partial_decl_string ) ) 167 elif base_desc.related_class.already_exposed: 168 bases.append( base_desc.related_class.partial_decl_string ) 169 if not bases: 170 return None 171 bases_identifier = algorithm.create_identifier( self, '::boost::python::bases' ) 172 return declarations.templates.join( bases_identifier, bases )
173
174 - def _generated_held_type(self):
175 if isinstance( self.held_type, smart_pointers.held_type_t ): 176 return self.held_type.create( self ) 177 elif isinstance( self.held_type, types.StringTypes): 178 return self.held_type 179 else: 180 return None
181
182 - def _generate_class_definition(self, base_creators):
183 class_identifier = algorithm.create_identifier( self, '::boost::python::class_' ) 184 args = [] 185 186 held_type = self._generated_held_type() 187 if self.wrapper: 188 if self.declaration.exposed_class_type == self.declaration.EXPOSED_CLASS_TYPE.WRAPPER: 189 args.append( self.wrapper.full_name ) 190 else: 191 if not self.target_configuration.boost_python_has_wrapper_held_type \ 192 or self.declaration.require_self_reference: 193 args.append( self.decl_identifier ) 194 if self.declaration.require_self_reference: 195 if not held_type: 196 args.append( self.wrapper.full_name ) 197 else: 198 args.append( self.wrapper.full_name ) 199 else: 200 args.append( self.decl_identifier ) 201 202 bases = self._generate_bases(base_creators) 203 if bases: 204 args.append( bases ) 205 206 if held_type: 207 args.append( held_type ) 208 notcopyable = self._generate_noncopyable() 209 if notcopyable: 210 args.append( notcopyable ) 211 return declarations.templates.join( class_identifier, args)
212
213 - def _generate_constructor(self):
214 result = [] 215 result.append( '(' ) 216 result.append( ' "%s"' % self.alias ) 217 if self.documentation: 218 result.append( ', %s' % self.documentation ) 219 used_init = None 220 inits = filter( lambda x: isinstance( x, calldef.constructor_t ), self.creators ) 221 222 trivial_constructor = self.declaration.find_trivial_constructor() 223 224 if self.declaration.no_init: 225 result.append( ", " ) 226 result.append( algorithm.create_identifier( self, '::boost::python::no_init' ) ) 227 else: 228 if inits: 229 used_init = inits[0] 230 result.append( ", " ) 231 result.append( used_init.create_init_code() ) 232 result.append( ' )' ) 233 return ( ''.join( result ), used_init )
234
235 - def _generate_code_no_scope(self):
236 result = [] 237 base_classes, base_creators = self._exported_base_classes() 238 result.append( self._generate_class_definition(base_creators) ) 239 class_constructor, used_init = self._generate_constructor() 240 result.append( class_constructor ) 241 creators = self.creators 242 if self.declaration.redefine_operators: 243 creators = self.creators + self._get_base_operators(base_classes, base_creators) 244 for x in creators: 245 if not ( x is used_init ): 246 code = x.create() 247 tmpl = '%s.%s' 248 if self.is_comment( code ): 249 tmpl = '%s%s' 250 result.append( self.indent( tmpl % ( os.linesep, code ) ) ) 251 result.append( ';' ) 252 return ''.join( result )
253 254 @property
255 - def class_var_name(self):
256 return self.declaration.class_var_name
257 258 @property
259 - def typedef_name( self ):
260 return self.class_var_name + '_t'
261
262 - def create_typedef_code( self ):
263 base_classes, base_creators = self._exported_base_classes() 264 return 'typedef ' + self._generate_class_definition(base_creators) + ' ' + self.typedef_name + ';'
265 266
268 result = [] 269 scope_var_name = self.alias + '_scope' 270 base_classes, base_creators = self._exported_base_classes() 271 result.append( 'typedef ' + self._generate_class_definition(base_creators) + ' ' + self.typedef_name + ';') 272 result.append( self.typedef_name + ' ' + self.class_var_name ) 273 result[-1] = result[-1] + ' = ' 274 class_constructor, used_init = self._generate_constructor() 275 result[-1] = result[-1] + self.typedef_name + class_constructor 276 result[-1] = result[-1] + ';' 277 278 result.append( algorithm.create_identifier( self, '::boost::python::scope' ) ) 279 result[-1] = result[-1] + ' ' + scope_var_name 280 result[-1] = result[-1] + '( %s );' % self.class_var_name 281 282 creators = self.creators 283 if self.declaration.redefine_operators: 284 creators = self.creators + self._get_base_operators(base_classes, base_creators) 285 286 for x in creators: 287 if x is used_init: 288 continue 289 if isinstance( x, ( calldef.calldef_t, calldef.calldef_overloads_t ) ): 290 x.works_on_instance = False 291 code = x.create() 292 if code: 293 result.append( code ) 294 continue 295 if not x.works_on_instance: 296 code = x.create() 297 if code: 298 result.append( code ) 299 else: 300 result.append( '%s.%s;' % ( self.class_var_name, x.create() ) ) 301 302 code = os.linesep.join( result ) 303 304 result = [ '{ //%s' % declarations.full_name( self.declaration, with_defaults=False ) ] 305 result.append( self.indent( code ) ) 306 result.append( '}' ) 307 308 return os.linesep.join( result )
309
310 - def is_exposed_using_scope(self):
311 if self.declaration.always_expose_using_scope: 312 return True 313 return bool( filter( lambda cc: not cc.works_on_instance, self.creators ) )
314
315 - def _create_impl(self):
316 if self.declaration.already_exposed: 317 return '' 318 if self.is_exposed_using_scope(): 319 return self._generate_code_with_scope() 320 else: 321 return self._generate_code_no_scope()
322
323 - def _get_system_headers_impl( self ):
324 return []
325
326 #open question: should I put class wrapper under some specifiec namespace? 327 -class class_wrapper_t( scoped.scoped_t ):
328 """ 329 Creates C++ code that creates wrapper arround some class 330 """ 331
332 - def __init__(self, declaration, class_creator ):
333 scoped.scoped_t.__init__( self, declaration=declaration ) 334 self._class_creator = class_creator 335 self._base_wrappers = []
336
337 - def _get_wrapper_alias( self ):
338 return self.declaration.wrapper_alias
339 - def _set_wrapper_alias( self, walias ):
340 self.declaration.wrapper_alias = walias
341 wrapper_alias = property( _get_wrapper_alias, _set_wrapper_alias ) 342 343 @property
344 - def base_wrappers( self ):
345 if self.declaration.is_abstract and not self._base_wrappers: 346 bases = [ hi.related_class for hi in self.declaration.bases ] 347 creators_before_me = algorithm.creators_affect_on_me( self ) 348 self._base_wrappers \ 349 = filter( lambda creator: isinstance( creator, class_wrapper_t ) 350 and creator.declaration in bases 351 , creators_before_me ) 352 return self._base_wrappers
353 354 @property
355 - def exposed_identifier(self):
357 358 @property
359 - def class_creator(self):
360 return self._class_creator
361 362 @property
363 - def full_name( self ):
364 if not isinstance( self.parent, class_wrapper_t ): 365 return self.declaration.wrapper_alias 366 else: 367 full_name = [self.wrapper_alias] 368 #may be we deal with enum 369 parent = self.parent 370 while isinstance( parent, class_wrapper_t ): 371 full_name.append( parent.wrapper_alias ) 372 parent = parent.parent 373 full_name.reverse() 374 return '::'.join( full_name )
375 376 @property
377 - def held_type(self):
378 return self._class_creator.held_type
379 380 @property
381 - def boost_wrapper_identifier(self):
382 boost_wrapper = algorithm.create_identifier( self, '::boost::python::wrapper' ) 383 return declarations.templates.join( boost_wrapper, [self.exposed_identifier] )
384
385 - def _create_bases(self):
386 return ', '.join( [self.exposed_identifier, self.boost_wrapper_identifier] )
387
388 - def _create_impl(self):
389 if self.declaration.already_exposed: 390 return '' 391 answer = ['struct %s : %s {' % ( self.wrapper_alias, self._create_bases() )] 392 answer.append( '' ) 393 answer.append( self.create_internal_code( self.creators ) ) 394 answer.append( '' ) 395 answer.append( '};' ) 396 return os.linesep.join( answer )
397
398 - def _get_system_headers_impl( self ):
399 return []
400