pygccxml-commit Mailing List for C++ Python language bindings (Page 63)
Brought to you by:
mbaas,
roman_yakovenko
You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
(190) |
Apr
(166) |
May
(170) |
Jun
(75) |
Jul
(105) |
Aug
(131) |
Sep
(99) |
Oct
(84) |
Nov
(67) |
Dec
(54) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(66) |
Feb
(49) |
Mar
(25) |
Apr
(62) |
May
(21) |
Jun
(34) |
Jul
(9) |
Aug
(21) |
Sep
(5) |
Oct
|
Nov
(63) |
Dec
(34) |
2008 |
Jan
(10) |
Feb
(42) |
Mar
(26) |
Apr
(25) |
May
(6) |
Jun
(40) |
Jul
(18) |
Aug
(29) |
Sep
(6) |
Oct
(32) |
Nov
(14) |
Dec
(56) |
2009 |
Jan
(127) |
Feb
(52) |
Mar
(2) |
Apr
(10) |
May
(29) |
Jun
(3) |
Jul
|
Aug
(16) |
Sep
(4) |
Oct
(11) |
Nov
(8) |
Dec
(14) |
2010 |
Jan
(31) |
Feb
(1) |
Mar
(7) |
Apr
(9) |
May
(1) |
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2011 |
Jan
|
Feb
(8) |
Mar
(4) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2014 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <rom...@us...> - 2006-07-11 07:25:48
|
Revision: 291 Author: roman_yakovenko Date: 2006-07-11 00:24:56 -0700 (Tue, 11 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=291&view=rev Log Message: ----------- adding different loggers for different functionality fixing some bug in generated code for member function, that belongs to template instantiated class Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/cpptypes.py pygccxml_dev/pygccxml/parser/source_reader.py pygccxml_dev/pygccxml/utils/__init__.py pyplusplus_dev/examples/pyboost_dev/dev/boost_random/generate_code.py pyplusplus_dev/examples/pyboost_dev/dev/crc/generate_code.py pyplusplus_dev/examples/pyboost_dev/dev/date_time/generate_code.py pyplusplus_dev/examples/pyboost_dev/dev/rational/generate_code.py pyplusplus_dev/pyplusplus/_logging_/__init__.py pyplusplus_dev/pyplusplus/code_creators/calldef.py pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py pyplusplus_dev/pyplusplus/file_writers/multiple_files.py pyplusplus_dev/pyplusplus/file_writers/writer.py pyplusplus_dev/pyplusplus/module_builder/builder.py pyplusplus_dev/pyplusplus/module_creator/types_database.py pyplusplus_dev/unittests/test_all.py Added Paths: ----------- pyplusplus_dev/unittests/data/unnamed_classes_to_be_exported.hpp pyplusplus_dev/unittests/unnamed_classes_tester.py Modified: pygccxml_dev/pygccxml/declarations/cpptypes.py =================================================================== --- pygccxml_dev/pygccxml/declarations/cpptypes.py 2006-07-10 19:12:24 UTC (rev 290) +++ pygccxml_dev/pygccxml/declarations/cpptypes.py 2006-07-11 07:24:56 UTC (rev 291) @@ -406,7 +406,8 @@ , [ arg.clone() for arg in self.arguments_types ] ) #TODO: create real typedef - def create_typedef( self, typedef_name): + def create_typedef( self, typedef_name, unused=None): + #unused argument simplifies user code return free_function_type_t.TYPEDEF_NAME_TEMPLATE % { 'typedef_name' : typedef_name , 'return_type' : self.return_type.decl_string @@ -438,7 +439,7 @@ ,doc="reference to parent L{class<declaration_t>}" ) #TODO: create real typedef - def create_typedef( self, typedef_name): + def create_typedef( self, typedef_name, class_alias=None): """ creates typedef to the function type @@ -447,11 +448,13 @@ """ has_const_str = '' if self.has_const: - has_const_str = 'const' + has_const_str = 'const' + if None is class_alias: + class_alias = self.class_inst.decl_string return member_function_type_t.TYPEDEF_NAME_TEMPLATE % { 'typedef_name' : typedef_name , 'return_type' : self.return_type.decl_string - , 'class' : self.class_inst.decl_string + , 'class' : class_alias , 'arguments' : ','.join( map( lambda x: x.decl_string, self.arguments_types ) ) , 'has_const' : has_const_str } Modified: pygccxml_dev/pygccxml/parser/source_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/source_reader.py 2006-07-10 19:12:24 UTC (rev 290) +++ pygccxml_dev/pygccxml/parser/source_reader.py 2006-07-11 07:24:56 UTC (rev 291) @@ -1,335 +1,335 @@ -# Copyright 2004 Roman Yakovenko. -# Distributed under the Boost Software License, Version 1.0. (See -# accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -import os -import sys -import config -import pygccxml.utils -import linker -import scanner -import declarations_cache -import patcher -from pygccxml.declarations import * -from pygccxml import utils - -class gccxml_runtime_error_t( RuntimeError ): - def __init__( self, msg ): - RuntimeError.__init__( self, msg ) - - -def bind_aliases( decls ): - """ - This function binds between class and it's typedefs. - - @param decls: list of all declarations - @type all_classes: list of L{declaration_t} items - - @return: None - """ - visited = set() - for decl in decls: - if not isinstance( decl, typedef_t ): - continue - type_ = remove_alias( decl.type ) - if not isinstance( type_, declarated_t ): - continue - cls_inst = type_.declaration - if not isinstance( cls_inst, class_t ): - continue - if id( cls_inst ) not in visited: - visited.add( id( cls_inst ) ) - del cls_inst.aliases[:] - cls_inst.aliases.append( decl ) - -class source_reader_t: - """ - This class reads C++ source code and returns declarations tree. - - This class is the only class that have an intime knowledge about GCC-XML. - It has only one responsibility: it calls GCC-XML with a source file specified - by user and creates declarations tree. The implementation of this class is split - to 2 classes: - - 1. L{scanner_t} - this class scans the "XML" file, generated by GCC-XML and - creates `pygccxml`_ declarations and types classes. After the xml file has - been processed declarations and type class instances keeps references to - each other using GCC-XML generated id's. - - 2. L{linker_t} - this class contains logic for replacing GCC-XML generated - ids with references to declarations or type class instances. - """ - def __init__( self, config, cache=None, decl_factory=None ): - """ - @param config: instance of L{config_t} class, that contains GCC-XML - configuration - @type config: L{config_t} - - @param cache: reference to cache object, that will be updated after - file has been parsed. - @param cache: instance of class, that derives from {cache_base_t} - - @param decl_factory: declarations factory, if not given default - declarations factory L{decl_factory_t} will be used +# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import os +import sys +import config +import pygccxml.utils +import linker +import scanner +import declarations_cache +import patcher +from pygccxml.declarations import * +from pygccxml import utils + +class gccxml_runtime_error_t( RuntimeError ): + def __init__( self, msg ): + RuntimeError.__init__( self, msg ) + + +def bind_aliases( decls ): + """ + This function binds between class and it's typedefs. + + @param decls: list of all declarations + @type all_classes: list of L{declaration_t} items + + @return: None + """ + visited = set() + for decl in decls: + if not isinstance( decl, typedef_t ): + continue + type_ = remove_alias( decl.type ) + if not isinstance( type_, declarated_t ): + continue + cls_inst = type_.declaration + if not isinstance( cls_inst, class_t ): + continue + if id( cls_inst ) not in visited: + visited.add( id( cls_inst ) ) + del cls_inst.aliases[:] + cls_inst.aliases.append( decl ) + +class source_reader_t: + """ + This class reads C++ source code and returns declarations tree. + + This class is the only class that have an intime knowledge about GCC-XML. + It has only one responsibility: it calls GCC-XML with a source file specified + by user and creates declarations tree. The implementation of this class is split + to 2 classes: + + 1. L{scanner_t} - this class scans the "XML" file, generated by GCC-XML and + creates `pygccxml`_ declarations and types classes. After the xml file has + been processed declarations and type class instances keeps references to + each other using GCC-XML generated id's. + + 2. L{linker_t} - this class contains logic for replacing GCC-XML generated + ids with references to declarations or type class instances. + """ + def __init__( self, config, cache=None, decl_factory=None ): """ - self.logger = utils.loggers.gccxml - self.__search_directories = [] - self.__config = config - self.__search_directories.append( config.working_directory ) - self.__search_directories.extend( config.include_paths ) - if not cache: - cache = declarations_cache.dummy_cache_t() - self.__dcache = cache - self.__raise_on_wrong_settings() - self.__decl_factory = decl_factory - if not decl_factory: - self.__decl_factory = decl_factory_t() - - def __raise_on_wrong_settings(self): - if not os.path.isfile( self.__config.gccxml_path ): - if sys.platform == 'win32': - gccxml_name = 'gccxml' + '.exe' - environment_var_delimiter = ';' - elif sys.platform == 'linux2' or sys.platform == 'darwin': - gccxml_name = 'gccxml' - environment_var_delimiter = ':' - else: - raise RuntimeError( 'unable to find out location of gccxml' ) - may_be_gccxml = os.path.join( self.__config.gccxml_path, gccxml_name ) - if os.path.isfile( may_be_gccxml ): - self.__config.gccxml_path = may_be_gccxml - else: - for path in os.environ['PATH'].split( environment_var_delimiter ): - gccxml_path = os.path.join( path, gccxml_name ) - if os.path.isfile( gccxml_path ): - self.__config.gccxml_path = gccxml_path - break - else: - msg = 'gccxml_path("%s") should exists or to be a valid file name.' \ - % self.__config.gccxml_path - raise RuntimeError( msg ) - if not os.path.isdir( self.__config.working_directory ): - msg = 'working_directory("%s") should exists or to be a valid directory name.' \ - % self.__config.working_directory - raise RuntimeError( msg ) - for include_path in self.__config.include_paths: - if not os.path.isdir( include_path ): - msg = 'include path "%s" should exists or to be a valid directory name.' \ - % include_path - raise RuntimeError( msg ) - - def __create_command_line(self, file, xmlfile): - assert isinstance( self.__config, config.config_t ) - #returns - cmd = [] - #first is gccxml executable - if 'win32' in sys.platform: - cmd.append( '"%s"' % os.path.normpath( self.__config.gccxml_path ) ) - else: - cmd.append( '%s' % os.path.normpath( self.__config.gccxml_path ) ) - # Add all cflags passed - if self.__config.cflags != "": - cmd.append(" %s "%self.__config.cflags) - #second all additional includes directories - cmd.append( ''.join( [' -I"%s"' % search_dir for search_dir in self.__search_directories] ) ) - #third all additional defined symbols - cmd.append( ''.join( [' -D"%s"' % defined_symbol for defined_symbol in self.__config.define_symbols] ) ) - cmd.append( ''.join( [' -U"%s"' % undefined_symbol for undefined_symbol in self.__config.undefine_symbols] ) ) - #fourth source file - cmd.append( '"%s"' % file ) - #five destination file - cmd.append( '-fxml="%s"' % xmlfile ) - if self.__config.start_with_declarations: - cmd.append( '-fxml-start="%s"' % ','.join( self.__config.start_with_declarations ) ) - - cmd_line = ' '.join(cmd) - if 'win32' in sys.platform : - cmd_line = '"%s"' % cmd_line - self.logger.info( 'gccxml cmd: %s' % cmd_line ) - return cmd_line - - def create_xml_file( self, header, destination=None ): - """ - This function will return the file name of the file, created by GCC-XML - for "header" file. If destination_file_path is not None, then this file - path will be used and returned. - - @param header: path to source file, that should be parsed - @type header: str - - @param destination: if given, will be used as target file/path for - GCC-XML generated file. - @type destination: str - - @return: path to GCC-XML generated file - """ - gccxml_file = destination - # If file specified, remove it to start else create new file name - if gccxml_file: - pygccxml.utils.remove_file_no_raise( gccxml_file ) - else: - gccxml_file = pygccxml.utils.create_temp_file_name( suffix='.xml' ) - try: - ffname = header - if not os.path.isabs( ffname ): - ffname = self.__file_full_name(header) - command_line = self.__create_command_line( ffname, gccxml_file ) - input_, output = os.popen4( command_line ) - input_.close() - gccxml_reports = [] - while True: - data = output.readline() - gccxml_reports.append( data ) - if not data: - break - exit_status = output.close() - gccxml_msg = ''.join(gccxml_reports) - if self.__config.ignore_gccxml_output: - if not os.path.isfile(gccxml_file): - raise gccxml_runtime_error_t( "Error occured while running GCC-XML: %s status:%s" % (gccxml_msg, exit_status) ) - else: - if gccxml_msg or exit_status or not os.path.isfile(gccxml_file): - raise gccxml_runtime_error_t( "Error occured while running GCC-XML: %s" % gccxml_msg ) - except Exception, error: - pygccxml.utils.remove_file_no_raise( gccxml_file ) - raise error - return gccxml_file - - def create_xml_file_from_string( self, content, destination=None ): - """ - Creates XML file from text. - - @param content: C++ source code - @type content: str - - @param destination: file name for GCC-XML generated file - @type destination: str - - @return: returns file name of GCC-XML generated file - """ - header_file = pygccxml.utils.create_temp_file_name( suffix='.h' ) - gccxml_file = None - try: - header_file_obj = file(header_file, 'w+') - header_file_obj.write( content ) - header_file_obj.close() - gccxml_file = self.create_xml_file( header_file, destination ) - finally: - pygccxml.utils.remove_file_no_raise( header_file ) - return gccxml_file - - def read_file(self, source_file): - """ - Reads C++ source file and returns declarations tree - - @param source_file: path to C++ source file - @type source_file: str - """ - declarations, types = None, None - gccxml_file = '' - try: - ffname = self.__file_full_name(source_file) - self.logger.debug( "Reading source file: [%s]." % ffname ) - declarations = self.__dcache.cached_value( ffname, self.__config ) - if not declarations: - self.logger.debug( "File has not been found in cache, parsing..." ) - gccxml_file = self.create_xml_file( ffname ) - declarations, files = self.__parse_gccxml_created_file( gccxml_file ) - self.__dcache.update( ffname, self.__config, declarations, files ) - else: - self.logger.debug( "File has not been changed, reading declarations from cache." ) - except Exception, error: - if gccxml_file: - pygccxml.utils.remove_file_no_raise( gccxml_file ) - raise error - if gccxml_file: - pygccxml.utils.remove_file_no_raise( gccxml_file ) - return declarations - - def read_xml_file(self, gccxml_created_file): - """ - Reads GCC-XML generated XML file. - - @param gccxml_created_file: path to GCC-XML generated file - @type gccxml_created_file: str - - @return: declarations tree - """ - self.logger.debug( "Reading xml file: [%s]" % gccxml_created_file ) - - declarations, files = self.__parse_gccxml_created_file( gccxml_created_file ) - return declarations - - def read_string(self, content): - """ - Reads Python string, that contains valid C++ code, and returns - declarations tree. - """ - header_file = pygccxml.utils.create_temp_file_name( suffix='.h' ) - header_file_obj = file(header_file, 'w+') - header_file_obj.write( content ) - header_file_obj.close() - declarations = None - try: - declarations = self.read_file( header_file ) - except Exception, error: - pygccxml.utils.remove_file_no_raise( header_file ) - raise error - pygccxml.utils.remove_file_no_raise( header_file ) - return declarations - - def __file_full_name( self, file ): - if os.path.isfile( file ): - return file - for path in self.__search_directories: - file_path = os.path.join( path, file ) - if os.path.isfile( file_path ): - return file_path - raise RuntimeError( "pygccxml error: file '%s' does not exist" % file ) - - def __produce_full_file( self, file_path ): - if os.path.isabs( file_path ): - return file_path - try: - abs_file_path = os.path.realpath( os.path.join( self.__config.working_directory, file_path ) ) - if os.path.exists( abs_file_path ): - return os.path.normpath( abs_file_path ) - return file_path - except Exception: - return file_path - - def __parse_gccxml_created_file( self, gccxml_file ): - scanner_ = scanner.scanner_t( gccxml_file, self.__decl_factory ) - scanner_.read() - decls = scanner_.declarations() - types = scanner_.types() - files = {} - for file_id, file_path in scanner_.files().items(): - files[file_id] = self.__produce_full_file(file_path) - linker_ = linker.linker_t( decls=decls - , types=types - , access=scanner_.access() - , membership=scanner_.members() - , files=files ) - for type_ in list( types.itervalues() ): - #I need this copy because internaly linker change types collection - linker_.instance = type_ - apply_visitor( linker_, type_ ) - for decl in decls.itervalues(): - linker_.instance = decl - apply_visitor( linker_, decl ) - bind_aliases( decls.itervalues() ) - decls = filter( lambda inst: isinstance(inst, declaration_t) and not inst.parent, decls.itervalues() ) - #some times gccxml report typedefs defined in no namespace - #it happens for example in next situation - #template< typename X> - #void ddd(){ typedef typename X::Y YY;} - decls = filter( lambda inst: isinstance( inst, namespace_t ), decls ) - decls = patcher.patch_it( decls ) - decls_all = make_flatten( decls ) - for decl in decls_all: - if decl.location: - decl.location.file_name = self.__produce_full_file( decl.location.file_name ) - return ( decls, files.values() ) - + @param config: instance of L{config_t} class, that contains GCC-XML + configuration + @type config: L{config_t} + + @param cache: reference to cache object, that will be updated after + file has been parsed. + @param cache: instance of class, that derives from {cache_base_t} + + @param decl_factory: declarations factory, if not given default + declarations factory L{decl_factory_t} will be used + """ + self.logger = utils.loggers.gccxml + self.__search_directories = [] + self.__config = config + self.__search_directories.append( config.working_directory ) + self.__search_directories.extend( config.include_paths ) + if not cache: + cache = declarations_cache.dummy_cache_t() + self.__dcache = cache + self.__raise_on_wrong_settings() + self.__decl_factory = decl_factory + if not decl_factory: + self.__decl_factory = decl_factory_t() + + def __raise_on_wrong_settings(self): + if not os.path.isfile( self.__config.gccxml_path ): + if sys.platform == 'win32': + gccxml_name = 'gccxml' + '.exe' + environment_var_delimiter = ';' + elif sys.platform == 'linux2' or sys.platform == 'darwin': + gccxml_name = 'gccxml' + environment_var_delimiter = ':' + else: + raise RuntimeError( 'unable to find out location of gccxml' ) + may_be_gccxml = os.path.join( self.__config.gccxml_path, gccxml_name ) + if os.path.isfile( may_be_gccxml ): + self.__config.gccxml_path = may_be_gccxml + else: + for path in os.environ['PATH'].split( environment_var_delimiter ): + gccxml_path = os.path.join( path, gccxml_name ) + if os.path.isfile( gccxml_path ): + self.__config.gccxml_path = gccxml_path + break + else: + msg = 'gccxml_path("%s") should exists or to be a valid file name.' \ + % self.__config.gccxml_path + raise RuntimeError( msg ) + if not os.path.isdir( self.__config.working_directory ): + msg = 'working_directory("%s") should exists or to be a valid directory name.' \ + % self.__config.working_directory + raise RuntimeError( msg ) + for include_path in self.__config.include_paths: + if not os.path.isdir( include_path ): + msg = 'include path "%s" should exists or to be a valid directory name.' \ + % include_path + raise RuntimeError( msg ) + + def __create_command_line(self, file, xmlfile): + assert isinstance( self.__config, config.config_t ) + #returns + cmd = [] + #first is gccxml executable + if 'win32' in sys.platform: + cmd.append( '"%s"' % os.path.normpath( self.__config.gccxml_path ) ) + else: + cmd.append( '%s' % os.path.normpath( self.__config.gccxml_path ) ) + # Add all cflags passed + if self.__config.cflags != "": + cmd.append(" %s "%self.__config.cflags) + #second all additional includes directories + cmd.append( ''.join( [' -I"%s"' % search_dir for search_dir in self.__search_directories] ) ) + #third all additional defined symbols + cmd.append( ''.join( [' -D"%s"' % defined_symbol for defined_symbol in self.__config.define_symbols] ) ) + cmd.append( ''.join( [' -U"%s"' % undefined_symbol for undefined_symbol in self.__config.undefine_symbols] ) ) + #fourth source file + cmd.append( '"%s"' % file ) + #five destination file + cmd.append( '-fxml="%s"' % xmlfile ) + if self.__config.start_with_declarations: + cmd.append( '-fxml-start="%s"' % ','.join( self.__config.start_with_declarations ) ) + + cmd_line = ' '.join(cmd) + if 'win32' in sys.platform : + cmd_line = '"%s"' % cmd_line + self.logger.info( 'gccxml cmd: %s' % cmd_line ) + return cmd_line + + def create_xml_file( self, header, destination=None ): + """ + This function will return the file name of the file, created by GCC-XML + for "header" file. If destination_file_path is not None, then this file + path will be used and returned. + + @param header: path to source file, that should be parsed + @type header: str + + @param destination: if given, will be used as target file/path for + GCC-XML generated file. + @type destination: str + + @return: path to GCC-XML generated file + """ + gccxml_file = destination + # If file specified, remove it to start else create new file name + if gccxml_file: + pygccxml.utils.remove_file_no_raise( gccxml_file ) + else: + gccxml_file = pygccxml.utils.create_temp_file_name( suffix='.xml' ) + try: + ffname = header + if not os.path.isabs( ffname ): + ffname = self.__file_full_name(header) + command_line = self.__create_command_line( ffname, gccxml_file ) + input_, output = os.popen4( command_line ) + input_.close() + gccxml_reports = [] + while True: + data = output.readline() + gccxml_reports.append( data ) + if not data: + break + exit_status = output.close() + gccxml_msg = ''.join(gccxml_reports) + if self.__config.ignore_gccxml_output: + if not os.path.isfile(gccxml_file): + raise gccxml_runtime_error_t( "Error occured while running GCC-XML: %s status:%s" % (gccxml_msg, exit_status) ) + else: + if gccxml_msg or exit_status or not os.path.isfile(gccxml_file): + raise gccxml_runtime_error_t( "Error occured while running GCC-XML: %s" % gccxml_msg ) + except Exception, error: + pygccxml.utils.remove_file_no_raise( gccxml_file ) + raise error + return gccxml_file + + def create_xml_file_from_string( self, content, destination=None ): + """ + Creates XML file from text. + + @param content: C++ source code + @type content: str + + @param destination: file name for GCC-XML generated file + @type destination: str + + @return: returns file name of GCC-XML generated file + """ + header_file = pygccxml.utils.create_temp_file_name( suffix='.h' ) + gccxml_file = None + try: + header_file_obj = file(header_file, 'w+') + header_file_obj.write( content ) + header_file_obj.close() + gccxml_file = self.create_xml_file( header_file, destination ) + finally: + pygccxml.utils.remove_file_no_raise( header_file ) + return gccxml_file + + def read_file(self, source_file): + """ + Reads C++ source file and returns declarations tree + + @param source_file: path to C++ source file + @type source_file: str + """ + declarations, types = None, None + gccxml_file = '' + try: + ffname = self.__file_full_name(source_file) + self.logger.debug( "Reading source file: [%s]." % ffname ) + declarations = self.__dcache.cached_value( ffname, self.__config ) + if not declarations: + self.logger.debug( "File has not been found in cache, parsing..." ) + gccxml_file = self.create_xml_file( ffname ) + declarations, files = self.__parse_gccxml_created_file( gccxml_file ) + self.__dcache.update( ffname, self.__config, declarations, files ) + else: + self.logger.debug( "File has not been changed, reading declarations from cache." ) + except Exception, error: + if gccxml_file: + pygccxml.utils.remove_file_no_raise( gccxml_file ) + raise error + if gccxml_file: + pygccxml.utils.remove_file_no_raise( gccxml_file ) + return declarations + + def read_xml_file(self, gccxml_created_file): + """ + Reads GCC-XML generated XML file. + + @param gccxml_created_file: path to GCC-XML generated file + @type gccxml_created_file: str + + @return: declarations tree + """ + self.logger.debug( "Reading xml file: [%s]" % gccxml_created_file ) + + declarations, files = self.__parse_gccxml_created_file( gccxml_created_file ) + return declarations + + def read_string(self, content): + """ + Reads Python string, that contains valid C++ code, and returns + declarations tree. + """ + header_file = pygccxml.utils.create_temp_file_name( suffix='.h' ) + header_file_obj = file(header_file, 'w+') + header_file_obj.write( content ) + header_file_obj.close() + declarations = None + try: + declarations = self.read_file( header_file ) + except Exception, error: + pygccxml.utils.remove_file_no_raise( header_file ) + raise error + pygccxml.utils.remove_file_no_raise( header_file ) + return declarations + + def __file_full_name( self, file ): + if os.path.isfile( file ): + return file + for path in self.__search_directories: + file_path = os.path.join( path, file ) + if os.path.isfile( file_path ): + return file_path + raise RuntimeError( "pygccxml error: file '%s' does not exist" % file ) + + def __produce_full_file( self, file_path ): + if os.path.isabs( file_path ): + return file_path + try: + abs_file_path = os.path.realpath( os.path.join( self.__config.working_directory, file_path ) ) + if os.path.exists( abs_file_path ): + return os.path.normpath( abs_file_path ) + return file_path + except Exception: + return file_path + + def __parse_gccxml_created_file( self, gccxml_file ): + scanner_ = scanner.scanner_t( gccxml_file, self.__decl_factory ) + scanner_.read() + decls = scanner_.declarations() + types = scanner_.types() + files = {} + for file_id, file_path in scanner_.files().items(): + files[file_id] = self.__produce_full_file(file_path) + linker_ = linker.linker_t( decls=decls + , types=types + , access=scanner_.access() + , membership=scanner_.members() + , files=files ) + for type_ in list( types.itervalues() ): + #I need this copy because internaly linker change types collection + linker_.instance = type_ + apply_visitor( linker_, type_ ) + for decl in decls.itervalues(): + linker_.instance = decl + apply_visitor( linker_, decl ) + bind_aliases( decls.itervalues() ) + decls = filter( lambda inst: isinstance(inst, declaration_t) and not inst.parent, decls.itervalues() ) + #some times gccxml report typedefs defined in no namespace + #it happens for example in next situation + #template< typename X> + #void ddd(){ typedef typename X::Y YY;} + decls = filter( lambda inst: isinstance( inst, namespace_t ), decls ) + decls = patcher.patch_it( decls ) + decls_all = make_flatten( decls ) + for decl in decls_all: + if decl.location: + decl.location.file_name = self.__produce_full_file( decl.location.file_name ) + return ( decls, files.values() ) + Modified: pygccxml_dev/pygccxml/utils/__init__.py =================================================================== --- pygccxml_dev/pygccxml/utils/__init__.py 2006-07-10 19:12:24 UTC (rev 290) +++ pygccxml_dev/pygccxml/utils/__init__.py 2006-07-11 07:24:56 UTC (rev 291) @@ -9,7 +9,7 @@ import tempfile def _create_logger_( name ): - logger = logging.getLogger('name') + logger = logging.getLogger(name) __handler = logging.StreamHandler(sys.stdout) __handler.setFormatter( logging.Formatter( '%(levelname)s %(message)s' ) ) logger.addHandler(__handler) @@ -17,10 +17,11 @@ return logger class loggers: - root = _create_logger_( 'pygccxml' ) gccxml = _create_logger_( 'pygccxml.gccxml' ) queries_engine = _create_logger_( 'pygccxml.queries_engine' ) declarations_cache = _create_logger_( 'pygccxml.declarations_cache' ) + #root logger exists for configuration purpose only + root = logging.getLogger( 'pygccxml' ) all = [ root, gccxml, queries_engine, declarations_cache ] def remove_file_no_raise(file_name ): Modified: pyplusplus_dev/examples/pyboost_dev/dev/boost_random/generate_code.py =================================================================== --- pyplusplus_dev/examples/pyboost_dev/dev/boost_random/generate_code.py 2006-07-10 19:12:24 UTC (rev 290) +++ pyplusplus_dev/examples/pyboost_dev/dev/boost_random/generate_code.py 2006-07-11 07:24:56 UTC (rev 291) @@ -1,162 +1,161 @@ -#! /usr/bin/python -# Copyright 2004 Roman Yakovenko. -# Distributed under the Boost Software License, Version 1.0. (See -# accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -import os -import time -import logging -import random_settings -from pygccxml import parser -from pyplusplus import module_builder -from pyplusplus.module_builder import call_policies - - -LICENSE = """// Copyright 2004 Roman Yakovenko. -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -""" - -class code_generator_t(object): - def __init__(self): - module_builder.set_logger_level( logging.INFO ) - self.__file = os.path.join( random_settings.working_dir, 'random_export.hpp' ) - self.__mb = module_builder.module_builder_t( - [ parser.create_cached_source_fc( - self.__file - , os.path.join( random_settings.generated_files_dir, 'random.xml' ) ) ] - , gccxml_path=random_settings.gccxml.executable +#! /usr/bin/python +# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import os +import time +import logging +import random_settings +from pygccxml import parser +from pyplusplus import module_builder +from pyplusplus.module_builder import call_policies + + +LICENSE = """// Copyright 2004 Roman Yakovenko. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +""" + +class code_generator_t(object): + def __init__(self): + self.__file = os.path.join( random_settings.working_dir, 'random_export.hpp' ) + self.__mb = module_builder.module_builder_t( + [ parser.create_cached_source_fc( + self.__file + , os.path.join( random_settings.generated_files_dir, 'random.xml' ) ) ] + , gccxml_path=random_settings.gccxml.executable , include_paths=[random_settings.boost.include] - , define_symbols=random_settings.defined_symbols + , define_symbols=random_settings.defined_symbols , undefine_symbols=random_settings.undefined_symbols , indexing_suite_version=2) - self.generators = [ "ecuyer1988" - , "hellekalek1995" - , "kreutzer1986" - , "lagged_fibonacci1279" - , "lagged_fibonacci19937" - , "lagged_fibonacci2281" - , "lagged_fibonacci23209" - , "lagged_fibonacci3217" - , "lagged_fibonacci4423" - , "lagged_fibonacci44497" - , "lagged_fibonacci607" - , "lagged_fibonacci9689" - , "minstd_rand" - , "minstd_rand0" - , "mt11213b" - , "mt19937" - , "ranlux3" - , "ranlux3_01" - , "ranlux4" - , "ranlux4_01" - , "ranlux64_3_01" - , "ranlux64_4_01" - , "taus88" ] - - self.no_min_max = [ 'py_cauchy_distribution' - , 'py_bernoulli_distribution' - , 'py_binomial_distribution' - , 'py_poisson_distribution' - , 'py_normal_distribution' - , 'py_gamma_distribution' - , 'py_triangle_distribution' - , 'py_uniform_on_sphere' - , 'py_exponential_distribution' - , 'py_geometric_distribution' - , 'py_lognormal_distribution' - ] - - def typedef2class( self, scope, name ): - typedef = scope.typedef( name ) - return typedef.type.declaration - + self.generators = [ "ecuyer1988" + , "hellekalek1995" + , "kreutzer1986" + , "lagged_fibonacci1279" + , "lagged_fibonacci19937" + , "lagged_fibonacci2281" + , "lagged_fibonacci23209" + , "lagged_fibonacci3217" + , "lagged_fibonacci4423" + , "lagged_fibonacci44497" + , "lagged_fibonacci607" + , "lagged_fibonacci9689" + , "minstd_rand" + , "minstd_rand0" + , "mt11213b" + , "mt19937" + , "ranlux3" + , "ranlux3_01" + , "ranlux4" + , "ranlux4_01" + , "ranlux64_3_01" + , "ranlux64_4_01" + , "taus88" ] + + self.no_min_max = [ 'py_cauchy_distribution' + , 'py_bernoulli_distribution' + , 'py_binomial_distribution' + , 'py_poisson_distribution' + , 'py_normal_distribution' + , 'py_gamma_distribution' + , 'py_triangle_distribution' + , 'py_uniform_on_sphere' + , 'py_exponential_distribution' + , 'py_geometric_distribution' + , 'py_lognormal_distribution' + ] + + def typedef2class( self, scope, name ): + typedef = scope.typedef( name ) + return typedef.type.declaration + def filter_declarations(self ): - self.__mb.global_ns.exclude() - boost_ns = self.__mb.global_ns.namespace( 'boost', recursive=False ) - for name in self.generators: - gen_cls = self.typedef2class( boost_ns, name ) - gen_cls.include() - #TODO: find out why compiler complains - gen_cls.member_functions( 'seed' ).create_with_signature = True - - pyimpl_ns = boost_ns.namespace( 'pyimpl' ) - helpers = pyimpl_ns.classes( lambda decl: decl.name.startswith( 'py_') ) - helpers.include() - for helper in helpers: - distrib_cls = self.typedef2class( helper, "distribution" ) - distrib_cls.include() - var_gen_typedefs = helper.typedefs( lambda decl: decl.name.startswith( 'variate_generator_' ) ) - for var_gen_typedef in var_gen_typedefs: - var_gen_cls = var_gen_typedef.type.declaration - var_gen_cls.include() - var_gen_cls.member_operators( symbol='()' ).create_with_signature = True - if helper.name in self.no_min_max: - var_gen_cls.member_function( 'max' ).exclude() - var_gen_cls.member_function( 'min' ).exclude() - - ecuyer1988 = self.typedef2class( boost_ns, 'ecuyer1988' ) - ecuyer1988.member_function( 'seed', arg_types=[None, None] ).exclude() - - def prepare_declarations( self ): - boost_ns = self.__mb.namespace( 'boost' ) - for name in self.generators: - gen_cls = self.typedef2class( boost_ns, name ) - gen_cls.alias = name - - pyimpl_ns = boost_ns.namespace( 'pyimpl' ) - helpers = pyimpl_ns.classes( lambda decl: decl.name.startswith( 'py_') ) - for helper in helpers: - distrib_cls = self.typedef2class( helper, "distribution" ) - distrib_cls.alias = helper.name[3:] #py_ - var_gen_typedefs = helper.typedefs( lambda decl: decl.name.startswith( 'variate_generator_' ) ) - for var_gen_typedef in var_gen_typedefs: - var_gen_cls = var_gen_typedef.type.declaration - var_gen_cls.alias = var_gen_typedef.name + '__' + distrib_cls.alias - - self.set_call_policies() - - def set_call_policies( self ): - boost_ns = self.__mb.namespace( 'boost' ) - engine_funcs = boost_ns.member_functions( name="engine" - , function=lambda decl: not decl.has_const ) - engine_funcs.call_policies = call_policies.return_internal_reference() - - distribution_funcs = boost_ns.member_functions( name="distribution" - , function=lambda decl: not decl.has_const ) - distribution_funcs.call_policies = call_policies.return_internal_reference() - - def customize_extmodule( self ): + self.__mb.global_ns.exclude() + boost_ns = self.__mb.global_ns.namespace( 'boost', recursive=False ) + for name in self.generators: + gen_cls = self.typedef2class( boost_ns, name ) + gen_cls.include() + #TODO: find out why compiler complains + gen_cls.member_functions( 'seed' ).create_with_signature = True + + pyimpl_ns = boost_ns.namespace( 'pyimpl' ) + helpers = pyimpl_ns.classes( lambda decl: decl.name.startswith( 'py_') ) + helpers.include() + for helper in helpers: + distrib_cls = self.typedef2class( helper, "distribution" ) + distrib_cls.include() + var_gen_typedefs = helper.typedefs( lambda decl: decl.name.startswith( 'variate_generator_' ) ) + for var_gen_typedef in var_gen_typedefs: + var_gen_cls = var_gen_typedef.type.declaration + var_gen_cls.include() + var_gen_cls.member_operators( symbol='()' ).create_with_signature = True + if helper.name in self.no_min_max: + var_gen_cls.member_function( 'max' ).exclude() + var_gen_cls.member_function( 'min' ).exclude() + + ecuyer1988 = self.typedef2class( boost_ns, 'ecuyer1988' ) + ecuyer1988.member_function( 'seed', arg_types=[None, None] ).exclude() + + def prepare_declarations( self ): + boost_ns = self.__mb.namespace( 'boost' ) + for name in self.generators: + gen_cls = self.typedef2class( boost_ns, name ) + gen_cls.alias = name + + pyimpl_ns = boost_ns.namespace( 'pyimpl' ) + helpers = pyimpl_ns.classes( lambda decl: decl.name.startswith( 'py_') ) + for helper in helpers: + distrib_cls = self.typedef2class( helper, "distribution" ) + distrib_cls.alias = helper.name[3:] #py_ + var_gen_typedefs = helper.typedefs( lambda decl: decl.name.startswith( 'variate_generator_' ) ) + for var_gen_typedef in var_gen_typedefs: + var_gen_cls = var_gen_typedef.type.declaration + var_gen_cls.alias = var_gen_typedef.name + '__' + distrib_cls.alias + + self.set_call_policies() + + def set_call_policies( self ): + boost_ns = self.__mb.namespace( 'boost' ) + engine_funcs = boost_ns.member_functions( name="engine" + , function=lambda decl: not decl.has_const ) + engine_funcs.call_policies = call_policies.return_internal_reference() + + distribution_funcs = boost_ns.member_functions( name="distribution" + , function=lambda decl: not decl.has_const ) + distribution_funcs.call_policies = call_policies.return_internal_reference() + + def customize_extmodule( self ): global LICENSE - extmodule = self.__mb.code_creator - extmodule.license = LICENSE - extmodule.user_defined_directories.append( random_settings.boost.include ) - extmodule.user_defined_directories.append( random_settings.working_dir ) - extmodule.user_defined_directories.append( random_settings.generated_files_dir ) - extmodule.precompiled_header = 'boost/python.hpp' - extmodule.replace_included_headers( ['boost/random.hpp', 'boost/nondet_random.hpp', 'random_export.hpp' ] ) - - def write_files( self ): - self.__mb.split_module( random_settings.generated_files_dir ) - - def create(self): - start_time = time.clock() + extmodule = self.__mb.code_creator + extmodule.license = LICENSE + extmodule.user_defined_directories.append( random_settings.boost.include ) + extmodule.user_defined_directories.append( random_settings.working_dir ) + extmodule.user_defined_directories.append( random_settings.generated_files_dir ) + extmodule.precompiled_header = 'boost/python.hpp' + extmodule.replace_included_headers( ['boost/random.hpp', 'boost/nondet_random.hpp', 'random_export.hpp' ] ) + + def write_files( self ): + self.__mb.split_module( random_settings.generated_files_dir ) + + def create(self): + start_time = time.clock() self.filter_declarations() - self.prepare_declarations() - self.__mb.build_code_creator( random_settings.module_name ) - - self.customize_extmodule() - self.write_files( ) - print 'time taken : ', time.clock() - start_time, ' seconds' - -def export(): - cg = code_generator_t() - cg.create() - -if __name__ == '__main__': - export() - print 'done' - - + self.prepare_declarations() + self.__mb.build_code_creator( random_settings.module_name ) + + self.customize_extmodule() + self.write_files( ) + print 'time taken : ', time.clock() - start_time, ' seconds' + +def export(): + cg = code_generator_t() + cg.create() + +if __name__ == '__main__': + export() + print 'done' + + Modified: pyplusplus_dev/examples/pyboost_dev/dev/crc/generate_code.py =================================================================== --- pyplusplus_dev/examples/pyboost_dev/dev/crc/generate_code.py 2006-07-10 19:12:24 UTC (rev 290) +++ pyplusplus_dev/examples/pyboost_dev/dev/crc/generate_code.py 2006-07-11 07:24:56 UTC (rev 291) @@ -21,7 +21,6 @@ class code_generator_t(object): def __init__(self): - module_builder.set_logger_level( logging.INFO ) self.__file = os.path.join( crc_settings.working_dir, 'crc_export.hpp' ) self.__mb = module_builder.module_builder_t( @@ -31,7 +30,8 @@ , gccxml_path=crc_settings.gccxml.executable , include_paths=[crc_settings.boost.include] , define_symbols=crc_settings.defined_symbols - , undefine_symbols=crc_settings.undefined_symbols) + , undefine_symbols=crc_settings.undefined_symbols + , indexing_suite_version=2) def filter_declarations(self ): self.__mb.global_ns.exclude() Modified: pyplusplus_dev/examples/pyboost_dev/dev/date_time/generate_code.py =================================================================== --- pyplusplus_dev/examples/pyboost_dev/dev/date_time/generate_code.py 2006-07-10 19:12:24 UTC (rev 290) +++ pyplusplus_dev/examples/pyboost_dev/dev/date_time/generate_code.py 2006-07-11 07:24:56 UTC (rev 291) @@ -18,7 +18,6 @@ class code_generator_t(object): def __init__(self): - module_builder.set_logger_level( logging.INFO ) self.__file = os.path.join( date_time_settings.date_time_pypp_include, 'date_time.pypp.hpp' ) def _create_xml_file( self ): Modified: pyplusplus_dev/examples/pyboost_dev/dev/rational/generate_code.py =================================================================== --- pyplusplus_dev/examples/pyboost_dev/dev/rational/generate_code.py 2006-07-10 19:12:24 UTC (rev 290) +++ pyplusplus_dev/examples/pyboost_dev/dev/rational/generate_code.py 2006-07-11 07:24:56 UTC (rev 291) @@ -22,9 +22,7 @@ #TODO: for some reason unary - was not exported class code_generator_t(object): - def __init__(self): - module_builder.set_logger_level( logging.INFO ) - + def __init__(self): self.__file = os.path.join( rational_settings.working_dir, 'rational_export.hpp' ) self.__mb = module_builder.module_builder_t( @@ -35,7 +33,8 @@ , include_paths=[rational_settings.boost.include] , define_symbols=rational_settings.defined_symbols , undefine_symbols=rational_settings.undefined_symbols - , optimize_queries=False ) + , optimize_queries=False + , indexing_suite_version=2 ) for f_decl in self.__mb.free_functions(): f_decl.alias = f_decl.name Modified: pyplusplus_dev/pyplusplus/_logging_/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/_logging_/__init__.py 2006-07-10 19:12:24 UTC (rev 290) +++ pyplusplus_dev/pyplusplus/_logging_/__init__.py 2006-07-11 07:24:56 UTC (rev 291) @@ -11,9 +11,19 @@ import sys import logging - -logger = logging.getLogger('pyplusplus') -__handler = logging.StreamHandler(sys.stdout) -__handler.setFormatter( logging.Formatter('%(message)s') ) -logger.addHandler(__handler) -logger.setLevel(logging.DEBUG) \ No newline at end of file + +def _create_logger_( name ): + logger = logging.getLogger(name) + __handler = logging.StreamHandler(sys.stdout) + __handler.setFormatter( logging.Formatter( '%(levelname)s %(message)s' ) ) + logger.addHandler(__handler) + logger.setLevel(logging.INFO) + return logger + +class loggers: + file_writer = _create_logger_( 'pyplusplus.file_writer' ) + declarations = _create_logger_( 'pyplusplus.declarations' ) + module_builder = _create_logger_( 'pyplusplus.module_builder' ) + #root logger exists for configuration purpose only + root = logging.getLogger( 'pyplusplus' ) + all = [ root, file_writer, module_builder ] Modified: pyplusplus_dev/pyplusplus/code_creators/calldef.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-07-10 19:12:24 UTC (rev 290) +++ pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-07-11 07:24:56 UTC (rev 291) @@ -78,15 +78,24 @@ def _get_function_type_alias( self ): return 'function_ptr_t' function_type_alias = property( _get_function_type_alias ) - - def create_function_type_alias_code( self ): + + def _get_exported_class_alias( self ): + return 'exported_class_t' + exported_class_alias = property( _get_exported_class_alias ) + + def create_function_type_alias_code( self, exported_class_alias=None ): raise NotImplementedError() def _create_impl( self ): result = [] - if False == self.works_on_instance: - result.append( self.create_function_type_alias_code() ) + if False == self.works_on_instance: + exported_class_alias = None + if declarations.templates.is_instantiation( self.declaration.parent.name ): + exported_class_alias = self.exported_class_alias + result.append( 'typedef %s %s;' % ( self.parent.decl_identifier, exported_class_alias ) ) + result.append( os.linesep ) + result.append( self.create_function_type_alias_code(exported_class_alias) ) result.append( os.linesep * 2 ) result.append( self.create_def_code() + '( ' ) @@ -190,7 +199,7 @@ def create_def_code( self ): return self.def_identifier() - def create_function_type_alias_code( self ): + def create_function_type_alias_code( self, exported_class_alias=None ): return 'typedef ' + self.declaration.function_type().create_typedef( self.function_type_alias ) + ';' def create_function_ref_code(self, use_function_alias=False): @@ -208,8 +217,9 @@ def __init__( self, function ): calldef_t.__init__( self, function=function ) - def create_function_type_alias_code( self ): - return 'typedef ' + self.declaration.function_type().create_typedef( self.function_type_alias ) + ';' + def create_function_type_alias_code( self, exported_class_alias=None ): + ftype = self.declaration.function_type() + return 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) def create_function_ref_code(self, use_function_alias=False): if use_function_alias: @@ -227,8 +237,9 @@ def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) - def create_function_type_alias_code( self ): - return 'typedef ' + self.declaration.function_type().create_typedef( self.function_type_alias ) + ';' + def create_function_type_alias_code( self, exported_class_alias=None ): + ftype = self.declaration.function_type() + return 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) def create_function_ref_code(self, use_function_alias=False): if use_function_alias: @@ -295,12 +306,15 @@ calldef_t.__init__( self, function=function, wrapper=wrapper ) self.default_function_type_alias = 'default_' + self.function_type_alias - def create_function_type_alias_code( self ): - result = [] - result.append( 'typedef ' + self.declaration.function_type().create_typedef( self.function_type_alias ) + ';' ) + def create_function_type_alias_code( self, exported_class_alias=None ): + result = [] + + ftype = self.declaration.function_type() + result.append( 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) ) if self.wrapper: - result.append( os.linesep ) - result.append( 'typedef ' + self.wrapper.function_type().create_typedef( self.default_function_type_alias ) + ';' ) + result.append( os.linesep ) + ftype = self.wrapper.function_type() + result.append( 'typedef %s;' % ftype.create_typedef( self.default_function_type_alias ) ) return ''.join( result ) def create_function_ref_code(self, use_function_alias=False): @@ -413,8 +427,9 @@ def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) - def create_function_type_alias_code( self ): - return 'typedef ' + self.wrapper.function_type().create_typedef( self.function_type_alias ) + ';' + def create_function_type_alias_code( self, exported_class_alias=None ): + ftype = self.wrapper.function_type() + return 'typedef ' + ftype.create_typedef( self.function_type_alias ) + ';' def create_function_ref_code(self, use_function_alias=False): if use_function_alias: @@ -484,8 +499,9 @@ def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) - def create_function_type_alias_code( self ): - return 'typedef ' + self.wrapper.function_type().create_typedef( self.function_type_alias ) + ';' + def create_function_type_alias_code( self, exported_class_alias=None ): + ftype = self.wrapper.function_type() + return 'typedef %s;' % ftype.create_typedef( self.function_type_alias ) def create_function_ref_code(self, use_function_alias=False): if use_function_alias: @@ -546,8 +562,9 @@ def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) - def create_function_type_alias_code( self ): - return 'typedef ' + self.wrapper.function_type().create_typedef( self.function_type_alias ) + ';' + def create_function_type_alias_code( self, exported_class_alias=None ): + ftype = self.wrapper.function_type() + return 'typedef %s;' % ftype.create_typedef( self.function_type_alias ) def create_function_ref_code(self, use_function_alias=False): if use_function_alias: @@ -622,8 +639,9 @@ def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) - def create_function_type_alias_code( self ): - return 'typedef ' + self.wrapper.function_type().create_typedef( self.function_type_alias ) + ';' + def create_function_type_alias_code( self, exported_class_alias=None ): + ftype = self.wrapper.function_type() + return 'typedef %s;' % ftype.create_typedef( self.function_type_alias ) def create_function_ref_code(self, use_function_alias=False): if use_function_alias: Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-10 19:12:24 UTC (rev 290) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-11 07:24:56 UTC (rev 291) @@ -6,7 +6,6 @@ import os import decl_wrapper from pygccxml import declarations -from pyplusplus import _logging_ ##May be in future I will enable this functionality again, right now it seems ##that this is useless ##def is_finalizable(self): @@ -104,7 +103,7 @@ msg = "Function '%s' with more then 10 arguments( %d ). " msg = msg + " You should adjest BOOST_PYTHON_MAX_ARITY" msg = msg + " For more information see: http://mail.python.org/pipermail/c++-sig/2002-June/001554.html" - _logging_.logger.info( msg % ( self.decl_string, len( self.arguments ) ) ) + self.logger.info( msg % ( self.decl_string, len( self.arguments ) ) ) all_type... [truncated message content] |
From: <rom...@us...> - 2006-07-10 19:12:35
|
Revision: 290 Author: roman_yakovenko Date: 2006-07-10 12:12:24 -0700 (Mon, 10 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=290&view=rev Log Message: ----------- updating indexing suite 2 documentation Modified Paths: -------------- pyplusplus_dev/docs/std_containers/containers.rest Modified: pyplusplus_dev/docs/std_containers/containers.rest =================================================================== --- pyplusplus_dev/docs/std_containers/containers.rest 2006-07-10 12:33:25 UTC (rev 289) +++ pyplusplus_dev/docs/std_containers/containers.rest 2006-07-10 19:12:24 UTC (rev 290) @@ -8,7 +8,7 @@ Introduction ------------ -C++ has a bunch of containers classes: +C++ has a bunch of container classes: * list * deque @@ -40,10 +40,15 @@ `boost.python`_ mailing list or `documentation`_ for the new indexing suite. -If this suite is soo good, why it is not in the main branch? You can find the -answer here(http://mail.python.org/pipermail/c++-sig/2006-June/010830.html) and -here(http://mail.python.org/pipermail/c++-sig/2006-June/010835.html). +Now, I am sure you have next question: if this suite is soo good, why it is not +in the main branch? The short answer is that this suite has some problems on +MSVC 6.0 compiler and there are few users, that still use that compiler. +The long answer is here: +* http://mail.python.org/pipermail/c++-sig/2006-June/010830.html +* http://mail.python.org/pipermail/c++-sig/2006-June/010835.html + + .. _`documentation` : ./indexing_suite_v2.html .. _`post` : http://mail.python.org/pipermail/c++-sig/2003-October/005802.html @@ -62,7 +67,7 @@ In both cases, `pyplusplus`_ provides almost "hands free" solution. `pyplusplus`_ keeps track of all exported functions and variables, and if it sees that there is a usage of stl container, it exports the container. In both cases, `pyplusplus`_ -analizes the container ``value_type`` ( or in case of mapping containers +analizes the container ``value_type`` ( or in case of mapping container ``mapped_type`` ), in order to set reasonable defaults, when it generates the code. ----------------------- @@ -84,7 +89,8 @@ How does `pyplusplus`_ know that a class represents stl container instantiation? Well, it uses ``pygccxml.declarations.container_traits`` to find out this. ``pygccxml.declarations.container_traits`` class, provides all functionality -needed to identify container and to find out its ``value_type``( ``mapped_type`` ). +needed to identify container and to find out its ``value_type`` +( ``mapped_type`` ). Built-in indexing suite API @@ -93,10 +99,14 @@ `pyplusplus`_ defines ``indexing_suite1_t`` class. This class allows configure any detail of generated code: -* ``no_proxy`` - a boolean, if value type is one of the next types +* ``no_proxy`` - a boolean, if ``value_type`` is one of the next types + * fundamental type + * enumeration - * [w]string + + * std::string or std::wstring + * boost::shared_ptr<?> then, ``no_proxy`` will be set to ``True``, otherwise to ``False``. @@ -113,7 +123,12 @@ functionality. Please take a look on next C++ code: :: - struct item{ ... }; + struct item{ + ... + private: + bool operator==( const item& ) const; + bool operator<( const item& ) const; + }; struct my_data{ std::vector<item> items; @@ -122,13 +137,42 @@ `pyplusplus`_ declarations tree will contains ``item``, ``my_data``, -``vector<item>`` and ``map<string,item>`` class declarations. Next version of -indexing suite allows you to configure what set of operation will be supported, -based on functionality provided by container ``value_type`` ( ``mapped_type`` ). -To be more specific, you can create ``value_traits`` and set ``equality_comparable`` -or ``less_than_comparable`` to ``True`` if the type has `operator==` or ``False`` +``vector<item>`` and ``map<string,item>`` class declarations. +If ``value_type`` does not support "equal" or "less than" functionality, sort +and search functionality could not be exported. +`pyplusplus`_ class declaration has two properties: ``equality_comparable`` and +``less_than_comparable``. The value of those properties is calculated on first +invocation. If `pyplusplus`_ can find ``operator==``, that works on ``value_type``, +then, ``equality_comparable`` property value will be set to ``True``, otherwise +to ``False``. Same process is applied on ``less_than_comparable`` property. + +In our case, `pyplusplus`_ will set both properties to ``False``, thus sort and +search functionality will not be exported. + +It is the time to introduce ``indexing_suite2_t`` class: + +* ``container_class`` - read only property, returns reference to container class + declaration + +* ``container_traits`` - read only property, returns reference to the relevant + container traits class. Container traits classes are defined in + ``pygccxml.declarations`` package. + +* ``element_type`` - is a reference to container ``value_type`` or ``mapped_type``. + +* ``call_policies`` - read/write property, in near future I will add code to + `pyplusplus`_ that will analize container ``value_type`` and will decide about + default call policies. Just an example: for non copy constructable classes + ``call_policies`` should be set to ``return_internal_reference``. + +* ``[disable|enable]_method`` - new indexing suite, allows to configure + functionality exported to Python, using simple bitwise operations on predefined + flags. `pyplusplus`_ allows you to specify what methods you want to disable + or enable. ``indexing_suite2_t.METHODS`` containes names of all supported methods. + + In this case, `pyplusplus` Generated code This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-10 12:33:57
|
Revision: 289 Author: roman_yakovenko Date: 2006-07-10 05:33:25 -0700 (Mon, 10 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=289&view=rev Log Message: ----------- adding different loggers for different functionality removing verbose flag Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/scopedef.py pygccxml_dev/pygccxml/parser/config.py pygccxml_dev/pygccxml/parser/declarations_cache.py pygccxml_dev/pygccxml/parser/project_reader.py pygccxml_dev/pygccxml/parser/scanner.py pygccxml_dev/pygccxml/parser/source_reader.py pygccxml_dev/pygccxml/utils/__init__.py pygccxml_dev/unittests/declarations_cache_tester.py pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py pyplusplus_dev/pyplusplus/module_builder/__init__.py pyplusplus_dev/pyplusplus/module_builder/builder.py Modified: pygccxml_dev/pygccxml/declarations/scopedef.py =================================================================== --- pygccxml_dev/pygccxml/declarations/scopedef.py 2006-07-09 19:53:40 UTC (rev 288) +++ pygccxml_dev/pygccxml/declarations/scopedef.py 2006-07-10 12:33:25 UTC (rev 289) @@ -75,7 +75,11 @@ self._type2decls_nr = {} self._type2name2decls_nr = {} self._all_decls = None - + + def _get_logger( self ): + return utils.loggers.queries_engine + _logger = property( _get_logger ) + def _get__cmp__scope_items(self): raise NotImplementedError() @@ -148,7 +152,7 @@ Those hashtables allows to search declaration very quick. """ if self.name == '::': - utils.logger.debug( "preparing data structures for query optimizer - started" ) + self._logger.debug( "preparing data structures for query optimizer - started" ) start_time = time.clock() self.clear_optimizer() @@ -178,7 +182,7 @@ map( lambda decl: decl.init_optimizer() , filter( lambda decl: isinstance( decl, scopedef_t ), self.declarations ) ) if self.name == '::': - utils.logger.debug( "preparing data structures for query optimizer - done( %f seconds ). " + self._logger.debug( "preparing data structures for query optimizer - done( %f seconds ). " % ( time.clock() - start_time ) ) self._optimized = True @@ -226,15 +230,15 @@ matcher = match_class( **matcher_args ) if keywds['function']: - utils.logger.debug( 'running query: %s and <user defined function>' % str( matcher ) ) + self._logger.debug( 'running query: %s and <user defined function>' % str( matcher ) ) return lambda decl: matcher( decl ) and keywds['function'](decl) else: - utils.logger.debug( 'running query: %s' % str( matcher ) ) + self._logger.debug( 'running query: %s' % str( matcher ) ) return matcher def __findout_range( self, name, decl_type, recursive ): if not self._optimized: - utils.logger.debug( 'running non optimized query - optimization has not been done' ) + self._logger.debug( 'running non optimized query - optimization has not been done' ) decls = self.declarations if recursive: decls = algorithm.make_flatten( self.declarations ) @@ -245,34 +249,34 @@ if matcher.is_full_name(): name = matcher.decl_name_only if recursive: - utils.logger.debug( 'query has been optimized on type and name' ) + self._logger.debug( 'query has been optimized on type and name' ) if self._type2name2decls[decl_type].has_key( name ): return self._type2name2decls[decl_type][name] else: return [] else: - utils.logger.debug( 'non recursive query has been optimized on type and name' ) + self._logger.debug( 'non recursive query has been optimized on type and name' ) if self._type2name2decls_nr[decl_type].has_key( name ): return self._type2name2decls_nr[decl_type][name] else: return [] elif decl_type: if recursive: - utils.logger.debug( 'query has been optimized on type' ) + self._logger.debug( 'query has been optimized on type' ) return self._type2decls[ decl_type ] else: - utils.logger.debug( 'non recursive query has been optimized on type' ) + self._logger.debug( 'non recursive query has been optimized on type' ) return self._type2decls_nr[ decl_type ] else: if recursive: - utils.logger.debug( 'query has not been optimized ( hint: query does not contain type and/or name )' ) + self._logger.debug( 'query has not been optimized ( hint: query does not contain type and/or name )' ) return self._all_decls else: - utils.logger.debug( 'non recursive query has not been optimized ( hint: query does not contain type and/or name )' ) + self._logger.debug( 'non recursive query has not been optimized ( hint: query does not contain type and/or name )' ) return self.declarations def _find_single( self, match_class, **keywds ): - utils.logger.debug( 'find single query execution - started' ) + self._logger.debug( 'find single query execution - started' ) start_time = time.clock() norm_keywds = self.__normalize_args( **keywds ) matcher = self.__create_matcher( match_class, **norm_keywds ) @@ -280,11 +284,11 @@ recursive_ = self.__findout_recursive( **norm_keywds ) decls = self.__findout_range( norm_keywds['name'], dtype, recursive_ ) found = matcher_module.matcher.get_single( matcher, decls, False ) - utils.logger.debug( 'find single query execution - done( %f seconds )' % ( time.clock() - start_time ) ) + self._logger.debug( 'find single query execution - done( %f seconds )' % ( time.clock() - start_time ) ) return found def _find_multiple( self, match_class, **keywds ): - utils.logger.debug( 'find all query execution - started' ) + self._logger.debug( 'find all query execution - started' ) start_time = time.clock() norm_keywds = self.__normalize_args( **keywds ) matcher = self.__create_matcher( match_class, **norm_keywds ) @@ -294,8 +298,8 @@ decls = self.__findout_range( norm_keywds['name'], dtype, recursive_ ) found = matcher_module.matcher.find( matcher, decls, False ) mfound = mdecl_wrapper.mdecl_wrapper_t( found ) - utils.logger.debug( '%d declaration(s) that match query' % len(mfound) ) - utils.logger.debug( 'find single query execution - done( %f seconds )' + self._logger.debug( '%d declaration(s) that match query' % len(mfound) ) + self._logger.debug( 'find single query execution - done( %f seconds )' % ( time.clock() - start_time ) ) if not mfound and not allow_empty: raise RuntimeError( "Multi declaration query returned 0 declarations." ) Modified: pygccxml_dev/pygccxml/parser/config.py =================================================================== --- pygccxml_dev/pygccxml/parser/config.py 2006-07-09 19:53:40 UTC (rev 288) +++ pygccxml_dev/pygccxml/parser/config.py 2006-07-10 12:33:25 UTC (rev 289) @@ -27,7 +27,6 @@ , define_symbols=None , undefine_symbols=None , start_with_declarations=None - , verbose=False , ignore_gccxml_output=False , cflags=""): """Constructor. @@ -52,7 +51,6 @@ start_with_declarations = [] self.__start_with_declarations = start_with_declarations - self.__verbose = verbose self.__ignore_gccxml_output = ignore_gccxml_output self.__cflags = cflags @@ -63,7 +61,6 @@ , define_symbols=self.__define_symbols[:] , undefine_symbols=self.__undefine_symbols[:] , start_with_declarations=self.__start_with_declarations[:] - , verbose=self.verbose , ignore_gccxml_output=self.ignore_gccxml_output , cflags=self.cflags) @@ -95,12 +92,6 @@ return self.__start_with_declarations start_with_declarations = property( __get_start_with_declarations ) - def __get_verbose(self): - return self.__verbose - def __set_verbose(self, val=True): - self.__verbose = val - verbose = property( __get_verbose, __set_verbose ) - def __get_ignore_gccxml_output(self): return self.__ignore_gccxml_output def __set_ignore_gccxml_output(self, val=True): Modified: pygccxml_dev/pygccxml/parser/declarations_cache.py =================================================================== --- pygccxml_dev/pygccxml/parser/declarations_cache.py 2006-07-09 19:53:40 UTC (rev 288) +++ pygccxml_dev/pygccxml/parser/declarations_cache.py 2006-07-10 12:33:25 UTC (rev 289) @@ -8,7 +8,7 @@ import md5 import time import cPickle -from pygccxml.utils import logger +from pygccxml import utils def file_signature( filename ): @@ -44,9 +44,11 @@ sig.update(str(u)) return sig.hexdigest() -class cache_base_t( object ): +class cache_base_t( object ): + logger = utils.loggers.declarations_cache + def __init__( self ): - object.__init__(self) + object.__init__(self) def flush(self): """ Flush (write out) the cache to disk if needed. """ @@ -146,7 +148,7 @@ """ @param name: name of the cache file. """ - cache_base_t.__init__( self ) + cache_base_t.__init__( self ) self.__name = name # Name of cache file self.__cache = self.__load( self.__name ) # Map record_key to record_t self.__needs_flushed = not bool( self.__cache ) # If empty then we need to flush @@ -163,15 +165,16 @@ return {} cache_file_obj = file( file_name, 'rb' ) try: - logger.info( "Loading cache file ..." ) + file_cache_t.logger.info( 'Loading cache file "%s".' % file_name ) start_time = time.clock() cache = cPickle.load( cache_file_obj ) - logger.info( "Cache file has been loaded in %.1f secs"%( time.clock() - start_time ) ) - logger.info( "Found cache in file: [%s] entries: %s" - % ( file_name, len( cache.keys() ) ) ) - except Exception: + file_cache_t.logger.debug( "Cache file has been loaded in %.1f secs"%( time.clock() - start_time ) ) + file_cache_t.logger.debug( "Found cache in file: [%s] entries: %s" + % ( file_name, len( cache.keys() ) ) ) + except Exception, error: + file_cache_t.logger.exception( "Error occured while reading cache file: %s", error ) cache_file_obj.close() - logger.info( "Invalid cache file: [%s] Regenerating." % file_name ) + file_cache_t.logger.info( "Invalid cache file: [%s] Regenerating." % file_name ) file(file_name, 'w+b').close() # Create empty file cache = {} # Empty cache return cache @@ -180,7 +183,7 @@ def flush(self): # If not marked as needing flushed, then return immediately if not self.__needs_flushed: - logger.info("Cache did not change, ignoring flush.") + self.logger.debug("Cache did not change, ignoring flush.") return # Remove entries that did not get a cache hit @@ -190,7 +193,7 @@ num_removed += 1 del self.__cache[key] if num_removed > 0: - logger.info( "There are %s removed entries from cache." % num_removed ) + self.logger.debug( "There are %s removed entries from cache." % num_removed ) # Save out the cache to disk cache_file = file( self.__name, 'w+b' ) cPickle.dump( self.__cache, cache_file, cPickle.HIGHEST_PROTOCOL ) Modified: pygccxml_dev/pygccxml/parser/project_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/project_reader.py 2006-07-09 19:53:40 UTC (rev 288) +++ pygccxml_dev/pygccxml/parser/project_reader.py 2006-07-10 12:33:25 UTC (rev 289) @@ -9,7 +9,7 @@ import source_reader import declarations_cache import pygccxml.declarations -from pygccxml.utils import logger +from pygccxml import utils class COMPILATION_MODE: ALL_AT_ONCE = 'all at once' @@ -179,7 +179,9 @@ self.__decl_factory = decl_factory if not decl_factory: self.__decl_factory = pygccxml.declarations.decl_factory_t() - + + self.logger = utils.loggers.gccxml + def get_os_file_names( files ): """Returns a list of OS file names @@ -219,14 +221,13 @@ "Unable to parse files using ALL_AT_ONCE mode. " , "There is some file configuration that is not file. " , "pygccxml.parser.project_reader_t switches to FILE_BY_FILE mode." ]) - logger.info( msg ) + self.logger.warning( msg ) return self.__parse_file_by_file(files) def __parse_file_by_file(self, files): namespaces = [] config = self.__config.clone() - if config.verbose: - logger.info( "Reading project files: file by file" ) + self.logger.debug( "Reading project files: file by file" ) for prj_file in files: reader = None header = None @@ -259,35 +260,28 @@ else: decls = reader.read_string( header ) namespaces.append( decls ) - if config.verbose: - logger.info( "Flushing cache... " ) + self.logger.debug( "Flushing cache... " ) start_time = time.clock() self.__dcache.flush() - if config.verbose: - logger.info( "Cache has been flushed in %.1f secs" - % ( time.clock() - start_time ) ) + self.logger.debug( "Cache has been flushed in %.1f secs" % ( time.clock() - start_time ) ) answer = [] - if config.verbose: - logger.info( "Joining namespaces ..." ) + self.logger.debug( "Joining namespaces ..." ) for file_nss in namespaces: answer = self._join_top_namespaces( answer, file_nss ) - if config.verbose: - logger.info( "Joining declarations ..." ) + self.logger.debug( "Joining declarations ..." ) for ns in answer: if isinstance( ns, pygccxml.declarations.namespace_t ): self._join_declarations( ns ) leaved_classes = self._join_class_hierarchy( answer ) types = self.__declarated_types(answer) - if config.verbose: - logger.info( "Relinking declared types ..." ) + self.logger.debug( "Relinking declared types ..." ) self._relink_declarated_types( leaved_classes, types ) source_reader.bind_aliases( pygccxml.declarations.make_flatten( answer ) ) return answer def __parse_all_at_once(self, files): config = self.__config.clone() - if config.verbose: - logger.info( "Reading project files: all at once" ) + self.logger.debug( "Reading project files: all at once" ) header_content = [] for header in files: if isinstance( header, file_configuration_t ): @@ -430,18 +424,16 @@ key = create_key(decl_wrapper_type.declaration) if leaved_classes.has_key( key ): decl_wrapper_type.declaration = leaved_classes[ create_key(decl_wrapper_type.declaration) ] - else: + else: + if decl_wrapper_type.declaration._name.startswith( '__vmi_class_type_info_pseudo' ): + continue msg = [] msg.append( "Unable to find out actual class definition: '%s'." % decl_wrapper_type.declaration._name ) msg.append( "Class definition has been changed from one compilation to an other." ) msg.append( "Why did it happen to me? Here is a short list of reasons: " ) msg.append( " 1. There are different preprocessor definitions applied on same file during compilation" ) - msg.append( " 2. GCC implementation details. Diamand class hierarchy will reproduce this behavior." ) - msg.append( " If name starts with '__vmi_class_type_info_pseudo' you can ignore this message." ) - msg.append( " 3. Bug in pygccxml." ) - logger.error( os.linesep.join(msg) ) - #'__vmi_class_type_info_pseudo1' - + msg.append( " 2. Bug in pygccxml." ) + self.logger.error( os.linesep.join(msg) ) def _join_declarations( self, declref ): self._join_namespaces( declref ) Modified: pygccxml_dev/pygccxml/parser/scanner.py =================================================================== --- pygccxml_dev/pygccxml/parser/scanner.py 2006-07-09 19:53:40 UTC (rev 288) +++ pygccxml_dev/pygccxml/parser/scanner.py 2006-07-10 12:33:25 UTC (rev 289) @@ -10,7 +10,7 @@ import warnings import xml.sax.handler from pygccxml.declarations import * -from pygccxml.utils import logger +from pygccxml import utils ##convention #XML_NN - XML Node Name @@ -75,7 +75,8 @@ class scanner_t( xml.sax.handler.ContentHandler ): def __init__(self, gccxml_file, decl_factory, *args ): - xml.sax.handler.ContentHandler.__init__(self, *args ) + xml.sax.handler.ContentHandler.__init__(self, *args ) + self.logger = utils.loggers.gccxml self.gccxml_file = gccxml_file #defining parsing tables self.__readers = { @@ -191,12 +192,12 @@ elif isinstance( obj, types.StringTypes ): self.__files[ attrs[XML_AN_ID] ] = obj else: - logger.warning( 'Unknown object type has been found.' - + ' Please report this bug to pygccxml development team.' ) + self.logger.warning( 'Unknown object type has been found.' + + ' Please report this bug to pygccxml development team.' ) except Exception, error: msg = 'error occured, while parsing element with name "%s" and attrs "%s".' msg = msg + os.linesep + 'Error: %s.' % str( error ) - logger.error( msg % ( name, pprint.pformat( attrs.keys() ) ) ) + self.logger.error( msg % ( name, pprint.pformat( attrs.keys() ) ) ) raise def endElement(self, name): Modified: pygccxml_dev/pygccxml/parser/source_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/source_reader.py 2006-07-09 19:53:40 UTC (rev 288) +++ pygccxml_dev/pygccxml/parser/source_reader.py 2006-07-10 12:33:25 UTC (rev 289) @@ -12,7 +12,7 @@ import declarations_cache import patcher from pygccxml.declarations import * -from pygccxml.utils import logger +from pygccxml import utils class gccxml_runtime_error_t( RuntimeError ): def __init__( self, msg ): @@ -72,7 +72,8 @@ @param decl_factory: declarations factory, if not given default declarations factory L{decl_factory_t} will be used - """ + """ + self.logger = utils.loggers.gccxml self.__search_directories = [] self.__config = config self.__search_directories.append( config.working_directory ) @@ -145,7 +146,7 @@ cmd_line = ' '.join(cmd) if 'win32' in sys.platform : cmd_line = '"%s"' % cmd_line - logger.debug( 'gccxml cmd: %s' % cmd_line ) + self.logger.info( 'gccxml cmd: %s' % cmd_line ) return cmd_line def create_xml_file( self, header, destination=None ): @@ -174,8 +175,6 @@ if not os.path.isabs( ffname ): ffname = self.__file_full_name(header) command_line = self.__create_command_line( ffname, gccxml_file ) - if self.__config.verbose: - logger.info( " Command line for GCC-XML: %s" % command_line ) input_, output = os.popen4( command_line ) input_.close() gccxml_reports = [] @@ -231,19 +230,15 @@ gccxml_file = '' try: ffname = self.__file_full_name(source_file) - if self.__config.verbose: - logger.info( "Reading source file: [%s]." % ffname ) + self.logger.debug( "Reading source file: [%s]." % ffname ) declarations = self.__dcache.cached_value( ffname, self.__config ) if not declarations: - if self.__config.verbose: - logger.info( "File has not been found in cache, parsing..." ) + self.logger.debug( "File has not been found in cache, parsing..." ) gccxml_file = self.create_xml_file( ffname ) declarations, files = self.__parse_gccxml_created_file( gccxml_file ) self.__dcache.update( ffname, self.__config, declarations, files ) else: - if self.__config.verbose: - logger.info( "File has not been changed, reading declarations from cache." ) - + self.logger.debug( "File has not been changed, reading declarations from cache." ) except Exception, error: if gccxml_file: pygccxml.utils.remove_file_no_raise( gccxml_file ) @@ -261,8 +256,7 @@ @return: declarations tree """ - if self.__config.verbose: - logger.info( "Reading xml file: [%s]" % gccxml_created_file ) + self.logger.debug( "Reading xml file: [%s]" % gccxml_created_file ) declarations, files = self.__parse_gccxml_created_file( gccxml_created_file ) return declarations Modified: pygccxml_dev/pygccxml/utils/__init__.py =================================================================== --- pygccxml_dev/pygccxml/utils/__init__.py 2006-07-09 19:53:40 UTC (rev 288) +++ pygccxml_dev/pygccxml/utils/__init__.py 2006-07-10 12:33:25 UTC (rev 289) @@ -7,14 +7,22 @@ import sys import logging import tempfile + +def _create_logger_( name ): + logger = logging.getLogger('name') + __handler = logging.StreamHandler(sys.stdout) + __handler.setFormatter( logging.Formatter( '%(levelname)s %(message)s' ) ) + logger.addHandler(__handler) + logger.setLevel(logging.INFO) + return logger + +class loggers: + root = _create_logger_( 'pygccxml' ) + gccxml = _create_logger_( 'pygccxml.gccxml' ) + queries_engine = _create_logger_( 'pygccxml.queries_engine' ) + declarations_cache = _create_logger_( 'pygccxml.declarations_cache' ) + all = [ root, gccxml, queries_engine, declarations_cache ] - -logger = logging.getLogger('pygccxml') -__handler = logging.StreamHandler(sys.stdout) -__handler.setFormatter( logging.Formatter('%(message)s') ) -logger.addHandler(__handler) -logger.setLevel(logging.DEBUG) - def remove_file_no_raise(file_name ): try: if os.path.exists(file_name): Modified: pygccxml_dev/unittests/declarations_cache_tester.py =================================================================== --- pygccxml_dev/unittests/declarations_cache_tester.py 2006-07-09 19:53:40 UTC (rev 288) +++ pygccxml_dev/unittests/declarations_cache_tester.py 2006-07-10 12:33:25 UTC (rev 289) @@ -41,11 +41,7 @@ #start_decls_changed = def_cfg.clone() #start_decls_changed.start_with_declarations = "test object" #self.assert_(configuration_signature(start_decls_changed) == def_sig) - - verbose_changed = def_cfg.clone() - verbose_changed.verbose = True - self.assert_(configuration_signature(verbose_changed) == def_sig) - + ignore_changed = def_cfg.clone() ignore_changed.ignore_gccxml_output = True self.assert_(configuration_signature(ignore_changed) == def_sig) @@ -101,7 +97,7 @@ """ Return a list of configurations that all differ. """ cfg_list = [] def_cfg = config_t("gccxml_path",'.',['tmp'],['sym'],['unsym'], - None,False,False,"") + None,False,"") cfg_list.append(def_cfg) # Test changes that should cause sig changes @@ -117,21 +113,21 @@ #inc_changed.include_paths = ["/var/tmp"] #self.assert_(configuration_signature(inc_changed) != def_sig) inc_changed = config_t("gccxml_path",'.',['/var/tmp'],['sym'],['unsym'], - None,False,False,"") + None,False,"") cfg_list.append(inc_changed) #def_changed = def_cfg.clone() #def_changed.define_symbols = ["symbol"] #self.assert_(configuration_signature(def_changed) != def_sig) def_changed = config_t("gccxml_path",'.',['/var/tmp'],['new-sym'],['unsym'], - None,False,False,"") + None,False,"") cfg_list.append(def_changed) #undef_changed = def_cfg.clone() #undef_changed.undefine_symbols = ["symbol"] #self.assert_(configuration_signature(undef_changed) != def_sig) undef_changed = config_t("gccxml_path",'.',['/var/tmp'],['sym'],['new-unsym'], - None,False,False,"") + None,False,"") cfg_list.append(undef_changed) cflags_changed = def_cfg.clone() Modified: pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2006-07-09 19:53:40 UTC (rev 288) +++ pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2006-07-10 12:33:25 UTC (rev 289) @@ -172,7 +172,8 @@ def _exportable_impl( self ): if not self.name: - return 'pyplusplus can not expose unnamed classes.' + return 'pyplusplus can not expose unnamed classes.' + #it is possible to do so, but not for unnamed classes defined under namespace. if isinstance( self.parent, declarations.namespace_t ): return '' if not self in self.parent.public_members: Modified: pyplusplus_dev/pyplusplus/module_builder/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/module_builder/__init__.py 2006-07-09 19:53:40 UTC (rev 288) +++ pyplusplus_dev/pyplusplus/module_builder/__init__.py 2006-07-10 12:33:25 UTC (rev 289) @@ -50,6 +50,7 @@ from pygccxml import utils as __pygccxml_utils from pyplusplus import _logging_ as __pyplusplus_logging -def set_logger_level( level ): - __pygccxml_utils.logger.setLevel( level ) +def set_logger_level( level ): + for l in __pygccxml_utils.loggers.all: + l.setLevel( level ) __pyplusplus_logging.logger.setLevel( level ) \ No newline at end of file Modified: pyplusplus_dev/pyplusplus/module_builder/builder.py =================================================================== --- pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-07-09 19:53:40 UTC (rev 288) +++ pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-07-10 12:33:25 UTC (rev 289) @@ -62,7 +62,6 @@ , define_symbols=define_symbols , undefine_symbols=undefine_symbols , start_with_declarations=start_with_declarations - , verbose=compilation_verbose , ignore_gccxml_output=ignore_gccxml_output) #may be in future I will add those directories to user_defined_directories This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-09 19:53:47
|
Revision: 288 Author: roman_yakovenko Date: 2006-07-09 12:53:40 -0700 (Sun, 09 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=288&view=rev Log Message: ----------- updating indexing suite 2 documentation Modified Paths: -------------- pyplusplus_dev/docs/std_containers/containers.rest pyplusplus_dev/docs/std_containers/www_configuration.py Modified: pyplusplus_dev/docs/std_containers/containers.rest =================================================================== --- pyplusplus_dev/docs/std_containers/containers.rest 2006-07-09 19:08:54 UTC (rev 287) +++ pyplusplus_dev/docs/std_containers/containers.rest 2006-07-09 19:53:40 UTC (rev 288) @@ -78,21 +78,57 @@ Every declarated class has ``indexing_suite`` property. If the class is an instantiation of stl container, this property containes reference to an instance -of ``indexing_suite1_t`` or ``indexing_suite2_t`` class. How does `pyplusplus`_ -know that the class represents stl container instantiation? Well, it uses -``pygccxml.declarations.container_traits`` to find out this. This class, provides -all functionality needed to identify container and to find out its ``value_type`` -( ``mapped_type`` ). May I give you small tip? You can use -``pygccxml.declarations.container_traits`` class in search functionality. +of ``indexing_suite1_t`` or ``indexing_suite2_t`` class. + + +How does `pyplusplus`_ know that a class represents stl container instantiation? +Well, it uses ``pygccxml.declarations.container_traits`` to find out this. +``pygccxml.declarations.container_traits`` class, provides all functionality +needed to identify container and to find out its ``value_type``( ``mapped_type`` ). -Built-in indexing suite ------------------------ -.. +Built-in indexing suite API +--------------------------- +`pyplusplus`_ defines ``indexing_suite1_t`` class. This class allows configure +any detail of generated code: -Indexing suite v1 ------------------ +* ``no_proxy`` - a boolean, if value type is one of the next types + * fundamental type + * enumeration + * [w]string + * boost::shared_ptr<?> + + then, ``no_proxy`` will be set to ``True``, otherwise to ``False``. + +* ``derived_policies`` - a string, that will be added as is to generated code + +* ``element_type`` - is a reference to container ``value_type`` or ``mapped_type``. + + +Next version of indexing suite API +---------------------------------- + +In this case there is no single place, where you can configure exported container +functionality. Please take a look on next C++ code: +:: + + struct item{ ... }; + + struct my_data{ + std::vector<item> items; + std::map< std::string, item > name2item_mapping; + }; + + +`pyplusplus`_ declarations tree will contains ``item``, ``my_data``, +``vector<item>`` and ``map<string,item>`` class declarations. Next version of +indexing suite allows you to configure what set of operation will be supported, +based on functionality provided by container ``value_type`` ( ``mapped_type`` ). +To be more specific, you can create ``value_traits`` and set ``equality_comparable`` +or ``less_than_comparable`` to ``True`` if the type has `operator==` or ``False`` + + In this case, `pyplusplus` Generated code Modified: pyplusplus_dev/docs/std_containers/www_configuration.py =================================================================== --- pyplusplus_dev/docs/std_containers/www_configuration.py 2006-07-09 19:08:54 UTC (rev 287) +++ pyplusplus_dev/docs/std_containers/www_configuration.py 2006-07-09 19:53:40 UTC (rev 288) @@ -1 +1,3 @@ -name = 'C++ containers' \ No newline at end of file +name = 'C++ containers' +main_html_file = 'containers.html' +files_to_skip = ['indexing_suite_v2.html'] \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-09 19:09:07
|
Revision: 287 Author: roman_yakovenko Date: 2006-07-09 12:08:54 -0700 (Sun, 09 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=287&view=rev Log Message: ----------- adding indexing suite 2 documentatio Added Paths: ----------- pyplusplus_dev/docs/std_containers/ pyplusplus_dev/docs/std_containers/containers.rest pyplusplus_dev/docs/std_containers/indexing_suite_v2.html pyplusplus_dev/docs/std_containers/indexing_suite_v2_files/ pyplusplus_dev/docs/std_containers/indexing_suite_v2_files/boost.css pyplusplus_dev/docs/std_containers/indexing_suite_v2_files/cboost.gif pyplusplus_dev/docs/std_containers/www_configuration.py Added: pyplusplus_dev/docs/std_containers/containers.rest =================================================================== --- pyplusplus_dev/docs/std_containers/containers.rest (rev 0) +++ pyplusplus_dev/docs/std_containers/containers.rest 2006-07-09 19:08:54 UTC (rev 287) @@ -0,0 +1,176 @@ +====================== +C++ containers support +====================== + +.. contents:: Table of contents + +------------ +Introduction +------------ + +C++ has a bunch of containers classes: + + * list + * deque + * queue + * priority_queue + * vector + * stack + * map + * multimap + * hash_map + * hash_multimap + * set + * hash_set + * multiset + * hash_multiset + +It is not a trivial task to expose C++ container to Python. Boost.Python has +a functionality that will help you to expose some of STL containers to `Python`_. +This functionality called - "indexing suite". If you want, you can read more +about indexing suite `here`__. + +.. __ : http://boost.org/libs/python/doc/v2/indexing.html + +Boost.Python, out of the box, supports only ``vector``, ``map`` and ``hash_map`` +containers. In October 2003, Raoul Gough implemented support for the rest of +containers. Well, actually he did much more - he implemented new framework. +This framework provides support for almost all C++ containers and also an easy +way to add support for custom ones. You'd better read his `post`_ to +`boost.python`_ mailing list or `documentation`_ for the new indexing suite. + + +If this suite is soo good, why it is not in the main branch? You can find the +answer here(http://mail.python.org/pipermail/c++-sig/2006-June/010830.html) and +here(http://mail.python.org/pipermail/c++-sig/2006-June/010835.html). + +.. _`documentation` : ./indexing_suite_v2.html +.. _`post` : http://mail.python.org/pipermail/c++-sig/2003-October/005802.html + +------------------------------ +pyplusplus and indexing suites +------------------------------ +`pyplusplus`_ implements support for both indexing suites. More over, you can +freely mix indexing suites. For example you can expose ``std::vector<int>`` using +`boost.python`_ built-in indexing suite and ``std::map< int, std::string>`` using +Raoul Gough's indexing suite. + +----------------- +How does it work? +----------------- + +In both cases, `pyplusplus`_ provides almost "hands free" solution. `pyplusplus`_ +keeps track of all exported functions and variables, and if it sees that there is +a usage of stl container, it exports the container. In both cases, `pyplusplus`_ +analizes the container ``value_type`` ( or in case of mapping containers +``mapped_type`` ), in order to set reasonable defaults, when it generates the code. + +----------------------- +Code, show me the code! +----------------------- + +By default, `pyplusplus`_ works with built-in indexing suite. If you want to use +next version of indexing suite, you should tell this to ``module_builder_t.__init__`` +method: +:: + + mb = module_builder_t( ..., indexing_suite_version=2 ) + +Every declarated class has ``indexing_suite`` property. If the class is an +instantiation of stl container, this property containes reference to an instance +of ``indexing_suite1_t`` or ``indexing_suite2_t`` class. How does `pyplusplus`_ +know that the class represents stl container instantiation? Well, it uses +``pygccxml.declarations.container_traits`` to find out this. This class, provides +all functionality needed to identify container and to find out its ``value_type`` +( ``mapped_type`` ). May I give you small tip? You can use +``pygccxml.declarations.container_traits`` class in search functionality. + + +Built-in indexing suite +----------------------- +.. + + +Indexing suite v1 +----------------- +In this case, `pyplusplus` + +Generated code +-------------- +All generated code will have next form: +:: + + class_< container, other class parameters >(name) + .def( concrete indexing suite class< container, proxy, derived policies >() ) + ; + +Usage example +------------- +C++ code: +:: + + #include <map> + #include <vector> + +:: + + std::vector<string> get_options(){...} + +:: + + struct my_data{...}; + std::map< int, my_data > get_data(); + +Assumption: user wants to use ``get_options`` and ``get_data`` functions. Next +steps will describe what `pyplusplus`_ will do in this case: + +1. `pyplusplus`_ will analyze functions return type and arguments. + +2. It will understand that ``std::vector< std::string >`` and ``std::map< int, my_data >`` + classes should be exported too. + +3. It will understand that those classes should be exported using indexing suite + functionality provided by `boost.python`_ library or `pyplusplus`_ + ``code repository``. + +4. It will generate the code, that will use that functionality. + +So far, so good. Sometimes, there are use cases, when user has to change default +values, for example ``NoProxy`` or ``DerivedPolicies``. What interface `pyplusplus`_ +will provide in order to change the defaults? Well, ``std::vector< std::string >`` +is the class that could be found in declarations tree, right? User can find the +class and change the defaults: +:: + + mb = module_builder_t( ... ) + #the next line will not work, because the real name of std::vector< std::string > + #is platform dependent and much longer. It is there for simplicity. + vector_of_strings = mb.class_( "std::vector< std::string >" ) + vector_of_strings.alias = "StringVector" + vector_of_strings.held_type = ... + vector_of_strings.indexing_suite.no_proxy = False + + +Please, pay attention to the next line: +:: + + vector_of_strings.indexing_suite.no_proxy = False + +Every class, that represents instantiation of some std container will have +class variable ``indexing_suite``, that will be intitialized with relevant +indexing suite class. + + + +.. _`pyplusplus` : ./../pyplusplus.html +.. _`boost.python`: http://www.boost.org/libs/python/doc/index.html +.. _`Python`: http://www.python.org +.. _`GCC-XML`: http://www.gccxml.org + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + End: Added: pyplusplus_dev/docs/std_containers/indexing_suite_v2.html =================================================================== --- pyplusplus_dev/docs/std_containers/indexing_suite_v2.html (rev 0) +++ pyplusplus_dev/docs/std_containers/indexing_suite_v2.html 2006-07-09 19:08:54 UTC (rev 287) @@ -0,0 +1,2213 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html><head> + + + <meta name="generator" content="A human being"> + <meta http-equiv="Content-Type" content="text/html; charset=us-ascii"> + <link rel="stylesheet" type="text/css" href="indexing_suite_v2_files/boost.css"><title>Boost.Python - C++ Container Support</title></head><body> + <table summary="header" border="0" cellpadding="7" cellspacing="0" width="100%"> + <tbody><tr> + <td valign="top" width="300"> + <h3> + <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/index.htm"><img alt="C++ Boost" src="indexing_suite_v2_files/cboost.gif" border="0" height="86" width="277"></a> + </h3> + </td> + <td valign="top"> + <h1 align="center"> + <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/doc/index.html">Boost.Python</a><br> + C++ Container Support + </h1> + </td> + </tr> + </tbody></table> + + <hr> + + <h2> + Contents + </h2> + + <dl class="page-index"> + <dt> + <a href="#introduction">Introduction</a> + </dt> + <dt> + <a href="#design_goals">Design goals</a> + </dt> + <dt> + <a href="#interface">Interface</a> + </dt> + <dd> + <dl class="page-index"> + <dt> + <a href="#container_suite">container_suite.hpp</a> + </dt> + <dt> + <a href="#specific">Container-specific headers</a> + </dt> + <dt> + <a href="#policies">Using policies</a> + </dt> + <dt> + <a href="#visitor_flags">Visitor flag values</a> + </dt> + <dt> + <a href="#extending">Extending and customizing</a> + </dt> + <dd> + <dl class="page-index"> + <dt> + <a href="#ValueTraits">ValueTraits</a> + </dt> + <dt> + <a href="#ContainerTraits">ContainerTraits</a> + </dt> + <dt> + <a href="#Algorithms">Algorithms</a> + </dt> + <dt> + <a href="#SliceHelper">SliceHelper</a> + </dt> + </dl> + </dd> + <dt> + <a href="#extending">Container adapters</a> + </dt> + <dd> + <dl class="page-index"> + <dt> + <a href="#container_proxy">container_proxy</a> + </dt> + <dt> + <a href="#iterator_range">iterator_range</a> + </dt> + </dl> + </dd> + <dt> + <a href="#workarounds">Compiler workarounds</a> + </dt> + <dt> + <a href="#limitations">Known limitations</a> + </dt> + </dl> + </dd> + <dt> + <a href="#references">References</a> + </dt> + <dt> + <a href="#acknoweldegments">Acknowledgements and Copyright</a> + </dt> + </dl> + + <h2><a name="introduction">Introduction</a></h2> + + The purpose of the container indexing suite is to allow Python + code to access C++ containers using regular Python + interfaces. Since each C++ container is different, it is + non-trivial to decide what Python methods can be emulated, and how + to map them to C++ function calls. The indexing suite provides a + framework for representing those decisions, as well as bindings + for the standard C++ container templates. The indexing headers are + in the Boost subdirectory + <i>boost/python/suite/indexing</i> and non-template + implementations are in + <i>libs/python/src/indexing</i>. Various tests, which can also + serve as examples are in <i>libs/python/test</i>. + + <h2><a name="design_goals">Design goals</a></h2> + + The primary design goals of the container indexing suite are as + follows. The suite should: + + <ul> + <li> + + Support instances of all useful standard container templates + + </li> + <li> + + Provide as much of the normal Python interface as is + reasonable for each container + + </li> + <li> + + Be extensible to user-defined container types + + </li> + <li> + + Support client-provided <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/doc/v2/CallPolicies.html">CallPolicies</a> + + </li> + </ul> + + Secondary design goals are as follows. The library should: + + <ul> + <li> + + Provide an emulation of Python reference semantics for + <i>values</i> in vector-like containers. + + </li> + <li> + + Provide an emulation of container semantics for iterator + ranges. + + </li> + </ul> + + <h2><a name="interface">Interface</a></h2> + + <p> + + The main iterface to the library is via the templated class + <code>container_suite</code>, an object of which adds a number + of Python functions to an extension class via a single + <code>def</code> call. Support is provided for all of the + standard container templates <a href="#Note1">[1]</a> via + container-specific header files, as shown in the following + example: + + </p> + +<pre>#include <boost/python/suite/indexing/container_suite.hpp> +#include <boost/python/suite/indexing/vector.hpp> +#include <boost/python/class.hpp> +#include <boost/python/module.hpp> +#include <vector> + +BOOST_PYTHON_MODULE(example) { + class_< std::vector<int> > ("vector_int") + .def (indexing::container_suite< std::vector<int> >()); +} +</pre> + + <p> + + The <code>container_suite</code> object achieves this using the + <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/doc/v2/def_visitor.html">def_visitor interface</a>, which + provides a hook for the <code>def</code> function to install + multiple Python methods in one call. If the container element + type (<code>int</code> in the example above) is a user-defined + type, you would have to expose this type to Python via a + separate <code>class_</code> instance. + + </p> + <p> + + <a name="Note1">[1]</a> Automatic operation with the standard + containers works properly if your compiler supports partial + template specializations. Otherwise, refer to the <a href="#workarounds">compiler workarounds</a> section. + + </p> + + <h2><a name="container_suite">boost/python/suite/indexing/container_suite.hpp</a></h2> + + <p> + + The <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/boost/python/suite/indexing/container_suite.hpp"><code>container_suite.hpp</code></a> + header is summarized below: + + </p> + <p> +</p><pre>#include <boost/python/suite/indexing/algo_selector.hpp> +#include <boost/python/suite/indexing/visitor.hpp> + +#include <boost/python/return_by_value.hpp> +#include <boost/python/return_value_policy.hpp> + +namespace boost { namespace python { namespace indexing { + typedef return_value_policy<return_by_value> default_container_policies; + + template<class Container, + int Flags = 0, + class Algorithms = algo_selector<Container> > + struct container_suite + : public visitor<Algorithms, default_container_policies, Flags> + { + typedef Algorithms algorithms; + + template<typename Policy> + static visitor<Algorithms, Policy, Flags> + with_policies (Policy const &policy) + { + return visitor <Algorithms, Policy> (policy); + } + }; +} } } +</pre> + <p></p> + + <p> + + Some important points to note about <code>container_suite</code>: + + </p><ol> + <li> + + It does not include any of the container-specific headers + (like <code>vector.hpp</code> or <code>set.hpp</code>), so + these must be included separately to add support each type + of container. + + </li> + <li> + + It derives from the <code>indexing::visitor</code> + template, using a <code>return_by_value</code> return + policy. This is a reasonable default, and follows the + Boost.Python idiom of passing a default-constructed object + to the <code>def</code> function. + + </li> + <li> + + The <code>with_policies</code> static function template + generates different instances of the + <code>indexing::visitor</code> template, with + client-provided policies. + + </li> + <li> + + The template parameter <code>Flags</code> allows client code + to disable unneeded features in order to reduce code + size. Details are provided <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/doc/v2/visitor_flags">below</a>. + + </li> + </ol> + + <p></p> + + <h2><a name="specific">Container-specific headers</a></h2> + + <p> + + The container indexing suite includes support for many of the + standard C++ container templates, but note that the support code + for each is in a separate header file. These header files (in + the <i>boost/python/suite/indexing</i> subdirectory) are: + <code>vector.hpp</code>, <code>deque.hpp</code>, + <code>list.hpp</code>, <code>set.hpp</code> and + <code>map.hpp</code>. These correspond in the obvious way to the + standard headers <code>vector</code>, <code>deque</code>, + etc. The header files for the <a href="#container_proxy"><code>container_proxy</code></a> and <a href="#iterator_range"><code>iterator_range</code></a> templates + provide their own support implicitly. + + </p> + + <h2><a name="policies">Using policies</a></h2> + + You can select call policies using the + <code>container_suite</code> static member function + <code>with_policies</code> as in the following example: + +<pre> class_< std::list<heavy_class> > ("list_heavy_class") + .def (indexing::container_suite< std::list<heavy_class> > + ::with_policies (my_policies)); +</pre> + + <h3>Caution with policies</h3> + + <p> + + It can be tempting to use <code>return_internal_reference</code> + if the container elements are expensive to copy. However, this + can be quite dangerous, since references to the elements can + easily become invalid (e.g. if the element is deleted or + moved). The Boost.Python code for + <code>return_internal_reference</code> can only manage the + lifetime of the entire container object, and not those of the + elements actually being referenced. Various alternatives exist, + the best of which is to store the container elements indirectly, + using <code>boost::shared_ptr</code> or an equivalent. If this + is not possible, + <code><a href="#container_proxy">container_proxy</a></code> + may provide a + solution, at least for vector-like containers. + + </p> + + <h3>Internal policies detail</h3> + + <p> + + The <code>container_suite</code> object typically adds more than + one function to the Python class, and not all of those functions + can, or should, use exactly the same policies. For instance, the + Python <code>len</code> method, if provided, should always + return its result by value. The library actually uses up to + three different sets of policies derived from the one provided + to the <code>with_policies</code> function. These are: + + </p><ol> + <li> + + The supplied policies, unchanged + + </li> + <li> + + The supplied precall policy only, using <code>default_call_policies</code> for result conversion. + + </li> + <li> + + The supplied precall policies, and the supplied result + conversion policies applied to <i>each element</i> of a + returned list. + + </li> + </ol> + + Roughly speaking, methods returning a single container element + use the first option, while methods returning an integer value + (or <code>void</code>) use the second option. The third option + applies only to the slice version of <code>__getitem__</code>, + which generates a Python list by applying the return conversion + policies to each element in the list. + + <p></p> + + <h2><a name="visitor_flags">Visitor Flag values</a></h2> + + <p> + + The <code>container_suite</code> template has an optional + <code>Flags</code> parameter that allows client code to disable + various optional features of the suite. This can lead to + significant savings in the size of object files and executables + if features such as sorting or Python slice support are not + needed. The <code>Flags</code> parameter (an integer) can be any + bitwise combination of the following values (defined in the + <code>boost::python::indexing</code> namespace by <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/boost/python/suite/indexing/visitor.hpp"><code>visitor.hpp</code></a>): + + </p> + + <p> + + <table border="1"> + <tbody><tr> + <th>Flag</th> + <th>Effect</th> + </tr> + <tr> + + <td><code>disable_len</code></td> + + <td>omits the Python <code>__len__</code> method</td> + + </tr> + <tr> + + <td><code>disable_slices</code></td> + + <td>omits slice support code from <code>__getitem__</code>, + <code>__setitem__</code> and <code>__delitem__</code>.</td> + + </tr> + <tr> + + <td><code>disable_search</code></td> + + <td>omits the container search methods <code>count<code>, + </code>index</code> and <code>__contains__</code></td> + + </tr> + <tr> + + <td><code>disable_reorder</code></td> + + <td>omits the container reordering operations + <code>sort</code> and <code>reverse</code></td> + + </tr> + <tr> + + <td><code>disable_extend</code></td> + + <td>omits the <code>extend</code> method</td> + + </tr> + <tr> + + <td><code>disable_insert</code></td> + + <td>omits the <code>insert</code> method</td> + + </tr> + </tbody></table> + + </p> + + <p> + + Note that some containers don't support some of the optional + features at all, in which case the relevant flags are + ignored. The value <code>minimum_support</code> may be passed as + a flag value to disable all optional features. A simple example + is provided in <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/test/test_vector_disable.cpp"><code>test_vector_disable.cpp</code></a> + + </p> + + <h2><a name="extending">Extending and customizing</a></h2> + + <p> + + The <code>container_suite</code> template relies on seven main + support templates, five of which are suitable for specialization + or replacement by client code. The following diagram shows the + templates <a href="#Note2">[2]</a> and their dependencies, with + the replaceable ones highlighted in grey. For full details, + refer to the specific section on each component – what + follows here is an overview. + + </p> + + <table align="right"> + <tbody><tr> + <td> + + <img src="indexing_suite_v2_files/overview.png" alt="Dependencies between main templates" height="261" width="486"> + + </td> + </tr> + <tr> + <td><font size="-1"> + + Diagram 1. Overview of class dependencies + + </font></td> + </tr> + </tbody></table> + + <p> + + The <code>visitor</code> template, which implements the <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/doc/v2/def_visitor.html">def_visitor interface</a>, decides what + Python methods to provide for a container. It takes two template + parameters, <code>Algorithms</code> and <code>Policy</code> (the + <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/libs/python/doc/v2/CallPolicies.html">CallPolicies</a> for the Python + methods on the container). The <code>Algorithms</code> argument + must provide implementations for the Python methods that the + container supports, as well as a matching + <code>ContainerTraits</code> type. This type provides various + compile-time constants that <code>visitor</code> uses to decide + what Python features the container provides. It also provides a + <code>value_traits</code> typedef, which has similar + compile-time constants related to the values stored in the + container. If the <code>visitor</code> instance decides to + provide Python slice support for the container, it instantiates + the <code>slice_handler</code> template, which also takes + <code>Algorithms</code> and <code>Policy</code> parameters. In + such cases, the <code>Algorithms</code> argument must supply a + <code>SliceHelper</code> type and factory function. + + </p> + <p> + + The high-level <code>container_suite</code> template uses the + <code>algo_selector</code> template to determine what types to + use in the instantiation of <code>visitor</code>. The + <code>algo_selector</code> template has partial specializations + for all of the STL container templates. + + </p> + + <p> + + <a name="Note2">[2]</a> Note that <code>Algorithms</code> and + <code>ContainerTraits</code> don't represent individual + templates in the diagram, but <i>groups</i> of related + templates. For instance, there are actually templates called + <code>list_algorithms</code> and <code>assoc_algorithms</code>, + among others. + + </p> + + + <h2><a name="ValueTraits">ValueTraits</a></h2> + + <p> + + A <code>ValueTraits</code> class provides simple information + about the type of value stored within a container that will be + exposed to Python via the <code>container_suite</code> + interface. It controls the provision of some operations that are + dependant on the operations supported by container elements (for + instance, <code>find</code> requires a comparison operator for + the elements). A <code>ValueTraits</code> class also provides a + hook called during initialization of the Python class, which can + be used for custom processing at this point. + + </p> + <p> + + The following table lists the static constants required in a + <code>ValueTraits</code> class: + + </p> + + <p> + <table border="1"> + <tbody><tr> + <th align="left"> + Static constant + </th> + <th align="center"> + Type + </th> + <th align="left"> + Meaning + </th> + </tr> + + <tr> + <td> + <code>equality_comparable</code> + </td> + <td> + bool + </td> + <td> + + Whether the value supports comparison via + <code>operator==</code>. + + </td> + </tr> + + <tr> + <td> + <code>lessthan_comparable</code> + </td> + <td> + bool + </td> + <td> + + Whether the value supports comparison via + <code>operator<</code>. + + </td> + </tr> + + </tbody></table> + </p> + + <p> + + A <code>ValueTraits</code> class should provide the following + member function template, which will be called during execution + of the <code>def</code> call for the container suite: + + </p> + + <p> + +</p><pre>template <typename PythonClass, typename Policy> +static void visitor_helper (PythonClass &, Policy const &); +</pre> + + <p></p> + + <h3>Usage notes for ValueTraits</h3> + + <p> + + In order to include a custom <code>ValueTraits</code> class into + the container suite, it is easiest to supply it as a + specialization of the template + <code>indexing::value_traits</code> for the container's element + type. The existing <code>ContainerTraits</code> classes all + make use of + <code>value_traits<container::value_type></code>, and so + will use a specialization for the value type if available. The + default, unspecialized, version of <code>value_traits</code> + sets both of the static constants to <code>true</code> and has + an empty implementation of <code>visitor_helper</code>. + + </p> + <p> + + As an example, if a user defined type does not have any + comparison operations, then there will probably be compile-time + errors caused by an attempt to provide the Python + <code>find</code> or <code>sort</code> methods. The solution is + to write a specialized version of + <code>indexing::value_traits</code> that disables the + appropriate features. For example: + + </p> + + <p> +</p><pre>namespace boost { namespace python { namespace indexing { + template<> + struct value_traits<my_type> : public value_traits<int> + { + static bool const equality_comparable = false; + static bool const lessthan_comparable = false; + }; +} } } +</pre> + <p></p> + + <p> + + In this example, there is no need to perform any processing in + the <code>visitor_helper</code> function, and deriving from an + unspecialized version of the template (e.g. + <code>value_traits<int></code>) exposes an empty + <code>visitor_helper</code>. + + </p> + + <h3>Synopsis: boost/python/suite/indexing/value_traits.hpp</h3> + + <p> +</p><pre>namespace boost { namespace python { namespace indexing { + template<typename T> + struct value_traits { + static bool const equality_comparable = true; + static bool const lessthan_comparable = true; + + template<typename PythonClass, typename Policy> + static void visitor_helper (PythonClass &, Policy const &) + { } + }; +} } } +</pre> + <p></p> + + <h2><a name="ContainerTraits">ContainerTraits</a></h2> + + <p> + + A <code>ContainerTraits</code> class serves three + purposes. Firstly, it identifies what facilities the container + supports in principle (i.e. either directly or via some support + code). Secondly, it identifies the types used to pass values + into and out of the supported operations. Thirdly, it provides a + hook for additional code to run during initialization of the + Python class (i.e. during the <code>def</code> call for the + suite). + + </p> + <p> + + Note that a <code>ContainerTraits</code> class can be any class, + derived from the existing implementations or not, as long as it + meets the requirements listed in the following sections. + + </p> + + <h3>Static constants for ContainerTraits</h3> + + The following table lists the static constants that a + <code>ContainerTraits</code> class should define. Note that these + must be <i>compile-time constants</i>, since parts of the library + use these constants to select between template specializations. + The constants must at least be convertible to the type shown in + the second column. + + <p> + <table border="1"> + <tbody><tr> + <th align="left"> + Static constant + </th> + <th align="center"> + Type + </th> + <th align="left"> + Meaning + </th> + <th align="left"> + Influence + </th> + </tr> + <tr> + <td> + <code>has_copyable_iter</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + + Whether copies of an iterator are independant <a href="#Note3">[3]</a> + + </td> + <td> + + Required for <code>len</code> and <code>__iter__</code> + + </td> + </tr> + + <tr> + <td> + <code>is_reorderable</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + + Whether it is possible to re-order the contents of the + container. + + </td> + <td> + + Required for <code>reverse</code> and <code>sort</code> + + </td> + </tr> + + <tr> + <td> + <code>has_mutable_ref</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + Whether container elements can be altered via a reference + </td> + <td> + Determines <code>is_reorderable</code> for most containers. + </td> + </tr> + + <tr> + <td> + <code>has_find</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + + Whether find is possible in principle (via member function + or otherwise) + + </td> + <td> + <code>__contains__</code>, + <code>index</code>, + <code>count</code>, + <code>has_key</code> + </td> + </tr> + + <tr> + <td> + <code>has_insert</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + + Whether it is possible to insert new elements into the container. + + </td> + <td> + <code>insert</code>, + <code>extend</code>, + slice version of <code>__setitem__</code> + </td> + </tr> + + <tr> + <td> + <code>has_erase</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + + Whether it is possible to erase elements from the container. + + </td> + <td> + <code>__delitem__</code>, + slice version of <code>__setitem__</code> + </td> + </tr> + + <tr> + <td> + <code>has_push_back</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + + Whether container supports insertion at the end. + + </td> + <td> + <code>append</code> + </td> + </tr> + + <tr> + <td> + <code>has_pop_back</code> + </td> + <td align="center"> + <code>bool</code> + </td> + <td> + + Whether container supports element deletion at the end. + + </td> + <td> + Currently unused + </td> + </tr> + + <tr> + <td> + <code>index_style</code> + </td> + <td align="center"> + <code>index_style_t</code> + </td> + <td> + + Type of indexing the container supports <a href="#Note4">[4]</a> + + </td> + <td> + <code>__getitem__</code>, + <code>__setitem__</code>, + <code>__delitem__</code>, + <code>__iter__</code>, + <code>extend</code>, + <code>index</code>, + <code>count</code>, + <code>has_key</code> + </td> + </tr> + </tbody></table> + </p> + + <p> + </p><h3>Notes</h3> + + <table> + <tbody><tr> + <td valign="top"> + <a name="Note3">[3]</a> + </td> + <td> + + For example, copies of stream iterators are <i>not</i> + independant. All iterator copies refer to the same stream, + which has only one read and one write position. + + </td> + </tr> + + <tr> + <td valign="top"> + <a name="Note4">[4]</a> + </td> + <td> + + <code>index_style_none</code>, no indexing at all + (e.g. <code>list</code>)<br> + + <code>index_style_linear</code>, continuous integer-like + index type (e.g. <code>vector</code>)<br> + + <code>index_style_nonlinear</code>, indexing via other + types (e.g. <code>map</code>). + + </td> + </tr> + </tbody></table> + + <p></p> + + <h3>Member types for ContainerTraits</h3> + + <p> + + The following table lists the type names that must be defined in + a compatible implementation of <code>ContainerTraits</code>. + The large number of types is supposed to provide flexibility for + containers with differing interfaces. For example, + <code>map</code> uses the same type for searching and "indexing" + (i.e. <code>find</code> and <code>operator[]</code>) so + <code>key_type</code> and <code>index_type</code> would have to + be the same. In contrast, searching a <code>vector</code> would + typically use a different type to that used for indexing into a + vector. + + </p> + + <p> + <table border="1"> + <tbody><tr> + <th align="left"> + Type name + </th> + <th align="left"> + Meaning + </th> + </tr> + + <tr> + <td> + <code>container</code> + </td> + <td> + The type of the C++ container. + </td> + </tr> + + <tr> + <td> + <code>size_type</code> + </td> + <td> + + The type used to represent the number of elements in the + container. + + </td> + </tr> + + <tr> + <td> + <code>iterator</code> + </td> + <td> + + The container's iterator type. This should be a non-const + iterator unless the container itself is const. + + </td> + </tr> + + <tr> + <td> + <code>index_type</code> + </td> + <td> + + The type used to represent indexes extracted from a + <code>__getitem__</code> call (and others). For + <code>index_style_linear</code>, this <i>should be a + signed type</i>, so that negative indices can be + processed. For <code>index_style_nonlinear</code>, this + will most likely be the same type as + <code>key_type</code>. + + </td> + </tr> + + <tr> + <td> + <code>index_param</code> + </td> + <td> + + The type to use when passing <code>index_type</code> into + a function. + + </td> + </tr> + + <tr> + <td> + <code>value_type</code> + </td> + <td> + + The type to use when copying a value into or out of the + container. + + </td> + </tr> + + <tr> + <td> + <code>value_param</code> + </td> + <td> + + The type to use when passing <code>value_type</code> into + a function. + + </td> + </tr> + + <tr> + <td> + <code>key_type</code> + </td> + <td> + + The type used for search operations like <code>find</code> + and <code>count</code>. + + </td> + </tr> + + <tr> + <td> + <code>key_param</code> + </td> + <td> + + The type to use when passing <code>key_type</code> into a + function. + + </td> + </tr> + + <tr> + <td> + <code>reference</code> + </td> + <td> + + The type to use when returning a reference to a container + element. + + </td> + </tr> + + <tr> + <td> + <code>value_traits_</code> + </td> + <td> + + Traits for the container elements. See <a href="#ValueTraits">the ValueTraits section</a> for + information about the requirements on this type. + + </td> + </tr> + + </tbody></table> + + </p> + + <h3>Member functions for ContainerTraits</h3> + + In order to support additional initialization code to run, a + <code>ContainerTraits</code> class should provide a static member + function template as follows: + + <p> +</p><pre>template <typename PythonClass, typename Policy> +static void visitor_helper (PythonClass &, Policy const &); +</pre> + <p></p> + + <p> + + Typically, the implementation would just forward the call to the + equivalent function in the <code>value_traits_</code> class. + + </p> + + <h3>Usage notes for ContainerTraits</h3> + + <p> + + It may be possible to mix your own <code>ContainerTraits</code> + class with one of the existing <code>Algorithms</code> + implementations, thus saving yourself a fair bit of work. The + easiest way to do this would be to specialize the + <code>algo_selector</code> template for your container type, + using public deriviation to get the implementation from one of + the existing <code>Algorithms</code> templates. For example, + assuming that <code>default_algorithms</code> is suitable for + your container: + + </p> + + <p> +</p><pre>namespace boost { namespace python { namespace indexing { + template<> + struct algo_selector<my_container> + : public default_algorithms<my_container_traits> + { + }; +} } } +</pre> + <p></p> + <p> + + Alternatively, you could select the algorithms and traits using + the <code>visitor</code> template directly, as described in the + <a href="#workarounds">compiler workarounds</a> section. + + </p> + + <h3><a name="simple_ctraits">Simplistic ContainerTraits example</a></h3> + + <p> + + The following block of code shows a simplistic implementation of + <code>ContainerTraits</code> for the container + <code>std::map<std::string, int></code>. The actual + implementation used by the suite relies on template + metaprogramming techniques, whereas this example is designed to + show only the essential elements of a + <code>ContainerTraits</code> implementation. + + </p> + + <p> +</p><pre>#include <map> +#include <string> +#include <boost/python/suite/indexing/suite_utils.hpp> +// Include suite_utils to get index_style_t + +struct simple_map_traits { + // Traits information for std::map<std::string, int> + + typedef std::map<std::string, int> container; + typedef container::size_type size_type; + typedef container::iterator iterator; + + typedef int value_type; + typedef int & reference; + typedef std::string key_type; + typedef std::string index_type; + + typedef int value_param; + typedef std::string const & key_param; + typedef std::string const & index_param; + + static bool const has_copyable_iter = true; + static bool const has_mutable_ref = true; + static bool const has_find = true; + static bool const has_insert = true; + static bool const has_erase = true; + static bool const has_pop_back = false; + static bool const has_push_back = false; + static bool const is_reorderable = false; + + static boost::python::indexing::index_style_t const index_style + = boost::python::indexing::index_style_nonlinear; + + struct value_traits_ { + // Traits information for our value_type + static bool const equality_comparable = true; + static bool const lessthan_comparable = true; + }; + + template<typename PythonClass, typename Policy> + static void visitor_helper (PythonClass &, Policy const &) + { + // Empty + } +}; +</pre> + <p></p> + + <p> + + Example usage of the <code>simple_map_traits</code>: + + </p> + + <p> +</p><pre>#include "simple_map_traits.hpp" + +#include <boost/python/suite/indexing/container_suite.hpp> + +#include <boost/python/module.hpp> +#include <boost/python/class.hpp> + +BOOST_PYTHON_MODULE(test_simple) { + using namespace boost::python; + + typedef std::map<std::string, int> container_t; + typedef indexing::map_algorithms<simple_map_traits> algorithms_t; + + class_<container_t> ("map") + .def (indexing::container_suite<container_t, algorithms_t>()); +} +</pre> + <p></p> + + <h2><a name="Algorithms">Algorithms</a></h2> + + <p> + + The <code>Algorithms</code> requirements are designed to provide + a predictable interface to any container, so that the same + <code>visitor</code> code can expose any supported container to + Python. An implemention of <code>Algorithms</code> does this by + providing functions and typedefs with fixed names. The exact + interfaces to the functions can vary to some extent, since the + <code>def</code> function calls used internally by the + <code>visitor</code> deduce the function type + automatically. However, certain points should be confomed to: + + </p><ol> + <li> + + The functions should be static, with + <code>container &</code> as first parameter. + + </li> + + <li> + + The functions should <i>not</i> be overloaded – this + avoids problems with type deduction. + + </li> + <li> + + Generally, not all of the possible functions need to be + implemented, dependant on the static constants in the + <code>ContainerTraits</code>. + + </li> + </ol> + + <p></p> + + <p> + + The block of code below shows the definition of the + <code>default_algorithms</code> class template, which is the + basis for all current implementations of + <code>Algorithms</code>. The typedefs that it defines are + primarily for convenience within the implementation itself, + however <code>container</code>, <code>reference</code> and + <code>slice_helper</code> are also required by the + <code>slice_handler</code> template, if slices are + supported. Note that <code>default_algorithms</code> derives all + of the type information from its <code>ContainerTraits</code> + template argument, which allows the same implementation to be + used for various container types. + + </p> + + <h3>Partial boost/python/suite/indexing/algorithms.hpp</h3> + + <p> +</p><pre>namespace boost { namespace python { namespace indexing { + template<typename ContainerTraits, typename Ovr = detail::no_override> + class default_algorithms + { + typedef default_algorithms<ContainerTraits, Ovr> self_type; + + public: + typedef ContainerTraits container_traits; + + typedef typename ContainerTraits::container container; + typedef typename ContainerTraits::iterator iterator; + typedef typename ContainerTraits::reference reference; + typedef typename ContainerTraits::size_type size_type; + typedef typename ContainerTraits::value_type value_type; + typedef typename ContainerTraits::value_param value_param; + typedef typename ContainerTraits::index_param index_param; + typedef typename ContainerTraits::key_param key_param; + + typedef int_slice_helper<self_type, integer_slice> slice_helper; + + static size_type size (container &); + static iterator find (container &, key_param); + static size_type get_index (container &, key_param); + static size_type count (container &, key_param); + static bool contains (container &, key_param); + static void reverse (container &); + static reference get (container &, index_param); + static void assign (container &, index_param, value_param); + static void insert (container &, index_param, value_param); + static void erase_one (container &, index_param); + static void erase_range(container &, index_param, index_param); + static void push_back (container &, value_param); + static void sort (container &); + + static slice_helper make_slice_helper (container &c, slice const &); + + template<typename PythonClass, typename Policy> + static void visitor_helper (PythonClass &, Policy const &); + }; +} } } +</pre> + <p></p> + + <h3>Slice support</h3> + <p> + + For containers that support Python slices, the + <code>visitor</code> template will instantiate and use + internally the <code>slice_handler</code> template. This + template requires a type called <code>slice_helper</code> and a + factory function called <code>make_slice_helper</code> from its + <code>Algorithms</code> argument. More details are provided in + the section <a href="#SliceHelper">SliceHelper</a>. + + </p> + + <h3>Usage notes for Algorithms</h3> + + <p> + + The existing <code>indexing::algo_selector</code> template uses + partial specializations and public derivation to select an + <code>Algorithms</code> implementation suitable for any of the + standard container types. Exactly how it does this should be + considered an implementation detail, and uses some tricks to + reuse various existing <code>Algorithms</code> + implementations. In any case, client code can specialize the + <code>algo_selector</code> template for new container types, as + long as the specialized instances conform to the requirements + for <code>Algorithms</code> as already given. + + </p> + <p> + + A new implementation of <code>Algorithms</code> could derive + from any one of the existing implementation templates, or be + completely independant. The existing implementation templates + are listed in the following table. They each take one template + parameter, which should be a valid <code>ContainerTraits</code> + class, as specified in a <a href="#ContainerTraits">previous + section</a>. + + </p> + + <p> + <table border="1"> + <tbody><tr> + <th> + Template name + </th> + <th> + Description + </th> + </tr> + + <tr> + <td> + + <code>default_algorithms</code> + + </td> + <td> + + Uses standard iterator-based algorithms wherever + possible. Assumes that the container provides + <code>begin</code> and end <code>end</code> member + functions that return iterators, and some or all of + <code>size</code>, <code>insert</code>, <code>erase</code> + and <code>push_back</code>, depending on what functions get + instantiated. + + </td> + </tr> + + <tr> + <td> + + <code>list_algorithms</code> + + </td> + <td> + + Similar to the above (in fact, it derives from + <code>default_algorithms</code>) except that it uses + container member functions <code>reverse</code> and + <code>sort</code> instead of the iterator-based + versions. Defined in + <code>boost/python/suite/indexing/list.hpp</code>. + + </td> + </tr> + + <tr> + <td> + + <code>assoc_algorithms</code> + + </td> + <td> + + Also derived from <code>default_algorithms</code>, for use + with associative containers. Uses the container member + function <code>find</code> for indexing, and member + function <code>count</code> instead of iterator-based + implementations. + + </td> + </tr> + + <tr> + <td> + + <code>set_algorithms</code> + + </td> + <td> + + Derived from <code>assoc_algorithms</code> to handle + <code>set</code> insertion operations, which are slightly + different to the <code>map</code> versions. + + </td> + </tr> + + <tr> + <td> + + <code>map_algorithms</code> + + </td> + <td> + + Derived from <code>assoc_algorithms</code> to handle + <code>map</code> insertion and lookup, which are slightly + different to the <code>set</code> versions. + + </td> + </tr> + </tbody></table> + + </p> + <p> + + The <code>default_algorithms</code> template attempts to place + as few restrictions as possible on the container type, by using + iterators and standard algorithms in most of its functions. It + accepts an optional second template parameter, which can be used + via the curiously recurring template idiom to replace any of its + functions that it relies on internally. For instance, if you've + created an iterator-style interface to a container that is not + at all STL-like (let's call it <code>weird_container</code>), + you might be able to re-use most of + <code>default_algorithms</code> by replacing its basic functions + like this: + + </p> + <p> +</p><pre>namespace indexing = boost::python::indexing; + +struct my_algorithms + : public indexing::default_algorithms < + weird_container_traits, my_algorithms + > +{ + size_t size (weird_container const &c) { + return ...; + } + + my_iterator_t begin (weird_container &c) { + return ...; + } + + my_iterator_t end (weird_container &c) { + return ...; + } +}; +</pre> + <p></p> + + <h2><a name="SliceHelper">SliceHelper</a></h2> + + <p> + + Support code for Python slices is split into two portions, the + <code>slice_handler</code> template, and a "slice helper" that + can easily be replaced by client code via a typedef and factory + function in the <code>Algorithms</code> argument supplied to + <code>container_suite</code>. The slice helper object takes care + of reading and writing elements from a slice in a C++ container, + and optionally insertion and deletion. Effectively, the slice + helper object maintains a pointer to the current element of the + slice within the container, and provides a <code>next</code> + function to advance to the next element of the slice. The + container suite uses the following interface for slices: + + </p> + <p> + <table border="1"> + <tbody><tr> + <th> + + Expression + + </th> + <th> + + Return type + + </th> + <th> + + Notes + + </th> + </tr> + <tr> + <td> + + <code>Algorithms::</code> <code>make_slice_helper</code> + <code>(c, s)</code> + + </td> + <td> + + <code>Algorithms::</code> <code>slice_helper</code> + + </td> + <td> + + <code>c</code> is of type + <code>Algorithms::</code> <code>container &</code> and + <code>s</code> is of type <code>indexing::</code> + <code>slice const &</code>. + Returns a newly constructed <code>slice_helper</code> + object by value. + + </td> + </tr> + + <tr> + <td> + + <code>slice_helper.</code><code>next()</code> + + </td> + <td> + + <code>bool</code> + + </td> + <td> + + Advances the slice helper's current element pointer to the + next element of the slice. Returns true if such an element + exists, and false otherwise. The first time this function + is called, it should set the current pointer to the first + element of the slice (if any). + + </td> + </tr> + + <tr> + <td> + + <code>slice_helper.</code> <code>current()</code> + + </td> + <td> + + <code>Algorithms::</code> <code>reference</code> + + </td> + <td> + + Returns a reference to the current element of the + slice. This will only be called if the last call to + <code>next()</code> returned true. + + </td> + </tr> + <tr> + <td> + + <code>slice_helper.</code><code>write (v)</code> + + </td> + <td> + + <code>void</code> + + </td> + <td> + + The parameter <code>v</code> is of type + <code>Algorthims::value_param</code>. Advances to the + next element of the slice, as defined in + <code>next</code>, and writes the given value + <code>v</code> at the new location in the container.If the + slice is exhausted (i.e. <code>next</code> would return + false) then <code>write</code> <i>either</i> inserts the + value into the container at the next location (past the + end of the slice), <i>or</i> sets a Python exception and + throws. + + </td> + </tr> + <tr> + <td> + + <code>slice_helper.</code> <code>erase_remaining()</code> + + </td> + <td> + + <code>void</code> + + </td> + <td> + + <i>Either</i> erases any remaining elements in the slice + not already consumed by calls to <code>next</code> or + <code>write</code>, + <i>or</i> sets a Python exception and throws. + + </td> + </tr> + </tbody></table> + </p> + + <p> + + The container suite provides a generic implementation of the + <code>SliceHelper</code> requirements for containers that have + integer-like indexes. It is parameterized with a + <code>SliceType</code> parameter that allows the integer index + values to come from various different sources, the default being + the <code>PySlice_GetIndices</code> function. Refer to the + header file <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/boost/python/suite/indexing/int_slice_helper.hpp"><code>int_slice_helper.hpp</code></a> + and the references to it in the <a href="http://boost.cvs.sourceforge.net/*checkout*/boost/boost/boost/python/suite/indexing/algorithms.hpp"><code>algorithms.hpp</code></a> + header for details. + + </p> + + <h2><a name="container_proxy">container_proxy</a></h2> + + <p> + + The <code>container_proxy</code> template provides an emulation + of Python reference semantics for objects held by value in a + vector-like container. Of course, this introduces some + performance penalties in terms of memory usage and run time, so + the primary application of this template is in situations where + all of the following apply: + + </p><ol> + <li> + + It is not practical to switch to a container of shared + pointers + + </li> + <li> + + Python code requires reference semantics for the objects + within the container + + </li> + <li> + + Element insertion, deletion or assignment takes place, so + that using <code>return_internal_reference</code> would be + dangerous. + + </li> + </ol> + + <p></p> + + <p> + + + The <code>container_proxy</code> template wraps any vector-like + container and presents an interface that is similar to that of + <code>std::vector</code>, but which returns + <code>element_proxy</code> objects instead of plain references + to values stored in the wrapped container. During an operation + that alters the position of an element within the container + (e.g. <code>insert</code>) the <code>container_proxy</code> code + updates the relevant proxy objects, so that they still refer to + the <i>same</i> elements at their new locations. Any operation + that would delete or overwrite a value in the container + (e.g. <code>erase</code>) copies the to-be-deleted value into + its corresponding proxy object. This means that a proxy's + "reference" to an element is robust in the face of changes to + the ele... [truncated message content] |
From: <rom...@us...> - 2006-07-09 11:45:10
|
Revision: 286 Author: roman_yakovenko Date: 2006-07-09 04:45:03 -0700 (Sun, 09 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=286&view=rev Log Message: ----------- small bug fix: don't export container, if value type is not exported Modified Paths: -------------- pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-09 07:33:06 UTC (rev 285) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-09 11:45:03 UTC (rev 286) @@ -406,7 +406,13 @@ used_headers.add( isuite[ container_name ] ) cls_creator = create_cls_cc( cls ) - element_type = cls.indexing_suite.element_type + element_type = cls.indexing_suite.element_type + if declarations.is_class( element_type ): + class_traits = declarations.class_traits + value_cls = class_traits.get_declaration( element_type ) + if value_cls.ignore: + continue #this collection could not be exported, because + #the value_type of collection is not exported if isuite is isuite1: if declarations.is_class( element_type ) and not declarations.has_public_equal( element_type ): cls_creator.adopt_creator( create_explanation( cls ) ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-09 07:33:16
|
Revision: 285 Author: roman_yakovenko Date: 2006-07-09 00:33:06 -0700 (Sun, 09 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=285&view=rev Log Message: ----------- fixing bugs in indexing suite v2 code generation Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/indexing_suites.py pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pyplusplus_dev/pyplusplus/code_creators/indexing_suites.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/indexing_suites.py 2006-07-09 05:31:25 UTC (rev 284) +++ pyplusplus_dev/pyplusplus/code_creators/indexing_suites.py 2006-07-09 07:33:06 UTC (rev 285) @@ -114,8 +114,11 @@ , "template<>" , "struct value_traits< %(value_class)s >{" , "" - , self.indent( "static bool const equality_comparable = %(has_equal)s;" ) + , self.indent( "static bool const equality_comparable = %(has_equal)s;" ) + , self.indent( "%(equal_to)s" ) + , "" , self.indent( "static bool const less_than_comparable = %(has_lessthan)s;" ) + , self.indent( "%(less)s" ) , "" , self.indent( "template<typename PythonClass, typename Policy>" ) , self.indent( "static void visit_container_class(PythonClass &, Policy const &){" ) @@ -126,10 +129,20 @@ , "" , "}/*indexing*/ } /*python*/ } /*boost*/" ]) + + less = '' + if self.declaration.less_than_comparable: + less = "typedef std::less< %s > less;" % self.decl_identifier + + equal_to = '' + if self.declaration.equality_comparable: + equal_to = "typedef std::equal_to< %s > equal_to;" % self.decl_identifier return tmpl % { 'value_class' : self.decl_identifier - , 'has_equal' : str( bool( self.declaration.equality_comparable ) ) .lower() - , 'has_lessthan' : str( bool( self.declaration.less_than_comparable ) ).lower() + , 'has_equal' : str( bool( self.declaration.equality_comparable ) ) .lower() + , 'equal_to' : equal_to + , 'has_lessthan' : str( bool( self.declaration.less_than_comparable ) ).lower() + , 'less' : less , 'visitor_helper_body' : '' } def generate_value_class_fwd_declaration( self ): Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-09 05:31:25 UTC (rev 284) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-09 07:33:06 UTC (rev 285) @@ -415,9 +415,8 @@ class_traits = declarations.class_traits if class_traits.is_my_case( element_type ): value_cls = class_traits.get_declaration( element_type ) - if not ( value_cls.equality_comparable and value_cls.less_than_comparable ): - element_type_cc = code_creators.value_traits_t( value_cls ) - self.__extmodule.adopt_creator( element_type_cc, self.__extmodule.creators.index( self.__module_body ) ) + element_type_cc = code_creators.value_traits_t( value_cls ) + self.__extmodule.adopt_creator( element_type_cc, self.__extmodule.creators.index( self.__module_body ) ) cls_creator.adopt_creator( code_creators.indexing_suite2_t(cls) ) self.__module_body.adopt_creator( cls_creator ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-09 05:31:36
|
Revision: 284 Author: roman_yakovenko Date: 2006-07-08 22:31:25 -0700 (Sat, 08 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=284&view=rev Log Message: ----------- fixing has_binary_operator type traits Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/type_traits.py pygccxml_dev/unittests/data/core_cache.hpp pygccxml_dev/unittests/data/has_public_binary_operator_traits.hpp pygccxml_dev/unittests/test_all.py Modified: pygccxml_dev/pygccxml/declarations/type_traits.py =================================================================== --- pygccxml_dev/pygccxml/declarations/type_traits.py 2006-07-09 05:00:25 UTC (rev 283) +++ pygccxml_dev/pygccxml/declarations/type_traits.py 2006-07-09 05:31:25 UTC (rev 284) @@ -14,7 +14,8 @@ Those functions are very valuable for code generation. Almost all functions within this module works on L{type_t} class hierarchy and\\or L{class_t}. """ - + +import filters import typedef import calldef import cpptypes @@ -366,28 +367,44 @@ return bool( constructors ) def has_public_binary_operator( type, operator_symbol ): - symbol = operator_symbol not_artificial = lambda decl: decl.is_artificial == False type = remove_alias( type ) type = remove_cv( type ) type = remove_declarated( type ) - assert isinstance( type, class_declaration.class_t ) - equals = type.member_operators( function=not_artificial, symbol=symbol, allow_empty=True, recursive=False ) - if equals: + assert isinstance( type, class_declaration.class_t ) + + if is_std_string( type ) or is_std_wstring( type ): + #In some case compare operators of std::basic_string are not instantiated + return True + + operators = type.member_operators( function=filters.custom_matcher_t( not_artificial ) \ + & filters.access_type_matcher_t( 'public' ) + , symbol=operator_symbol + , allow_empty=True + , recursive=False ) + if operators: return True t = cpptypes.declarated_t( type ) t = cpptypes.const_t( t ) t = cpptypes.reference_t( t ) - equals = type.parent.operators( function=not_artificial, symbol=symbol, arg_types=[t, None], allow_empty=True, recursive=False ) - if equals: + operators = type.top_parent.operators( function=not_artificial + , arg_types=[t, None] + , symbol=operator_symbol + , allow_empty=True + , recursive=True ) + if operators: return True for bi in type.recursive_bases: assert isinstance( bi, class_declaration.hierarchy_info_t ) if bi.access_type != class_declaration.ACCESS_TYPES.PUBLIC: continue - equals = bi.related_class.member_operators( function=not_artificial, symbol=symbol, allow_empty=True, recursive=False ) - if equals: + operators = bi.related_class.member_operators( function=filters.custom_matcher_t( not_artificial ) \ + & filters.access_type_matcher_t( 'public' ) + , symbol=operator_symbol + , allow_empty=True + , recursive=False ) + if operators: return True return False Modified: pygccxml_dev/unittests/data/core_cache.hpp =================================================================== --- pygccxml_dev/unittests/data/core_cache.hpp 2006-07-09 05:00:25 UTC (rev 283) +++ pygccxml_dev/unittests/data/core_cache.hpp 2006-07-09 05:31:25 UTC (rev 284) @@ -22,4 +22,4 @@ #endif//__core_cache_hpp__ -//touch//touch//touch \ No newline at end of file +//touch//touch//touch//touch \ No newline at end of file Modified: pygccxml_dev/unittests/data/has_public_binary_operator_traits.hpp =================================================================== --- pygccxml_dev/unittests/data/has_public_binary_operator_traits.hpp 2006-07-09 05:00:25 UTC (rev 283) +++ pygccxml_dev/unittests/data/has_public_binary_operator_traits.hpp 2006-07-09 05:31:25 UTC (rev 284) @@ -10,10 +10,6 @@ namespace yes{ typedef std::string yes1; - inline bool instantiate_templ(){ - return std::string( "1" ) == std::string( "2" ); - } - struct trivial{ bool operator==(const trivial& other); }; Modified: pygccxml_dev/unittests/test_all.py =================================================================== --- pygccxml_dev/unittests/test_all.py 2006-07-09 05:00:25 UTC (rev 283) +++ pygccxml_dev/unittests/test_all.py 2006-07-09 05:31:25 UTC (rev 284) @@ -37,6 +37,7 @@ import vector_traits_tester import string_traits_tester import declarations_cache_tester +import has_binary_operator_traits_tester def create_suite(): testers = [ @@ -72,7 +73,8 @@ , unnamed_enums_bug_tester , vector_traits_tester , string_traits_tester - , declarations_cache_tester + , declarations_cache_tester + , has_binary_operator_traits_tester ] main_suite = unittest.TestSuite() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-09 05:00:30
|
Revision: 283 Author: roman_yakovenko Date: 2006-07-08 22:00:25 -0700 (Sat, 08 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=283&view=rev Log Message: ----------- adding test case for operator() Modified Paths: -------------- pyplusplus_dev/unittests/member_functions_tester.py Modified: pyplusplus_dev/unittests/member_functions_tester.py =================================================================== --- pyplusplus_dev/unittests/member_functions_tester.py 2006-07-09 04:59:09 UTC (rev 282) +++ pyplusplus_dev/unittests/member_functions_tester.py 2006-07-09 05:00:25 UTC (rev 283) @@ -29,7 +29,9 @@ , 'private_base_t' ] - mb.classes( lambda decl: decl.name in names ).always_expose_using_scope = True + mb.classes( lambda decl: decl.name in names ).always_expose_using_scope = True + #will reporoduce bug + mb.class_('callable_t').always_expose_using_scope = True def create_test_class_inst(self, class_ ): class tester_impl_t( class_ ): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-09 04:59:15
|
Revision: 282 Author: roman_yakovenko Date: 2006-07-08 21:59:09 -0700 (Sat, 08 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=282&view=rev Log Message: ----------- adding test case for operator() Modified Paths: -------------- pyplusplus_dev/unittests/data/member_functions_to_be_exported.hpp Modified: pyplusplus_dev/unittests/data/member_functions_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/member_functions_to_be_exported.hpp 2006-07-08 20:28:29 UTC (rev 281) +++ pyplusplus_dev/unittests/data/member_functions_to_be_exported.hpp 2006-07-09 04:59:09 UTC (rev 282) @@ -149,8 +149,12 @@ virtual int pure_virtual_const_overloaded( int x ) const { return x * x; } virtual int pure_virtual_const_overloaded( int x, int y ) const { return x * y; } }; + +struct callable_t{ + int operator()( int i, int j ) const { return i + j; } + int operator()( int i, int j, int k ) const { return i + j + k; } +}; - } #endif//__member_functions_to_be_exported_hpp__ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-08 20:28:45
|
Revision: 281 Author: roman_yakovenko Date: 2006-07-08 13:28:29 -0700 (Sat, 08 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=281&view=rev Log Message: ----------- integrating has_public_equal and has_public_less with indexing suite 2. Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/__init__.py pygccxml_dev/pygccxml/declarations/type_traits.py pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py Added Paths: ----------- pygccxml_dev/unittests/data/has_public_binary_operator_traits.hpp pygccxml_dev/unittests/has_binary_operator_traits_tester.py Modified: pygccxml_dev/pygccxml/declarations/__init__.py =================================================================== --- pygccxml_dev/pygccxml/declarations/__init__.py 2006-07-08 18:48:46 UTC (rev 280) +++ pygccxml_dev/pygccxml/declarations/__init__.py 2006-07-08 20:28:29 UTC (rev 281) @@ -147,6 +147,7 @@ from type_traits import remove_declarated from type_traits import has_destructor +from type_traits import has_public_less from type_traits import has_trivial_copy from type_traits import has_public_equal from type_traits import has_public_assign @@ -154,8 +155,8 @@ from type_traits import has_public_constructor from type_traits import has_trivial_constructor from type_traits import find_trivial_constructor +from type_traits import has_public_binary_operator from type_traits import has_any_non_copyconstructor - from type_traits import smart_pointer_traits Modified: pygccxml_dev/pygccxml/declarations/type_traits.py =================================================================== --- pygccxml_dev/pygccxml/declarations/type_traits.py 2006-07-08 18:48:46 UTC (rev 280) +++ pygccxml_dev/pygccxml/declarations/type_traits.py 2006-07-08 20:28:29 UTC (rev 281) @@ -365,32 +365,40 @@ , type.public_members ) return bool( constructors ) -def has_public_equal( type ): - """returns True if class has public operator==, otherwise False""" +def has_public_binary_operator( type, operator_symbol ): + symbol = operator_symbol not_artificial = lambda decl: decl.is_artificial == False type = remove_alias( type ) type = remove_cv( type ) type = remove_declarated( type ) assert isinstance( type, class_declaration.class_t ) - equals = type.member_operators( function=not_artificial, symbol='==', allow_empty=True, recursive=False ) + equals = type.member_operators( function=not_artificial, symbol=symbol, allow_empty=True, recursive=False ) if equals: return True t = cpptypes.declarated_t( type ) t = cpptypes.const_t( t ) t = cpptypes.reference_t( t ) - equals = type.parent.operators( function=not_artificial, symbol='==', arg_types=[t, None], allow_empty=True, recursive=False ) + equals = type.parent.operators( function=not_artificial, symbol=symbol, arg_types=[t, None], allow_empty=True, recursive=False ) if equals: return True for bi in type.recursive_bases: assert isinstance( bi, class_declaration.hierarchy_info_t ) if bi.access_type != class_declaration.ACCESS_TYPES.PUBLIC: continue - equals = bi.related_class.member_operators( function=not_artificial, symbol='==', allow_empty=True, recursive=False ) + equals = bi.related_class.member_operators( function=not_artificial, symbol=symbol, allow_empty=True, recursive=False ) if equals: return True return False - + +def has_public_equal( type ): + """returns True if class has public operator==, otherwise False""" + return has_public_binary_operator( type, '==' ) + +def has_public_less( type ): + """returns True if class has public operator<, otherwise False""" + return has_public_binary_operator( type, '<' ) + def is_unary_operator( oper ): """returns True if operator is unary operator, otherwise False""" #~ definition: Added: pygccxml_dev/unittests/data/has_public_binary_operator_traits.hpp =================================================================== --- pygccxml_dev/unittests/data/has_public_binary_operator_traits.hpp (rev 0) +++ pygccxml_dev/unittests/data/has_public_binary_operator_traits.hpp 2006-07-08 20:28:29 UTC (rev 281) @@ -0,0 +1,39 @@ +// Copyright 2004 Roman Yakovenko. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <string> +#include <vector> + +namespace binary_operator{ +namespace yes{ + typedef std::string yes1; + + inline bool instantiate_templ(){ + return std::string( "1" ) == std::string( "2" ); + } + + struct trivial{ + bool operator==(const trivial& other); + }; + + typedef trivial yes2; + + struct external{ + }; + + bool operator==( const external& left, const external& right ); + + typedef external yes3; +} +namespace no{ + + struct x1{ + private: + bool operator==( const x1& other ); + }; + + typedef x1 no1; +} +} \ No newline at end of file Added: pygccxml_dev/unittests/has_binary_operator_traits_tester.py =================================================================== --- pygccxml_dev/unittests/has_binary_operator_traits_tester.py (rev 0) +++ pygccxml_dev/unittests/has_binary_operator_traits_tester.py 2006-07-08 20:28:29 UTC (rev 281) @@ -0,0 +1,49 @@ +# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import unittest +import autoconfig +import parser_test_case + +from pygccxml import utils +from pygccxml import parser +from pygccxml import declarations + +class tester_t( parser_test_case.parser_test_case_t ): + COMPILATION_MODE = parser.COMPILATION_MODE.ALL_AT_ONCE + global_ns = None + def __init__(self, *args ): + parser_test_case.parser_test_case_t.__init__( self, *args ) + self.header = 'has_public_binary_operator_traits.hpp' + self.global_ns = None + + def setUp(self): + if not tester_t.global_ns: + decls = parser.parse( [self.header], self.config ) + tester_t.global_ns = declarations.get_global_namespace( decls ) + self.global_ns = tester_t.global_ns + + def test_yes( self ): + yes_ns = self.global_ns.namespace( 'yes' ) + for typedef in yes_ns.typedefs(): + self.failUnless( declarations.has_public_equal( typedef ) + , "Class '%s' should have public operator==" % typedef.decl_string ) + + def test_no( self ): + no_ns = self.global_ns.namespace( 'no' ) + for typedef in no_ns.typedefs(): + self.failUnless( not declarations.has_public_equal( typedef ) + , "Class '%s' should not have public operator==" % typedef.decl_string ) + +def create_suite(): + suite = unittest.TestSuite() + suite.addTest( unittest.makeSuite(tester_t)) + return suite + +def run_suite(): + unittest.TextTestRunner(verbosity=2).run( create_suite() ) + +if __name__ == "__main__": + run_suite() \ No newline at end of file Modified: pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2006-07-08 18:48:46 UTC (rev 280) +++ pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2006-07-08 20:28:29 UTC (rev 281) @@ -49,7 +49,6 @@ indexing_suite = property( _get_indexing_suite ) def _get_equality_comparable( self ): - return False if None is self._equality_comparable: self._equality_comparable = declarations.has_public_equal( self ) return self._equality_comparable @@ -60,7 +59,6 @@ equality_comparable = property( _get_equality_comparable, _set_equality_comparable ) def _get_less_than_comparable( self ): - return False if None is self._less_than_comparable: self._less_than_comparable = declarations.has_public_less( self ) return self._less_than_comparable This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-08 18:48:58
|
Revision: 280 Author: roman_yakovenko Date: 2006-07-08 11:48:46 -0700 (Sat, 08 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=280&view=rev Log Message: ----------- improve readability and bug fix for msvc7.1 operator() Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/calldef.py pyplusplus_dev/pyplusplus/code_creators/class_declaration.py pyplusplus_dev/pyplusplus/code_creators/declaration_based.py Modified: pyplusplus_dev/pyplusplus/code_creators/calldef.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-07-08 18:27:50 UTC (rev 279) +++ pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-07-08 18:48:46 UTC (rev 280) @@ -41,7 +41,7 @@ return algorithm.create_identifier( self, '::boost::python::pure_virtual' ) def param_sep(self): - return os.linesep + self.indent( self.PARAM_SEPARATOR, 2 ) + return os.linesep + self.indent( self.PARAM_SEPARATOR ) def keywords_args(self): boost_arg = algorithm.create_identifier( self, '::boost::python::arg' ) @@ -66,21 +66,34 @@ result.append( ' )' ) return ''.join( result ) - def create_def_code( self ): - return 'def' + def create_def_code( self ): + if not self.works_on_instance: + return '%s.def' % self.parent.class_var_name + else: + return 'def' - def create_function_ref_code( self ): + def create_function_ref_code( self, use_function_alias=False ): raise NotImplementedError() + + def _get_function_type_alias( self ): + return 'function_ptr_t' + function_type_alias = property( _get_function_type_alias ) + def create_function_type_alias_code( self ): + raise NotImplementedError() + def _create_impl( self ): result = [] - result.append( self.create_def_code() ) - result.append( '( ' ) - result.append( os.linesep + self.indent( '"%s"' % self.alias, 2 ) ) + if False == self.works_on_instance: + result.append( self.create_function_type_alias_code() ) + result.append( os.linesep * 2 ) + + result.append( self.create_def_code() + '( ' ) + result.append( os.linesep + self.indent( '"%s"' % self.alias ) ) result.append( self.param_sep() ) - result.append( self.create_function_ref_code() ) + result.append( self.create_function_ref_code( not self.works_on_instance ) ) if self.declaration.use_keywords: result.append( self.param_sep() ) @@ -96,6 +109,15 @@ if not self.works_on_instance: result.append( ';' ) + if not self.works_on_instance: + #indenting and adding scope + code = ''.join( result ) + result = [ '{ //%s' % declarations.full_name( self.declaration ) ] + result.append( os.linesep * 2 ) + result.append( self.indent( code ) ) + result.append( os.linesep * 2 ) + result.append( '}' ) + return ''.join( result ) @@ -164,12 +186,18 @@ def __init__( self, function ): calldef_t.__init__( self, function=function ) self.works_on_instance = False - + def create_def_code( self ): return self.def_identifier() - def create_function_ref_code(self): - if self.declaration.create_with_signature: + def create_function_type_alias_code( self ): + return 'typedef ' + self.declaration.function_type().create_typedef( self.function_type_alias ) + ';' + + def create_function_ref_code(self, use_function_alias=False): + if use_function_alias: + return '%s( &%s )' \ + % ( self.function_type_alias, declarations.full_name( self.declaration ) ) + elif self.declaration.create_with_signature: return '(%s)( &%s )' \ % ( self.declaration.function_type().decl_string , declarations.full_name( self.declaration ) ) @@ -179,9 +207,15 @@ class mem_fun_t( calldef_t ): def __init__( self, function ): calldef_t.__init__( self, function=function ) - - def create_function_ref_code(self): - if self.declaration.create_with_signature: + + def create_function_type_alias_code( self ): + return 'typedef ' + self.declaration.function_type().create_typedef( self.function_type_alias ) + ';' + + def create_function_ref_code(self, use_function_alias=False): + if use_function_alias: + return '%s( &%s )' \ + % ( self.function_type_alias, declarations.full_name( self.declaration ) ) + elif self.declaration.create_with_signature: return '(%s)( &%s )' \ % ( self.declaration.function_type().decl_string , declarations.full_name( self.declaration ) ) @@ -192,9 +226,17 @@ class mem_fun_pv_t( calldef_t ): def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) - - def create_function_ref_code(self): - if self.declaration.create_with_signature: + + def create_function_type_alias_code( self ): + return 'typedef ' + self.declaration.function_type().create_typedef( self.function_type_alias ) + ';' + + def create_function_ref_code(self, use_function_alias=False): + if use_function_alias: + return '%s( %s(&%s) )' \ + % ( self.pure_virtual_identifier() + , self.function_type_alias + , declarations.full_name( self.declaration ) ) + elif self.declaration.create_with_signature: return '%s( (%s)(&%s) )' \ % ( self.pure_virtual_identifier() , self.declaration.function_type().decl_string @@ -251,10 +293,26 @@ class mem_fun_v_t( calldef_t ): def __init__( self, function, wrapper=None ): calldef_t.__init__( self, function=function, wrapper=wrapper ) + self.default_function_type_alias = 'default_' + self.function_type_alias + + def create_function_type_alias_code( self ): + result = [] + result.append( 'typedef ' + self.declaration.function_type().create_typedef( self.function_type_alias ) + ';' ) + if self.wrapper: + result.append( os.linesep ) + result.append( 'typedef ' + self.wrapper.function_type().create_typedef( self.default_function_type_alias ) + ';' ) + return ''.join( result ) - def create_function_ref_code(self): - result = [] - if self.declaration.create_with_signature: + def create_function_ref_code(self, use_function_alias=False): + result = [] + if use_function_alias: + result.append( '%s(&%s)' + % ( self.function_type_alias, declarations.full_name( self.declaration ) ) ) + if self.wrapper: + result.append( self.param_sep() ) + result.append( '%s(&%s)' + % ( self.default_function_type_alias, self.wrapper.default_full_name() ) ) + elif self.declaration.create_with_signature: result.append( '(%s)(&%s)' % ( self.declaration.function_type().decl_string , declarations.full_name( self.declaration ) ) ) @@ -355,8 +413,14 @@ def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) - def create_function_ref_code(self): - if self.declaration.create_with_signature: + def create_function_type_alias_code( self ): + return 'typedef ' + self.wrapper.function_type().create_typedef( self.function_type_alias ) + ';' + + def create_function_ref_code(self, use_function_alias=False): + if use_function_alias: + return '%s( &%s )' \ + % ( self.function_type_alias, self.wrapper.full_name() ) + elif self.declaration.create_with_signature: return '(%s)(&%s)' \ % ( self.wrapper.function_type().decl_string, self.wrapper.full_name() ) else: @@ -419,9 +483,15 @@ class mem_fun_protected_s_t( calldef_t ): def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) - - def create_function_ref_code(self): - if self.declaration.create_with_signature: + + def create_function_type_alias_code( self ): + return 'typedef ' + self.wrapper.function_type().create_typedef( self.function_type_alias ) + ';' + + def create_function_ref_code(self, use_function_alias=False): + if use_function_alias: + return '%s( &%s )' \ + % ( self.function_type_alias, self.wrapper.full_name() ) + elif self.declaration.create_with_signature: return '(%s)(&%s)' \ % ( self.wrapper.function_type().decl_string, self.wrapper.full_name() ) else: @@ -475,9 +545,15 @@ class mem_fun_protected_v_t( calldef_t ): def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) - - def create_function_ref_code(self): - if self.declaration.create_with_signature: + + def create_function_type_alias_code( self ): + return 'typedef ' + self.wrapper.function_type().create_typedef( self.function_type_alias ) + ';' + + def create_function_ref_code(self, use_function_alias=False): + if use_function_alias: + return '%s( &%s )' \ + % ( self.function_type_alias, self.wrapper.full_name() ) + elif self.declaration.create_with_signature: return '(%s)(&%s)' \ % ( self.wrapper.function_type().decl_string, self.wrapper.full_name() ) else: @@ -545,9 +621,15 @@ class mem_fun_protected_pv_t( calldef_t ): def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) + + def create_function_type_alias_code( self ): + return 'typedef ' + self.wrapper.function_type().create_typedef( self.function_type_alias ) + ';' - def create_function_ref_code(self): - if self.declaration.create_with_signature: + def create_function_ref_code(self, use_function_alias=False): + if use_function_alias: + return '%s( &%s )' \ + % ( self.function_type_alias, self.wrapper.full_name() ) + elif self.declaration.create_with_signature: return '(%s)(&%s)' \ % ( self.wrapper.function_type().decl_string, self.wrapper.full_name() ) else: @@ -729,7 +811,10 @@ return ''.join( answer ) def _create_impl( self ): - return 'def( %s )' % self.create_init_code() + code = 'def( %s )' % self.create_init_code() + if not self.works_on_instance: + code = self.parent.class_var_name + '.' + code + ';' + return code class static_method_t( declaration_based.declaration_based_t ): """ Modified: pyplusplus_dev/pyplusplus/code_creators/class_declaration.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-07-08 18:27:50 UTC (rev 279) +++ pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-07-08 18:48:46 UTC (rev 280) @@ -263,6 +263,10 @@ for x in creators: if x is used_init: continue + if isinstance( x, calldef.calldef_t ): + x.works_on_instance = False + result.append( x.create() ) + continue if not x.works_on_instance: result.append( x.create() ) else: @@ -270,9 +274,9 @@ code = os.linesep.join( result ) - result = [ '{ //scope begin' ] + result = [ '{ //%s' % declarations.full_name( self.declaration ) ] result.append( self.indent( code ) ) - result.append( '} //scope end' ) + result.append( '}' ) return os.linesep.join( result ) Modified: pyplusplus_dev/pyplusplus/code_creators/declaration_based.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/declaration_based.py 2006-07-08 18:27:50 UTC (rev 279) +++ pyplusplus_dev/pyplusplus/code_creators/declaration_based.py 2006-07-08 18:48:46 UTC (rev 280) @@ -44,4 +44,5 @@ def _get_decl_identifier( self ): return algorithm.create_identifier( self, self.declaration.decl_string ) - decl_identifier = property( _get_decl_identifier ) \ No newline at end of file + decl_identifier = property( _get_decl_identifier ) + \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-08 18:28:03
|
Revision: 279 Author: roman_yakovenko Date: 2006-07-08 11:27:50 -0700 (Sat, 08 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=279&view=rev Log Message: ----------- updating unittests to new interface of enumeration_t Modified Paths: -------------- pygccxml_dev/unittests/declarations_tester.py pygccxml_dev/unittests/type_traits_tester.py pygccxml_dev/unittests/unnamed_enums_bug_tester.py Modified: pygccxml_dev/unittests/declarations_tester.py =================================================================== --- pygccxml_dev/unittests/declarations_tester.py 2006-07-08 18:26:29 UTC (rev 278) +++ pygccxml_dev/unittests/declarations_tester.py 2006-07-08 18:27:50 UTC (rev 279) @@ -32,8 +32,8 @@ def test_enumeration_t(self): enum = self.global_ns.enum( 'ENumbers' ) - expected_values = dict( zip( [ 'e%d' % index for index in range(10) ] - , [ '%d' % index for index in range(10) ] ) ) + expected_values = zip( [ 'e%d' % index for index in range(10) ] + , [ index for index in range(10) ] ) self.failUnless( expected_values == enum.values , "expected enum values ( '%s' ) and existings ( '%s' ) are different" % \ ( pprint.pformat( expected_values ), pprint.pformat( enum.values ) ) ) Modified: pygccxml_dev/unittests/type_traits_tester.py =================================================================== --- pygccxml_dev/unittests/type_traits_tester.py 2006-07-08 18:26:29 UTC (rev 278) +++ pygccxml_dev/unittests/type_traits_tester.py 2006-07-08 18:27:50 UTC (rev 279) @@ -210,7 +210,7 @@ expected_type = declarations.find_declaration( defs , name='expected' , type=declarations.enumeration_t ) - expected_value = bool( int( expected_type.values['value'] ) ) + expected_value = bool( expected_type.get_name2value_dict()['value'] ) if expected_value != declarations.is_convertible( source_type, target_type ): print decl.name Modified: pygccxml_dev/unittests/unnamed_enums_bug_tester.py =================================================================== --- pygccxml_dev/unittests/unnamed_enums_bug_tester.py 2006-07-08 18:26:29 UTC (rev 278) +++ pygccxml_dev/unittests/unnamed_enums_bug_tester.py 2006-07-08 18:27:50 UTC (rev 279) @@ -26,8 +26,8 @@ def test( self ): names = [] - enums = self.global_ns.enums() - map( lambda enum: names.extend( enum.values.keys() ), enums ) + enums = self.global_ns.enums() + map( lambda enum: names.extend( enum.get_name2value_dict().keys() ), enums ) self.failUnless( len( names ) == 4 ) self.failUnless( 'x1' in names ) self.failUnless( 'x2' in names ) @@ -49,7 +49,7 @@ def test( self ): names = [] enums = self.global_ns.enums() - map( lambda enum: names.extend( enum.values.keys() ), enums ) + map( lambda enum: names.extend( enum.get_name2value_dict().keys() ), enums ) self.failUnless( len( names ) == 4 ) self.failUnless( 'x1' in names ) self.failUnless( 'x2' in names ) @@ -71,7 +71,7 @@ def test( self ): names = [] enums = self.global_ns.enums() - map( lambda enum: names.extend( enum.values.keys() ), enums ) + map( lambda enum: names.extend( enum.get_name2value_dict().keys() ), enums ) self.failUnless( len( names ) == 6 ) self.failUnless( 'x1' in names ) self.failUnless( 'x2' in names ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-08 18:26:37
|
Revision: 278 Author: roman_yakovenko Date: 2006-07-08 11:26:29 -0700 (Sat, 08 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=278&view=rev Log Message: ----------- adding new function get_name2value_dict to enumeration_t Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/decl_printer.py pygccxml_dev/pygccxml/declarations/enumeration.py Modified: pygccxml_dev/pygccxml/declarations/decl_printer.py =================================================================== --- pygccxml_dev/pygccxml/declarations/decl_printer.py 2006-07-08 14:09:08 UTC (rev 277) +++ pygccxml_dev/pygccxml/declarations/decl_printer.py 2006-07-08 18:26:29 UTC (rev 278) @@ -168,7 +168,7 @@ self.writer( ' ' * curr_level * self.INDENT_SIZE + 'values:'.ljust( self.JUSTIFY ) ) value_level = ' ' * ( curr_level + 1 )* self.INDENT_SIZE self.writer( os.linesep ) - for name, value in self.__inst.values.items(): + for name, value in self.__inst.values: self.writer( value_level + "%s : %s"% (name, value) + os.linesep ) def visit_namespace(self ): Modified: pygccxml_dev/pygccxml/declarations/enumeration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/enumeration.py 2006-07-08 14:09:08 UTC (rev 277) +++ pygccxml_dev/pygccxml/declarations/enumeration.py 2006-07-08 18:26:29 UTC (rev 278) @@ -105,5 +105,9 @@ if val==name: return True return False - - + + def get_name2value_dict( self ): + x = {} + for val, num in self._values: + x[val] = num + return x \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-07-08 14:09:14
|
Revision: 277 Author: mbaas Date: 2006-07-08 07:09:08 -0700 (Sat, 08 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=277&view=rev Log Message: ----------- Updates to reflect the changes in enumeration_t (the values are now stored in a list instead of a dict). Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/enum.py pyplusplus_dev/pyplusplus/code_creators/unnamed_enum.py pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py Modified: pyplusplus_dev/pyplusplus/code_creators/enum.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/enum.py 2006-07-08 14:07:13 UTC (rev 276) +++ pyplusplus_dev/pyplusplus/code_creators/enum.py 2006-07-08 14:09:08 UTC (rev 277) @@ -7,10 +7,10 @@ import algorithm import declaration_based -class enum_t( declaration_based.declaration_based_t ): - """ - Creates boost.python code that expose C++ enum +class enum_t( declaration_based.declaration_based_t ): """ + Creates boost.python code that expose C++ enum + """ def __init__(self, enum ): declaration_based.declaration_based_t.__init__( self, declaration=enum) self.works_on_instance = False @@ -39,17 +39,20 @@ % { 'bpl::enum_' : algorithm.create_identifier( self, '::boost::python::enum_' ) , 'name' : algorithm.create_identifier( self, self.declaration.decl_string ) , 'alias' : self.alias } - values = [] - for value_name in self.export_values: + + values = [] + # Add the values that should be exported + for value_name in self.declaration.export_values: values.append( self._generate_value_code( value_name ) ) - - if self.export_values: + + # Export the values + if len(self.declaration.export_values)>0: values.append( '.export_values()' ) - - for name in self.declaration.values.keys(): - if name not in self.export_values: - values.append( self._generate_value_code( name ) ) + # Add the values that should not be exported + for name in self.declaration.no_export_values: + values.append( self._generate_value_code( name ) ) + values.append( ';' ) values = self.indent( os.linesep.join( values ) ) Modified: pyplusplus_dev/pyplusplus/code_creators/unnamed_enum.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/unnamed_enum.py 2006-07-08 14:07:13 UTC (rev 276) +++ pyplusplus_dev/pyplusplus/code_creators/unnamed_enum.py 2006-07-08 14:09:08 UTC (rev 277) @@ -23,7 +23,7 @@ tmpl = algorithm.create_identifier( self, '::boost::python::scope' ) + '().attr("%s") = (int)%s;' full_name = pygccxml.declarations.full_name( self.declaration ) result = [] - for name, value in self.declaration.values.items(): + for name, value in self.declaration.values: result.append( tmpl % ( self.value_aliases.get( name, name ) , algorithm.create_identifier( self, full_name + '::' + name ) ) ) return os.linesep.join( result ) Modified: pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py 2006-07-08 14:07:13 UTC (rev 276) +++ pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py 2006-07-08 14:09:08 UTC (rev 277) @@ -10,22 +10,53 @@ def __init__(self, *arguments, **keywords): declarations.enumeration_t.__init__(self, *arguments, **keywords ) decl_wrapper.decl_wrapper_t.__init__( self ) - + + # A dict with new names for particular enumeration values + # Key: Original name as it appears in the C++ source file + # Value: New name as it should appear in the Python bindings self._value_aliases = {} - #by default export all values + + # A list of enumeration names (C++ names, not aliases!) that should be + # exported. + # By default, export all values self._export_values = None def _get_value_aliases(self): return self._value_aliases def _set_value_aliases(self, value_aliases): self._value_aliases = value_aliases - value_aliases = property( _get_value_aliases, _set_value_aliases ) + value_aliases = property( _get_value_aliases, _set_value_aliases, doc= + """A translation table from C++ enumeration value names to desired Python names. + @type: dict""") def _get_export_values(self): if self._export_values is None: - return self.values.keys() + return map(lambda x: x[0], self.values) else: return self._export_values def _set_export_values(self, export_values): self._export_values = export_values - export_values = property( _get_export_values, _set_export_values ) + export_values = property( _get_export_values, _set_export_values, doc= + """A list of (C++) enumeration names that should be exported. + @type: list""") + + def _get_no_export_values(self): + all_values = map(lambda x: x[0], self.values) + export_values = self.export_values + res = [] + for name in all_values: + if name not in export_values: + res.append(name) + return res + + def _set_no_export_values(self, no_export_values): + all_values = map(lambda x: x[0], self.values) + export_values = [] + for name in all_values: + if name not in no_export_values: + export_values.append(name) + self.export_values = export_values + + no_export_values = property( _get_no_export_values, _set_export_values, doc= + """A list of (C++) enumeration names that should not be exported. + @type: list""") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-07-08 14:07:19
|
Revision: 276 Author: mbaas Date: 2006-07-08 07:07:13 -0700 (Sat, 08 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=276&view=rev Log Message: ----------- Changed the internal storage for enumerations from dict to list so that the original order of the values is maintained. Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/enumeration.py pygccxml_dev/pygccxml/parser/patcher.py pygccxml_dev/pygccxml/parser/scanner.py Modified: pygccxml_dev/pygccxml/declarations/enumeration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/enumeration.py 2006-07-07 18:44:39 UTC (rev 275) +++ pygccxml_dev/pygccxml/declarations/enumeration.py 2006-07-08 14:07:13 UTC (rev 276) @@ -8,17 +8,35 @@ """ import declaration +import copy +import types class enumeration_t( declaration.declaration_t ): """ describes C++ enum """ def __init__( self, name='', parent=None, values=None ): + """Constructor. + + The items of the list 'values' may either be strings containing + the enumeration value name or tuples (name, numvalue). + + @param name: Enum name + @type name: str + @param parent: Parent declaration + @type parent: declaration_t + @param values: Enumeration values + @type values: list + """ declaration.declaration_t.__init__( self, name, parent ) - if not values: - values = {} - self._values = values # dict name(str) -> value(int) + # A list of tuples (valname(str), valnum(int)). The order of the list should + # be the same as the order in the C/C++ source file. + self._values = [] + + # Initialize values via property access + self.values = values + def __eq__(self, other): if not declaration.declaration_t.__eq__( self, other ): return False @@ -28,9 +46,64 @@ return [self.values] def _get_values(self): - return self._values + return copy.copy(self._values) def _set_values(self, values): - self._values = values + self._values = [] + # None is treated like an empty list + if (values==None): + return + # Check that we have indeed a list... + if type(values)!=list: + raise ValueError, "'values' must be a list (got a %s instead)"%type(values).__name__ + # Append the items individually. This has the effect that there's + # some additional type checking and that a copy of 'values' is stored + # and the caller cannot further manipulate the list via his own reference + for item in values: + if isinstance(item, types.StringTypes): + self.append_value(item) + elif type(item)==tuple: + name,num = item + self.append_value(name, num) + else: + raise ValueError, "'values' contains an invalid item: %s"%item values = property( _get_values, _set_values - , doc="dictionary that contains mapping between name and value, { name(str) : value(int) }") + , doc="""A list of tuples (valname(str), valnum(int)) that contain the enumeration values. + @type: list""") + def append_value(self, valuename, valuenum=None): + """Append another enumeration value to the enum. + + The numeric value may be None in which case it is automatically determined by + increasing the value of the last item. + + When the 'values' attribute is accessed the resulting list will be in the same + order as append_value() was called. + + @param valuename: The name of the value. + @type valuename: str + @param valuenum: The numeric value or None. + @type valuenum: int + """ + # No number given? Then use the previous one + 1 + if valuenum==None: + if len(self._values)==0: + valuenum = 0 + else: + valuenum = self._values[-1][1]+1 + + # Store the new value + self._values.append((valuename, int(valuenum))) + + def has_value_name(self, name): + """Check if this enum has a particular name among its values. + + @param name: Enumeration value name + @type name: str + @return: True if there is an enumeration value with the given name + """ + for val,num in self._values: + if val==name: + return True + return False + + Modified: pygccxml_dev/pygccxml/parser/patcher.py =================================================================== --- pygccxml_dev/pygccxml/parser/patcher.py 2006-07-07 18:44:39 UTC (rev 275) +++ pygccxml_dev/pygccxml/parser/patcher.py 2006-07-08 14:07:13 UTC (rev 276) @@ -56,7 +56,7 @@ type_ = declarations.remove_reference( declarations.remove_cv( arg.type ) ) if not declarations.is_enum( type_ ): return False - return type_.declaration.values.has_key( arg.default_value ) + return type_.declaration.has_value_name( arg.default_value ) def __fix_unqualified_enum( self, func, arg): type_ = declarations.remove_reference( declarations.remove_cv( arg.type ) ) @@ -106,9 +106,11 @@ enums = filter( lambda decl: isinstance( decl, declarations.enumeration_t ) , scope.declarations ) for enum_decl in enums: - if default_value in enum_decl.values.keys(): + valnames = map(lambda x: x[0], enum_decl.values) + valnums = map(lambda x: x[1], enum_decl.values) + if default_value in valnames: return enum_decl - if default_value in enum_decl.values.values(): + if default_value in valnums: return enum_decl else: return None @@ -188,4 +190,4 @@ patcher2 = fix_casting_operator_name_patcher_t( decls ) patcher2.patch_it() return patcher.decls - \ No newline at end of file + Modified: pygccxml_dev/pygccxml/parser/scanner.py =================================================================== --- pygccxml_dev/pygccxml/parser/scanner.py 2006-07-07 18:44:39 UTC (rev 275) +++ pygccxml_dev/pygccxml/parser/scanner.py 2006-07-08 14:07:13 UTC (rev 276) @@ -255,7 +255,9 @@ return self.__decl_factory.create_enumeration( name=enum_name ) def __read_enumeration_value( self, attrs ): - self.__inst.values[attrs.get( XML_AN_NAME, '' )] = attrs[XML_AN_INIT] + name = attrs.get( XML_AN_NAME, '' ) + num = int(attrs[XML_AN_INIT]) + self.__inst.append_value(name, num) def __read_array_type( self, attrs ): type_ = attrs[ XML_AN_TYPE ] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-07 18:44:45
|
Revision: 275 Author: roman_yakovenko Date: 2006-07-07 11:44:39 -0700 (Fri, 07 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=275&view=rev Log Message: ----------- another small refactoring before implementing bug fix for msvc 7.1 operator () Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/calldef.py Modified: pyplusplus_dev/pyplusplus/code_creators/calldef.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-07-05 12:55:47 UTC (rev 274) +++ pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-07-07 18:44:39 UTC (rev 275) @@ -66,29 +66,39 @@ result.append( ' )' ) return ''.join( result ) - def append_def_code( self, result ): - result.append( 'def( ' ) - - def append_def_end_code( self, result ): - result.append( ' )' ) - - def append_alias_code( self, result ): - result.append( '"%s"' % self.alias ) - - def append_use_keywords_code( self, result ): - if not self.declaration.use_keywords: - return - result.append( self.param_sep() ) - result.append( self.keywords_args() ) - - def append_call_policies_code( self, result ): - if self.declaration.call_policies: - result.append( self.param_sep() ) - result.append( self.declaration.call_policies.create( self ) ) - else: - result.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) - + def create_def_code( self ): + return 'def' + + def create_function_ref_code( self ): + raise NotImplementedError() + + def _create_impl( self ): + result = [] + + result.append( self.create_def_code() ) + result.append( '( ' ) + result.append( os.linesep + self.indent( '"%s"' % self.alias, 2 ) ) + result.append( self.param_sep() ) + + result.append( self.create_function_ref_code() ) + if self.declaration.use_keywords: + result.append( self.param_sep() ) + result.append( self.keywords_args() ) + + if self.declaration.call_policies: + result.append( self.param_sep() ) + result.append( self.declaration.call_policies.create( self ) ) + else: + result.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) + + result.append( ' )' ) + if not self.works_on_instance: + result.append( ';' ) + + return ''.join( result ) + + class calldef_wrapper_t( declaration_based.declaration_based_t): def __init__(self, function ): declaration_based.declaration_based_t.__init__( self, declaration=function ) @@ -135,7 +145,7 @@ return ', '.join( params ) def wrapped_class_identifier( self ): - return algorithm.create_identifier( self, self.declaration.parent.decl_string ) + return algorithm.create_identifier( self, declarations.full_name( self.declaration.parent ) ) def unoverriden_function_body( self ): msg = r'This function could not be overriden in Python!' @@ -153,86 +163,46 @@ class free_function_t( calldef_t ): def __init__( self, function ): calldef_t.__init__( self, function=function ) - - def _create_impl(self): - param_sep = self.param_sep() - - result = [ self.def_identifier() ] - result.append( '(' ) - - self.append_alias_code( result ) - - result.append( param_sep ) + self.works_on_instance = False + + def create_def_code( self ): + return self.def_identifier() + + def create_function_ref_code(self): if self.declaration.create_with_signature: - result.append( '(%s)( &%s )' - %( self.declaration.function_type().decl_string - , declarations.full_name( self.declaration ) ) ) + return '(%s)( &%s )' \ + % ( self.declaration.function_type().decl_string + , declarations.full_name( self.declaration ) ) else: - result.append( '&%s' % declarations.full_name( self.declaration ) ) - - self.append_use_keywords_code( result ) - self.append_call_policies_code( result ) - - result.append( ' );' ) - return ''.join( result ) + return '&%s' % declarations.full_name( self.declaration ) class mem_fun_t( calldef_t ): def __init__( self, function ): calldef_t.__init__( self, function=function ) - def _create_impl(self): - param_sep = self.param_sep() - - result = [] - - self.append_def_code( result ) - self.append_alias_code( result ) - - result.append( param_sep ) + def create_function_ref_code(self): if self.declaration.create_with_signature: - result.append( '(%s)( &%s )' - %( self.declaration.function_type().decl_string - , declarations.full_name( self.declaration ) ) ) + return '(%s)( &%s )' \ + % ( self.declaration.function_type().decl_string + , declarations.full_name( self.declaration ) ) else: - result.append( '&%s' % declarations.full_name( self.declaration ) ) - - self.append_use_keywords_code( result ) - self.append_call_policies_code( result ) + return '&%s' % declarations.full_name( self.declaration ) - self.append_def_end_code( result ) - - return ''.join( result ) - class mem_fun_pv_t( calldef_t ): def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) - def _create_impl(self): - param_sep = self.param_sep() - - result = [] - - self.append_def_code( result ) - self.append_alias_code( result ) - - result.append( param_sep ) + def create_function_ref_code(self): if self.declaration.create_with_signature: - result.append( '%s( (%s)(&%s) )' - % ( self.pure_virtual_identifier() - , self.declaration.function_type().decl_string - , declarations.full_name( self.declaration ) ) ) + return '%s( (%s)(&%s) )' \ + % ( self.pure_virtual_identifier() + , self.declaration.function_type().decl_string + , declarations.full_name( self.declaration ) ) else: - result.append( '%s( &%s )' - % ( self.pure_virtual_identifier() - , declarations.full_name( self.declaration ) ) ) - - self.append_use_keywords_code( result ) - self.append_call_policies_code( result ) - - self.append_def_end_code( result ) - - return ''.join( result ) + return '%s( &%s )' \ + % ( self.pure_virtual_identifier() + , declarations.full_name( self.declaration ) ) class mem_fun_pv_wrapper_t( calldef_wrapper_t ): def __init__( self, function ): @@ -282,34 +252,21 @@ def __init__( self, function, wrapper=None ): calldef_t.__init__( self, function=function, wrapper=wrapper ) - def _create_impl(self): - param_sep = self.param_sep() - + def create_function_ref_code(self): result = [] - - self.append_def_code( result ) - self.append_alias_code( result ) - - result.append( param_sep ) if self.declaration.create_with_signature: result.append( '(%s)(&%s)' % ( self.declaration.function_type().decl_string , declarations.full_name( self.declaration ) ) ) if self.wrapper: - result.append( param_sep ) + result.append( self.param_sep() ) result.append( '(%s)(&%s)' % ( self.wrapper.function_type().decl_string, self.wrapper.default_full_name() ) ) else: result.append( '&%s'% declarations.full_name( self.declaration ) ) if self.wrapper: - result.append( param_sep ) + result.append( self.param_sep() ) result.append( '&%s' % self.wrapper.default_full_name() ) - - self.append_use_keywords_code( result ) - self.append_call_policies_code( result ) - - self.append_def_end_code( result ) - return ''.join( result ) class mem_fun_v_wrapper_t( calldef_wrapper_t ): @@ -398,29 +355,12 @@ def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) - def _create_impl(self): - param_sep = self.param_sep() - - result = [] - - self.append_def_code( result ) - self.append_alias_code( result ) - - result.append( param_sep ) + def create_function_ref_code(self): if self.declaration.create_with_signature: - result.append( '(%s)(&%s)' - % ( self.wrapper.function_type().decl_string - , self.wrapper.full_name() ) ) + return '(%s)(&%s)' \ + % ( self.wrapper.function_type().decl_string, self.wrapper.full_name() ) else: - result.append( '&%s' % self.wrapper.full_name() ) - - - self.append_use_keywords_code( result ) - self.append_call_policies_code( result ) - - self.append_def_end_code( result ) - - return ''.join( result ) + return '&%s' % self.wrapper.full_name() class mem_fun_protected_wrapper_t( calldef_wrapper_t ): def __init__( self, function ): @@ -480,28 +420,12 @@ def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) - def _create_impl(self): - param_sep = self.param_sep() - - result = [] - - self.append_def_code( result ) - self.append_alias_code( result ) - - result.append( param_sep ) + def create_function_ref_code(self): if self.declaration.create_with_signature: - result.append( '(%s)(&%s)' - % ( self.wrapper.function_type().decl_string - , self.wrapper.full_name() ) ) + return '(%s)(&%s)' \ + % ( self.wrapper.function_type().decl_string, self.wrapper.full_name() ) else: - result.append( '&%s' % self.wrapper.full_name() ) - - self.append_use_keywords_code( result ) - self.append_call_policies_code( result ) - - self.append_def_end_code( result ) - - return ''.join( result ) + return '&%s' % self.wrapper.full_name() class mem_fun_protected_s_wrapper_t( calldef_wrapper_t ): def __init__( self, function ): @@ -552,30 +476,13 @@ def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) - def _create_impl(self): - param_sep = self.param_sep() - - result = [] - - self.append_def_code( result ) - self.append_alias_code( result ) - - result.append( param_sep ) + def create_function_ref_code(self): if self.declaration.create_with_signature: - result.append( '(%s)(&%s)' - % ( self.wrapper.function_type().decl_string, self.wrapper.full_name() ) ) + return '(%s)(&%s)' \ + % ( self.wrapper.function_type().decl_string, self.wrapper.full_name() ) else: - result.append( '&%s' % self.wrapper.full_name() ) - - - self.append_use_keywords_code( result ) - self.append_call_policies_code( result ) - - self.append_def_end_code( result ) - - return ''.join( result ) + return '&%s' % self.wrapper.full_name() - class mem_fun_protected_v_wrapper_t( calldef_wrapper_t ): def __init__( self, function): calldef_wrapper_t.__init__( self, function=function ) @@ -639,29 +546,12 @@ def __init__( self, function, wrapper ): calldef_t.__init__( self, function=function, wrapper=wrapper ) - def _create_impl(self): - param_sep = self.param_sep() - - result = [] - - self.append_def_code( result ) - self.append_alias_code( result ) - - result.append( param_sep ) + def create_function_ref_code(self): if self.declaration.create_with_signature: - result.append( '(%s)(&%s)' - % ( self.wrapper.function_type().decl_string - , self.wrapper.full_name() ) ) + return '(%s)(&%s)' \ + % ( self.wrapper.function_type().decl_string, self.wrapper.full_name() ) else: - result.append( '&%s' % self.wrapper.full_name() ) - - - self.append_use_keywords_code( result ) - self.append_call_policies_code( result ) - - self.append_def_end_code( result ) - - return ''.join( result ) + return '&%s' % self.wrapper.full_name() class mem_fun_protected_pv_wrapper_t( calldef_wrapper_t ): def __init__( self, function): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-05 12:55:53
|
Revision: 274 Author: roman_yakovenko Date: 2006-07-05 05:55:47 -0700 (Wed, 05 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=274&view=rev Log Message: ----------- small refactoring before adding fix for operator() Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/calldef.py Modified: pyplusplus_dev/pyplusplus/code_creators/calldef.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-07-05 08:12:38 UTC (rev 273) +++ pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-07-05 12:55:47 UTC (rev 274) @@ -34,7 +34,7 @@ self._wrapper = new_wrapper wrapper = property( _get_wrapper, _set_wrapper ) - def def_identifier( self ): + def def_identifier( self ): return algorithm.create_identifier( self, '::boost::python::def' ) def pure_virtual_identifier( self ): @@ -65,7 +65,30 @@ result.append( '=%s()' % boost_obj ) result.append( ' )' ) return ''.join( result ) - + + def append_def_code( self, result ): + result.append( 'def( ' ) + + def append_def_end_code( self, result ): + result.append( ' )' ) + + def append_alias_code( self, result ): + result.append( '"%s"' % self.alias ) + + def append_use_keywords_code( self, result ): + if not self.declaration.use_keywords: + return + result.append( self.param_sep() ) + result.append( self.keywords_args() ) + + def append_call_policies_code( self, result ): + if self.declaration.call_policies: + result.append( self.param_sep() ) + result.append( self.declaration.call_policies.create( self ) ) + else: + result.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) + + class calldef_wrapper_t( declaration_based.declaration_based_t): def __init__(self, function ): declaration_based.declaration_based_t.__init__( self, declaration=function ) @@ -136,7 +159,9 @@ result = [ self.def_identifier() ] result.append( '(' ) - result.append( '"%s"' % self.alias ) + + self.append_alias_code( result ) + result.append( param_sep ) if self.declaration.create_with_signature: result.append( '(%s)( &%s )' @@ -144,15 +169,10 @@ , declarations.full_name( self.declaration ) ) ) else: result.append( '&%s' % declarations.full_name( self.declaration ) ) - - if self.declaration.use_keywords: - result.append( param_sep ) - result.append( self.keywords_args() ) - if self.declaration.call_policies: - result.append( param_sep ) - result.append( self.declaration.call_policies.create( self ) ) - else: - result.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) + + self.append_use_keywords_code( result ) + self.append_call_policies_code( result ) + result.append( ' );' ) return ''.join( result ) @@ -163,9 +183,11 @@ def _create_impl(self): param_sep = self.param_sep() - result = [ 'def' ] - result.append( '(' ) - result.append( '"%s"' % self.alias ) + result = [] + + self.append_def_code( result ) + self.append_alias_code( result ) + result.append( param_sep ) if self.declaration.create_with_signature: result.append( '(%s)( &%s )' @@ -173,16 +195,12 @@ , declarations.full_name( self.declaration ) ) ) else: result.append( '&%s' % declarations.full_name( self.declaration ) ) + + self.append_use_keywords_code( result ) + self.append_call_policies_code( result ) + + self.append_def_end_code( result ) - if self.declaration.use_keywords: - result.append( param_sep ) - result.append( self.keywords_args() ) - if self.declaration.call_policies: - result.append( param_sep ) - result.append( self.declaration.call_policies.create( self ) ) - else: - result.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) - result.append( ' )' ) return ''.join( result ) @@ -193,9 +211,11 @@ def _create_impl(self): param_sep = self.param_sep() - result = [ 'def' ] - result.append( '(' ) - result.append( '"%s"' % self.alias ) + result = [] + + self.append_def_code( result ) + self.append_alias_code( result ) + result.append( param_sep ) if self.declaration.create_with_signature: result.append( '%s( (%s)(&%s) )' @@ -207,15 +227,11 @@ % ( self.pure_virtual_identifier() , declarations.full_name( self.declaration ) ) ) - if self.declaration.use_keywords: - result.append( param_sep ) - result.append( self.keywords_args() ) - if self.declaration.call_policies: - result.append( param_sep ) - result.append( self.declaration.call_policies.create( self ) ) - else: - result.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) - result.append( ' )' ) + self.append_use_keywords_code( result ) + self.append_call_policies_code( result ) + + self.append_def_end_code( result ) + return ''.join( result ) class mem_fun_pv_wrapper_t( calldef_wrapper_t ): @@ -269,9 +285,11 @@ def _create_impl(self): param_sep = self.param_sep() - result = [ 'def' ] - result.append( '(' ) - result.append( '"%s"' % self.alias ) + result = [] + + self.append_def_code( result ) + self.append_alias_code( result ) + result.append( param_sep ) if self.declaration.create_with_signature: result.append( '(%s)(&%s)' @@ -286,16 +304,12 @@ if self.wrapper: result.append( param_sep ) result.append( '&%s' % self.wrapper.default_full_name() ) - - if self.declaration.use_keywords: - result.append( param_sep ) - result.append( self.keywords_args() ) - if self.declaration.call_policies: - result.append( param_sep ) - result.append( self.declaration.call_policies.create( self ) ) - else: - result.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) - result.append( ' )' ) + + self.append_use_keywords_code( result ) + self.append_call_policies_code( result ) + + self.append_def_end_code( result ) + return ''.join( result ) class mem_fun_v_wrapper_t( calldef_wrapper_t ): @@ -387,9 +401,11 @@ def _create_impl(self): param_sep = self.param_sep() - result = [ 'def' ] - result.append( '(' ) - result.append( '"%s"' % self.alias ) + result = [] + + self.append_def_code( result ) + self.append_alias_code( result ) + result.append( param_sep ) if self.declaration.create_with_signature: result.append( '(%s)(&%s)' @@ -398,15 +414,12 @@ else: result.append( '&%s' % self.wrapper.full_name() ) - if self.declaration.use_keywords: - result.append( param_sep ) - result.append( self.keywords_args() ) - if self.declaration.call_policies: - result.append( param_sep ) - result.append( self.declaration.call_policies.create( self ) ) - else: - result.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) - result.append( ' )' ) + + self.append_use_keywords_code( result ) + self.append_call_policies_code( result ) + + self.append_def_end_code( result ) + return ''.join( result ) class mem_fun_protected_wrapper_t( calldef_wrapper_t ): @@ -470,9 +483,11 @@ def _create_impl(self): param_sep = self.param_sep() - result = [ 'def' ] - result.append( '(' ) - result.append( '"%s"' % self.alias ) + result = [] + + self.append_def_code( result ) + self.append_alias_code( result ) + result.append( param_sep ) if self.declaration.create_with_signature: result.append( '(%s)(&%s)' @@ -480,16 +495,12 @@ , self.wrapper.full_name() ) ) else: result.append( '&%s' % self.wrapper.full_name() ) - - if self.declaration.use_keywords: - result.append( param_sep ) - result.append( self.keywords_args() ) - if self.declaration.call_policies: - result.append( param_sep ) - result.append( self.declaration.call_policies.create( self ) ) - else: - result.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) - result.append( ' )' ) + + self.append_use_keywords_code( result ) + self.append_call_policies_code( result ) + + self.append_def_end_code( result ) + return ''.join( result ) class mem_fun_protected_s_wrapper_t( calldef_wrapper_t ): @@ -544,9 +555,11 @@ def _create_impl(self): param_sep = self.param_sep() - result = [ 'def' ] - result.append( '(' ) - result.append( '"%s"' % self.alias ) + result = [] + + self.append_def_code( result ) + self.append_alias_code( result ) + result.append( param_sep ) if self.declaration.create_with_signature: result.append( '(%s)(&%s)' @@ -554,15 +567,12 @@ else: result.append( '&%s' % self.wrapper.full_name() ) - if self.declaration.use_keywords: - result.append( param_sep ) - result.append( self.keywords_args() ) - if self.declaration.call_policies: - result.append( param_sep ) - result.append( self.declaration.call_policies.create( self ) ) - else: - result.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) - result.append( ' )' ) + + self.append_use_keywords_code( result ) + self.append_call_policies_code( result ) + + self.append_def_end_code( result ) + return ''.join( result ) @@ -632,9 +642,11 @@ def _create_impl(self): param_sep = self.param_sep() - result = [ 'def' ] - result.append( '(' ) - result.append( '"%s"' % self.alias ) + result = [] + + self.append_def_code( result ) + self.append_alias_code( result ) + result.append( param_sep ) if self.declaration.create_with_signature: result.append( '(%s)(&%s)' @@ -643,15 +655,12 @@ else: result.append( '&%s' % self.wrapper.full_name() ) - if self.declaration.use_keywords: - result.append( param_sep ) - result.append( self.keywords_args() ) - if self.declaration.call_policies: - result.append( param_sep ) - result.append( self.declaration.call_policies.create( self ) ) - else: - result.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) - result.append( ' )' ) + + self.append_use_keywords_code( result ) + self.append_call_policies_code( result ) + + self.append_def_end_code( result ) + return ''.join( result ) class mem_fun_protected_pv_wrapper_t( calldef_wrapper_t ): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-05 08:13:06
|
Revision: 273 Author: roman_yakovenko Date: 2006-07-05 01:12:38 -0700 (Wed, 05 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=273&view=rev Log Message: ----------- renaming value_type to element_type and making it to be a property Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/container_traits.py pygccxml_dev/unittests/vector_traits_tester.py pyplusplus_dev/examples/pyboost_dev/dev/date_time/generate_code.py pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/indexing_suite1.py pyplusplus_dev/pyplusplus/decl_wrappers/indexing_suite2.py pyplusplus_dev/pyplusplus/file_writers/multiple_files.py pyplusplus_dev/pyplusplus/module_creator/creator.py pyplusplus_dev/pyplusplus/module_creator/types_database.py pyplusplus_dev/unittests/indexing_suites_tester.py Modified: pygccxml_dev/pygccxml/declarations/container_traits.py =================================================================== --- pygccxml_dev/pygccxml/declarations/container_traits.py 2006-07-04 13:30:48 UTC (rev 272) +++ pygccxml_dev/pygccxml/declarations/container_traits.py 2006-07-05 08:12:38 UTC (rev 273) @@ -1,23 +1,24 @@ -# Copyright 2004 Roman Yakovenko. -# Distributed under the Boost Software License, Version 1.0. (See -# accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -""" -defines few algorithms, that deals with different properties of std containers -""" - -import calldef -import cpptypes -import namespace -import templates -import class_declaration -import type_traits - +# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +""" +defines few algorithms, that deals with different properties of std containers +""" + +import calldef +import cpptypes +import namespace +import templates +import class_declaration +import type_traits + class container_traits_impl_t: - def __init__( self, container_name, value_type_index ): + def __init__( self, container_name, element_type_index, element_type_typedef ): self.name = container_name - self.value_type_index = value_type_index + self.element_type_index = element_type_index + self.element_type_typedef = element_type_typedef def get_container_or_none( self, type ): """returns reference to the class declaration or None""" @@ -50,22 +51,22 @@ raise TypeError( 'Type "%s" is not instantiation of std::%s' % ( type.decl_string, self.name ) ) return cls - def value_type( self, type ): + def element_type( self, type ): cls = self.class_declaration( type ) if isinstance( cls, class_declaration.class_t ): - value_type = cls.typedef( "value_type", recursive=False ).type + value_type = cls.typedef( self.element_type_typedef, recursive=False ).type return type_traits.remove_declarated( value_type ) else: - value_type_str = templates.args( cls.name )[self.value_type_index] + value_type_str = templates.args( cls.name )[self.element_type_index] ref = type_traits.impl_details.find_value_type( cls.top_parent, value_type_str ) if None is ref: raise RuntimeError( "Unable to find out %s '%s' value type." % ( self.name, cls.decl_string ) ) return ref -def create_traits_class( container_name, value_type_index ): +def create_traits_class( container_name, element_type_index, element_type_typedef ): class xxx_traits: - impl = container_traits_impl_t( container_name, value_type_index ) + impl = container_traits_impl_t( container_name, element_type_index, element_type_typedef ) @staticmethod def is_my_case( type ): @@ -76,34 +77,35 @@ return xxx_traits.impl.class_declaration( type ) @staticmethod - def value_type( type ): - return xxx_traits.impl.value_type( type ) + def element_type( type ): + return xxx_traits.impl.element_type( type ) return xxx_traits -list_traits = create_traits_class( 'list', 0 ) +list_traits = create_traits_class( 'list', 0, 'value_type' ) -deque_traits = create_traits_class( 'deque', 0 ) +deque_traits = create_traits_class( 'deque', 0, 'value_type' ) -queue_traits = create_traits_class( 'queue', 0 ) -priority_queue = create_traits_class( 'priority_queue', 0 ) +queue_traits = create_traits_class( 'queue', 0, 'value_type' ) -vector_traits = create_traits_class( 'vector', 0 ) +priority_queue = create_traits_class( 'priority_queue', 0, 'value_type' ) -stack_traits = create_traits_class( 'stack', 0 ) +vector_traits = create_traits_class( 'vector', 0, 'value_type' ) -map_traits = create_traits_class( 'map', 1 ) -multimap_traits = create_traits_class( 'multimap', 1 ) +stack_traits = create_traits_class( 'stack', 0, 'value_type' ) -hash_map_traits = create_traits_class( 'hash_map', 1 ) -hash_multimap_traits = create_traits_class( 'hash_multimap', 1 ) +map_traits = create_traits_class( 'map', 1, 'mapped_type' ) +multimap_traits = create_traits_class( 'multimap', 1, 'mapped_type' ) -set_traits = create_traits_class( 'set', 0 ) -hash_set_traits = create_traits_class( 'hash_set', 0 ) +hash_map_traits = create_traits_class( 'hash_map', 1, 'mapped_type' ) +hash_multimap_traits = create_traits_class( 'hash_multimap', 1, 'mapped_type' ) -multiset_traits = create_traits_class( 'multiset', 0 ) -hash_multiset_traits = create_traits_class( 'hash_multiset', 0 ) +set_traits = create_traits_class( 'set', 0, 'value_type' ) +hash_set_traits = create_traits_class( 'hash_set', 0, 'value_type' ) +multiset_traits = create_traits_class( 'multiset', 0, 'value_type' ) +hash_multiset_traits = create_traits_class( 'hash_multiset', 0, 'value_type' ) + Modified: pygccxml_dev/unittests/vector_traits_tester.py =================================================================== --- pygccxml_dev/unittests/vector_traits_tester.py 2006-07-04 13:30:48 UTC (rev 272) +++ pygccxml_dev/unittests/vector_traits_tester.py 2006-07-05 08:12:38 UTC (rev 273) @@ -28,7 +28,7 @@ def validate_yes( self, value_type, container ): traits = declarations.vector_traits self.failUnless( traits.is_my_case( container ) ) - self.failUnless( declarations.is_same( value_type, traits.value_type( container ) ) ) + self.failUnless( declarations.is_same( value_type, traits.element_type( container ) ) ) def test_global_ns( self ): value_type = self.global_ns.class_( '_0_' ) Modified: pyplusplus_dev/examples/pyboost_dev/dev/date_time/generate_code.py =================================================================== --- pyplusplus_dev/examples/pyboost_dev/dev/date_time/generate_code.py 2006-07-04 13:30:48 UTC (rev 272) +++ pyplusplus_dev/examples/pyboost_dev/dev/date_time/generate_code.py 2006-07-05 08:12:38 UTC (rev 273) @@ -144,7 +144,7 @@ def is_vector_of_strings( decl ): if not declarations.vector_traits.is_my_case( decl ): return False - return declarations.is_std_string( declarations.vector_traits.value_type(decl) ) + return declarations.is_std_string( declarations.vector_traits.element_type(decl) ) str_vec = mb.class_( is_vector_of_strings ) str_vec.alias = "strings" Modified: pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-07-04 13:30:48 UTC (rev 272) +++ pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-07-05 08:12:38 UTC (rev 273) @@ -30,7 +30,6 @@ this class are never created by the user, instead they are returned by the API. """ - def __init__(self): object.__init__(self) self._alias = None @@ -45,9 +44,11 @@ def _get_alias(self): if not self._alias: - if declarations.templates.is_instantiation( self.name ): + if declarations.templates.is_instantiation( self.name ): + container_aliases = [ 'value_type', 'key_type' ] if isinstance( self, declarations.class_t ) \ - and 1 == len( set( map( lambda typedef: typedef.name, self.aliases ) ) ): + and 1 == len( set( map( lambda typedef: typedef.name, self.aliases ) ) ) \ + and self.aliases[0].name not in container_aliases: self._alias = self.aliases[0].name else: self._alias = self._generate_valid_name() Modified: pyplusplus_dev/pyplusplus/decl_wrappers/indexing_suite1.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/indexing_suite1.py 2006-07-04 13:30:48 UTC (rev 272) +++ pyplusplus_dev/pyplusplus/decl_wrappers/indexing_suite1.py 2006-07-05 08:12:38 UTC (rev 273) @@ -28,17 +28,18 @@ return self.__container_class container_class = property( _get_container_class ) - def value_type(self): - return self.__container_traits.value_type( self.container_class ) + def _get_element_type(self): + return self.__container_traits.element_type( self.container_class ) + element_type = property( _get_element_type ) def _get_no_proxy( self ): if self.__no_proxy is None: - value_type = self.value_type() - if declarations.is_fundamental( value_type ) \ - or declarations.is_enum( value_type ) \ - or declarations.is_std_string( value_type ) \ - or declarations.is_std_wstring( value_type ) \ - or declarations.smart_pointer_traits.is_smart_pointer( value_type ): + element_type = self.element_type + if declarations.is_fundamental( element_type ) \ + or declarations.is_enum( element_type ) \ + or declarations.is_std_string( element_type ) \ + or declarations.is_std_wstring( element_type ) \ + or declarations.smart_pointer_traits.is_smart_pointer( element_type ): self.__no_proxy = True else: self.__no_proxy = False Modified: pyplusplus_dev/pyplusplus/decl_wrappers/indexing_suite2.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/indexing_suite2.py 2006-07-04 13:30:48 UTC (rev 272) +++ pyplusplus_dev/pyplusplus/decl_wrappers/indexing_suite2.py 2006-07-05 08:12:38 UTC (rev 273) @@ -59,8 +59,9 @@ return self._get_container_traits() container_traits = property( _get_container_traits ) - def value_type( self ): - return self.__container_traits.value_type( self.container_class ) + def _get_element_type(self): + return self.__container_traits.element_type( self.container_class ) + element_type = property( _get_element_type ) def _get_call_policies( self ): #TODO find out call policies @@ -73,7 +74,7 @@ if self._default_applied: return self._default_applied = True - #find out what operators are supported by value_type and + #find out what operators are supported by element_type and #then configure the _disable_[methods|groups] pass Modified: pyplusplus_dev/pyplusplus/file_writers/multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-07-04 13:30:48 UTC (rev 272) +++ pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-07-05 08:12:38 UTC (rev 273) @@ -86,11 +86,11 @@ return None if not isinstance( code_creator.declaration.indexing_suite, decl_wrappers.indexing_suite2_t ): return None - value_type = code_creator.declaration.indexing_suite.value_type() + element_type = code_creator.declaration.indexing_suite.element_type class_traits = declarations.class_traits - if not class_traits.is_my_case( value_type ): + if not class_traits.is_my_case( element_type ): return None - value_class = class_traits.get_declaration( value_type ) + value_class = class_traits.get_declaration( element_type ) return self.create_value_traits_header_name( value_class ) def create_source( self, file_name, function_name, creators ): Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-04 13:30:48 UTC (rev 272) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-05 08:12:38 UTC (rev 273) @@ -357,7 +357,7 @@ def _treat_indexing_suite( self ): def create_explanation(cls): msg = '//WARNING: the next line of code will not compile, because "%s" does not have operator== !' - msg = msg % cls.indexing_suite.value_type().decl_string + msg = msg % cls.indexing_suite.element_type.decl_string return code_creators.custom_text_t( msg, False ) def create_cls_cc( cls ): @@ -406,18 +406,18 @@ used_headers.add( isuite[ container_name ] ) cls_creator = create_cls_cc( cls ) - value_type = cls.indexing_suite.value_type() + element_type = cls.indexing_suite.element_type if isuite is isuite1: - if declarations.is_class( value_type ) and not declarations.has_public_equal( value_type ): + if declarations.is_class( element_type ) and not declarations.has_public_equal( element_type ): cls_creator.adopt_creator( create_explanation( cls ) ) cls_creator.adopt_creator( code_creators.indexing_suite1_t(cls) ) else: class_traits = declarations.class_traits - if class_traits.is_my_case( value_type ): - value_cls = class_traits.get_declaration( value_type ) + if class_traits.is_my_case( element_type ): + value_cls = class_traits.get_declaration( element_type ) if not ( value_cls.equality_comparable and value_cls.less_than_comparable ): - value_type_cc = code_creators.value_traits_t( value_cls ) - self.__extmodule.adopt_creator( value_type_cc, self.__extmodule.creators.index( self.__module_body ) ) + element_type_cc = code_creators.value_traits_t( value_cls ) + self.__extmodule.adopt_creator( element_type_cc, self.__extmodule.creators.index( self.__module_body ) ) cls_creator.adopt_creator( code_creators.indexing_suite2_t(cls) ) self.__module_body.adopt_creator( cls_creator ) Modified: pyplusplus_dev/pyplusplus/module_creator/types_database.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/types_database.py 2006-07-04 13:30:48 UTC (rev 272) +++ pyplusplus_dev/pyplusplus/module_creator/types_database.py 2006-07-05 08:12:38 UTC (rev 273) @@ -71,8 +71,7 @@ return False try: - #checking whether value_type could be extracted - container_cls.indexing_suite.value_type() + check_extraction = container_cls.indexing_suite.element_type except RuntimeError, error: msg = 'WARNING: pyplusplus found "%s" instantiation declaration, ' % container_cls.name msg = msg + 'but can not find out value type!' Modified: pyplusplus_dev/unittests/indexing_suites_tester.py =================================================================== --- pyplusplus_dev/unittests/indexing_suites_tester.py 2006-07-04 13:30:48 UTC (rev 272) +++ pyplusplus_dev/unittests/indexing_suites_tester.py 2006-07-05 08:12:38 UTC (rev 273) @@ -24,8 +24,8 @@ def matcher( item, decl ): if not declarations.vector_traits.is_my_case( decl ): return False - value_type = declarations.vector_traits.value_type(decl) - if item is value_type: + element_type = declarations.vector_traits.element_type(decl) + if item is element_type: return True return False This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-04 13:30:55
|
Revision: 272 Author: roman_yakovenko Date: 2006-07-04 06:30:48 -0700 (Tue, 04 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=272&view=rev Log Message: ----------- updating Python location Modified Paths: -------------- pyplusplus_dev/environment.py Modified: pyplusplus_dev/environment.py =================================================================== --- pyplusplus_dev/environment.py 2006-07-02 18:48:46 UTC (rev 271) +++ pyplusplus_dev/environment.py 2006-07-04 13:30:48 UTC (rev 272) @@ -29,8 +29,8 @@ scons.ccflags = ['/MD', '/EHsc', '/GR', '/Zc:wchar_t', '/Zc:forScope' ] boost.libs = 'd:/boost_cvs/bin' boost.include = 'd:/boost_cvs' - python.libs = 'c:/python/libs' - python.include = 'c:/python/include' + python.libs = 'e:/python24/libs' + python.include = 'e:/python24/include' gccxml.executable = 'd:/gccxml_cvs/gccxml-build/bin/release/gccxml.exe' else: scons.suffix = '.so' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-02 18:48:56
|
Revision: 271 Author: roman_yakovenko Date: 2006-07-02 11:48:46 -0700 (Sun, 02 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=271&view=rev Log Message: ----------- fixing some bug in generated code for unnamed enums, that has been declared within class Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/calldef.py pyplusplus_dev/unittests/unnamed_enums_tester.py Modified: pyplusplus_dev/pyplusplus/code_creators/calldef.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-07-02 17:26:30 UTC (rev 270) +++ pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-07-02 18:48:46 UTC (rev 271) @@ -1,4 +1,4 @@ -# Copyright 2004 Roman Yakovenko. +# Copyright 2004 Roman Yakovenko # Distributed under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) @@ -54,7 +54,13 @@ result.append( '("%s")' % arg.name ) if self.declaration.use_default_arguments and arg.default_value: if not declarations.is_pointer( arg.type ) or arg.default_value != '0': - result.append( '=%s' % arg.default_value ) + arg_type_no_alias = declarations.remove_alias( arg.type ) + if declarations.is_fundamental( arg_type_no_alias ) \ + and declarations.is_integral( arg_type_no_alias ) \ + and not arg.default_value.startswith( arg_type_no_alias.decl_string ): + result.append( '=(%s)(%s)' % ( arg_type_no_alias.decl_string, arg.default_value ) ) + else: + result.append( '=%s' % arg.default_value ) else: result.append( '=%s()' % boost_obj ) result.append( ' )' ) Modified: pyplusplus_dev/unittests/unnamed_enums_tester.py =================================================================== --- pyplusplus_dev/unittests/unnamed_enums_tester.py 2006-07-02 17:26:30 UTC (rev 270) +++ pyplusplus_dev/unittests/unnamed_enums_tester.py 2006-07-02 18:48:46 UTC (rev 271) @@ -18,13 +18,6 @@ , unnamed_enums_tester_t.EXTENSION_NAME , *args ) - def customize( self, mb ): - return - #for f in mb.class_( 'enum_user_t' ).member_functions(): - #for arg in f.arguments: - #if arg.default_value: - #arg.default_value = "%s(%s)" % ( arg.type.decl_string, arg.default_value ) - def run_tests(self, module): self.failUnless( module.OK == 1 ) self.failUnless( module.CANCEL == 0 ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-02 17:26:58
|
Revision: 270 Author: roman_yakovenko Date: 2006-07-02 10:26:30 -0700 (Sun, 02 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=270&view=rev Log Message: ----------- integrating cflags patch from Allen Modified Paths: -------------- pygccxml_dev/unittests/autoconfig.py pygccxml_dev/unittests/test_all.py Added Paths: ----------- pygccxml_dev/unittests/data/decl_cache_file1.txt pygccxml_dev/unittests/data/decl_cache_file1_duplicate.txt pygccxml_dev/unittests/data/decl_cache_file2.txt pygccxml_dev/unittests/declarations_cache_tester.py Modified: pygccxml_dev/unittests/autoconfig.py =================================================================== --- pygccxml_dev/unittests/autoconfig.py 2006-07-02 17:25:19 UTC (rev 269) +++ pygccxml_dev/unittests/autoconfig.py 2006-07-02 17:26:30 UTC (rev 270) @@ -13,13 +13,14 @@ gccxml_path = '' data_directory = os.path.abspath( os.path.join( os.curdir, 'data' ) ) +build_dir = os.path.abspath( os.path.join( os.curdir, 'temp' ) ) if 'roman' in getpass.getuser(): if sys.platform == 'win32': gccxml_path = 'd:/gccxml_cvs/gccxml-build/bin/release/gccxml.exe' else: gccxml_path = '/home/roman/gccxml-build/bin/gccxml' - + try: import pygccxml print 'unittests will run on INSTALLED version' @@ -73,4 +74,4 @@ #, 'wstring' #] ) #except ImportError: - #pass \ No newline at end of file + #pass Added: pygccxml_dev/unittests/data/decl_cache_file1.txt =================================================================== --- pygccxml_dev/unittests/data/decl_cache_file1.txt (rev 0) +++ pygccxml_dev/unittests/data/decl_cache_file1.txt 2006-07-02 17:26:30 UTC (rev 270) @@ -0,0 +1 @@ +// Line 1: Test file for declaration_cache testing Added: pygccxml_dev/unittests/data/decl_cache_file1_duplicate.txt =================================================================== --- pygccxml_dev/unittests/data/decl_cache_file1_duplicate.txt (rev 0) +++ pygccxml_dev/unittests/data/decl_cache_file1_duplicate.txt 2006-07-02 17:26:30 UTC (rev 270) @@ -0,0 +1 @@ +// Line 1: Test file for declaration_cache testing Added: pygccxml_dev/unittests/data/decl_cache_file2.txt =================================================================== --- pygccxml_dev/unittests/data/decl_cache_file2.txt (rev 0) +++ pygccxml_dev/unittests/data/decl_cache_file2.txt 2006-07-02 17:26:30 UTC (rev 270) @@ -0,0 +1,2 @@ +// Line 1: Test file for declaration_cache testing +// Line 2: Added: pygccxml_dev/unittests/declarations_cache_tester.py =================================================================== --- pygccxml_dev/unittests/declarations_cache_tester.py (rev 0) +++ pygccxml_dev/unittests/declarations_cache_tester.py 2006-07-02 17:26:30 UTC (rev 270) @@ -0,0 +1,153 @@ +# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import os, sys, unittest, os.path +import autoconfig +import pygccxml.parser +from pygccxml.parser.config import config_t +from pygccxml.parser.declarations_cache import * + +class decl_cache_tester(unittest.TestCase): + def __init__(self, *args ): + unittest.TestCase.__init__(self, *args) + if not os.path.exists( autoconfig.build_dir ): + os.makedirs( autoconfig.build_dir ) + + def test_file_signature(self): + file1 = os.path.join(autoconfig.data_directory, 'decl_cache_file1.txt') + file1_dup = os.path.join(autoconfig.data_directory, 'decl_cache_file1_duplicate.txt') + file2 = os.path.join(autoconfig.data_directory, 'decl_cache_file2.txt') + sig1 = file_signature(file1) + sig1_dup = file_signature(file1_dup) + sig2 = file_signature(file2) + self.assert_(sig1 == sig1_dup) + self.assert_(sig1 != sig2) + + def test_config_signature(self): + diff_cfg_list = self.build_differing_cfg_list() + def_cfg = diff_cfg_list[0] + def_sig = configuration_signature(def_cfg) + + # Test changes that should cause sig changes + for cfg in diff_cfg_list[1:]: + self.assert_(configuration_signature(cfg) != def_sig) + + # Test changes that should not cause sig changes + no_changes = def_cfg.clone() + self.assert_(configuration_signature(no_changes) == def_sig) + + #start_decls_changed = def_cfg.clone() + #start_decls_changed.start_with_declarations = "test object" + #self.assert_(configuration_signature(start_decls_changed) == def_sig) + + verbose_changed = def_cfg.clone() + verbose_changed.verbose = True + self.assert_(configuration_signature(verbose_changed) == def_sig) + + ignore_changed = def_cfg.clone() + ignore_changed.ignore_gccxml_output = True + self.assert_(configuration_signature(ignore_changed) == def_sig) + + def test_cache_interface(self): + cache_file = os.path.join(autoconfig.build_dir, 'decl_cache_test.test_cache_read.cache') + file1 = os.path.join(autoconfig.data_directory, 'decl_cache_file1.txt') + file1_dup = os.path.join(autoconfig.data_directory, 'decl_cache_file1_duplicate.txt') + file2 = os.path.join(autoconfig.data_directory, 'decl_cache_file2.txt') + diff_cfg_list = self.build_differing_cfg_list() + def_cfg = diff_cfg_list[0] + + if os.path.exists(cache_file): + os.remove(cache_file) + + cache = file_cache_t(cache_file) + self.assert_(len(cache._file_cache_t__cache) == 0) + + # test creating new entries for differing files + cache.update(file1, def_cfg, 1,[]) + self.assert_(len(cache._file_cache_t__cache) == 1) + cache.update(file1_dup, def_cfg, 2,[]) + self.assert_(len(cache._file_cache_t__cache) == 1) + cache.update(file2, def_cfg, 3,[]) + self.assert_(len(cache._file_cache_t__cache) == 2) + + self.assert_(cache.cached_value(file1,def_cfg) == 2) + self.assert_(cache.cached_value(file2,def_cfg) == 3) + + # Test reading again + cache.flush() + cache = file_cache_t(cache_file) + self.assert_(len(cache._file_cache_t__cache) == 2) + self.assert_(cache.cached_value(file1,def_cfg) == 2) + self.assert_(cache.cached_value(file2,def_cfg) == 3) + + # Test flushing doesn't happen if we don't touch the cache + cache = file_cache_t(cache_file) + self.assert_(cache.cached_value(file1,def_cfg) == 2) # Read from cache + cache.flush() # should not actually flush + cache = file_cache_t(cache_file) + self.assert_(len(cache._file_cache_t__cache) == 2) + + # Test flush culling + cache = file_cache_t(cache_file) + cache.update(file1_dup, def_cfg, 4,[]) # Modify cache + cache.flush() # should cull off one entry + cache = file_cache_t(cache_file) + self.assert_(len(cache._file_cache_t__cache) == 1) + + + def build_differing_cfg_list(self): + """ Return a list of configurations that all differ. """ + cfg_list = [] + def_cfg = config_t("gccxml_path",'.',['tmp'],['sym'],['unsym'], + None,False,False,"") + cfg_list.append(def_cfg) + + # Test changes that should cause sig changes + gccxml_changed = def_cfg.clone() + gccxml_changed.gccxml_path = "other_path" + cfg_list.append(gccxml_changed) + + wd_changed = def_cfg.clone() + wd_changed.working_directory = "other_dir" + cfg_list.append(wd_changed) + + #inc_changed = def_cfg.clone() + #inc_changed.include_paths = ["/var/tmp"] + #self.assert_(configuration_signature(inc_changed) != def_sig) + inc_changed = config_t("gccxml_path",'.',['/var/tmp'],['sym'],['unsym'], + None,False,False,"") + cfg_list.append(inc_changed) + + #def_changed = def_cfg.clone() + #def_changed.define_symbols = ["symbol"] + #self.assert_(configuration_signature(def_changed) != def_sig) + def_changed = config_t("gccxml_path",'.',['/var/tmp'],['new-sym'],['unsym'], + None,False,False,"") + cfg_list.append(def_changed) + + #undef_changed = def_cfg.clone() + #undef_changed.undefine_symbols = ["symbol"] + #self.assert_(configuration_signature(undef_changed) != def_sig) + undef_changed = config_t("gccxml_path",'.',['/var/tmp'],['sym'],['new-unsym'], + None,False,False,"") + cfg_list.append(undef_changed) + + cflags_changed = def_cfg.clone() + cflags_changed.cflags = "new flags" + cfg_list.append(cflags_changed) + + return cfg_list + + +def create_suite(): + suite = unittest.TestSuite() + suite.addTest( unittest.makeSuite(decl_cache_tester)) + return suite + +def run_suite(): + unittest.TextTestRunner(verbosity=2).run( create_suite() ) + +if __name__ == "__main__": + run_suite() Modified: pygccxml_dev/unittests/test_all.py =================================================================== --- pygccxml_dev/unittests/test_all.py 2006-07-02 17:25:19 UTC (rev 269) +++ pygccxml_dev/unittests/test_all.py 2006-07-02 17:26:30 UTC (rev 270) @@ -36,7 +36,7 @@ import unnamed_enums_bug_tester import vector_traits_tester import string_traits_tester - +import declarations_cache_tester def create_suite(): testers = [ @@ -72,6 +72,7 @@ , unnamed_enums_bug_tester , vector_traits_tester , string_traits_tester + , declarations_cache_tester ] main_suite = unittest.TestSuite() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-02 17:25:33
|
Revision: 269 Author: roman_yakovenko Date: 2006-07-02 10:25:19 -0700 (Sun, 02 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=269&view=rev Log Message: ----------- integrating cflags patch from Allen Modified Paths: -------------- pygccxml_dev/pygccxml/parser/config.py pygccxml_dev/pygccxml/parser/declarations_cache.py pygccxml_dev/pygccxml/parser/directory_cache.py pygccxml_dev/pygccxml/parser/source_reader.py Modified: pygccxml_dev/pygccxml/parser/config.py =================================================================== --- pygccxml_dev/pygccxml/parser/config.py 2006-06-29 13:05:12 UTC (rev 268) +++ pygccxml_dev/pygccxml/parser/config.py 2006-07-02 17:25:19 UTC (rev 269) @@ -28,7 +28,8 @@ , undefine_symbols=None , start_with_declarations=None , verbose=False - , ignore_gccxml_output=False): + , ignore_gccxml_output=False + , cflags=""): """Constructor. """ object.__init__( self ) @@ -53,6 +54,7 @@ self.__verbose = verbose self.__ignore_gccxml_output = ignore_gccxml_output + self.__cflags = cflags def clone(self): return config_t( gccxml_path=self.__gccxml_path @@ -62,7 +64,8 @@ , undefine_symbols=self.__undefine_symbols[:] , start_with_declarations=self.__start_with_declarations[:] , verbose=self.verbose - , ignore_gccxml_output=self.ignore_gccxml_output) + , ignore_gccxml_output=self.ignore_gccxml_output + , cflags=self.cflags) def __get_gccxml_path(self): return self.__gccxml_path @@ -103,3 +106,9 @@ def __set_ignore_gccxml_output(self, val=True): self.__ignore_gccxml_output = val ignore_gccxml_output = property( __get_ignore_gccxml_output, __set_ignore_gccxml_output ) + + def __get_cflags(self): + return self.__cflags + def __set_cflags(self, val): + self.__cflags = val + cflags = property( __get_cflags, __set_cflags ) Modified: pygccxml_dev/pygccxml/parser/declarations_cache.py =================================================================== --- pygccxml_dev/pygccxml/parser/declarations_cache.py 2006-06-29 13:05:12 UTC (rev 268) +++ pygccxml_dev/pygccxml/parser/declarations_cache.py 2006-07-02 17:25:19 UTC (rev 269) @@ -25,33 +25,59 @@ f.close() return sig.hexdigest() +def configuration_signature( config ): + """ Return a signature for a configuration (config_t) + object. This can then be used as a key in the cache. + This method must take into account anything about + a configuration that could cause the declarations generated + to be different between runs. + """ + sig = md5.new() + sig.update(str(config.gccxml_path)) + sig.update(str(config.working_directory)) + sig.update(str(config.cflags)) + for p in config.include_paths: + sig.update(str(p)) + for s in config.define_symbols: + sig.update(str(s)) + for u in config.undefine_symbols: + sig.update(str(u)) + return sig.hexdigest() + class cache_base_t( object ): def __init__( self ): object.__init__(self) def flush(self): + """ Flush (write out) the cache to disk if needed. """ raise NotImplementedError() def update(self, source_file, configuration, declarations, included_files): + """ Update cache entry. + @param source_file: path to the C++ source file being parsed + @param configuration: configuration used in parsing (config_t) + @param declarations: declaration tree found when parsing + @param included_files: files included by parsing. + """ raise NotImplementedError() def cached_value(self, source_file, configuration): - #returns declarations, types + """ Return declarations we have cached for the source_file and configuration + given. + @param source_file: path to the C++ source file being parsed. + @param configuration: configuration to use for parsing (config_t) + """ raise NotImplementedError() class record_t( object ): def __init__( self , source_signature - , working_directory - , include_paths - , define_symbols + , config_signature , included_files , included_files_signature , declarations ): self.__source_signature = source_signature - self.__working_directory = working_directory - self.__include_paths = include_paths - self.__define_symbols = define_symbols + self.__config_signature = config_signature self.__included_files = included_files self.__included_files_signature = included_files_signature self.__declarations = declarations @@ -64,16 +90,11 @@ was_hit = property( _get_was_hit, _set_was_hit ) def key(self): - return ( self.__source_signature - , self.__working_directory - , tuple(self.__include_paths) - , tuple(self.__define_symbols ) ) + return ( self.__source_signature, self.__config_signature) def create_key( source_file, configuration ): return ( file_signature(source_file) - , configuration.working_directory - , tuple( configuration.include_paths ) - , tuple( configuration.define_symbols ) ) + , configuration_signature(configuration)) create_key = staticmethod( create_key ) #def value(self): @@ -97,22 +118,10 @@ return self.__source_signature source_signature = property( __source_signature ) - def __source_file(self): - return self.__source_file - source_file = property( __source_file ) - - def __working_directory(self): - return self.__working_directory - working_directory = property( __working_directory ) - - def __include_paths(self): - return self.__include_paths - include_paths = property( __include_paths ) - - def __define_symbols(self): - return self.__define_symbols - define_symbols = property( __define_symbols ) - + def __config_signature(self): + return self.__config_signature + config_signature = property( __config_signature ) + def __included_files(self): return self.__included_files included_files = property( __included_files ) @@ -134,14 +143,18 @@ """ def __init__( self, name ): + """ + @param name: name of the cache file. + """ cache_base_t.__init__( self ) - self.__name = name - self.__cache = self.__load( self.__name ) + self.__name = name # Name of cache file + self.__cache = self.__load( self.__name ) # Map record_key to record_t self.__needs_flushed = not bool( self.__cache ) # If empty then we need to flush for entry in self.__cache.itervalues(): # Clear hit flags entry.was_hit = False - def __load( file_name ): + def __load( file_name ): + " Load pickled cache from file and return the object. " cache = None if os.path.exists( file_name ) and not os.path.isfile( file_name ): raise RuntimeError( 'Cache should be initialized with valid full file name' ) @@ -165,10 +178,12 @@ __load = staticmethod( __load ) def flush(self): - # Remove entries that did not get a cache hit + # If not marked as needing flushed, then return immediately if not self.__needs_flushed: + logger.info("Cache did not change, ignoring flush.") return + # Remove entries that did not get a cache hit num_removed = 0 for key in self.__cache.keys(): if not self.__cache[key].was_hit: @@ -184,9 +199,7 @@ def update(self, source_file, configuration, declarations, included_files): """ Update a cached record with the current key and value contents. """ record = record_t( source_signature=file_signature(source_file) - , working_directory=configuration.working_directory - , include_paths=configuration.include_paths - , define_symbols=configuration.define_symbols + , config_signature=configuration_signature(configuration) , included_files=included_files , included_files_signature=map( file_signature, included_files) , declarations=declarations Modified: pygccxml_dev/pygccxml/parser/directory_cache.py =================================================================== --- pygccxml_dev/pygccxml/parser/directory_cache.py 2006-06-29 13:05:12 UTC (rev 268) +++ pygccxml_dev/pygccxml/parser/directory_cache.py 2006-07-02 17:25:19 UTC (rev 269) @@ -345,6 +345,7 @@ map(lambda p: m.update(p), config.include_paths) map(lambda p: m.update(p), config.define_symbols) map(lambda p: m.update(p), config.undefine_symbols) + map(lambda p: m.update(p), config.cflags) return m.digest() Modified: pygccxml_dev/pygccxml/parser/source_reader.py =================================================================== --- pygccxml_dev/pygccxml/parser/source_reader.py 2006-06-29 13:05:12 UTC (rev 268) +++ pygccxml_dev/pygccxml/parser/source_reader.py 2006-07-02 17:25:19 UTC (rev 269) @@ -127,6 +127,9 @@ cmd.append( '"%s"' % os.path.normpath( self.__config.gccxml_path ) ) else: cmd.append( '%s' % os.path.normpath( self.__config.gccxml_path ) ) + # Add all cflags passed + if self.__config.cflags != "": + cmd.append(" %s "%self.__config.cflags) #second all additional includes directories cmd.append( ''.join( [' -I"%s"' % search_dir for search_dir in self.__search_directories] ) ) #third all additional defined symbols This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-06-29 13:05:23
|
Revision: 268 Author: roman_yakovenko Date: 2006-06-29 06:05:12 -0700 (Thu, 29 Jun 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=268&view=rev Log Message: ----------- adding bug test case reported by Allen Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/class_declaration.py pyplusplus_dev/unittests/data/unnamed_enums_to_be_exported.hpp pyplusplus_dev/unittests/unnamed_enums_tester.py Modified: pyplusplus_dev/pyplusplus/code_creators/class_declaration.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-06-29 12:02:08 UTC (rev 267) +++ pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-06-29 13:05:12 UTC (rev 268) @@ -49,7 +49,7 @@ typedef_name = self.class_var_name + '_t' result.append( 'typedef ' + self._generate_class_definition() + ' ' + typedef_name + ';') result.append( typedef_name + ' ' + self.class_var_name ) - result[-1] = result[-1] + ' = '+ typedef_name + '(%s);' % self.declaration.alias + result[-1] = result[-1] + ' = '+ typedef_name + '("%s");' % self.declaration.alias result.append( algorithm.create_identifier( self, '::boost::python::scope' ) ) result[-1] = result[-1] + ' ' + scope_var_name Modified: pyplusplus_dev/unittests/data/unnamed_enums_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/unnamed_enums_to_be_exported.hpp 2006-06-29 12:02:08 UTC (rev 267) +++ pyplusplus_dev/unittests/data/unnamed_enums_to_be_exported.hpp 2006-06-29 13:05:12 UTC (rev 268) @@ -9,6 +9,17 @@ namespace unnamed_enums{ enum{ OK=1, CANCEL=0 }; + +struct enum_holder_t{ + enum {ZERO=0, ONE=1, TWO=2 }; +}; + +struct enum_user_t{ + void do_smth1(unsigned param=enum_holder_t::ZERO){}; + void do_smth2(int param=enum_holder_t::ONE){}; + void do_smth3(char param=enum_holder_t::TWO){}; +}; + } Modified: pyplusplus_dev/unittests/unnamed_enums_tester.py =================================================================== --- pyplusplus_dev/unittests/unnamed_enums_tester.py 2006-06-29 12:02:08 UTC (rev 267) +++ pyplusplus_dev/unittests/unnamed_enums_tester.py 2006-06-29 13:05:12 UTC (rev 268) @@ -17,7 +17,14 @@ self , unnamed_enums_tester_t.EXTENSION_NAME , *args ) - + + def customize( self, mb ): + return + #for f in mb.class_( 'enum_user_t' ).member_functions(): + #for arg in f.arguments: + #if arg.default_value: + #arg.default_value = "%s(%s)" % ( arg.type.decl_string, arg.default_value ) + def run_tests(self, module): self.failUnless( module.OK == 1 ) self.failUnless( module.CANCEL == 0 ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-06-29 12:02:17
|
Revision: 267 Author: roman_yakovenko Date: 2006-06-29 05:02:08 -0700 (Thu, 29 Jun 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=267&view=rev Log Message: ----------- compilation bug fix Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/calldef.py Modified: pyplusplus_dev/pyplusplus/code_creators/calldef.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-06-29 12:00:38 UTC (rev 266) +++ pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-06-29 12:02:08 UTC (rev 267) @@ -97,7 +97,7 @@ and not declarations.is_enum( arg_base_type ): params.append( 'boost::ref(%s)' % self.argument_name( index ) ) elif declarations.is_pointer( arg_type ) \ - and not( declarations.is_pointer( arg_type.base ) \ + and not declarations.is_pointer( arg_type.base ) \ and not declarations.is_fundamental( arg_type.base ) \ and not declarations.is_enum( arg_base_type ): params.append( 'boost::python::ptr(%s)' % self.argument_name( index ) ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |