Package pyplusplus :: Package decl_wrappers :: Module properties

Source Code for Module pyplusplus.decl_wrappers.properties

  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 property_t helper class" 
  7   
  8  import algorithm 
  9  from pyplusplus import messages 
 10  from pyplusplus import _logging_ 
 11  from pygccxml import declarations 
12 13 -class property_t( object ):
14 """This class describes a "property". 15 16 It keeps 17 """
18 - def __init__( self, name, fget, fset=None, doc=None, is_static=False ):
19 self._name = name 20 self._fget = fget 21 self._fset = fset 22 self._doc = doc 23 self._is_static = is_static
24 25 @property
26 - def name( self ):
27 return self._name
28 29 @property
30 - def fget( self ):
31 return self._fget
32 33 @property
34 - def fset( self ):
35 return self._fset
36
37 - def _get_doc( self ):
38 if None is self._doc: 39 doc = ['get'] 40 if self.fset: 41 doc.append( r'\\set' ) 42 doc.append( r' property, built on top of \"%s\"' % self.fget ) 43 if self.fset: 44 doc.append( r' and \"%s\"' % self.fset ) 45 self._doc = '"%s"' % ''.join( doc ) 46 return self._doc
47 - def _set_doc( self, doc ):
48 self._doc = doc
49 doc = property( _get_doc, _set_doc ) 50 51 @property
52 - def is_static( self ):
53 return self._is_static
54
55 - def __str__( self ):
56 desc = [] 57 desc.append( 'fget=%s' % declarations.full_name( self.fget ) ) 58 if self.fset: 59 desc.append( ', ' ) 60 desc.append( 'fset=%s' % declarations.full_name( self.fset ) ) 61 return 'property "%s"[%s]' % ( self.name, ''.join( desc ) )
62
63 64 -class property_recognizer_i(object):
65 - def __init__( self ):
66 object.__init__( self )
67
68 - def create_property( self, fget, fset ):
69 raise NotImplementedError()
70
71 - def create_read_only_property( sefl, fget ):
72 raise NotImplementedError()
73
74 - def is_accessor( self, mem_fun ):
75 if mem_fun.ignore: 76 return False 77 if mem_fun.access_type != 'public': 78 return False 79 if mem_fun.has_static: 80 return False #TODO: should be supported 81 if mem_fun.virtuality == declarations.VIRTUALITY_TYPES.PURE_VIRTUAL: 82 return False 83 return True
84
85 - def is_getter( self, mem_fun ):
86 if mem_fun.arguments: 87 return False 88 if declarations.is_void( mem_fun.return_type ): 89 return False 90 if not mem_fun.has_const: 91 return False 92 if mem_fun.overloads: 93 return False 94 return True
95
96 - def is_setter( self, mem_fun ):
97 if len( mem_fun.arguments ) != 1: 98 return False 99 if not declarations.is_void( mem_fun.return_type ): 100 return False 101 if mem_fun.has_const: 102 return False 103 if mem_fun.overloads: 104 return False 105 return True
106
107 - def __get_accessors( self, mem_funs ):
108 getters = [] 109 setters = [] 110 for mem_fun in mem_funs: 111 if not self.is_accessor( mem_fun ): 112 continue 113 elif self.is_getter( mem_fun ): 114 getters.append( mem_fun ) 115 elif self.is_setter( mem_fun ): 116 setters.append( mem_fun ) 117 else: 118 continue 119 return ( getters, setters )
120
121 - def class_accessors( self, cls ):
122 return self.__get_accessors( cls.mem_funs( recursive=False, allow_empty=True ) )
123
124 - def base_classes( self, cls ):
125 base_clss = [] 126 for hierarchy_info in cls.recursive_bases: 127 if hierarchy_info.related_class.ignore: #don't scan excluded classes 128 continue 129 if 'public' != hierarchy_info.access_type: #don't scan non public hierarchy 130 continue 131 base_clss.append( hierarchy_info.related_class ) 132 return base_clss
133
134 - def inherited_accessors( self, cls ):
135 mem_funs = [] 136 map( lambda base_cls: mem_funs.extend( base_cls.mem_funs( recursive=False, allow_empty=True ) ) 137 , self.base_classes( cls ) ) 138 return self.__get_accessors( mem_funs )
139
140 141 -class name_based_recognizer_t( property_recognizer_i ):
142 - def __init__( self ):
144
145 - def prefixes( self ):
146 return [ ( 'is', 'set' ) 147 , ( 'get', 'set' ) 148 , ( 'has', 'set' ) 149 , ( '', 'set' ) ]
150
151 - def check_prefix( self, name, prefix ):
152 if not name.startswith( prefix ): 153 return False 154 if len( name ) < len( prefix ): 155 return False 156 return True
157
158 - def check_name_compatibility( self, gname, sname, gprefix, sprefix ):
159 if not self.check_prefix( gname, gprefix ): 160 return False 161 if not self.check_prefix( sname, sprefix ): 162 return False 163 if gname[ len( gprefix ): ] != sname[ len( sprefix ): ]: 164 return False 165 return True
166
167 - def make_std_convention( self, gprefix, sprefix ):
168 convert = lambda x: x + '_' 169 if gprefix: 170 gprefix = convert( gprefix ) 171 return ( gprefix, convert( sprefix ) )
172
173 - def make_u_camel_convention( self, gprefix, sprefix ):
174 convert = lambda x: x[0].upper() + x[1:] 175 if gprefix: 176 gprefix = convert( gprefix ) 177 return ( gprefix, convert( sprefix ) )
178
179 - def make_l_camel_convention( self, gprefix, sprefix ):
180 convert = lambda x: x[0].lower() + x[1:] 181 if gprefix: 182 gprefix = convert( gprefix ) 183 return ( gprefix, convert( sprefix ) )
184
185 - def find_out_prefixes( self, gname, sname ):
186 convention_makers = [ 187 self.make_std_convention #longest first 188 , self.make_u_camel_convention 189 , self.make_l_camel_convention ] 190 191 for convention_maker in convention_makers: 192 for g, s in self.prefixes(): 193 gc, sc = convention_maker( g, s ) 194 if self.check_name_compatibility( gname, sname, gc, sc ): 195 return ( gc, sc ) 196 return None
197
198 - def find_out_ro_prefixes( self, gname ):
199 convention_makers = [ 200 self.make_std_convention #longest first 201 , self.make_u_camel_convention 202 , self.make_l_camel_convention ] 203 204 for convention_maker in convention_makers: 205 for g, unused in self.prefixes(): 206 if not g: 207 continue 208 gc, unused = convention_maker( g, 'set' ) 209 if self.check_prefix( gname, gc ): 210 return gc 211 return ''
212
213 - def check_type_compatibility( self, fget, fset ):
214 #algorithms allows "const" differences between types 215 t1 = fget.return_type 216 t2 = fset.arguments[0].type 217 218 if declarations.is_same( t1, t2 ): 219 return True 220 elif declarations.is_pointer( t1 ) and declarations.is_pointer( t2 ): 221 t1 = declarations.remove_cv( declarations.remove_pointer( t1 ) ) 222 t2 = declarations.remove_cv( declarations.remove_pointer( t2 ) ) 223 return declarations.is_same( t1, t2 ) 224 elif declarations.is_reference( t1 ) and declarations.is_reference( t2 ): 225 t1 = declarations.remove_cv( declarations.remove_reference( t1 ) ) 226 t2 = declarations.remove_cv( declarations.remove_reference( t2 ) ) 227 return declarations.is_same( t1, t2 ) 228 else: 229 return False
230
231 - def find_out_property_name( self, fget, prefix ):
232 if fget.name == prefix: 233 #use class name for property name 234 return algorithm.create_valid_name( fget.parent.name ) 235 else: 236 return fget.name[len(prefix):]
237
238 - def create_property( self, fget, fset ):
239 if not self.check_type_compatibility( fget, fset ): 240 return None 241 found = self.find_out_prefixes( fget.name, fset.name ) 242 if not found: 243 return None 244 return property_t( self.find_out_property_name( fget, found[0] ), fget, fset )
245
246 - def create_read_only_property( self, fget ):
247 found = self.find_out_ro_prefixes( fget.name ) 248 if None is found: 249 return None 250 else: 251 return property_t( self.find_out_property_name( fget, found ), fget )
252
253 -class properties_finder_t:
254 - def __init__( self, cls, recognizer=None, exclude_accessors=False ):
255 self.cls = cls 256 if None is recognizer: 257 recognizer = name_based_recognizer_t() 258 self.recognizer = recognizer 259 self.exclude_accessors = exclude_accessors 260 self.getters, self.setters = recognizer.class_accessors( cls ) 261 self.inherited_getters, self.inherited_setters = recognizer.inherited_accessors( cls )
262
263 - def __report_illegal_property( self, property_ ):
264 logger = _logging_.loggers.declarations 265 if not messages.filter_disabled_msgs([messages.W1041], property_.fget.parent.disabled_messages ): 266 return #user disabled property warning 267 logger.warn( "%s;%s" % ( property_.fget.parent, messages.W1041 % property_ ) )
268 286 287 relevant_decls = [] 288 relevant_classes = [self.cls] + self.recognizer.base_classes( self.cls ) 289 for cls in relevant_classes: 290 relevant_decls.extend( cls.decls( is_relevant, recursive=False, allow_empty=True ) ) 291 return not bool( relevant_decls )
292
293 - def find_properties( self, getters, setters, used_getters, used_setters ):
294 properties = [] 295 for fget in getters: 296 if fget in used_getters: 297 continue 298 for fset in setters: 299 if fset in used_setters: 300 continue 301 property_ = self.recognizer.create_property( fget, fset ) 302 if property_: 303 if self.__is_legal_property( property_ ): 304 used_getters.add( fget ) 305 used_setters.add( fset ) 306 properties.append( property_ ) 307 break 308 else: 309 self.__report_illegal_property( property_ ) 310 return properties
311
312 - def __call__( self ):
313 used_getters = set() 314 used_setters = set() 315 properties = [] 316 #this get, this set 317 properties.extend( 318 self.find_properties( self.getters, self.setters, used_getters, used_setters ) ) 319 #this get, base set 320 properties.extend( 321 self.find_properties( self.getters, self.inherited_setters, used_getters, used_setters ) ) 322 #base get, this set 323 properties.extend( 324 self.find_properties( self.inherited_getters, self.setters, used_getters, used_setters ) ) 325 326 for fget in self.getters: 327 if fget in used_getters: 328 continue 329 property_ = self.recognizer.create_read_only_property( fget ) 330 if property_: 331 if self.__is_legal_property( property_ ): 332 used_getters.add( fget ) 333 properties.append( property_ ) 334 else: 335 self.__report_illegal_property( property_ ) 336 337 if self.exclude_accessors: 338 map( lambda accessor: accessor.exclude(), used_getters ) 339 map( lambda accessor: accessor.exclude(), used_setters ) 340 341 return properties
342
343 -def find_properties( cls, recognizer=None, exclude_accessors=False ):
344 pf = properties_finder_t( cls, recognizer, exclude_accessors ) 345 properties = pf() 346 return properties
347