Package pyplusplus :: Package decl_wrappers :: Module variable_wrapper

Source Code for Module pyplusplus.decl_wrappers.variable_wrapper

  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 class that configure global and member variable exposing""" 
  7   
  8  import decl_wrapper 
  9  import python_traits 
 10  import call_policies 
 11  import python_traits 
 12  from pyplusplus import messages 
 13  from pygccxml import declarations 
 14   
15 -class variable_t(decl_wrapper.decl_wrapper_t, declarations.variable_t):
16 """defines a set of properties, that will instruct Py++ how to expose the variable"""
17 - def __init__(self, *arguments, **keywords):
18 declarations.variable_t.__init__(self, *arguments, **keywords ) 19 decl_wrapper.decl_wrapper_t.__init__( self ) 20 self._getter_call_policies = None 21 self._setter_call_policies = None 22 self._apply_smart_ptr_wa = False 23 self._is_read_only = None 24 self._use_make_functions = None 25 self._expose_address = None 26 self._expose_value = None
27 28 __call_policies_doc__ = \ 29 """There are usecase, when exporting member variable forces Py++ to 30 create accessors functions. Sometime, those functions requires call policies. 31 To be more specific: when you export member variable that has reference or 32 pointer type, you need to tell Boost.Python library how to manage object 33 life-time. In all cases, Py++ will give reasonable default value. I am 34 sure, that there are use cases, when you will have to change it. You should 35 use this property to change it. 36 """ 37
38 - def get_getter_call_policies( self ):
39 if None is self._getter_call_policies: 40 if self.apply_smart_ptr_wa: 41 value_policy = '' 42 if self.is_read_only: 43 value_policy = call_policies.copy_const_reference 44 else: 45 value_policy = call_policies.copy_non_const_reference 46 self._getter_call_policies = call_policies.return_value_policy( value_policy ) 47 elif self.use_make_functions: 48 self._getter_call_policies = call_policies.return_internal_reference() 49 else: 50 pass 51 return self._getter_call_policies
52 - def set_getter_call_policies( self, call_policies ):
53 self._getter_call_policies = call_policies
54 getter_call_policies = property( get_getter_call_policies, set_getter_call_policies 55 , doc=__call_policies_doc__ ) 56
57 - def get_setter_call_policies( self ):
58 if None is self._getter_call_policies: 59 if self.apply_smart_ptr_wa or self.use_make_functions: 60 self._setter_call_policies = call_policies.default_call_policies() 61 return self._setter_call_policies
62 - def set_setter_call_policies( self, call_policies ):
63 self._setter_call_policies = call_policies
64 setter_call_policies = property( get_setter_call_policies, set_setter_call_policies 65 , doc=__call_policies_doc__ ) 66 67 __use_make_functions_doc__ = \ 68 """Generate code using make_getter and make_setter functions 69 70 Basically you don't need to use this, untill you have one of the next use-cases: 71 * member variable is smart pointer - in this case Boost.Python has small problem 72 to expose it right. Using the functions is a work around to the problem. 73 * member variable defined custom r-value converter - may be you don't know 74 but the conversion is applied only on functions arguments. So you need to 75 use make_getter/make_setter in order to allow user to enjoy from the 76 conversion. 77 78 Setting "apply_smart_ptr_wa" and/or "use_make_functions" to "True" will tell 79 Py++ to generate such code. 80 """ 81
82 - def get_apply_smart_ptr_wa( self ):
83 return self._apply_smart_ptr_wa
84 - def set_apply_smart_ptr_wa( self, value):
85 self._apply_smart_ptr_wa = value
86 apply_smart_ptr_wa = property( get_apply_smart_ptr_wa, set_apply_smart_ptr_wa 87 , doc=__use_make_functions_doc__ ) 88
89 - def get_use_make_functions( self ):
90 return self._use_make_functions
91 - def set_use_make_functions( self, value ):
92 self._use_make_functions = value
93 use_make_functions = property( get_use_make_functions, set_use_make_functions 94 , doc=__use_make_functions_doc__) 95
97 type_ = declarations.remove_alias( self.type ) 98 type_ = declarations.remove_const( type_ ) 99 type_ = declarations.remove_pointer( type_ ) 100 if not declarations.class_traits.is_my_case( type_ ): 101 return False 102 cls = declarations.class_traits.get_declaration( type_ ) 103 if cls.class_type == declarations.CLASS_TYPES.UNION: 104 return True 105 elif not cls.name: 106 return True 107 else: 108 return False
109 110 __expose_address_doc__ = \ 111 """There are some cases when Boost.Python doesn't provide a convenient way 112 to expose the variable to Python. For example: 113 114 double* x[10]; 115 //or 116 char* buffer; //in case you want to modify the buffer in place 117 118 In this cases Py++ doesn't help too. In these cases it is possible to expose 119 the actual address of the variable. After that, you can use built-in "ctypes" 120 package to edit the content of the variable. 121 """
122 - def get_expose_address( self ):
123 if None is self._expose_address: 124 self._expose_address = self.__should_be_exposed_by_address_only() 125 return self._expose_address
126 - def set_expose_address( self, value ):
127 self._expose_address = value
128 expose_address = property( get_expose_address, set_expose_address 129 , doc= __expose_address_doc__ ) 130 131 __expose_value_doc__ = \ 132 """Boost.Python is not able to expose unions. Using ctypes module 133 it is possible to get access to the data stored in a variable, which 134 has some union type. 135 136 This property controls whether Py++ should expose the variable value 137 or not. In case, this variable has type union, this property will be False. 138 """
139 - def get_expose_value( self ):
140 if None is self._expose_value: 141 self._expose_value = not self.__should_be_exposed_by_address_only() 142 return self._expose_value
143 - def set_expose_value( self, value ):
144 self._expose_value = value
145 expose_value = property( get_expose_value, set_expose_value 146 , doc= __expose_value_doc__ ) 147
148 - def __find_out_is_read_only(self):
149 type_ = declarations.remove_alias( self.type ) 150 151 if isinstance( type_, declarations.const_t ): 152 return True 153 154 if declarations.is_pointer( type_ ): 155 type_ = declarations.remove_pointer( type_ ) 156 157 if declarations.is_reference( type_ ): 158 type_ = declarations.remove_reference( type_ ) 159 160 if isinstance( type_, declarations.const_t ): 161 return True 162 163 if self.apply_smart_ptr_wa: 164 return False #all smart pointers has assign operator 165 166 if isinstance( type_, declarations.declarated_t ) \ 167 and isinstance( type_.declaration, declarations.class_t ) \ 168 and not declarations.has_public_assign( type_.declaration ): 169 return True 170 return False
171
172 - def get_is_read_only( self ):
173 if None is self._is_read_only: 174 self._is_read_only = self.__find_out_is_read_only() 175 return self._is_read_only
176 - def set_is_read_only( self, v ):
177 self._is_read_only = v
178 is_read_only = property( get_is_read_only, set_is_read_only ) 179
180 - def _exportable_impl( self ):
181 if not self.parent.name and self.is_wrapper_needed(): 182 #return messages.W1057 % str( self ) 183 return messages.W1058 % str( self ) 184 if not self.name: 185 return messages.W1033 186 if self.bits == 0 and self.name == "": 187 return messages.W1034 188 if not self.expose_address: 189 if declarations.is_array( self.type ) and declarations.array_size( self.type ) < 1: 190 return messages.W1045 191 type_ = declarations.remove_alias( self.type ) 192 type_ = declarations.remove_const( type_ ) 193 if declarations.is_pointer( type_ ): 194 if not self.expose_address and self.type_qualifiers.has_static: 195 return messages.W1035 196 if not self.expose_address and python_traits.is_immutable( type_.base ): 197 return messages.W1036 198 199 units = declarations.decompose_type( type_ ) 200 ptr2functions = filter( lambda unit: isinstance( unit, declarations.calldef_type_t ) 201 , units ) 202 if ptr2functions: 203 return messages.W1037 204 type_ = declarations.remove_pointer( type_ ) 205 if declarations.class_traits.is_my_case( type_ ): 206 cls = declarations.class_traits.get_declaration( type_ ) 207 if not cls.name: 208 return messages.W1038 209 #if cls.class_type == declarations.CLASS_TYPES.UNION: 210 # return messages.W1061 % ( str( self ), str( cls ) ) 211 if isinstance( self.parent, declarations.class_t ): 212 if self.access_type != declarations.ACCESS_TYPES.PUBLIC: 213 return messages.W1039 214 if declarations.is_array( type_ ): 215 item_type = declarations.array_item_type( type_ ) 216 if declarations.is_pointer( item_type ): 217 item_type_no_ptr = declarations.remove_pointer( item_type ) 218 if python_traits.is_immutable( item_type_no_ptr ): 219 return messages.W1056 220 return ''
221
222 - def is_wrapper_needed(self):
223 """returns an explanation( list of str ) why wrapper is needed. 224 225 If wrapper is not needed than [] will be returned. 226 """ 227 explanation = [] 228 if self.bits: 229 explanation.append( messages.W1024 % self.name ) 230 if declarations.is_pointer( self.type ): 231 explanation.append( messages.W1025 % self.name ) 232 if declarations.is_reference( self.type ): 233 explanation.append( messages.W1026 % self.name ) 234 if declarations.is_array( self.type ): 235 explanation.append( messages.W1027 % self.name) 236 return explanation
237