pygccxml-commit Mailing List for C++ Python language bindings (Page 61)
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: <mb...@us...> - 2006-07-24 15:49:38
|
Revision: 341 Author: mbaas Date: 2006-07-24 08:49:30 -0700 (Mon, 24 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=341&view=rev Log Message: ----------- Implemented a new formatter that reformats a message so that long messages are split into several lines. This new 'multi line formatter' is now used for the default stream handler that writes the messages to stdout. Modified Paths: -------------- pyplusplus_dev/pyplusplus/_logging_/__init__.py Added Paths: ----------- pyplusplus_dev/pyplusplus/_logging_/multilineformatter.py Modified: pyplusplus_dev/pyplusplus/_logging_/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/_logging_/__init__.py 2006-07-24 15:48:04 UTC (rev 340) +++ pyplusplus_dev/pyplusplus/_logging_/__init__.py 2006-07-24 15:49:30 UTC (rev 341) @@ -8,23 +8,25 @@ This package contains logging configuration for pyplusplus. Default log level is DEBUG. Default log messages destination is sys.stdout. """ - + import os import sys import logging - -def _create_logger_( name ): - logger = logging.getLogger(name) - __handler = logging.StreamHandler(sys.stdout) - __handler.setFormatter( logging.Formatter( os.linesep + '%(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 ] +from multilineformatter import multi_line_formatter_t + +def _create_logger_( name ): + logger = logging.getLogger(name) + __handler = logging.StreamHandler(sys.stdout) +# __handler.setFormatter( logging.Formatter( os.linesep + '%(levelname)s %(message)s' ) ) + __handler.setFormatter( multi_line_formatter_t( os.linesep + '%(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 ] Added: pyplusplus_dev/pyplusplus/_logging_/multilineformatter.py =================================================================== --- pyplusplus_dev/pyplusplus/_logging_/multilineformatter.py (rev 0) +++ pyplusplus_dev/pyplusplus/_logging_/multilineformatter.py 2006-07-24 15:49:30 UTC (rev 341) @@ -0,0 +1,89 @@ +# 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) + +# Initial version by Matthias Baas (ba...@ir...). + +import os, logging, textwrap + +class multi_line_formatter_t(logging.Formatter): + """Custom log formatter to split long message into several lines. + + This formatter is used for the default stream handler that outputs + its messages to stdout. + """ + + def __init__(self, fmt=None, datefmt=None, width=70): + """Constructor. + + See the Python standard library reference for a documentation + of fmt and datefmt. + width is the maximum width of the generated text blocks. + """ + logging.Formatter.__init__(self, fmt, datefmt) + self._width = width + + def format(self, record): + """This method overwrites the original one. + + The first thing that is done in the original format() method + is the creation of the record.message attribute: + + record.message = record.getMessage() + + Now this method temporarily replaces the getMessage() method of + the record by a version that returns a pregenerated message that + spans several lines. Then the original format() method is called + which will invoke the 'fake' method. + """ + # Get the original single-line message + message = record.getMessage() + # Distribute the message among several lines... + message = self.formatMessage(message, width=self._width) + # ...and temporarily replace the getMessage() method so that the + # reformatted message is used + mth = record.getMessage + record.getMessage = lambda x=message: x + # Invoke the inherited format() method + res = logging.Formatter.format(self, record) + # Restore the original method + record.getMessage = mth + return res + + @staticmethod + def formatMessage(msgline, width=70): + """Format a long single line message so that it is easier to read. + + msgline is a string containing a single message. It can either be + a plain message string which is reformatted using the textwrap + module or it can be of the form <decl>;<msg> where <decl> is the + declaration string and <msg> an arbitrary message. Lines of this + form will be separated so that the declaration and the message + appear in individual text blocks separated by the string '->'. + + In any case the return string will be indented except for the first + line. + + width is the maximum width of any text blocks (without indendation). + """ + txts = msgline.split(";") + # Ensure that there are no more than two items in txts + if len(txts)>2: + txts = [txts[0], ";".join(txts[1:])] + + # Insert a separator if there are two parts (=decl and msg) + if len(txts)==2: + txts.insert(1, "->") + + # Apply the text wrapper to shorten the maximum line length + lines = [] + for txt in txts: + txt = txt.strip().replace(os.linesep, " ") + lines.extend(textwrap.wrap(txt, width)) + + # Indent the text (except for the first line) + lines[1:] = map(lambda s: (2*" ")+s, lines[1:]) + return os.linesep.join(lines) + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mb...@us...> - 2006-07-24 15:48:15
|
Revision: 340 Author: mbaas Date: 2006-07-24 08:48:04 -0700 (Mon, 24 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=340&view=rev Log Message: ----------- Write the warnings as one single line (<decl>;<msg>). 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-24 14:33:50 UTC (rev 339) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-24 15:48:04 UTC (rev 340) @@ -151,12 +151,12 @@ if reason in DO_NOT_REPORT_MSGS: continue readme = readme[1:] - msg = [ 'Declaration "%s" could not be exported.' % decl ] - msg.append( reason.replace( os.linesep, os.linesep + '\t' ) ) - self.decl_logger.warn( os.linesep.join( msg ) ) + msgstr = "%s;%s"%(decl, reason.replace(os.linesep, " ")) + self.decl_logger.warn( msgstr ) for msg in readme: - self.decl_logger.warn( 'Declaration "%s": %s' % ( decl, msg ) ) + msgstr = "%s;%s"%(decl, msg.replace(os.linesep, " ")) + self.decl_logger.warn( msgstr ) #leave only declarations defined under namespace, but remove namespaces decls = filter( lambda x: not isinstance( x, declarations.namespace_t ) \ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-24 14:33:58
|
Revision: 339 Author: roman_yakovenko Date: 2006-07-24 07:33:50 -0700 (Mon, 24 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=339&view=rev Log Message: ----------- adding functionality for "huge classes" feature Modified Paths: -------------- pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py pyplusplus_dev/pyplusplus/file_writers/multiple_files.py Modified: pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-07-24 09:06:59 UTC (rev 338) +++ pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-07-24 14:33:50 UTC (rev 339) @@ -31,9 +31,9 @@ self.internal_splitters = [ self.split_internal_enums , self.split_internal_unnamed_enums - #, self.split_internal_member_functions + , self.split_internal_member_functions , self.split_internal_classes - #, self.split_internal_member_variables + , self.split_internal_member_variables ] def split_class_impl( self, class_creator): @@ -67,31 +67,18 @@ self.split_header_names.append(header_name) self.split_method_names.append(function_name) + def wrapper_header( self, class_creator ): + return os.path.join( class_creator.alias, 'wrapper' + self.HEADER_EXT ) + def write_wrapper( self, class_creator ): answer = [] if self.extmodule.license: answer.append( self.extmodule.license.create() ) - - # Include all 'global' include files... - include_creators = filter( lambda creator: isinstance( creator, code_creators.include_t ) - , self.extmodule.creators ) - includes = map( lambda include_creator: include_creator.create() - , include_creators ) - - # Write all 'global' namespace_alias_t and namespace_using_t creators first... - affect_creators = filter( lambda x: isinstance( x, code_creators.namespace_alias_t ) - or isinstance( x, code_creators.namespace_using_t ) - , self.extmodule.creators ) + + answer.append( self.create_include_code( [class_creator] ) ) + answer.append( '' ) + answer.append( self.create_namespaces_code( [class_creator] ) ) - affect_creators.extend( filter( lambda x: isinstance( x, code_creators.namespace_alias_t ) - or isinstance( x, code_creators.namespace_using_t ) - , self.extmodule.body.creators ) ) - - namespace_aliases = map( lambda creator: creator.create(), affect_creators ) - if namespace_aliases: - answer.append( '' ) - answer.append( os.linesep.join(namespace_aliases) ) - if class_creator.wrapper: answer.append( class_creator.wrapper.create() ) class_creator.wrapper.create = lambda: '' @@ -101,28 +88,54 @@ code = os.linesep.join( answer ) wrapper_code = self.create_header( class_creator.alias + '_wrapper', code ) - header_file = os.path.join( self.directory_path, class_creator.alias, 'wrapper' + self.HEADER_EXT ) + header_file = os.path.join( self.directory_path, self.wrapper_header(class_creator) ) self.write_file( header_file, wrapper_code ) def split_internal_creators( self, class_creator, creators, pattern ): file_path = os.path.join( self.directory_path , class_creator.alias , pattern ) - - function_name = 'register_%s_%s' % ( class_creator.alias, pattern ) + + function_name = 'register_%(cls_alias)s_%(pattern)s' \ + % { 'cls_alias' : class_creator.alias, 'pattern' : pattern } + + function_decl = 'void %(fname)s( %(exposer_type)s& %(var_name)s )' \ + % { 'fname' : function_name + , 'exposer_type' : class_creator.typedef_name + , 'var_name' : class_creator.class_var_name } + + #writting header file + header_code = [ '#include "%s"' % self.wrapper_header( class_creator ) ] + header_code.append( '' ) + header_code.append( function_decl + ';' ) + self.write_file( file_path + self.HEADER_EXT + , self.create_header( pattern, os.linesep.join(header_code) ) ) - self.write_file( file_path + self.HEADER_EXT - , self.create_header( pattern, self.create_function_code( function_name ) ) ) + #writting source file + source_code = [] + if self.extmodule.license: + source_code.append( self.extmodule.license.create() ) + + head_headers = [ file_path + self.HEADER_EXT ]#relevant header file + tail_headers = [ self.wrapper_header(class_creator) ] + source_code.append( self.create_include_code( creators, head_headers, tail_headers ) ) - self.write_file( file_path + self.SOURCE_EXT - , self.create_source( pattern - , function_name - , creators )) + source_code.append( '' ) + source_code.append( self.create_namespaces_code( creators ) ) + + # Write the register() function... + source_code.append( '' ) + source_code.append( '%s{' % function_decl ) + source_code.append( '' ) for index, creator in enumerate( creators ): + source_code.append( code_creators.code_creator_t.indent( creator.create() ) ) + source_code.append( '' ) if 0 == index: - creator.create = lambda: function_name + '();' - else: - creator.create = lambda: '' + creator.create = lambda: function_name + '(%s);' % class_creator.class_var_name + else: + creator.create = lambda: '' + source_code.append( '}' ) + self.write_file( file_path + self.SOURCE_EXT, os.linesep.join( source_code ) ) def split_internal_enums( self, class_creator ): """Write all enumerations into a separate .h/.cpp file. @@ -174,30 +187,32 @@ , self.create_function_code( function_name ) ) ) self.write_wrapper( class_creator ) - wrapper_include = code_creators.include_t( os.path.join( class_creator.alias, 'wrapper' + self.HEADER_EXT ) ) - extmodule.adopt_include( wrapper_include ) - - include_creators = [ wrapper_include ] - splitter_includes = [] + tail_headers = [] for splitter in self.internal_splitters: pattern = splitter( class_creator ) - include_creator = code_creators.include_t( os.path.join( class_creator.alias, pattern + self.HEADER_EXT ) ) - splitter_includes.append( include_creator ) + tail_headers.append( os.path.join( class_creator.alias, pattern + self.HEADER_EXT ) ) - for creator in splitter_includes: - extmodule.adopt_include( creator ) + #writting source file + source_code = [] + if self.extmodule.license: + source_code.append( self.extmodule.license.create() ) + + source_code.append( self.create_include_code( [class_creator], tail_headers=tail_headers ) ) - # Write the .cpp file... - cpp_code = self.create_source( class_creator.alias - , function_name - , [class_creator] ) - - self.write_file( file_path + self.SOURCE_EXT, cpp_code ) - - extmodule.remove_creator( wrapper_include ) - for creator in splitter_includes: - extmodule.remove_creator( creator ) + source_code.append( '' ) + source_code.append( self.create_namespaces_code( [class_creator] ) ) + + # Write the register() function... + source_code.append( '' ) + source_code.append( 'void %s{' % function_name ) + source_code.append( '' ) + for creator in class_creator.creators: + source_code.append( code_creators.code_creator_t.indent( creator.create() ) ) + source_code.append( '' ) + source_code.append( '}' ) + self.write_file( file_path + self.SOURCE_EXT, os.linesep.join( source_code ) ) + # Replace the create() method so that only the register() method is called # (this is called later for the main source file). class_creator.create = lambda: function_name +'();' Modified: pyplusplus_dev/pyplusplus/file_writers/multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-07-24 09:06:59 UTC (rev 338) +++ pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-07-24 14:33:50 UTC (rev 339) @@ -90,7 +90,38 @@ return None value_class = class_traits.get_declaration( element_type ) return self.create_value_traits_header_name( value_class ) - + + def create_include_code( self, creators, head_headers=None, tail_headers=None ): + answer = [] + if head_headers: + answer.extend( map( lambda header: '#include "%s"' % header, head_headers ) ) + + # Include all 'global' include files... + includes = filter( lambda creator: isinstance( creator, code_creators.include_t ) + , self.extmodule.creators ) + answer.extend( map( lambda creator: creator.create(), includes ) ) + + for creator in creators: + header = self.find_out_value_traits_header( creator ) + if header: + answer.append( '#include "%s"' % header ) + + if tail_headers: + answer.extend( map( lambda header: '#include "%s"' % header, tail_headers ) ) + + return os.linesep.join( answer ) + + def create_namespaces_code( self, creators ): + # Write all 'global' namespace_alias_t and namespace_using_t creators first... + ns_types = ( code_creators.namespace_alias_t, code_creators.namespace_using_t ) + ns_creators = filter( lambda x: isinstance( x, ns_types ), self.extmodule.creators ) + + ns_creators.extend( filter( lambda x: isinstance( x, ns_types ), self.extmodule.body.creators ) ) + if not ns_creators: + return '' + else: + return os.linesep.join( map( lambda creator: creator.create(), ns_creators ) ) + def create_source( self, file_name, function_name, registration_creators, declaration_creators=None ): """Return the content of a cpp file. @@ -111,35 +142,13 @@ answer = [] if self.extmodule.license: answer.append( self.extmodule.license.create() ) - - answer.append( '#include "%s%s"' % ( file_name, self.HEADER_EXT ) ) - - # Include all 'global' include files... - include_creators = filter( lambda creator: isinstance( creator, code_creators.include_t ) - , self.extmodule.creators ) - includes = map( lambda include_creator: include_creator.create() - , include_creators ) - - for creator in registration_creators: - value_traits_header = self.find_out_value_traits_header( creator ) - if value_traits_header: - includes.append( '#include "%s"' % value_traits_header ) - answer.append( os.linesep.join(includes) ) - - # Write all 'global' namespace_alias_t and namespace_using_t creators first... - affect_creators = filter( lambda x: isinstance( x, code_creators.namespace_alias_t ) - or isinstance( x, code_creators.namespace_using_t ) - , self.extmodule.creators ) - - affect_creators.extend( filter( lambda x: isinstance( x, code_creators.namespace_alias_t ) - or isinstance( x, code_creators.namespace_using_t ) - , self.extmodule.body.creators ) ) - - namespace_aliases = map( lambda creator: creator.create(), affect_creators ) - if namespace_aliases: - answer.append( '' ) - answer.append( os.linesep.join(namespace_aliases) ) - + + head_headers = [ file_name + self.HEADER_EXT ] + answer.append( self.create_include_code( creators, head_headers ) ) + + answer.append( '' ) + answer.append( self.create_namespaces_code( creators ) ) + # Write wrapper classes... for creator in declaration_creators: answer.append( '' ) @@ -147,7 +156,8 @@ # Write the register() function... answer.append( '' ) - answer.append( 'void %s(){' % function_name ) + answer.append( 'void %s(){' % function_name ) + answer.append( '' ) for creator in registration_creators: answer.append( code_creators.code_creator_t.indent( creator.create() ) ) answer.append( '' ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-24 09:07:11
|
Revision: 338 Author: roman_yakovenko Date: 2006-07-24 02:06:59 -0700 (Mon, 24 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=338&view=rev Log Message: ----------- fixing bug reported by Matthias suspicious_type( type_ ) will not check self.return_type any more Modified Paths: -------------- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py pyplusplus_dev/unittests/algorithms_tester.py Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-23 19:58:46 UTC (rev 337) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-24 09:06:59 UTC (rev 338) @@ -122,7 +122,7 @@ def _readme_impl( self ): def suspicious_type( type_ ): - if not declarations.is_reference( self.return_type ): + if not declarations.is_reference( type_ ): return False type_no_ref = declarations.remove_reference( type_ ) return not declarations.is_const( type_no_ref ) \ Modified: pyplusplus_dev/unittests/algorithms_tester.py =================================================================== --- pyplusplus_dev/unittests/algorithms_tester.py 2006-07-23 19:58:46 UTC (rev 337) +++ pyplusplus_dev/unittests/algorithms_tester.py 2006-07-24 09:06:59 UTC (rev 338) @@ -107,7 +107,7 @@ int do_smth(int); typedef int Int; struct data_t{ - int operator--(); + data_t& operator--(int a); }; } """ @@ -119,7 +119,7 @@ fun = xxx.calldef( 'do_smth' ) self.failUnless( fun.readme() == [] ) minus_minus = xxx.operator( symbol='--' ) - self.failUnless( 1 == len( minus_minus.readme() ) ) + self.failUnless( 1 == len( minus_minus.readme() ), os.linesep.join( minus_minus.readme() ) ) class class_multiple_files_tester_t(unittest.TestCase): CLASS_DEF = \ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-23 19:58:54
|
Revision: 337 Author: roman_yakovenko Date: 2006-07-23 12:58:46 -0700 (Sun, 23 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=337&view=rev Log Message: ----------- adding new functionality for class_multiple_writers.py Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/class_declaration.py pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py Modified: pyplusplus_dev/pyplusplus/code_creators/class_declaration.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-07-23 18:50:43 UTC (rev 336) +++ pyplusplus_dev/pyplusplus/code_creators/class_declaration.py 2006-07-23 19:58:46 UTC (rev 337) @@ -42,14 +42,16 @@ return True return bool( filter( lambda cc: not cc.works_on_instance, self.creators ) ) + @property + def typedef_name( self ): + return self.class_var_name + '_t' def _generate_code_with_scope(self): result = [] scope_var_name = self.alias + '_scope' - 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.append( 'typedef ' + self._generate_class_definition() + ' ' + self.typedef_name + ';') + result.append( self.typedef_name + ' ' + self.class_var_name ) + result[-1] = result[-1] + ' = '+ self.typedef_name + '("%s");' % self.declaration.alias result.append( algorithm.create_identifier( self, '::boost::python::scope' ) ) result[-1] = result[-1] + ' ' + scope_var_name @@ -241,17 +243,25 @@ def _get_class_var_name(self): return self.alias + '_exposer' class_var_name = property( _get_class_var_name ) + + @property + def typedef_name( self ): + return self.class_var_name + '_t' + def create_typedef_code( self ): + base_classes, base_creators = self._exported_base_classes() + return 'typedef ' + self._generate_class_definition(base_creators) + ' ' + self.typedef_name + ';' + + def _generate_code_with_scope(self): result = [] scope_var_name = self.alias + '_scope' - typedef_name = self.class_var_name + '_t' base_classes, base_creators = self._exported_base_classes() - result.append( 'typedef ' + self._generate_class_definition(base_creators) + ' ' + typedef_name + ';') - result.append( typedef_name + ' ' + self.class_var_name ) + result.append( 'typedef ' + self._generate_class_definition(base_creators) + ' ' + self.typedef_name + ';') + result.append( self.typedef_name + ' ' + self.class_var_name ) result[-1] = result[-1] + ' = ' class_constructor, used_init = self._generate_constructor() - result[-1] = result[-1] + typedef_name + class_constructor + result[-1] = result[-1] + self.typedef_name + class_constructor result[-1] = result[-1] + ';' result.append( algorithm.create_identifier( self, '::boost::python::scope' ) ) Modified: pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-07-23 18:50:43 UTC (rev 336) +++ pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-07-23 19:58:46 UTC (rev 337) @@ -67,13 +67,40 @@ self.split_header_names.append(header_name) self.split_method_names.append(function_name) - def write_wrapper( self, class_creator ): - code = '' + def write_wrapper( self, class_creator ): + answer = [] + if self.extmodule.license: + answer.append( self.extmodule.license.create() ) + + # Include all 'global' include files... + include_creators = filter( lambda creator: isinstance( creator, code_creators.include_t ) + , self.extmodule.creators ) + includes = map( lambda include_creator: include_creator.create() + , include_creators ) + + # Write all 'global' namespace_alias_t and namespace_using_t creators first... + affect_creators = filter( lambda x: isinstance( x, code_creators.namespace_alias_t ) + or isinstance( x, code_creators.namespace_using_t ) + , self.extmodule.creators ) + + affect_creators.extend( filter( lambda x: isinstance( x, code_creators.namespace_alias_t ) + or isinstance( x, code_creators.namespace_using_t ) + , self.extmodule.body.creators ) ) + + namespace_aliases = map( lambda creator: creator.create(), affect_creators ) + if namespace_aliases: + answer.append( '' ) + answer.append( os.linesep.join(namespace_aliases) ) + if class_creator.wrapper: - code = class_creator.wrapper.create() - class_creator.wrapper.create = lambda: '' + answer.append( class_creator.wrapper.create() ) + class_creator.wrapper.create = lambda: '' + + answer.append( '' ) + answer.append( class_creator.create_typedef_code() ) - wrapper_code = self.create_header( class_creator.alias + '_wrapper', code ) + code = os.linesep.join( answer ) + wrapper_code = self.create_header( class_creator.alias + '_wrapper', code ) header_file = os.path.join( self.directory_path, class_creator.alias, 'wrapper' + self.HEADER_EXT ) self.write_file( header_file, wrapper_code ) @@ -132,9 +159,10 @@ def split_class_impl( self, class_creator): if not class_creator.declaration in self.huge_classes: return super( class_multiple_files_t, self ).split_class_impl( class_creator ) - + + class_creator.declaration.always_expose_using_scope = True extmodule = class_creator.top_parent - + self.create_dir( os.path.join( self.directory_path, class_creator.alias ) ) function_name = 'register_%s_class' % class_creator.alias This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-23 18:50:50
|
Revision: 336 Author: roman_yakovenko Date: 2006-07-23 11:50:43 -0700 (Sun, 23 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=336&view=rev Log Message: ----------- adding new unit test for bug reported by Matthias Modified Paths: -------------- pyplusplus_dev/unittests/algorithms_tester.py Modified: pyplusplus_dev/unittests/algorithms_tester.py =================================================================== --- pyplusplus_dev/unittests/algorithms_tester.py 2006-07-23 13:25:56 UTC (rev 335) +++ pyplusplus_dev/unittests/algorithms_tester.py 2006-07-23 18:50:43 UTC (rev 336) @@ -99,6 +99,27 @@ mem_funs = arr.calldefs( 'x', arg_types=[None,None] ) for x in mem_funs: self.failUnless( x.exportable == False ) + +class readme_tester_t( unittest.TestCase ): + CODE = \ + """ + namespace xxx{ + int do_smth(int); + typedef int Int; + struct data_t{ + int operator--(); + }; + } + """ + def test(self): + mb = module_builder.module_builder_t( + [ module_builder.create_text_fc( self.CODE )] + , gccxml_path=autoconfig.gccxml.executable ) + xxx = mb.namespace( name='xxx' ) + fun = xxx.calldef( 'do_smth' ) + self.failUnless( fun.readme() == [] ) + minus_minus = xxx.operator( symbol='--' ) + self.failUnless( 1 == len( minus_minus.readme() ) ) class class_multiple_files_tester_t(unittest.TestCase): CLASS_DEF = \ @@ -129,12 +150,13 @@ def create_suite(): suite = unittest.TestSuite() - #~ suite.addTest( unittest.makeSuite(class_organizer_tester_t)) - #~ suite.addTest( unittest.makeSuite(indent_tester_t)) - #~ suite.addTest( unittest.makeSuite(make_flatten_tester_t)) - #~ suite.addTest( unittest.makeSuite(creator_finder_tester_t)) - #~ suite.addTest( unittest.makeSuite(exclude_function_with_array_arg_tester_t)) - suite.addTest( unittest.makeSuite(class_multiple_files_tester_t)) + suite.addTest( unittest.makeSuite(class_organizer_tester_t)) + suite.addTest( unittest.makeSuite(indent_tester_t)) + suite.addTest( unittest.makeSuite(make_flatten_tester_t)) + suite.addTest( unittest.makeSuite(creator_finder_tester_t)) + suite.addTest( unittest.makeSuite(exclude_function_with_array_arg_tester_t)) + suite.addTest( unittest.makeSuite(class_multiple_files_tester_t)) + suite.addTest( unittest.makeSuite(readme_tester_t)) return suite This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-23 13:26:14
|
Revision: 335 Author: roman_yakovenko Date: 2006-07-23 06:25:56 -0700 (Sun, 23 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=335&view=rev Log Message: ----------- adding initial support for huge classes Modified Paths: -------------- pyplusplus_dev/pyplusplus/file_writers/__init__.py pyplusplus_dev/pyplusplus/file_writers/multiple_files.py pyplusplus_dev/pyplusplus/module_builder/builder.py pyplusplus_dev/unittests/algorithms_tester.py Added Paths: ----------- pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py Modified: pyplusplus_dev/pyplusplus/file_writers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/__init__.py 2006-07-23 06:02:19 UTC (rev 334) +++ pyplusplus_dev/pyplusplus/file_writers/__init__.py 2006-07-23 13:25:56 UTC (rev 335) @@ -18,7 +18,8 @@ import types from writer import writer_t from single_file import single_file_t -from multiple_files import multiple_files_t +from multiple_files import multiple_files_t +from class_multiple_files import class_multiple_files_t def write_file( data, file_path ): if isinstance( data, types.StringTypes ): @@ -29,4 +30,8 @@ def write_multiple_files( extmodule, dir_path ): mfs = multiple_files_t( extmodule, dir_path ) - mfs.write() \ No newline at end of file + mfs.write() + +def write_class_multiple_files( extmodule, dir_path, huge_classes ): + mfs = class_multiple_files_t( extmodule, dir_path, huge_classes ) + mfs.write() \ No newline at end of file Added: pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py (rev 0) +++ pyplusplus_dev/pyplusplus/file_writers/class_multiple_files.py 2006-07-23 13:25:56 UTC (rev 335) @@ -0,0 +1,178 @@ +# 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 writer +import multiple_files +from sets import Set as set +from pygccxml import declarations +from pyplusplus import decl_wrappers +from pyplusplus import code_creators + +#TODO: to add namespace_alias_t classes +class class_multiple_files_t(multiple_files.multiple_files_t): + """ + This class will split code, generated for huge classes, to few files. + Next strategy will be used: + 1. New directory with class alias name will be created. + 2. pyplusplus will generate + wrapper header - header that will contain code generated for class wrappers + classes h/cpp - will contain registration code for internal classes + memfun h/cpp - will contain registration code for member functions + + alias + _main h/cpp this class will contain main registration function. + """ + + def __init__(self, extmodule, directory_path, huge_classes): + multiple_files.multiple_files_t.__init__(self, extmodule, directory_path) + self.huge_classes = huge_classes + self.internal_splitters = [ + self.split_internal_enums + , self.split_internal_unnamed_enums + #, self.split_internal_member_functions + , self.split_internal_classes + #, self.split_internal_member_variables + ] + + def split_class_impl( self, class_creator): + function_name = 'register_%s_class' % class_creator.alias + file_path = os.path.join( self.directory_path, class_creator.alias ) + # Write the .h file... + header_name = file_path + self.HEADER_EXT + self.write_file( header_name + , self.create_header( class_creator.alias + , self.create_function_code( function_name ) ) ) + class_wrapper = None + decl_creators = None + if isinstance( class_creator, code_creators.class_t ) and class_creator.wrapper: + class_wrapper = class_creator.wrapper + decl_creators = [ class_creator.wrapper ] + # Write the .cpp file... + cpp_code = self.create_source( class_creator.alias + , function_name + , [class_creator] + , decl_creators ) + self.write_file( file_path + self.SOURCE_EXT, cpp_code ) + if class_wrapper: + # The wrapper has already been written above, so replace the create() + # method with a new 'method' that just returns an empty string because + # this method is later called again for the main source file. + class_wrapper.create = lambda: '' + # Replace the create() method so that only the register() method is called + # (this is called later for the main source file). + class_creator.create = lambda: function_name +'();' + self.__include_creators.append( code_creators.include_t( header_name ) ) + self.split_header_names.append(header_name) + self.split_method_names.append(function_name) + + def write_wrapper( self, class_creator ): + code = '' + if class_creator.wrapper: + code = class_creator.wrapper.create() + class_creator.wrapper.create = lambda: '' + + wrapper_code = self.create_header( class_creator.alias + '_wrapper', code ) + header_file = os.path.join( self.directory_path, class_creator.alias, 'wrapper' + self.HEADER_EXT ) + self.write_file( header_file, wrapper_code ) + + def split_internal_creators( self, class_creator, creators, pattern ): + file_path = os.path.join( self.directory_path + , class_creator.alias + , pattern ) + + function_name = 'register_%s_%s' % ( class_creator.alias, pattern ) + + self.write_file( file_path + self.HEADER_EXT + , self.create_header( pattern, self.create_function_code( function_name ) ) ) + + self.write_file( file_path + self.SOURCE_EXT + , self.create_source( pattern + , function_name + , creators )) + for index, creator in enumerate( creators ): + if 0 == index: + creator.create = lambda: function_name + '();' + else: + creator.create = lambda: '' + + def split_internal_enums( self, class_creator ): + """Write all enumerations into a separate .h/.cpp file. + """ + enums_creators = filter( lambda x: isinstance(x, code_creators.enum_t ) + , class_creator.creators ) + self.split_internal_creators( class_creator, enums_creators, 'enums' ) + return 'enums' + + def split_internal_unnamed_enums( self, class_creator ): + creators = filter( lambda x: isinstance(x, code_creators.unnamed_enum_t ) + , class_creator.creators ) + self.split_internal_creators( class_creator, creators, 'unnamed_enums' ) + return 'unnamed_enums' + + def split_internal_member_functions( self, class_creator ): + creators = filter( lambda x: isinstance(x, code_creators.mem_fun_t ) + , class_creator.creators ) + self.split_internal_creators( class_creator, creators, 'memfuns' ) + return 'memfuns' + + def split_internal_classes( self, class_creator ): + class_types = ( code_creators.class_t, code_creators.class_declaration_t ) + creators = filter( lambda x: isinstance(x, class_types ), class_creator.creators ) + self.split_internal_creators( class_creator, creators, 'classes' ) + return 'classes' + + def split_internal_member_variables( self, class_creator ): + creators = filter( lambda x: isinstance(x, code_creators.member_variable_base_t) + , class_creator.creators ) + self.split_internal_creators( class_creator, creators, 'memvars' ) + return 'memvars' + + def split_class_impl( self, class_creator): + if not class_creator.declaration in self.huge_classes: + return super( class_multiple_files_t, self ).split_class_impl( class_creator ) + + extmodule = class_creator.top_parent + + self.create_dir( os.path.join( self.directory_path, class_creator.alias ) ) + + function_name = 'register_%s_class' % class_creator.alias + file_path = os.path.join( self.directory_path, class_creator.alias ) + # Write the .h file... + header_name = file_path + self.HEADER_EXT + self.write_file( header_name + , self.create_header( class_creator.alias + , self.create_function_code( function_name ) ) ) + + self.write_wrapper( class_creator ) + wrapper_include = code_creators.include_t( os.path.join( class_creator.alias, 'wrapper' + self.HEADER_EXT ) ) + + extmodule.adopt_include( wrapper_include ) + + include_creators = [ wrapper_include ] + splitter_includes = [] + for splitter in self.internal_splitters: + pattern = splitter( class_creator ) + include_creator = code_creators.include_t( os.path.join( class_creator.alias, pattern + self.HEADER_EXT ) ) + splitter_includes.append( include_creator ) + + for creator in splitter_includes: + extmodule.adopt_include( creator ) + + # Write the .cpp file... + cpp_code = self.create_source( class_creator.alias + , function_name + , [class_creator] ) + + self.write_file( file_path + self.SOURCE_EXT, cpp_code ) + + extmodule.remove_creator( wrapper_include ) + for creator in splitter_includes: + extmodule.remove_creator( creator ) + # Replace the create() method so that only the register() method is called + # (this is called later for the main source file). + class_creator.create = lambda: function_name +'();' + self.include_creators.append( code_creators.include_t( header_name ) ) + self.split_header_names.append(header_name) + self.split_method_names.append(function_name) Modified: pyplusplus_dev/pyplusplus/file_writers/multiple_files.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-07-23 06:02:19 UTC (rev 334) +++ pyplusplus_dev/pyplusplus/file_writers/multiple_files.py 2006-07-23 13:25:56 UTC (rev 335) @@ -29,19 +29,19 @@ """ writer.writer_t.__init__(self, extmodule) self.__directory_path = directory_path - self._create_dir() - self.__include_creators = [] # List of include_t creators that contain the generated headers + self.create_dir( directory_path ) + self.include_creators = [] # List of include_t creators that contain the generated headers self.split_header_names = [] # List of include file names for split files self.split_method_names = [] # List of methods from the split files - def _create_dir( self ): + def create_dir( self, directory_path ): """Create the output directory if it doesn't already exist. """ - if os.path.exists( self.__directory_path ) and not os.path.isdir(self.__directory_path): + if os.path.exists( directory_path ) and not os.path.isdir(directory_path): raise RuntimeError( 'directory_path should contain path to directory.' ) - if not os.path.exists( self.__directory_path ): - os.makedirs( self.__directory_path ) + if not os.path.exists( directory_path ): + os.makedirs( directory_path ) def _get_directory_path(self): return self.__directory_path @@ -181,7 +181,7 @@ # Replace the create() method so that only the register() method is called # (this is called later for the main source file). class_creator.create = lambda: function_name +'();' - self.__include_creators.append( code_creators.include_t( header_name ) ) + self.include_creators.append( code_creators.include_t( header_name ) ) self.split_header_names.append(header_name) self.split_method_names.append(function_name) @@ -246,7 +246,7 @@ self.extmodule.body.adopt_creator( code_creators.custom_text_t( function_name + '();' ) , registrator_pos) - self.__include_creators.append( code_creators.include_t( header_name ) ) + self.include_creators.append( code_creators.include_t( header_name ) ) self.split_header_names.append(header_name) self.split_method_names.append(function_name) @@ -304,8 +304,8 @@ self.split_free_functions() if write_main: - self.__include_creators.sort( cmp=lambda ic1, ic2: cmp( ic1.header, ic2.header ) ) + self.include_creators.sort( cmp=lambda ic1, ic2: cmp( ic1.header, ic2.header ) ) map( lambda creator: self.extmodule.adopt_include( creator ) - , self.__include_creators ) + , self.include_creators ) main_cpp = os.path.join( self.directory_path, self.extmodule.body.name + '.main.cpp' ) self.write_file( main_cpp, self.extmodule.create() + os.linesep ) Modified: pyplusplus_dev/pyplusplus/module_builder/builder.py =================================================================== --- pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-07-23 06:02:19 UTC (rev 334) +++ pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-07-23 13:25:56 UTC (rev 335) @@ -235,14 +235,19 @@ """ file_writers.write_file( self.code_creator, file_name ) - def split_module(self, dir_name): + def split_module(self, dir_name, huge_classes=None): """ Writes module to multiple files @param dir_name: directory name - @type dir_name: string - """ - file_writers.write_multiple_files( self.code_creator, dir_name ) + @type dir_name: string + + @param huge_classes: list that contains reference to classes, that should be split + """ + if None is huge_classes: + file_writers.write_multiple_files( self.code_creator, dir_name ) + else: + file_writers.write_class_multiple_files( self.code_creator, dir_name, huge_classes ) #select decl(s) interfaces def decl( self, name=None, function=None, header_dir=None, header_file=None, recursive=None ): Modified: pyplusplus_dev/unittests/algorithms_tester.py =================================================================== --- pyplusplus_dev/unittests/algorithms_tester.py 2006-07-23 06:02:19 UTC (rev 334) +++ pyplusplus_dev/unittests/algorithms_tester.py 2006-07-23 13:25:56 UTC (rev 335) @@ -99,15 +99,44 @@ mem_funs = arr.calldefs( 'x', arg_types=[None,None] ) for x in mem_funs: self.failUnless( x.exportable == False ) + +class class_multiple_files_tester_t(unittest.TestCase): + CLASS_DEF = \ + """ + namespace tester{ + struct X{ + enum EColor{ red, blue }; + enum EFruit{ apple, orange }; + + X(){} + X( int ){} + + void do_nothing(){} + + int do_somghing(){ return 1; } + + int m_dummy; + }; + } + """ + def test(self): + mb = module_builder.module_builder_t( + [ module_builder.create_text_fc( self.CLASS_DEF ) ] + , gccxml_path=autoconfig.gccxml.executable ) + mb.namespace( name='::tester' ).include() + mb.build_code_creator('dummy') + mb.split_module( autoconfig.build_dir, [ mb.class_( '::tester::X' ) ] ) def create_suite(): suite = unittest.TestSuite() - suite.addTest( unittest.makeSuite(class_organizer_tester_t)) - suite.addTest( unittest.makeSuite(indent_tester_t)) - suite.addTest( unittest.makeSuite(make_flatten_tester_t)) - suite.addTest( unittest.makeSuite(creator_finder_tester_t)) - suite.addTest( unittest.makeSuite(exclude_function_with_array_arg_tester_t)) + #~ suite.addTest( unittest.makeSuite(class_organizer_tester_t)) + #~ suite.addTest( unittest.makeSuite(indent_tester_t)) + #~ suite.addTest( unittest.makeSuite(make_flatten_tester_t)) + #~ suite.addTest( unittest.makeSuite(creator_finder_tester_t)) + #~ suite.addTest( unittest.makeSuite(exclude_function_with_array_arg_tester_t)) + suite.addTest( unittest.makeSuite(class_multiple_files_tester_t)) + return suite def run_suite(): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-23 06:02:26
|
Revision: 334 Author: roman_yakovenko Date: 2006-07-22 23:02:19 -0700 (Sat, 22 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=334&view=rev Log Message: ----------- changing from msg = [ 'Declaration "%s" could not be exported.' % full_name ] to [ 'Declaration "%s" could not be exported.' % decl ] 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-20 19:12:15 UTC (rev 333) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-23 06:02:19 UTC (rev 334) @@ -145,22 +145,18 @@ readme = decl.readme() if not readme: continue - #Now we should print what py++ has to say to user - full_name = declarations.full_name( decl ) - if not decl.name: - full_name = full_name + '::{unnamed}' if not decl.exportable: reason = readme[0] if reason in DO_NOT_REPORT_MSGS: continue readme = readme[1:] - msg = [ 'Declaration "%s" could not be exported.' % full_name ] + msg = [ 'Declaration "%s" could not be exported.' % decl ] msg.append( reason.replace( os.linesep, os.linesep + '\t' ) ) self.decl_logger.warn( os.linesep.join( msg ) ) for msg in readme: - self.decl_logger.warn( 'Declaration "%s": %s' % ( full_name, msg ) ) + self.decl_logger.warn( 'Declaration "%s": %s' % ( decl, msg ) ) #leave only declarations defined under namespace, but remove namespaces decls = filter( lambda x: not isinstance( x, declarations.namespace_t ) \ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-20 19:12:27
|
Revision: 333 Author: roman_yakovenko Date: 2006-07-20 12:12:15 -0700 (Thu, 20 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=333&view=rev Log Message: ----------- adding documentation for documentation strings Modified Paths: -------------- pyplusplus_dev/docs/documentation/www_configuration.py Added Paths: ----------- pyplusplus_dev/docs/documentation/doc_string.rest Added: pyplusplus_dev/docs/documentation/doc_string.rest =================================================================== --- pyplusplus_dev/docs/documentation/doc_string.rest (rev 0) +++ pyplusplus_dev/docs/documentation/doc_string.rest 2006-07-20 19:12:15 UTC (rev 333) @@ -0,0 +1,75 @@ +==================== +Documentation string +==================== + +.. contents:: Table of contents + +------------ +Introduction +------------ + +`pyplusplus`_ provides a convenient way to export documentation from C++ source +files as `Python`_ `documentation string`_ + +--------------- +API description +--------------- + +:: + + mb = module_builder_t( ... ) + my_class = mb.class_( 'my_class' ) + my_class.documentation = '"very helpful documentation string"' + my_class.member_function( "do_nothing" ).documentation = \ + '"This function does nothing."' + +In `pyplusplus`_ every class, that describes C++ declarations has ``documentation`` +property. This property should contain valid C++ string or ``None``. + +`boost.python`_ not always provides functionality, that exports documentation string. +In those cases, `pyplusplus`_ will not generate documentation string. + +Also the previous method is pretty clear, it is not practical. There should be a +better way, to complete the task. Lets take a look on +``module_builder_t.build_code_creator`` method. One of the arguments of this method +is ``doc_extractor``. + + +``doc_extractor`` is a callable object, that takes one argument - reference to declaration. + +:: + + def doc_extractor( decl ): + ... + +How it could help? Every declaration has location information: + + * ``decl.location.file_name`` - absolute file name, where this declaration + has been declared. + + * ``decl.location.line`` - line number. + +So, you can go to the source file and to extract declaration from it. +`pyplusplus`_ will call ``doc_extractor`` on every exported declaration. + +Now, when I think you understand what functionality `pyplusplus`_ provides. +It is a time to say what functionality is missing. `pyplusplus`_ does not +provide any documentation extractor. It is not completely true. You can find +document extractor for `doxygen`_ format in ``contrib/doc_extractors`` directory. +It has been contributed by Georgiy Dernovoy. + + +.. _`doxygen` : http://www.stack.nl/~dimitri/doxygen/ +.. _`documentation string` : http://docs.python.org/tut/node6.html#SECTION006760000000000000000 +.. _`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: Modified: pyplusplus_dev/docs/documentation/www_configuration.py =================================================================== --- pyplusplus_dev/docs/documentation/www_configuration.py 2006-07-20 17:50:37 UTC (rev 332) +++ pyplusplus_dev/docs/documentation/www_configuration.py 2006-07-20 19:12:15 UTC (rev 333) @@ -1,5 +1,7 @@ name = 'documentation' main_html_file = 'index.html' -files_to_skip = ['indexing_suite_v2.html'] -names = { 'containers' : 'STL containers' - , 'how_to' : 'how to ... ?' } \ No newline at end of file +files_to_skip = ['indexing_suite_v2.html'] +names = { 'containers' : 'STL containers' + , 'how_to' : 'how to ... ?' + , 'doc_string' : 'documentation string' +} \ 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-20 17:50:47
|
Revision: 332 Author: roman_yakovenko Date: 2006-07-20 10:50:37 -0700 (Thu, 20 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=332&view=rev Log Message: ----------- fixing warning report Modified Paths: -------------- pyplusplus_dev/pyplusplus/module_creator/creator.py pyplusplus_dev/unittests/member_functions_tester.py Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-20 15:25:23 UTC (rev 331) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-20 17:50:37 UTC (rev 332) @@ -132,39 +132,44 @@ def _prepare_decls( self, decls, doc_extractor ): global DO_NOT_REPORT_MSGS + decls = declarations.make_flatten( decls ) + + for decl in decls: + if decl.ignore: + continue + + if doc_extractor and decl.exportable: + decl.documentation = doc_extractor( decl ) + + readme = decl.readme() + if not readme: + continue + #Now we should print what py++ has to say to user + full_name = declarations.full_name( decl ) + if not decl.name: + full_name = full_name + '::{unnamed}' + + if not decl.exportable: + reason = readme[0] + if reason in DO_NOT_REPORT_MSGS: + continue + readme = readme[1:] + msg = [ 'Declaration "%s" could not be exported.' % full_name ] + msg.append( reason.replace( os.linesep, os.linesep + '\t' ) ) + self.decl_logger.warn( os.linesep.join( msg ) ) + + for msg in readme: + self.decl_logger.warn( 'Declaration "%s": %s' % ( full_name, msg ) ) + #leave only declarations defined under namespace, but remove namespaces decls = filter( lambda x: not isinstance( x, declarations.namespace_t ) \ and isinstance( x.parent, declarations.namespace_t ) , decls ) - #leave only decls that user wants to export - decls = filter( lambda x: not x.ignore, decls ) - - for decl in decls: - if doc_extractor and decl.exportable: - decl.documentation = doc_extractor( decl ) - - readme = decl.readme() - if not readme: - continue - #Now we should print what py++ has to say to user - full_name = declarations.full_name( decl ) - if not decl.name: - full_name = full_name + '::{unnamed}' - - if not decl.exportable: - reason = readme[0] - if reason in DO_NOT_REPORT_MSGS: - continue - readme = readme[1:] - msg = [ 'Declaration "%s" could not be exported.' % full_name ] - msg.append( reason.replace( os.linesep, os.linesep + '\t' ) ) - self.decl_logger.warn( os.linesep.join( msg ) ) - - for msg in readme: - self.decl_logger.warn( 'Declaration "%s": %s' % ( full_name, msg ) ) - - return filter( lambda x: x.exportable, decls ) + #leave only decls that user wants to export and that could be exported + decls = filter( lambda x: x.ignore == False and x.exportable == True, decls ) + + return decls def _reorder_decls(self, decls ): classes = filter( lambda x: isinstance( x, declarations.class_t ) Modified: pyplusplus_dev/unittests/member_functions_tester.py =================================================================== --- pyplusplus_dev/unittests/member_functions_tester.py 2006-07-20 15:25:23 UTC (rev 331) +++ pyplusplus_dev/unittests/member_functions_tester.py 2006-07-20 17:50:37 UTC (rev 332) @@ -32,6 +32,7 @@ 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 + mb.BOOST_PYTHON_MAX_ARITY = 1 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: <mb...@us...> - 2006-07-20 15:25:27
|
Revision: 331 Author: mbaas Date: 2006-07-20 08:25:23 -0700 (Thu, 20 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=331&view=rev Log Message: ----------- Removed the 'experimental' directory. Its successor is already in contrib/pypp_api (which can still be considered to be an experimental high level API that has slightly different features than the official high level API). Removed Paths: ------------- pyplusplus_dev/experimental/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-20 11:13:06
|
Revision: 330 Author: roman_yakovenko Date: 2006-07-20 04:12:54 -0700 (Thu, 20 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=330&view=rev Log Message: ----------- adding request for help Modified Paths: -------------- pyplusplus_dev/docs/documentation/index.rest Modified: pyplusplus_dev/docs/documentation/index.rest =================================================================== --- pyplusplus_dev/docs/documentation/index.rest 2006-07-20 07:15:20 UTC (rev 329) +++ pyplusplus_dev/docs/documentation/index.rest 2006-07-20 11:12:54 UTC (rev 330) @@ -1,20 +1,29 @@ -============= -Documentation -============= +======================== +pyplusplus documentation +======================== .. contents:: Table of contents ----- -XXXX ----- +------------ +Help needed! +------------ - ??? +`pyplusplus`_ documentation is always under active development. It is not an easy +task to create and maintain it. I will appriciate any help! +How can you help? -.. _`STL Containers` : ./containers.html - +* Lets face it: today it is not possible to use `pyplusplus`_ without looking + into source code. `pyplusplus`_ uses `Epydoc`_ to generate documentation from + source files. So, if you found some undocumented piece of code and you understand + what it does, please write documentation string and send it to me. + +* You are reading documentation and my English cause you to scream? Please, fix + those errors and send me new version of document. I will integrate the changes. + +.. _`Epydoc` : http://epydoc.sourceforge.net/ .. _`pyplusplus` : ./../pyplusplus.html .. _`boost.python`: http://www.boost.org/libs/python/doc/index.html .. _`Python`: http://www.python.org This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-20 07:15:32
|
Revision: 329 Author: roman_yakovenko Date: 2006-07-20 00:15:20 -0700 (Thu, 20 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=329&view=rev Log Message: ----------- u[dating documentation an setup scripts Modified Paths: -------------- pygccxml_dev/setup.py pyplusplus_dev/docs/documentation/tutorials/tutorials.rest pyplusplus_dev/setup.py Modified: pygccxml_dev/setup.py =================================================================== --- pygccxml_dev/setup.py 2006-07-20 07:01:05 UTC (rev 328) +++ pygccxml_dev/setup.py 2006-07-20 07:15:20 UTC (rev 329) @@ -21,7 +21,9 @@ html_writer = HTMLWriter( docindex , prj_name='pygccxml' , prj_url='http://www.language-binding.net' - , include_sourcecode=True ) + , include_sourcecode=False #This will decrease the size of generated documentation + , show_private=False + , show_frames=False) html_writer.write( os.path.join('docs', 'apidocs') ) Modified: pyplusplus_dev/docs/documentation/tutorials/tutorials.rest =================================================================== --- pyplusplus_dev/docs/documentation/tutorials/tutorials.rest 2006-07-20 07:01:05 UTC (rev 328) +++ pyplusplus_dev/docs/documentation/tutorials/tutorials.rest 2006-07-20 07:15:20 UTC (rev 329) @@ -8,7 +8,7 @@ What is pyplusplus? ------------------- -.. include:: ./../definition.rest +.. include:: ./../../definition.rest ------------------- Graphical interface Modified: pyplusplus_dev/setup.py =================================================================== --- pyplusplus_dev/setup.py 2006-07-20 07:01:05 UTC (rev 328) +++ pyplusplus_dev/setup.py 2006-07-20 07:15:20 UTC (rev 329) @@ -54,9 +54,11 @@ html_writer = HTMLWriter( docindex , prj_name='pyplusplus' , prj_url='http://www.language-binding.net' - , include_sourcecode=True ) + , include_sourcecode=False #This will decrease the size of generated documentation + , show_private=False + , show_frames=False ) - html_writer.write( os.path.join('docs', 'apidocs') ) + html_writer.write( os.path.join('docs', 'documentation', 'apidocs') ) class doc_cmd(Command): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-20 07:01:23
|
Revision: 328 Author: roman_yakovenko Date: 2006-07-20 00:01:05 -0700 (Thu, 20 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=328&view=rev Log Message: ----------- moving tutorials to "documentation" directory Added Paths: ----------- pyplusplus_dev/docs/documentation/tutorials/ pyplusplus_dev/docs/documentation/tutorials/module_builder/ pyplusplus_dev/docs/documentation/tutorials/module_builder/generate_code.html pyplusplus_dev/docs/documentation/tutorials/module_builder/hello_world.html pyplusplus_dev/docs/documentation/tutorials/module_builder/module_builder.rest pyplusplus_dev/docs/documentation/tutorials/module_builder/result.html pyplusplus_dev/docs/documentation/tutorials/module_builder/www_configuration.py pyplusplus_dev/docs/documentation/tutorials/pyplusplus_demo.png pyplusplus_dev/docs/documentation/tutorials/tutorials.rest pyplusplus_dev/docs/documentation/tutorials/www_configuration.py Removed Paths: ------------- pyplusplus_dev/docs/tutorials/ Added: pyplusplus_dev/docs/documentation/tutorials/module_builder/generate_code.html =================================================================== --- pyplusplus_dev/docs/documentation/tutorials/module_builder/generate_code.html (rev 0) +++ pyplusplus_dev/docs/documentation/tutorials/module_builder/generate_code.html 2006-07-20 07:01:05 UTC (rev 328) @@ -0,0 +1,101 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>generate_code.py</title> +<meta name="GENERATOR" content="SciTE - www.Scintilla.org" /> +<style type="text/css"> +.S0 { + color: #808080; + background: #FFFFFF; +} +.S1 { + font-family: 'Courier New'; + color: #007F00; + background: #FFFFFF; + font-size: 9pt; +} +.S4 { + font-family: 'Courier New'; + color: #7F007F; + background: #FFFFFF; + font-size: 10pt; +} +.S5 { + font-weight: bold; + color: #00007F; + background: #FFFFFF; +} +.S10 { + font-weight: bold; + color: #000000; + background: #FFFFFF; +} +.S12 { + color: #7F7F7F; + background: #FFFFFF; +} +span { + font-family: 'Courier New'; + color: #000000; + background: #FFFFFF; + font-size: 10pt; +} +</style> +</head> +<body bgcolor="#FFFFFF"> +<span><span class="S1">#! /usr/bin/python</span><br /> +<span class="S1"># Copyright 2004 Roman Yakovenko.</span><br /> +<span class="S1"># Distributed under the Boost Software License, Version 1.0. (See</span><br /> +<span class="S1"># accompanying file LICENSE_1_0.txt or copy at</span><br /> +<span class="S1"># http://www.boost.org/LICENSE_1_0.txt)</span><br /> +<br /> +<span class="S5">import</span><span class="S0"> </span>os<br /> +<span class="S5">import</span><span class="S0"> </span>sys<br /> +sys<span class="S10">.</span>path<span class="S10">.</span>append<span class="S10">(</span><span class="S0"> </span><span class="S4">'../..'</span><span class="S0"> </span><span class="S10">)</span><br /> +<span class="S5">from</span><span class="S0"> </span>environment<span class="S0"> </span><span class="S5">import</span><span class="S0"> </span>gccxml<br /> +<span class="S5">from</span><span class="S0"> </span>pyplusplus<span class="S0"> </span><span class="S5">import</span><span class="S0"> </span>module_builder<br /> +<br /> +mb<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>module_builder<span class="S10">.</span>module_builder_t<span class="S10">(</span><br /> +<span class="S0"> </span>files<span class="S10">=[</span><span class="S4">'hello_world.hpp'</span><span class="S10">]</span><br /> +<span class="S0"> </span><span class="S10">,</span><span class="S0"> </span>gccxml_path<span class="S10">=</span>gccxml<span class="S10">.</span>executable<span class="S0"> </span><span class="S10">)</span><span class="S0"> </span><span class="S1">#path to gccxml executable</span><br /> +<br /> +<span class="S1">#rename enum Color to color</span><br /> +Color<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>mb<span class="S10">.</span>enum<span class="S10">(</span><span class="S0"> </span><span class="S4">'color'</span><span class="S0"> </span><span class="S10">)</span><br /> +Color<span class="S10">.</span>rename<span class="S10">(</span><span class="S4">'Color'</span><span class="S10">)</span><br /> +<br /> +<span class="S1">#Set call policies to animal::get_name_ptr</span><br /> +animal<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>mb<span class="S10">.</span>class_<span class="S10">(</span><span class="S0"> </span><span class="S4">'animal'</span><span class="S0"> </span><span class="S10">)</span><br /> +get_name_ptr<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>animal<span class="S10">.</span>member_function<span class="S10">(</span><span class="S0"> </span><span class="S4">'get_name_ptr'</span><span class="S10">,</span><span class="S0"> </span>recursive<span class="S10">=</span>False<span class="S0"> </span><span class="S10">)</span><br /> +get_name_ptr<span class="S10">.</span>call_policies<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>module_builder<span class="S10">.</span>call_policies<span class="S10">.</span>return_internal_reference<span class="S10">()</span><br /> +<br /> +<span class="S1">#next code has same effect</span><br /> +get_name_ptr<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>mb<span class="S10">.</span>member_function<span class="S10">(</span><span class="S0"> </span><span class="S4">'get_name_ptr'</span><span class="S0"> </span><span class="S10">)</span><br /> +get_name_ptr<span class="S10">.</span>call_policies<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>module_builder<span class="S10">.</span>call_policies<span class="S10">.</span>return_internal_reference<span class="S10">()</span><br /> +<br /> +<span class="S1">#I want to exclude all classes with name starts with impl</span><br /> +impl_classes<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>mb<span class="S10">.</span>classes<span class="S10">(</span><span class="S0"> </span><span class="S5">lambda</span><span class="S0"> </span>decl<span class="S10">:</span><span class="S0"> </span>decl<span class="S10">.</span>name<span class="S10">.</span>startswith<span class="S10">(</span><span class="S0"> </span><span class="S4">'impl'</span><span class="S0"> </span><span class="S10">)</span><span class="S0"> </span><span class="S10">)</span><br /> +impl_classes<span class="S10">.</span>exclude<span class="S10">()</span><br /> +<br /> +<span class="S1">#I want to exclude all functions that returns pointer to int</span><br /> +ptr_to_int<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>mb<span class="S10">.</span>free_functions<span class="S10">(</span><span class="S0"> </span>return_type<span class="S10">=</span><span class="S4">'int *'</span><span class="S0"> </span><span class="S10">)</span><br /> +ptr_to_int<span class="S10">.</span>exclude<span class="S10">()</span><br /> +<br /> +<span class="S1">#I can print declarations to see what is going on</span><br /> +mb<span class="S10">.</span>print_declarations<span class="S10">()</span><br /> +<br /> +<span class="S1">#I can print single declaration</span><br /> +mb<span class="S10">.</span>print_declarations<span class="S10">(</span><span class="S0"> </span>animal<span class="S0"> </span><span class="S10">)</span><br /> +<br /> +<span class="S1">#Now it is the time to give a name to our module</span><br /> +mb<span class="S10">.</span>build_code_creator<span class="S10">(</span><span class="S0"> </span>module_name<span class="S10">=</span><span class="S4">'hw'</span><span class="S0"> </span><span class="S10">)</span><br /> +<br /> +<span class="S1">#It is common requirement in software world - each file should have license</span><br /> +mb<span class="S10">.</span>code_creator<span class="S10">.</span>license<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">'//Boost Software License( http://boost.org/more/license_info.html )'</span><br /> +<br /> +<span class="S1">#I don't want absolute includes within code</span><br /> +mb<span class="S10">.</span>code_creator<span class="S10">.</span>user_defined_directories<span class="S10">.</span>append<span class="S10">(</span><span class="S0"> </span>os<span class="S10">.</span>path<span class="S10">.</span>abspath<span class="S10">(</span><span class="S4">'.'</span><span class="S10">)</span><span class="S0"> </span><span class="S10">)</span><br /> +<br /> +<span class="S1">#And finally we can write code to the disk</span><br /> +mb<span class="S10">.</span>write_module<span class="S10">(</span><span class="S0"> </span>os<span class="S10">.</span>path<span class="S10">.</span>join<span class="S10">(</span><span class="S0"> </span>os<span class="S10">.</span>path<span class="S10">.</span>abspath<span class="S10">(</span><span class="S4">'.'</span><span class="S10">),</span><span class="S0"> </span><span class="S4">'hello_world.py.cpp'</span><span class="S0"> </span><span class="S10">)</span><span class="S0"> </span><span class="S10">)</span></span> +</body> +</html> Added: pyplusplus_dev/docs/documentation/tutorials/module_builder/hello_world.html =================================================================== --- pyplusplus_dev/docs/documentation/tutorials/module_builder/hello_world.html (rev 0) +++ pyplusplus_dev/docs/documentation/tutorials/module_builder/hello_world.html 2006-07-20 07:01:05 UTC (rev 328) @@ -0,0 +1,97 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>hello_world.hpp</title> +<meta name="GENERATOR" content="SciTE - www.Scintilla.org" /> +<style type="text/css"> +.S0 { + color: #808080; + background: #FFFFFF; +} +.S2 { + font-family: 'Courier New'; + color: #007F00; + background: #FFFFFF; + font-size: 9pt; +} +.S3 { + font-family: 'Courier New'; + color: #3F703F; + background: #FFFFFF; + font-size: 9pt; +} +.S4 { + color: #007F7F; + background: #FFFFFF; +} +.S5 { + font-weight: bold; + color: #00007F; + background: #FFFFFF; +} +.S6 { + color: #7F007F; + background: #FFFFFF; +} +.S9 { + color: #7F7F00; + background: #FFFFFF; +} +.S10 { + font-weight: bold; + color: #000000; + background: #FFFFFF; +} +span { + font-family: 'Courier New'; + color: #000000; + background: #FFFFFF; + font-size: 10pt; +} +</style> +</head> +<body bgcolor="#FFFFFF"> +<span><span class="S2">// Copyright 2004 Roman Yakovenko.</span><br /> +<span class="S2">// Distributed under the Boost Software License, Version 1.0. (See</span><br /> +<span class="S2">// accompanying file LICENSE_1_0.txt or copy at</span><br /> +<span class="S2">// http://www.boost.org/LICENSE_1_0.txt)</span><br /> +<br /> +<span class="S9">#ifndef __hello_world_hpp__</span><br /> +<span class="S9">#define __hello_world_hpp__</span><br /> +<br /> +<span class="S9">#include <string></span><br /> +<br /> +<span class="S2">//I want to rename color to Color</span><br /> +<span class="S5">enum</span><span class="S0"> </span>color<span class="S10">{</span><span class="S0"> </span>red<span class="S10">,</span><span class="S0"> </span>green<span class="S10">,</span><span class="S0"> </span>blue<span class="S0"> </span><span class="S10">};</span><br /> +<br /> +<span class="S5">struct</span><span class="S0"> </span>animal<span class="S10">{</span><br /> +<span class="S0"> </span><br /> +<span class="S0"> </span>animal<span class="S10">(</span><span class="S0"> </span><span class="S5">const</span><span class="S0"> </span>std<span class="S10">::</span>string<span class="S10">&</span><span class="S0"> </span>name<span class="S10">=</span><span class="S6">""</span><span class="S0"> </span><span class="S10">)</span><br /> +<span class="S0"> </span><span class="S10">:</span><span class="S0"> </span>m_name<span class="S10">(</span><span class="S0"> </span>name<span class="S0"> </span><span class="S10">)</span><br /> +<span class="S0"> </span><span class="S10">{}</span><br /> +<span class="S0"> </span><br /> +<span class="S0"> </span><span class="S2">//I need to set call policies to the function</span><br /> +<span class="S0"> </span><span class="S5">const</span><span class="S0"> </span>std<span class="S10">::</span>string<span class="S10">*</span><span class="S0"> </span>get_name_ptr<span class="S10">()</span><span class="S0"> </span><span class="S5">const</span><br /> +<span class="S0"> </span><span class="S10">{</span><span class="S0"> </span><span class="S5">return</span><span class="S0"> </span><span class="S10">&</span>m_name<span class="S10">;</span><span class="S0"> </span><span class="S10">}</span><br /> +<br /> +<span class="S0"> </span><span class="S5">const</span><span class="S0"> </span>std<span class="S10">::</span>string<span class="S10">&</span><span class="S0"> </span>name<span class="S10">()</span><span class="S0"> </span><span class="S5">const</span><br /> +<span class="S0"> </span><span class="S10">{</span><span class="S0"> </span><span class="S5">return</span><span class="S0"> </span>m_name<span class="S10">;</span><span class="S0"> </span><span class="S10">}</span><br /> +<span class="S0"> </span><br /> +<span class="S5">private</span><span class="S10">:</span><span class="S0"> </span><br /> +<span class="S0"> </span>std<span class="S10">::</span>string<span class="S0"> </span>m_name<span class="S10">;</span><br /> +<br /> +<span class="S10">};</span><br /> +<br /> +<span class="S2">//I want to exclude next declarations:</span><br /> +<span class="S5">struct</span><span class="S0"> </span>impl1<span class="S10">{};</span><br /> +<span class="S5">struct</span><span class="S0"> </span>impl2<span class="S10">{};</span><br /> +<br /> +<span class="S5">inline</span><span class="S0"> </span><span class="S5">int</span><span class="S10">*</span><span class="S0"> </span>get_int_ptr<span class="S10">(){</span><span class="S0"> </span><span class="S5">return</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;}</span><span class="S0"> </span><br /> +<span class="S5">inline</span><span class="S0"> </span><span class="S5">int</span><span class="S10">*</span><span class="S0"> </span>get_int_ptr<span class="S10">(</span><span class="S5">int</span><span class="S10">){</span><span class="S0"> </span><span class="S5">return</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;}</span><br /> +<span class="S5">inline</span><span class="S0"> </span><span class="S5">int</span><span class="S10">*</span><span class="S0"> </span>get_int_ptr<span class="S10">(</span><span class="S5">double</span><span class="S10">){</span><span class="S0"> </span><span class="S5">return</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;}</span><br /> +<span class="S0"> </span><br /> +<span class="S9">#endif</span><span class="S2">//__hello_world_hpp__</span><br /> +<br /> +<span class="S0"></span></span> +</body> +</html> Added: pyplusplus_dev/docs/documentation/tutorials/module_builder/module_builder.rest =================================================================== --- pyplusplus_dev/docs/documentation/tutorials/module_builder/module_builder.rest (rev 0) +++ pyplusplus_dev/docs/documentation/tutorials/module_builder/module_builder.rest 2006-07-20 07:01:05 UTC (rev 328) @@ -0,0 +1,167 @@ +==================== +pyplusplus tutorials +==================== + +.. contents:: Table of contents + +------------------- +What is pyplusplus? +------------------- + +.. include:: ./../../../definition.rest + +-------- +Preamble +-------- + +I guess you decided to try `pyplusplus`_ API. Good! Lets start. First of all, +please take a look on two files: + +* `hello_world.hpp`_ - C++ source code, that we want to export to Python + +* `generate_code.py`_ - Python code, that uses `pyplusplus`_ to export + declarations from the source file + +.. _`hello_world.hpp` : ./hello_world.html +.. _`generate_code.py` : ./generate_code.html + +---------------- +module_builder_t +---------------- + +`pyplusplus`_ is built from a few packages, but there is only one package, you +should really to be familiar with - ``module_builder``. This package is some kind +of facade to low level API. It provides simple and intuitive API. The main +class within this package is ``module_builder_t``. The instance of this class will +guide you through the whole process. Next few paragraphs will tell you more about +this class. + +------------------------- +module_builder_t.__init__ +------------------------- + +First of all, what is needed in order to create an instance of the class? + +``module_builder_t.__init__`` methods takes few arguments: + +1. ``files`` - list of all C++ source files, that declarations from them you want + to export. This is the only required parameter. + +2. ``gccxml_path`` - path to `GCC-XML`_ binary. If you don't supply this argument + `pygccxml`_ will look for it using your environment variable ``PATH``. + +There some other arguments: + +* additional include directories +* [un]defined symbols ( macros ) +* declarations cache +* ... + +Parsing of source files is done within this method. Post condition of this +method is - all declarations has been successfully extracted from the sources +files. + +-------------------------- +Declarations customization +-------------------------- +Not all declarations should be exported! Not every declaration could be exported +without human invocation! As you already saw from example, `pyplusplus`_ provides +simple and powerful declarations query interface. By default, only declarations +that belongs to files, you have asked to parse, and to files, that lies in the same +directories as parsed files, will be exported: +:: + + project_root/ + details/ + impl_a.h + impl_b.h + include/ + a.h //includes impl_a.h + b.h //includes impl_b.h + all.h //includes a.h and b.h + mb = module_builder( [ 'all.h' ] ) + +All declarations that belongs to ``include`` directory will be signed as included +to exporting. All other declarations will be ignored. + +You can change the set of exported declarations by calling ``exclude`` or +``include`` methods, on declarations. + +Basically, this is a second step of code generation process. During this step +you could/should/may change `pyplusplus`_ defaults: + +* to rename exposed declarations +* to include/exclude declarations +* to set call policies +* ... + +I think it is critical for beginers to see what is going on, right? +``module_builder_t`` class has ``print_declarations`` method. You can print whole +declarations tree or some specific declaration. Very convinient, very useful. + +----------------------------------- +module_builder_t.build_code_creator +----------------------------------- + +Now it is a time to create module code creator. Do you remember, in inroduction +to `pyplusplus`_, I told you that before writing code to disc, `pyplusplus`_ will +create some kind of `AST`_. Well this is done by calling +``module_builder_t.build_code_creator`` function. Right now, the only important +argument to the function is ``module_name``. Self explained, is it? + +What is the main value of code creators? Code creators allow you to modify +code before it has been written to disk. For example one common requirement for +open source projects it to have license text within every source file. You can +do it with one line of code only: +:: + + mb.code_creator.license = your license text + +After you call this function, I recommend you not to change declarations +configuration. In most cases the change will take effect, in some cases it will +not! + +This tutorials is not cover code creators and how you should work with them. +I will write an other tutorial. + +.. _`AST`: http://en.wikipedia.org/wiki/Abstract_syntax_tree + +----------------------------- +module_builder_t.write_module +----------------------------- +You have almost created your module. The last things left is to write module +code to file(s). You can do it with + +* ``module_builder_t.write_module`` - you should provide file name, the code + will be written in. + +* ``module_builder_t.split_module`` - you should provide directory name. + For big projects it is a must to minimize compilation time. So `pyplusplus`_ + splits your module source code to different files within the directory. + + +------ +Result +------ + +`View generated file`_ + +.. _`View generated file` : ./result.html + + +That's all. I hope you enjoyed. + +.. _`pyplusplus` : ./../../../pyplusplus.html +.. _`pygccxml` : ./../../../../pygccxml/pygccxml.html +.. _`boost.python`: http://www.boost.org/libs/python/doc/index.html +.. _`SourceForge`: http://sourceforge.net/index.php +.. _`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/documentation/tutorials/module_builder/result.html =================================================================== --- pyplusplus_dev/docs/documentation/tutorials/module_builder/result.html (rev 0) +++ pyplusplus_dev/docs/documentation/tutorials/module_builder/result.html 2006-07-20 07:01:05 UTC (rev 328) @@ -0,0 +1,78 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>hello_world.py.cpp</title> +<meta name="GENERATOR" content="SciTE - www.Scintilla.org" /> +<style type="text/css"> +.S0 { + color: #808080; + background: #FFFFFF; +} +.S2 { + font-family: 'Courier New'; + color: #007F00; + background: #FFFFFF; + font-size: 9pt; +} +.S4 { + color: #007F7F; + background: #FFFFFF; +} +.S5 { + font-weight: bold; + color: #00007F; + background: #FFFFFF; +} +.S6 { + color: #7F007F; + background: #FFFFFF; +} +.S9 { + color: #7F7F00; + background: #FFFFFF; +} +.S10 { + font-weight: bold; + color: #000000; + background: #FFFFFF; +} +span { + font-family: 'Courier New'; + color: #000000; + background: #FFFFFF; + font-size: 10pt; +} +</style> +</head> +<body bgcolor="#FFFFFF"> +<span><span class="S2">// This file has been generated by pyplusplus.</span><br /> +<br /> +<span class="S2">//Boost Software License( http://boost.org/more/license_info.html )</span><br /> +<br /> +<span class="S9">#include "boost/python.hpp"</span><br /> +<br /> +<span class="S9">#include "hello_world.hpp"</span><br /> +<br /> +<span class="S5">namespace</span><span class="S0"> </span>bp<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>boost<span class="S10">::</span>python<span class="S10">;</span><br /> +<br /> +BOOST_PYTHON_MODULE<span class="S10">(</span>hw<span class="S10">){</span><br /> +<span class="S0"> </span>bp<span class="S10">::</span>enum_<span class="S10"><</span>color<span class="S10">>(</span><span class="S6">"Color"</span><span class="S10">)</span><br /> +<span class="S0"> </span><span class="S10">.</span>value<span class="S10">(</span><span class="S6">"blue"</span><span class="S10">,</span><span class="S0"> </span>blue<span class="S10">)</span><br /> +<span class="S0"> </span><span class="S10">.</span>value<span class="S10">(</span><span class="S6">"green"</span><span class="S10">,</span><span class="S0"> </span>green<span class="S10">)</span><br /> +<span class="S0"> </span><span class="S10">.</span>value<span class="S10">(</span><span class="S6">"red"</span><span class="S10">,</span><span class="S0"> </span>red<span class="S10">)</span><br /> +<span class="S0"> </span><span class="S10">.</span>export_values<span class="S10">()</span><br /> +<span class="S0"> </span><span class="S10">;</span><br /> +<br /> +<span class="S0"> </span>bp<span class="S10">::</span>class_<span class="S10"><</span><span class="S0"> </span>animal<span class="S10">,</span><span class="S0"> </span>boost<span class="S10">::</span>noncopyable<span class="S0"> </span><span class="S10">>(</span><span class="S0"> </span><span class="S6">"animal"</span><span class="S10">,</span><span class="S0"> </span>bp<span class="S10">::</span>init<span class="S10"><</span><span class="S0"> </span>bp<span class="S10">::</span>optional<span class="S10"><</span><span class="S0"> </span>std<span class="S10">::</span>string<span class="S0"> </span><span class="S5">const</span><span class="S0"> </span><span class="S10">&</span><span class="S0"> </span><span class="S10">></span><span class="S0"> </span><span class="S10">>((</span><span class="S0"> </span>bp<span class="S10">::</span>arg<span class="S10">(</span><span class="S6">"name"</span><span class="S10">)=</span><span class="S6">""</span><span class="S0"> </span><span class="S10">))</span><span class="S0"> </span><span class="S10">)</span><span class="S0"> </span><br /> +<span class="S0"> </span><span class="S10">.</span>def<span class="S10">(</span><span class="S6">"get_name_ptr"</span><br /> +<span class="S0"> </span><span class="S10">,</span><span class="S0"> </span><span class="S10">&::</span>animal<span class="S10">::</span>get_name_ptr<br /> +<span class="S0"> </span><span class="S10">,</span><span class="S0"> </span>bp<span class="S10">::</span>return_internal_reference<span class="S10"><</span><span class="S0"> </span><span class="S4">1</span><span class="S10">,</span><span class="S0"> </span>bp<span class="S10">::</span>default_call_policies<span class="S0"> </span><span class="S10">>()</span><span class="S0"> </span><span class="S10">)</span><span class="S0"> </span><br /> +<span class="S0"> </span><span class="S10">.</span>def<span class="S10">(</span><span class="S6">"name"</span><br /> +<span class="S0"> </span><span class="S10">,</span><span class="S0"> </span><span class="S10">&::</span>animal<span class="S10">::</span>name<br /> +<span class="S0"> </span><span class="S10">,</span><span class="S0"> </span>bp<span class="S10">::</span>return_value_policy<span class="S10"><</span><span class="S0"> </span>bp<span class="S10">::</span>copy_const_reference<span class="S10">,</span><span class="S0"> </span>bp<span class="S10">::</span>default_call_policies<span class="S0"> </span><span class="S10">>()</span><span class="S0"> </span><span class="S10">);</span><br /> +<br /> +<span class="S0"> </span>bp<span class="S10">::</span>implicitly_convertible<span class="S10"><</span><span class="S0"> </span>std<span class="S10">::</span>string<span class="S0"> </span><span class="S5">const</span><span class="S0"> </span><span class="S10">&,</span><span class="S0"> </span>animal<span class="S0"> </span><span class="S10">>();</span><br /> +<span class="S10">}</span><br /> +<span class="S0"></span></span> +</body> +</html> Added: pyplusplus_dev/docs/documentation/tutorials/module_builder/www_configuration.py =================================================================== --- pyplusplus_dev/docs/documentation/tutorials/module_builder/www_configuration.py (rev 0) +++ pyplusplus_dev/docs/documentation/tutorials/module_builder/www_configuration.py 2006-07-20 07:01:05 UTC (rev 328) @@ -0,0 +1 @@ +name = 'module builder' \ No newline at end of file Added: pyplusplus_dev/docs/documentation/tutorials/pyplusplus_demo.png =================================================================== (Binary files differ) Property changes on: pyplusplus_dev/docs/documentation/tutorials/pyplusplus_demo.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: pyplusplus_dev/docs/documentation/tutorials/tutorials.rest =================================================================== --- pyplusplus_dev/docs/documentation/tutorials/tutorials.rest (rev 0) +++ pyplusplus_dev/docs/documentation/tutorials/tutorials.rest 2006-07-20 07:01:05 UTC (rev 328) @@ -0,0 +1,64 @@ +========= +tutorials +========= + +.. contents:: Table of contents + +------------------- +What is pyplusplus? +------------------- + +.. include:: ./../definition.rest + +------------------- +Graphical interface +------------------- + +`pyplusplus`_ includes a `graphical interface`_. `Graphical interface`_ +is invoked with the ``pyplusplus_gui`` command, or with ``pyplusplus_gui.pyw`` +from the ``scripts`` subdirectory of the `Python`_ installation directory. + +My advise to you - start with `graphical interface`_, because: + * you don't have to learn new API + * few clicks with mouse and you have `boost.python`_ code for your file(s) + * it is very easy to evaluate `pyplusplus`_ using it + * you can check whether `GCC-XML`_ is able to compile your code or not + * you can use it as a guide to `boost.python`_ library + * it is able to generate `pyplusplus`_ code for you + +.. _`graphical interface` : ./pyplusplus_demo.png +.. _`Graphical interface` : ./pyplusplus_demo.png + +--------------- +Getting started +--------------- + +I suppose you decided to do some coding with `pyplusplus`_. `Module builder`_ +tutorials will help you. + +.. _`Module builder` : ./module_builder/module_builder.html + +-------- +Advanced +-------- + +To be written. I think I should cover here the usage of code creators and code +creator's tree. Meanwhile you can take a look on the content of +``examples/custom_code_creator`` directory. It contains example, that shows how +to create your own code creator. To be more specific, it exposes ``get*`` and +``set*`` methods as a single property. + +.. _`pyplusplus` : ./../../pyplusplus.html +.. _`pygccxml` : ./../....//pygccxml/pygccxml.html +.. _`boost.python`: http://www.boost.org/libs/python/doc/index.html +.. _`SourceForge`: http://sourceforge.net/index.php +.. _`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/documentation/tutorials/www_configuration.py =================================================================== --- pyplusplus_dev/docs/documentation/tutorials/www_configuration.py (rev 0) +++ pyplusplus_dev/docs/documentation/tutorials/www_configuration.py 2006-07-20 07:01:05 UTC (rev 328) @@ -0,0 +1 @@ +name = 'tutorials' \ 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-20 06:53:20
|
Revision: 327 Author: roman_yakovenko Date: 2006-07-19 23:53:14 -0700 (Wed, 19 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=327&view=rev Log Message: ----------- moving FAQs to "documentation" directory Removed Paths: ------------- pyplusplus_dev/docs/faqs/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-20 06:50:51
|
Revision: 326 Author: roman_yakovenko Date: 2006-07-19 23:50:38 -0700 (Wed, 19 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=326&view=rev Log Message: ----------- adding "how to ... ?" to documentation Modified Paths: -------------- pyplusplus_dev/docs/documentation/index.rest pyplusplus_dev/docs/documentation/www_configuration.py Added Paths: ----------- pyplusplus_dev/docs/documentation/how_to.rest Added: pyplusplus_dev/docs/documentation/how_to.rest =================================================================== --- pyplusplus_dev/docs/documentation/how_to.rest (rev 0) +++ pyplusplus_dev/docs/documentation/how_to.rest 2006-07-20 06:50:38 UTC (rev 326) @@ -0,0 +1,124 @@ +============ +How to ... ? +============ + +.. contents:: Table of contents + +---------------------------------------- +How to add custom exception translation? +---------------------------------------- +:: + + struct my_exception{ + ... + const std::string& error() const; + ... + } + +First of all lets define ``translate`` function: + +:: + + translate_code = \ + """ + void translate(const my_exception &exception){ + PyErr_SetString( PyExc_RuntimeError, exception.error().c_str() ); + } + """ + +:: + + mb.add_declaration_code( translate_code ) + + +Now we should register it: + +:: + + registration_code = "boost::python::register_exception_translator<my_exception>(&translate);" + mb.add_registration_code( registration_code ) + +Small usage advice. +------------------- + +`pyplusplus`_ allows you to define a query that will return you all exception classes: + +:: + + mb = module_builder_t( ... ) + exception_classes = mb.decls( lambda decl: decl.name.endswith( 'exception' ) ) + +Now you can iterate on ``exception_classes``, generate and register translate +code for every class. + +That's all. + +------------------------------------------------------- +How to expose function, which has hand-written wrapper? +------------------------------------------------------- +:: + + struct window_t{ + ... + void get_size( int& height, int& widht ) const; + ... + }; + +You can not expose ``get_size`` function as is - ``int`` is immutable type in +Python. So, we need to create a wrapper to the function: +:: + + boost::python::tuple get_size_wrapper( const window_t& win ){ + int height(0), width( 0 ); + win.get_size( height, widht ); + return boost::python::make_tuple( height, width ); + } + +:: + + class_<window_t>( ... ) + .def( "get_size", &get_size_wrapper ) + ... + ; + +Now, after you know how this problem is solved. I will show how this solution +could be integrated with `pyplusplus`_. + + +:: + + wrapper_code = \ + """ + static boost::python::tuple get_size( const window_t& win ){ + int height(0), width( 0 ); + win.get_size( height, widht ); + return boost::python::make_tuple( height, width ); + } + """ + +:: + + registration_code = 'def( "get_size", &%s::get_size )' % window.wrapper_alias + +:: + + mb = module_builder_t( ... ) + window = mb.class_( "window_t" ) + window.member_function( "get_size" ).exclude() + window.add_wrapper_code( wrapper_code ) + window.add_code( registration_code ) + +That's all. + +.. _`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: Modified: pyplusplus_dev/docs/documentation/index.rest =================================================================== --- pyplusplus_dev/docs/documentation/index.rest 2006-07-20 06:23:22 UTC (rev 325) +++ pyplusplus_dev/docs/documentation/index.rest 2006-07-20 06:50:38 UTC (rev 326) @@ -4,8 +4,13 @@ .. contents:: Table of contents -* `STL Containers`_ +---- +XXXX +---- + ??? + + .. _`STL Containers` : ./containers.html Modified: pyplusplus_dev/docs/documentation/www_configuration.py =================================================================== --- pyplusplus_dev/docs/documentation/www_configuration.py 2006-07-20 06:23:22 UTC (rev 325) +++ pyplusplus_dev/docs/documentation/www_configuration.py 2006-07-20 06:50:38 UTC (rev 326) @@ -1,3 +1,5 @@ -name = 'C++ containers' -main_html_file = 'containers.html' -files_to_skip = ['indexing_suite_v2.html'] \ No newline at end of file +name = 'documentation' +main_html_file = 'index.html' +files_to_skip = ['indexing_suite_v2.html'] +names = { 'containers' : 'STL containers' + , 'how_to' : 'how to ... ?' } \ 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-20 06:23:28
|
Revision: 325 Author: roman_yakovenko Date: 2006-07-19 23:23:22 -0700 (Wed, 19 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=325&view=rev Log Message: ----------- fixing docutils errors Modified Paths: -------------- pyplusplus_dev/docs/faqs/faqs.rest Modified: pyplusplus_dev/docs/faqs/faqs.rest =================================================================== --- pyplusplus_dev/docs/faqs/faqs.rest 2006-07-20 05:33:34 UTC (rev 324) +++ pyplusplus_dev/docs/faqs/faqs.rest 2006-07-20 06:23:22 UTC (rev 325) @@ -18,6 +18,7 @@ First of all lets define ``translate`` function: :: + translate_code = \ """ void translate(const my_exception &exception){ @@ -29,6 +30,7 @@ mb.add_declaration_code( translate_code ) + Now we should register it: :: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-20 05:33:40
|
Revision: 324 Author: roman_yakovenko Date: 2006-07-19 22:33:34 -0700 (Wed, 19 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=324&view=rev Log Message: ----------- moving "std_containers" to "documentation" directory Removed Paths: ------------- pyplusplus_dev/docs/std_containers/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-20 05:31:33
|
Revision: 323 Author: roman_yakovenko Date: 2006-07-19 22:31:26 -0700 (Wed, 19 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=323&view=rev Log Message: ----------- moving API docs to "documentation" directory Added Paths: ----------- pyplusplus_dev/docs/documentation/apidocs/ pyplusplus_dev/docs/documentation/apidocs/www_configuration.py Added: pyplusplus_dev/docs/documentation/apidocs/www_configuration.py =================================================================== --- pyplusplus_dev/docs/documentation/apidocs/www_configuration.py (rev 0) +++ pyplusplus_dev/docs/documentation/apidocs/www_configuration.py 2006-07-20 05:31:26 UTC (rev 323) @@ -0,0 +1,2 @@ +name = 'API docs' +main_html_file = 'index.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-20 05:29:53
|
Revision: 322 Author: roman_yakovenko Date: 2006-07-19 22:29:42 -0700 (Wed, 19 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=322&view=rev Log Message: ----------- moving API docs to "documentation" directory Removed Paths: ------------- pyplusplus_dev/docs/apidocs/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-20 05:25:04
|
Revision: 321 Author: roman_yakovenko Date: 2006-07-19 22:24:58 -0700 (Wed, 19 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=321&view=rev Log Message: ----------- updating FAQs to use new interface Modified Paths: -------------- pyplusplus_dev/docs/faqs/faqs.rest Modified: pyplusplus_dev/docs/faqs/faqs.rest =================================================================== --- pyplusplus_dev/docs/faqs/faqs.rest 2006-07-20 05:21:56 UTC (rev 320) +++ pyplusplus_dev/docs/faqs/faqs.rest 2006-07-20 05:24:58 UTC (rev 321) @@ -1,6 +1,6 @@ -====================== -C++ containers support -====================== +============ +How to ... ? +============ .. contents:: Table of contents @@ -15,34 +15,26 @@ ... } -Generate exception translation function. ----------------------------------------- +First of all lets define ``translate`` function: -First of all you have to generate a header file, that will contain exception -translation function: :: + translate_code = \ + """ + void translate(const my_exception &exception){ + PyErr_SetString( PyExc_RuntimeError, exception.error().c_str() ); + } + """ - void translate(const my_exception &exception){ - PyErr_SetString( PyExc_RuntimeError, exception.error().c_str() ); - } - -Register exception translation function. ----------------------------------------- - :: - from pyplusplus import code_creators + mb.add_declaration_code( translate_code ) -:: +Now we should register it: - mb.build_code_creator( ... ) - mb.code_creator.add_include( generated header file name ) - :: - code = "boost::python::register_exception_translator<my_exception>(&translate);" - my_exc_translator = code_creators.custom_text_t( code ) - mb.code_creator.body.adopt_creator( my_exc_translator ) + registration_code = "boost::python::register_exception_translator<my_exception>(&translate);" + mb.add_registration_code( registration_code ) Small usage advice. ------------------- @@ -93,7 +85,8 @@ :: - wrapper_code = """ + wrapper_code = \ + """ static boost::python::tuple get_size( const window_t& win ){ int height(0), width( 0 ); win.get_size( height, widht ); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-20 05:22:03
|
Revision: 320 Author: roman_yakovenko Date: 2006-07-19 22:21:56 -0700 (Wed, 19 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=320&view=rev Log Message: ----------- testing new interface Modified Paths: -------------- pyplusplus_dev/unittests/module_body_tester.py Modified: pyplusplus_dev/unittests/module_body_tester.py =================================================================== --- pyplusplus_dev/unittests/module_body_tester.py 2006-07-20 05:19:45 UTC (rev 319) +++ pyplusplus_dev/unittests/module_body_tester.py 2006-07-20 05:21:56 UTC (rev 320) @@ -16,9 +16,14 @@ self , tester_t.EXTENSION_NAME , *args ) + + def customize(self, mb): + mb.build_code_creator( self.EXTENSION_NAME ) + mb.add_declaration_code( "int get1(){ return 1;} ") + mb.add_registration_code( 'bp::def( "get1", &get1 );' ) def run_tests(self, module): - pass + self.failUnless( 1 == module.get1() ) def create_suite(): 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-20 05:19:59
|
Revision: 319 Author: roman_yakovenko Date: 2006-07-19 22:19:45 -0700 (Wed, 19 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=319&view=rev Log Message: ----------- adding declaration/registration helpers Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/module.py pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py pyplusplus_dev/pyplusplus/module_builder/builder.py pyplusplus_dev/pyplusplus/module_creator/creator.py Modified: pyplusplus_dev/pyplusplus/code_creators/module.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/module.py 2006-07-20 05:04:20 UTC (rev 318) +++ pyplusplus_dev/pyplusplus/code_creators/module.py 2006-07-20 05:19:45 UTC (rev 319) @@ -4,9 +4,10 @@ # http://www.boost.org/LICENSE_1_0.txt) import os -import types +import types +import custom import license -import include +import include import namespace import compound import algorithm @@ -180,6 +181,13 @@ alias=alias , full_namespace_name=full_namespace_name ) , self.last_include_index() + 1 ) + + def adopt_declaration_creator( self, creator ): + self.adopt_creator( creator, self.creators.index( self.body ) ) + + def add_declaration_code( self, code, position ): + creator = custom.custom_text_t( code ) + self.adopt_creator( creator, min( position, self.creators.index( self.body ) ) ) @@ -189,6 +197,4 @@ - - \ No newline at end of file Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-20 05:04:20 UTC (rev 318) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-07-20 05:19:45 UTC (rev 319) @@ -97,14 +97,6 @@ return '' def _exportable_impl( self ): - #TODO: functions that takes as argument pointer to pointer to smth, could not be exported - #see http://www.boost.org/libs/python/doc/v2/faq.html#funcptr - if len( self.arguments ) > calldef_t.BOOST_PYTHON_MAX_ARITY: - msg = "Function '%s' has more than %d arguments ( %d ). " - msg = msg + " You should adjust BOOST_PYTHON_MAX_ARITY." - msg = msg + " For more information see: http://mail.python.org/pipermail/c++-sig/2002-June/001554.html" - self.logger.warning( msg % ( self.decl_string, calldef_t.BOOST_PYTHON_MAX_ARITY, len( self.arguments ) ) ) - all_types = [ arg.type for arg in self.arguments ] all_types.append( self.return_type ) for some_type in all_types: @@ -128,26 +120,35 @@ return "pyplusplus can not expose fuction that takes as argument/returns C++ arrays. This will be changed in near future." return self._exportable_impl_derived() - def _readme_impl( self ): + def _readme_impl( self ): def suspicious_type( type_ ): if not declarations.is_reference( self.return_type ): return False type_no_ref = declarations.remove_reference( type_ ) return not declarations.is_const( type_no_ref ) \ and declarations.is_fundamental( type_no_ref ) - msg = [] + msgs = [] + #TODO: functions that takes as argument pointer to pointer to smth, could not be exported + #see http://www.boost.org/libs/python/doc/v2/faq.html#funcptr + if len( self.arguments ) > calldef_t.BOOST_PYTHON_MAX_ARITY: + tmp = [ "Function '%s' has more than %d arguments ( %d ). " ] + tmp.append( os.linesep + "\tYou should adjust BOOST_PYTHON_MAX_ARITY." ) + tmp.append( os.linesep + "\tFor more information see: http://mail.python.org/pipermail/c++-sig/2002-June/001554.html" ) + tmp = ''.join( tmp ) + msgs.append( tmp % ( self.decl_string, calldef_t.BOOST_PYTHON_MAX_ARITY, len( self.arguments ) ) ) + if suspicious_type( self.return_type ) and None is self.call_policies: - msg.append( 'WARNING: Function "%s" returns non-const reference to C++ fundamental type - value can not be modified from Python.' % str( self ) ) + msgs.append( 'Function "%s" returns non-const reference to C++ fundamental type - value can not be modified from Python.' % str( self ) ) for index, arg in enumerate( self.arguments ): if suspicious_type( arg.type ): - tmpl = 'WARNING: Function "%s" takes as argument (name=%s, pos=%d ) ' \ + tmpl = 'Function "%s" takes as argument (name=%s, pos=%d ) ' \ + 'non-const reference to C++ fundamental type - ' \ + 'function could not be called from Python.' - msg.append( tmpl % ( str( self ), arg.name, index ) ) + msgs.append( tmpl % ( str( self ), arg.name, index ) ) if False == self.overridable: - msg.append( self.get_overridable.__doc__ ) - return msg + msgs.append( self.get_overridable.__doc__ ) + return msgs class member_function_t( declarations.member_function_t, calldef_t ): def __init__(self, *arguments, **keywords): Modified: pyplusplus_dev/pyplusplus/module_builder/builder.py =================================================================== --- pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-07-20 05:04:20 UTC (rev 318) +++ pyplusplus_dev/pyplusplus/module_builder/builder.py 2006-07-20 05:19:45 UTC (rev 319) @@ -6,14 +6,18 @@ import os import sys import time -import types +import types + from sets import Set as set + from pygccxml import parser -from pygccxml import declarations as decls_package +from pygccxml import declarations as decls_package + +from pyplusplus import _logging_ from pyplusplus import decl_wrappers -from pyplusplus import module_creator as mcreator_package -from pyplusplus import file_writers -from pyplusplus import _logging_ +from pyplusplus import file_writers +from pyplusplus import code_creators +from pyplusplus import module_creator as mcreator_package class module_builder_t(object): """ @@ -494,4 +498,18 @@ return decl_wrappers.calldef_t.BOOST_PYTHON_MAX_ARITY def _set_BOOST_PYTHON_MAX_ARITY( self, value ): decl_wrappers.calldef_t.BOOST_PYTHON_MAX_ARITY = value - BOOST_PYTHON_MAX_ARITY = property( _get_BOOST_PYTHON_MAX_ARITY, _set_BOOST_PYTHON_MAX_ARITY ) \ No newline at end of file + BOOST_PYTHON_MAX_ARITY = property( _get_BOOST_PYTHON_MAX_ARITY, _set_BOOST_PYTHON_MAX_ARITY ) + + def add_declaration_code( self, code, tail=True ): + position = 0 + if tail: + position = -1 + self.code_creator.add_declaration_code( code, position ) + + def add_registration_code( self, code, tail=True ): + position = 0 + if tail: + position = -1 + creator = code_creators.custom_text_t( code ) + self.code_creator.body.adopt_creator( creator, position ) + \ No newline at end of file Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-20 05:04:20 UTC (rev 318) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-20 05:19:45 UTC (rev 319) @@ -488,7 +488,7 @@ and class_traits.is_my_case( element_type ): value_cls = class_traits.get_declaration( element_type ) element_type_cc = code_creators.value_traits_t( value_cls ) - self.__extmodule.adopt_creator( element_type_cc, self.__extmodule.creators.index( self.__module_body ) ) + self.__extmodule.adopt_declaration_creator( element_type_cc ) cls_creator.adopt_creator( code_creators.indexing_suite2_t(cls) ) if INDEXING_SUITE_2_MAIN_HEADER in used_headers: @@ -701,7 +701,7 @@ #we deal with internal class self.curr_code_creator.wrapper.adopt_creator( wrapper ) else: - self.__extmodule.adopt_creator( wrapper, self.__extmodule.creators.index( self.__module_body ) ) + self.__extmodule.adopt_declaration_creator( wrapper ) if declarations.has_trivial_copy( self.curr_decl ): #I don't know but sometimes boost.python requieres #to construct wrapper from wrapped classe @@ -782,8 +782,7 @@ else: maker = code_creators.global_variable_t( variable=self.curr_decl ) if wrapper: - self.__extmodule.adopt_creator( wrapper - , self.__extmodule.creators.index( self.__module_body ) ) + self.__extmodule.adopt_declaration_creator( wrapper ) else: maker = None wrapper = None This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-07-20 05:04:33
|
Revision: 318 Author: roman_yakovenko Date: 2006-07-19 22:04:20 -0700 (Wed, 19 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=318&view=rev Log Message: ----------- moving indexing suite under documentation directory Added Paths: ----------- pyplusplus_dev/docs/documentation/ pyplusplus_dev/docs/documentation/containers.rest pyplusplus_dev/docs/documentation/index.rest pyplusplus_dev/docs/documentation/indexing_suite_v2.html pyplusplus_dev/docs/documentation/indexing_suite_v2_files/ pyplusplus_dev/docs/documentation/indexing_suite_v2_files/boost.css pyplusplus_dev/docs/documentation/indexing_suite_v2_files/cboost.gif pyplusplus_dev/docs/documentation/indexing_suite_v2_files/www_configuration.py pyplusplus_dev/docs/documentation/www_configuration.py Added: pyplusplus_dev/docs/documentation/containers.rest =================================================================== --- pyplusplus_dev/docs/documentation/containers.rest (rev 0) +++ pyplusplus_dev/docs/documentation/containers.rest 2006-07-20 05:04:20 UTC (rev 318) @@ -0,0 +1,202 @@ +====================== +C++ containers support +====================== + +.. contents:: Table of contents + +------------ +Introduction +------------ + +C++ has a bunch of container 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. + + +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 + +------------------------------ +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 container +``mapped_type`` ), in order to set reasonable defaults, when it generates the code. + +------------------- +Indexing suites API +------------------- + +By default, `pyplusplus`_ works with built-in indexing suite. If you want to use +next version of indexing suite, you should tell this to the ``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 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 API +--------------------------- + +`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 + + * fundamental type + + * enumeration + + * std::string or std::wstring + + * 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{ + ... + private: + bool operator==( const item& ) const; + bool operator<( const item& ) const; + }; + + 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. + +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. + +* ``[disable|enable]_methods_group`` - almost same as above, but allows you + to specify what group of methods you want to disable or enable. + ``indexing_suite2_t.METHOD_GROUPS`` containes names of all supported groups. + +Small tips/hints +---------------- + +1. If you set ``equality_comparable`` or ``less_than_comparable`` to ``False``. + The indexing suite will disable relevant functionality. You don't have + explicitly to disable method or mothods group. + +2. The documentation of new indexing suite containes few small mistakes. + I hope, I will have time to fix them. Any way, `pyplusplus`_ generates + correct code. + + +.. _`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/documentation/index.rest =================================================================== --- pyplusplus_dev/docs/documentation/index.rest (rev 0) +++ pyplusplus_dev/docs/documentation/index.rest 2006-07-20 05:04:20 UTC (rev 318) @@ -0,0 +1,24 @@ +============= +Documentation +============= + +.. contents:: Table of contents + +* `STL Containers`_ + +.. _`STL Containers` : ./containers.html + + + +.. _`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/documentation/indexing_suite_v2.html =================================================================== --- pyplusplus_dev/docs/documentation/indexing_suite_v2.html (rev 0) +++ pyplusplus_dev/docs/documentation/indexing_suite_v2.html 2006-07-20 05:04:20 UTC (rev 318) @@ -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 t... [truncated message content] |
From: <rom...@us...> - 2006-07-18 13:13:57
|
Revision: 317 Author: roman_yakovenko Date: 2006-07-18 06:13:47 -0700 (Tue, 18 Jul 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=317&view=rev Log Message: ----------- fixing warnings reporting Now py++ will write why declaration could not be exported. Also it will write additional information it has about declaration. Modified Paths: -------------- pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py pyplusplus_dev/pyplusplus/module_creator/creator.py pyplusplus_dev/pyplusplus/module_creator/types_database.py Modified: pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-07-18 08:52:35 UTC (rev 316) +++ pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-07-18 13:13:47 UTC (rev 317) @@ -24,10 +24,7 @@ this class are never created by the user, instead they are returned by the API. """ - - DO_NOT_REPORT_MSGS = [ "pyplusplus does not exports compiler generated constructors" ] - ALREADY_REPORTED_MSGS = set() - + def __init__(self): object.__init__(self) self._alias = None @@ -75,21 +72,8 @@ def rename( self, new_name ): self.alias = new_name - def __report_warning( self, reason ): - if reason in decl_wrapper_t.DO_NOT_REPORT_MSGS: - return - if reason in decl_wrapper_t.ALREADY_REPORTED_MSGS: - return - decl_wrapper_t.ALREADY_REPORTED_MSGS.add( reason ) - msg = [ 'Declaration "%s" could not be exported.' % declarations.full_name( self ) ] - reason = reason.replace( os.linesep, os.linesep + '\t' ) - msg.append( '\tReason: %s' % reason ) - self.logger.warn( os.linesep.join( msg ) ) - def _get_ignore( self ): - if False == self._ignore and not self.exportable: - self.__report_warning( self.why_not_exportable() ) - return self._ignore or not self.exportable + return self._ignore def _set_ignore( self, value ): self._ignore = value @@ -129,23 +113,6 @@ exportable = property( get_exportable, set_exportable , doc="Returns True if declaration could be exported to Python, otherwise False" ) - #TODO: - #I think that almost every declaration could have some wrapper. This is the - #main reason why those 3 functions does not have some well defined interface. - #def has_wrapper( self ): - #return False - - #def _finalize_impl( self, error_behavior ): - #pass - - #def finalize( self, error_behavior=None): - #try: - #self._finalize_impl( self ) - #except Exception, error: - #if None is error_behavior or error_behavior == ERROR_BEHAVIOR.PRINT: - #print 'Unable to finalize declaration: ', str( error ) - #else: - #raise def _readme_impl( self ): return [] @@ -157,6 +124,6 @@ """ text = [] if not self.exportable: - text.append( 'WARNING: ' + self.why_not_exportable() ) + text.append( self.why_not_exportable() ) text.extend( self._readme_impl() ) return text Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-18 08:52:35 UTC (rev 316) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-07-18 13:13:47 UTC (rev 317) @@ -2,7 +2,8 @@ # 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 types_database import class_organizer @@ -43,8 +44,9 @@ #TODO: queue, priority, stack, multimap, hash_multimap, multiset, hash_multiset } -INDEXING_SUITE_2_MAIN_HEADER = "boost/python/suite/indexing/container_suite.hpp" +INDEXING_SUITE_2_MAIN_HEADER = "boost/python/suite/indexing/container_suite.hpp" +DO_NOT_REPORT_MSGS = [ "pyplusplus does not exports compiler generated constructors" ] class creator_t( declarations.decl_visitor_t ): """Creating code creators. @@ -90,7 +92,8 @@ @type doc_extractor: callable """ declarations.decl_visitor_t.__init__(self) - self.logger = _logging_.loggers.module_builder + self.logger = _logging_.loggers.module_builder + self.decl_logger = _logging_.loggers.declarations self.__enable_indexing_suite = enable_indexing_suite self.__target_configuration = target_configuration @@ -127,25 +130,42 @@ self.__array_1_registered = set() #(type.decl_string,size) self.__free_operators = [] - def _prepare_decls( self, decls, doc_extractor ): + def _prepare_decls( self, decls, doc_extractor ): + global DO_NOT_REPORT_MSGS decls = declarations.make_flatten( decls ) #leave only declarations defined under namespace, but remove namespaces decls = filter( lambda x: not isinstance( x, declarations.namespace_t ) \ and isinstance( x.parent, declarations.namespace_t ) , decls ) - #leave only decls that should be exported - decls = filter( lambda x: not x.ignore, decls ) - if doc_extractor: - start_time = time.clock() - self.logger.debug( 'Documentation extraction process started.' ) + #leave only decls that user wants to export + decls = filter( lambda x: not x.ignore, decls ) + + for decl in decls: + if doc_extractor and decl.exportable: + decl.documentation = doc_extractor( decl ) + + readme = decl.readme() + if not readme: + continue + #Now we should print what py++ has to say to user + full_name = declarations.full_name( decl ) + if not decl.name: + full_name = full_name + '::{unnamed}' + + if not decl.exportable: + reason = readme[0] + if reason in DO_NOT_REPORT_MSGS: + continue + readme = readme[1:] + msg = [ 'Declaration "%s" could not be exported.' % full_name ] + msg.append( reason.replace( os.linesep, os.linesep + '\t' ) ) + self.decl_logger.warn( os.linesep.join( msg ) ) + + for msg in readme: + self.decl_logger.warn( 'Declaration "%s": %s' % ( full_name, msg ) ) + + return filter( lambda x: x.exportable, decls ) - for decl in decls: - decl.documentation = doc_extractor( decl ) - - self.logger.debug( 'Documentation extraction process finished in %F seconds' - % ( time.clock() - start_time ) ) - return decls - def _reorder_decls(self, decls ): classes = filter( lambda x: isinstance( x, declarations.class_t ) , decls ) @@ -192,7 +212,7 @@ def _exportable_class_members( self, class_decl ): assert isinstance( class_decl, declarations.class_t ) - members = filter( lambda mv: mv.ignore == False, class_decl.public_members ) + members = filter( lambda mv: mv.ignore == False and mv.exportable, class_decl.public_members ) #protected and private virtual functions that not overridable and not pure #virtual should not be exported for member in class_decl.protected_members: @@ -214,7 +234,7 @@ members = filter( lambda decl: not isinstance( decl, declarations.constructor_t ) or not decl.is_artificial , members ) - members = filter( lambda member: not member.ignore, members ) + members = filter( lambda member: member.ignore == False and member.exportable, members ) ordered_members = self._reorder_decls( members ) return ordered_members @@ -253,7 +273,7 @@ return True def redefined_funcs( self, cls ): - all_included = declarations.custom_matcher_t( lambda decl: decl.ignore == False ) + all_included = declarations.custom_matcher_t( lambda decl: decl.ignore == False and decl.exportable ) all_protected = declarations.access_type_matcher_t( 'protected' ) & all_included all_pure_virtual = declarations.virtuality_type_matcher_t( VIRTUALITY_TYPES.PURE_VIRTUAL ) all_not_pure_virtual = ~all_pure_virtual @@ -567,8 +587,6 @@ return ( maker_cls, fwrapper_cls ) def visit_member_function( self ): - if self.curr_decl.ignore: - return fwrapper = None self.__types_db.update( self.curr_decl ) if None is self.curr_decl.call_policies: @@ -601,9 +619,6 @@ self.curr_code_creator.adopt_creator( static_method ) def visit_constructor( self ): - if self.curr_decl.ignore: - return - if self.curr_decl.is_copy_constructor: return self.__types_db.update( self.curr_decl ) @@ -629,9 +644,6 @@ pass def visit_member_operator( self ): - if self.curr_decl.ignore: - return - if self.curr_decl.symbol in ( '()', '[]' ): self.visit_member_function() else: @@ -640,9 +652,6 @@ self.curr_code_creator.adopt_creator( maker ) def visit_casting_operator( self ): - if self.curr_decl.ignore: - return - if not declarations.is_fundamental( self.curr_decl.return_type ) \ and not self.curr_decl.has_const: return #only const casting operators can generate implicitly_convertible @@ -661,8 +670,6 @@ self.curr_code_creator.adopt_creator( maker ) def visit_free_function( self ): - if self.curr_decl.ignore: - return self.__types_db.update( self.curr_decl ) maker = code_creators.free_function_t( function=self.curr_decl ) if None is self.curr_decl.call_policies: @@ -670,9 +677,6 @@ self.curr_code_creator.adopt_creator( maker ) def visit_free_operator( self ): - if self.curr_decl.ignore: - return - self.__types_db.update( self.curr_decl ) self.__free_operators.append( self.curr_decl ) @@ -680,8 +684,6 @@ pass def visit_class(self ): - if self.curr_decl.ignore: - return assert isinstance( self.curr_decl, declarations.class_t ) temp_curr_decl = self.curr_decl temp_curr_parent = self.curr_code_creator @@ -736,9 +738,6 @@ self.curr_code_creator = temp_curr_parent def visit_enumeration(self): - if self.curr_decl.ignore: - return - assert isinstance( self.curr_decl, declarations.enumeration_t ) maker = None if self.curr_decl.name: @@ -762,9 +761,6 @@ return True def visit_variable(self): - if self.curr_decl.ignore: - return - self.__types_db.update( self.curr_decl ) if declarations.is_array( self.curr_decl.type ): Modified: pyplusplus_dev/pyplusplus/module_creator/types_database.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/types_database.py 2006-07-18 08:52:35 UTC (rev 316) +++ pyplusplus_dev/pyplusplus/module_creator/types_database.py 2006-07-18 13:13:47 UTC (rev 317) @@ -74,10 +74,10 @@ check_extraction = container_cls.indexing_suite.element_type except RuntimeError, error: msg = [] - msg.append( 'pyplusplus found class "%s" - instantiation declaration, not definition.' % container_cls.name ) - msg.append( 'pyplusplus can not find out container value_type( mapped_type )!' ) - msg.append( 'This class will be exported, but there is a posiblity, that generated code will not compile.' ) - msg.append( 'The solution to the problem is to create a variable of the class.' ) + msg.append( 'pyplusplus found template class instantiation "%s" declaration ( not definition ). ' % container_cls.name ) + msg.append( '\tpyplusplus can not find out container value_type( mapped_type )!' ) + msg.append( '\tThis class will be exported, but there is a posiblity, that generated code will not compile.' ) + msg.append( '\tThe solution to the problem is to create a variable of the class.' ) _logging_.loggers.declarations.warn( os.linesep.join( msg ) ) self.__containers.add( container_cls ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |