Package pyplusplus :: Package decl_wrappers :: Module decl_wrapper |

# Source Code for Module pyplusplus.decl_wrappers.decl_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 base class for all code generator configuration classes"""
      7
      8  import algorithm
      9  from pyplusplus import _logging_
     10  from pygccxml import declarations
     11  from pyplusplus import messages
     12
     13 -class decl_wrapper_t(object):
     14      """code generator declaration configuration base class
     15
     16      This class contains configuration that could be applied to all declarations.
     17      """
     18
     19      SPECIAL_TYPEDEF_PICK_ANY = True
     20
     21 -    def __init__(self):
     22          object.__init__(self)
     23          self._alias = None
     24          self._ignore = False
     25          self._already_exposed = False
     26          self._exportable = None
     27          self._exportable_reason = None
     28          self._documentation = None
     29          self.__msgs_to_ignore = set()
     30          self._include_files = []
     31
     32      @property
     33 -    def logger( self ):
     34          """reference to L{_logging_.loggers.declarations}"""
     35          return _logging_.loggers.declarations
     36
     37 -    def _get_documentation( self ):
     38          return self._documentation
     39 -    def _set_documentation( self, value ):
     40          self._documentation = value
     41      documentation = property( _get_documentation, _set_documentation
     42                               , doc="exposed declaration Python documentation string" )
     43
     44 -    def _generate_valid_name(self, name=None):
     45          if name == None:
     46              name = self.name
     47          return algorithm.create_valid_name( name )
     48
     49 -    def __select_alias_directives( self, be_smart ):
     50          if not isinstance( self, declarations.class_types ):
     51              return []
     52          typedefs = list( set( filter( lambda typedef: typedef.is_directive, self.aliases ) ) )
     53          if decl_wrapper_t.SPECIAL_TYPEDEF_PICK_ANY:
     54              if typedefs and be_smart:
     55                  longest_name_len = 0
     56                  longest_typedef = None
     57                  for typedef in typedefs:
     58                      typedef_name_len = len( typedef.name )
     59                      if longest_name_len < typedef_name_len:
     60                          longest_name_len = typedef_name_len
     61                          longest_typedef = typedef
     62                  return [longest_typedef]
     63              else:
     64                  return typedefs
     65          else:
     66              return typedefs
     67
     68 -    def _get_alias(self):
     69          if not self._alias:
     70              directives = self.__select_alias_directives(be_smart=True)
     71              if 1 == len( directives ):
     72                  self._alias = directives[0].name
     73              else:
     74                  if declarations.templates.is_instantiation( self.name ):
     75                      container_aliases = [ 'value_type', 'key_type', 'mapped_type' ]
     76                      if isinstance( self, declarations.class_t ) \
     77                          and 1 == len( set( map( lambda typedef: typedef.name, self.aliases ) ) ) \
     78                          and self.aliases[0].name not in container_aliases:
     79                              self._alias = self.aliases[0].name
     80                      else:
     81                          self._alias = algorithm.create_valid_name( self.partial_name )
     82                  else:
     83                      if declarations.is_class( self ) or declarations.is_class_declaration( self ):
     84                          self._alias = algorithm.create_valid_name( self.partial_name )
     85                      else:
     86                          self._alias = self.partial_name
     87          return self._alias
     88 -    def _set_alias(self, alias):
     89          self._alias = alias
     90      alias = property( _get_alias, _set_alias
     91                        , doc="the name under which, Python will know the declaration" )
     92
     93 -    def rename( self, new_name ):
     94          """give new name to the declaration, under which Python will know the declaration"""
     95          self.alias = new_name
     96
     97 -    def _get_ignore( self ):
     98          return self._ignore
     99 -    def _set_ignore( self, value ):
    100          self._ignore = value
    101      ignore = property( _get_ignore, _set_ignore
    102                         , doc="boolean flag, which says whether to export declaration to Python or not" )
    103
    104 -    def get_already_exposed( self ):
    105          return self._already_exposed
    106 -    def set_already_exposed( self, value ):
    107          self._already_exposed = value
    108      already_exposed = property( get_already_exposed, set_already_exposed
    109                                  , doc="boolean flag, which says whether the declaration is already exposed or not" )
    110
    111 -    def exclude( self, compilation_errors=False ):
    112          """exclude "self" and child declarations from being exposed.
    113
    114          If compile_time_errors is True, than only declarations, which will cause
    115          compilation error will be excluded
    116          """
    117          self.ignore = True
    118
    119 -    def include( self, already_exposed=False ):
    120          """include "self" and child declarations to be exposed."""
    121          self.ignore = False
    122          self.already_exposed = already_exposed
    123
    124 -    def why_not_exportable( self ):
    125          """return the reason( string ) that explains why this declaration could not be exported
    126
    127          If declaration could be exported, than method will return None
    128          """
    129          if None is self._exportable_reason:
    130              self.get_exportable()
    131          return self._exportable_reason
    132
    133 -    def _exportable_impl( self ):
    134          return ''
    135
    136 -    def get_exportable( self ):
    137          """return True if declaration could be exposed to Python, False otherwise"""
    138          if self._exportable is None:
    139              if self.name.startswith( '__' ) or '.' in self.name:
    140                  self._exportable_reason = messages.W1000
    141              elif self.location and self.location.file_name == "<internal>":
    142                  self._exportable_reason = messages.W1001
    143              elif self.is_artificial \
    144                   and not isinstance( self, ( declarations.class_t, declarations.enumeration_t ) ):
    145                  self._exportable_reason = messages.W1002
    146              else:
    147                  self._exportable_reason = self._exportable_impl( )
    148              self._exportable = not bool( self._exportable_reason )
    149          return self._exportable
    150 -    def set_exportable( self, exportable ):
    151          """change "exportable" status
    152
    153          This function should be use in case Py++ made a mistake and signed the
    154          declaration as unexportable."""
    155          self._exportable = exportable
    156
    157      exportable = property( get_exportable, set_exportable
    158                            , doc="Returns True if declaration could be exported to Python, otherwise False" )
    159
    160 -    def _readme_impl( self ):
    161          return []
    162
    163 -    def readme( self, skip_ignored=True ):
    164          """return important information( hints/tips/warning message ) Py++ has about
    165          this declaration.
    166
    167          skip_ignored argument allows you to control the information reported to you.
    168          For more information please read: http://www.language-binding.net/pyplusplus/documentation/warnings.html
    169          """
    170          msgs = []
    171          if not self.exportable:
    172              msgs.append( self.why_not_exportable() )
    173
    174          if declarations.templates.is_instantiation( self.name ) \
    175             and self.alias == self._generate_valid_name():
    176              msgs.append( messages.W1043 % self.alias )
    177
    178          directives = self.__select_alias_directives(be_smart=False)
    179          if 1 < len( directives ):
    180              msgs.append( messages.W1048
    181                           % ( self.alias, ', '.join( map( lambda typedef: typedef.name, directives ) ) ) )
    182
    183          msgs.extend( self._readme_impl() )
    184
    185          return messages.filter_disabled_msgs( msgs, self.__msgs_to_ignore )
    186
    187      @property
    188 -    def disabled_messages( self ):
    189          """list of messages to ignore"""
    190          return self.__msgs_to_ignore
    191          disabled_messaged = disabled_messages
    192
    193 -    def disable_messages( self, *args ):
    194          """set messages, which should not be reported to you
    195
    196          Usage example: decl.disable_messages( messages.W1001, messages.W1040 )
    197          """
    198          for msg in args:
    199              msg_id = messages.find_out_message_id( msg )
    200              if not msg_id:
    201                  raise RuntimeError( "Unable to find out message id. The message is: " + msg )
    202              self.__msgs_to_ignore.add( msg )
    203      disable_warnings = disable_messages
    204
    205      @property
    206 -    def include_files( self ):
    207          """list of header files, to be included from the file, the generated code will be placed-in"""
    208          return self._include_files
    209