Package pyplusplus :: Package decl_wrappers :: Module call_policies |

# Source Code for Module pyplusplus.decl_wrappers.call_policies

      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  """Contains definition of call policies classes"""
      7
      8  import algorithm
      9  import python_traits
     10  from pygccxml import declarations
     11
     12  #keeps file name, where Py++ defined call policies will be defined
     13  PYPP_CALL_POLICIES_HEADER_FILE = "__call_policies.pypp.hpp"
     14
     15 -class CREATION_POLICY:
     16      """Implementation details"""
     17      AS_INSTANCE = 'as instance'
     18      AS_TEMPLATE_ARGUMENT = 'as template argument'
     19
     20 -class call_policy_t(object):
     21      """base class for all classes, which generate "call policies" code"""
     22 -    def __init__(self):
     23          object.__init__(self)
     24
     25 -    def create(self, function_creator, creation_policy=CREATION_POLICY.AS_INSTANCE):
     26          """Creates code from the call policies class instance.
     27          @param function_creator: parent code creator
     28          @type function_creator: L{code_creators.function_t} or L{code_creators.constructor_t}
     29
     30          @param creation_policy: indicates whether we this call policy used as template
     31                                  argument or as an instance
     32          @type creation_policy: L{CREATION_POLICY}
     33          """
     34          code = self._create_impl( function_creator )
     35          if code and creation_policy == CREATION_POLICY.AS_INSTANCE:
     36              code = code + '()'
     37          return code
     38
     39 -    def create_type(self):
     40          """return call policies class declaration as string"""
     41          return self.create( None, CREATION_POLICY.AS_TEMPLATE_ARGUMENT )
     42
     43 -    def create_template_arg( self, function_creator ):
     44          """return call policies class declaration as string"""
     45          return self.create( function_creator, CREATION_POLICY.AS_TEMPLATE_ARGUMENT )
     46
     47 -    def is_default( self ):
     48          """return True is self is instance of L{default_call_policies_t} class"""
     49          return False
     50
     51 -    def is_predefined( self ):
     52          """return True if call policy is defined in Boost.Python library, False otherwise"""
     53          return True
     54
     55 -    def _create_impl( self, function_creator ):
     56          raise NotImplementedError()
     57
     58      @property
     59 -    def header_file(self):
     60          """return a name of the header file the call policy is defined in"""
     61          return "boost/python.hpp"
     62
     63 -class default_call_policies_t(call_policy_t):
     64      """implements code generation for boost::python::default_call_policies"""
     65 -    def __init__( self ):
     66          call_policy_t.__init__( self )
     67
     68 -    def _create_impl(self, function_creator ):
     69          return algorithm.create_identifier( function_creator, '::boost::python::default_call_policies' )
     70
     71 -    def is_default( self ):
     72          return True
     73
     74 -    def __str__(self):
     75          return 'default_call_policies'
     76
     77 -def default_call_policies():
     78      """create ::boost::python::default_call_policies call policies code generator"""
     79      return default_call_policies_t()
     80
     81 -class compound_policy_t( call_policy_t ):
     82      """base class for all call policies, except the default one"""
     83 -    def __init__( self, base=None ):
     84          call_policy_t.__init__( self )
     85          self._base = base
     86          if not base:
     87              self._base = default_call_policies_t()
     88
     89 -    def _get_base_policy( self ):
     90          return self._base
     91 -    def _set_base_policy( self, new_policy ):
     92          self._base = new_policy
     93      base_policy = property( _get_base_policy, _set_base_policy
     94                              , doc="base call policy, by default is reference to L{default_call_policies_t} call policy")
     95
     96 -    def _get_args(self, function_creator):
     97          return []
     98
     99 -    def _get_name(self, function_creator):
    100          raise NotImplementedError()
    101
    102 -    def _create_impl( self, function_creator ):
    103          args = self._get_args(function_creator)
    104          if not self._base.is_default():
    105              args.append( self._base.create( function_creator, CREATION_POLICY.AS_TEMPLATE_ARGUMENT ) )
    106          name = algorithm.create_identifier( function_creator, self._get_name(function_creator) )
    107          return declarations.templates.join( name, args )
    108
    109 -    def __str__(self):
    110          name = self._get_name(None).replace('::boost::python::', '' )
    111          args = map( lambda text: text.replace( '::boost::python::', '' )
    112                      , self._get_args( None ) )
    113          return declarations.templates.join( name, args )
    114
    115 -class return_argument_t( compound_policy_t ):
    116      """implements code generation for boost::python::return_argument call policies"""
    117 -    def __init__( self, position=1, base=None):
    118          compound_policy_t.__init__( self, base )
    119          self._position = position
    120
    121 -    def _get_position( self ):
    122          return self._position
    123 -    def _set_position( self, new_position):
    124          self._position = new_position
    125      position = property( _get_position, _set_position )
    126
    127 -    def _get_name(self, function_creator):
    128          if self.position == 1:
    129              return '::boost::python::return_self'
    130          else:
    131              return '::boost::python::return_arg'
    132
    133 -    def _get_args(self, function_creator):
    134          if self.position == 1:
    135              return []
    136          else:
    137              return [ str( self.position ) ]
    138
    139 -def return_arg( arg_pos, base=None ):
    140      """create boost::python::return_arg call policies code generator"""
    141      return return_argument_t( arg_pos, base )
    142
    143 -def return_self(base=None):
    144      """create boost::python::return_self call policies code generator"""
    145      return return_argument_t( 1, base )
    146
    147 -class return_internal_reference_t( compound_policy_t ):
    148      """implements code generation for boost::python::return_internal_reference call policies"""
    149 -    def __init__( self, position=1, base=None):
    150          compound_policy_t.__init__( self, base )
    151          self._position = position
    152
    153 -    def _get_position( self ):
    154          return self._position
    155 -    def _set_position( self, new_position):
    156          self._position = new_position
    157      position = property( _get_position, _set_position )
    158
    159 -    def _get_name(self, function_creator):
    160          return '::boost::python::return_internal_reference'
    161
    162 -    def _get_args(self, function_creator):
    163          if self.position == 1:
    164              return [] #don't generate default template arguments
    165          else:
    166              return [ str( self.position ) ]
    167
    168 -def return_internal_reference( arg_pos=1, base=None):
    169      """create boost::python::return_internal_reference call policies code generator"""
    170      return return_internal_reference_t( arg_pos, base )
    171
    172 -class with_custodian_and_ward_t( compound_policy_t ):
    173      """implements code generation for boost::python::with_custodian_and_ward call policies"""
    174 -    def __init__( self, custodian, ward, base=None):
    175          compound_policy_t.__init__( self, base )
    176          self._custodian = custodian
    177          self._ward = ward
    178
    179 -    def _get_custodian( self ):
    180          return self._custodian
    181 -    def _set_custodian( self, new_custodian):
    182          self._custodian = new_custodian
    183      custodian = property( _get_custodian, _set_custodian )
    184
    185 -    def _get_ward( self ):
    186          return self._ward
    187 -    def _set_ward( self, new_ward):
    188          self._ward = new_ward
    189      ward = property( _get_ward, _set_ward )
    190
    191 -    def _get_name(self, function_creator):
    192          return '::boost::python::with_custodian_and_ward'
    193
    194 -    def _get_args(self, function_creator):
    195          return [ str( self.custodian ), str( self.ward ) ]
    196
    197 -def with_custodian_and_ward( custodian, ward, base=None):
    198      """create boost::python::with_custodian_and_ward call policies code generator"""
    199      return with_custodian_and_ward_t( custodian, ward, base )
    200
    201 -class with_custodian_and_ward_postcall_t( with_custodian_and_ward_t ):
    202      """implements code generation for boost::python::with_custodian_and_ward_postcall call policies"""
    203 -    def __init__( self, custodian, ward, base=None):
    204          with_custodian_and_ward_t.__init__( self, custodian, ward, base )
    205
    206 -    def _get_name(self, function_creator):
    207          return '::boost::python::with_custodian_and_ward_postcall'
    208
    209 -def with_custodian_and_ward_postcall( custodian, ward, base=None):
    210      """create boost::python::with_custodian_and_ward_postcall call policies code generator"""
    211      return with_custodian_and_ward_postcall_t( custodian, ward, base )
    212
    213 -class return_value_policy_t( compound_policy_t ):
    214      """implements code generation for boost::python::return_value_policy call policies"""
    215 -    def __init__( self, result_converter_generator, base=None):
    216          compound_policy_t.__init__( self, base )
    217          self._result_converter_generator = result_converter_generator
    218
    219 -    def _get_result_converter_generator( self ):
    220          return self._result_converter_generator
    221 -    def _set_result_converter_generator( self, new_result_converter_generator):
    222          self._result_converter_generator = new_result_converter_generator
    223      result_converter_generator = property( _get_result_converter_generator
    224                                             , _set_result_converter_generator )
    225
    226 -    def _get_name(self, function_creator):
    227          return '::boost::python::return_value_policy'
    228
    229 -    def _get_args(self, function_creator):
    230          if function_creator:
    231              rcg = algorithm.create_identifier( function_creator, self.result_converter_generator )
    232              return [ rcg ]
    233          else:
    234              return [self.result_converter_generator]
    235
    236 -    def is_predefined( self ):
    237          """Returns True if call policy is defined in Boost.Python library, False otherwise"""
    238          global return_addressof
    239          global return_pointee_value
    240          if self.result_converter_generator in (return_pointee_value, return_addressof ):
    241              return False
    242          else:
    243              return True
    244
    245      @property
    246 -    def header_file(self):
    247          """Return name of the header file to be included"""
    248          if self.is_predefined():
    249              return super( return_value_policy_t, self ).header_file
    250          else:
    251              return PYPP_CALL_POLICIES_HEADER_FILE
    252
    253
    254  copy_const_reference = '::boost::python::copy_const_reference'
    255  copy_non_const_reference = '::boost::python::copy_non_const_reference'
    256  manage_new_object = '::boost::python::manage_new_object'
    257  reference_existing_object = '::boost::python::reference_existing_object'
    258  return_by_value = '::boost::python::return_by_value'
    259  return_opaque_pointer = '::boost::python::return_opaque_pointer'
    260  return_pointee_value = '::pyplusplus::call_policies::return_pointee_value'
    261  return_addressof = '::pyplusplus::call_policies::return_addressof'
    262
    263 -def return_value_policy( result_converter_generator, base=None):
    264      """create boost::python::return_value_policy call policies code generator"""
    265      return return_value_policy_t( result_converter_generator, base )
    266
    267 -def is_return_opaque_pointer_policy( policy ):
    268      """returns True is policy represents return_value_policy<return_opaque_pointer>, False otherwise"""
    269      return isinstance( policy, return_value_policy_t ) \
    270              and policy.result_converter_generator == return_opaque_pointer
    271
    272 -class custom_call_policies_t(call_policy_t):
    273      """implements code generation for user defined call policies"""
    274 -    def __init__( self, call_policies, header_file=None ):
    275          call_policy_t.__init__( self )
    276          self.__call_policies = call_policies
    277          self.__header_file = header_file
    278
    279 -    def _create_impl(self, function_creator ):
    280          return str( self.__call_policies )
    281
    282 -    def __str__(self):
    283          return 'custom call policies'
    284
    285 -    def get_header_file( self ):
    286          return self.__header_file
    287 -    def set_header_file( self, header_file_name ):
    288          self.__header_file = header_file_name
    289      header_file = property( get_header_file, set_header_file
    290                              , doc="""Return name of the header file to be included""" )
    291
    292 -def custom_call_policies(call_policies, header_file=None):
    293      """create custom\\user defined call policies code generator"""
    294      return custom_call_policies_t(call_policies, header_file)
    295
    296 -class memory_managers:
    297      """implements code generation for Py++ defined memory managers
    298
    299      For complete documentation and usage example see http://language-binding.net/pyplusplus/documentation/functions/call_policies.html
    300      """
    301      none = 'none'
    302      delete_ = 'delete_'
    303      all = [ none, delete_ ]
    304
    305      @staticmethod
    306 -    def create( manager, function_creator=None):
    307          mem_manager = 'pyplusplus::call_policies::memory_managers::' + manager
    308          if function_creator:
    309              mem_manager = algorithm.create_identifier( function_creator, mem_manager )
    310          return mem_manager
    311
    312 -class convert_array_to_tuple_t( compound_policy_t ):
    313      """implements code generation for Py++ defined "as_tuple" value policy
    314
    315      For complete documentation and usage example see http://language-binding.net/pyplusplus/documentation/functions/call_policies.html
    316      """
    317 -    def __init__( self, array_size, memory_manager, make_object_call_policies=None, base=None):
    318          compound_policy_t.__init__( self, base )
    319          self._array_size = array_size
    320          self._memory_manager = memory_manager
    321          self._make_objec_call_policies = make_object_call_policies
    322
    323 -    def is_predefined( self ):
    324          """Returns True if call policy is defined in Boost.Python library, False otherwise"""
    325          return False
    326
    327      @property
    328 -    def header_file(self):
    329          """Return name of the header file to be included"""
    330          return PYPP_CALL_POLICIES_HEADER_FILE
    331
    332 -    def _get_array_size( self ):
    333          return self._array_size
    334 -    def _set_array_size( self, new_array_size):
    335          self._array_size = new_array_size
    336      array_size = property( _get_array_size, _set_array_size )
    337
    338 -    def _get_memory_manager( self ):
    339          return self._memory_manager
    340 -    def _set_memory_manager( self, new_memory_manager):
    341          self._memory_manager = new_memory_manager
    342      memory_manager = property( _get_memory_manager, _set_memory_manager )
    343
    344 -    def _get_make_objec_call_policies( self ):
    345          if None is self._make_objec_call_policies:
    346              self._make_objec_call_policies = default_call_policies()
    347          return self._make_objec_call_policies
    348 -    def _set_make_objec_call_policies( self, new_make_objec_call_policies):
    349          self._make_objec_call_policies = new_make_objec_call_policies
    350      make_objec_call_policies = property( _get_make_objec_call_policies, _set_make_objec_call_policies )
    351
    352 -    def _get_name(self, function_creator):
    353          return '::boost::python::return_value_policy'
    354
    355 -    def _get_args(self, function_creator):
    356          as_tuple_args = [ str( self.array_size ) ]
    357          as_tuple_args.append( memory_managers.create( self.memory_manager, function_creator ) )
    358          if not self.make_objec_call_policies.is_default():
    359              as_tuple_args.append( self.make_objec_call_policies.create_template_arg( function_creator ) )
    360          as_tuple = '::pyplusplus::call_policies::arrays::as_tuple'
    361          if function_creator:
    362              as_tuple = algorithm.create_identifier( function_creator, as_tuple )
    363          return [ declarations.templates.join( as_tuple, as_tuple_args ) ]
    364
    365 -def convert_array_to_tuple( array_size, memory_manager, make_object_call_policies=None, base=None ):
    366      """create boost::python::return_value_policy< py++::as_tuple > call policies code generator"""
    367      return convert_array_to_tuple_t( array_size, memory_manager, make_object_call_policies, base )
    368
    369 -class return_range_t( call_policy_t ):
    370      """implements code generation for Py++ defined "return_range" call policies
    371
    372      For complete documentation and usage example see http://language-binding.net/pyplusplus/documentation/functions/call_policies.html
    373      """
    374      HEADER_FILE = "__return_range.pypp.hpp"
    375 -    def __init__( self, get_size_class, value_type, value_policies):
    376          call_policy_t.__init__( self )
    377          self._value_type = value_type
    378          self._get_size_class = get_size_class
    379          self._value_policies = value_policies
    380
    381 -    def is_predefined( self ):
    382          """Returns True if call policy is defined in Boost.Python library, False otherwise"""
    383          return False
    384
    385      @property
    386 -    def header_file(self):
    387          """Return name of the header file to be included"""
    388          return self.HEADER_FILE
    389
    390 -    def _get_get_size_class( self ):
    391          return self._get_size_class
    392 -    def _set_get_size_class( self, new_get_size_class):
    393          self._get_size_class = new_get_size_class
    394      get_size_class = property( _get_get_size_class, _set_get_size_class )
    395
    396 -    def _get_value_type( self ):
    397          return self._value_type
    398 -    def _set_value_type( self, new_value_type):
    399          self._value_type = new_value_type
    400      value_type = property( _get_value_type, _set_value_type )
    401
    402 -    def _get_value_policies( self ):
    403          return self._value_policies
    404 -    def _set_value_policies( self, new_value_policies):
    405          self._value_policies = new_value_policies
    406      value_policies = property( _get_value_policies, _set_value_policies )
    407
    408 -    def _create_impl(self, function_creator ):
    409          name = algorithm.create_identifier( function_creator, '::pyplusplus::call_policies::return_range' )
    410          args = [ self.get_size_class, self.value_type.decl_string ]
    411          if not self.value_policies.is_default():
    412              args.append( self.value_policies.create_type() )
    413          return declarations.templates.join( name, args )
    414
    415 -def return_range( function, get_size_class, value_policies=None ):
    416      """create Py++ defined return_range call policies code generator"""
    417      r_type = function.return_type
    418      if not declarations.is_pointer( r_type ):
    419          raise TypeError( 'Function "%s" return type should be pointer, got "%s"'
    420                           % r_type.decl_string )
    421
    422      value_type = declarations.remove_pointer( r_type )
    423      if None is value_policies:
    424          if python_traits.is_immutable( value_type ):
    425              value_policies = default_call_policies()
    426          else:
    427              raise RuntimeError( "return_range call policies requieres specification of value_policies" )
    428      return return_range_t( get_size_class, value_type, value_policies )
    429