[pygccxml-commit] SF.net SVN: pygccxml: [805] pyplusplus_dev
Brought to you by:
mbaas,
roman_yakovenko
From: <rom...@us...> - 2006-12-20 06:56:59
|
Revision: 805 http://svn.sourceforge.net/pygccxml/?rev=805&view=rev Author: roman_yakovenko Date: 2006-12-19 22:56:58 -0800 (Tue, 19 Dec 2006) Log Message: ----------- improving named_tuple functionality Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_repository/convenience.py pyplusplus_dev/pyplusplus/code_repository/named_tuple.py pyplusplus_dev/pyplusplus/file_writers/writer.py pyplusplus_dev/pyplusplus/function_transformers/controllers.py pyplusplus_dev/pyplusplus/function_transformers/templates.py pyplusplus_dev/pyplusplus/function_transformers/transformer.py pyplusplus_dev/pyplusplus/module_creator/creator.py pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp pyplusplus_dev/unittests/function_transformations_tester.py pyplusplus_dev/unittests/temp/named_tuple.py Modified: pyplusplus_dev/pyplusplus/code_repository/convenience.py =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/convenience.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/pyplusplus/code_repository/convenience.py 2006-12-20 06:56:58 UTC (rev 805) @@ -137,19 +137,32 @@ inline boost::python::object get_out_argument( boost::python::object result, const char* arg_name ){ - if( PySequence_Check( result.ptr() ) ){ - return boost::python::getattr( result, arg_name ); + if( !PySequence_Check( result.ptr() ) ){ + return result; } + boost::python::object cls = boost::python::getattr( result, "__class__" ); + boost::python::object cls_name = boost::python::getattr( cls, "__name__" ); + std::string name = boost::python::extract< std::string >( cls_name ); + if( "named_tuple" == name ){ + return boost::python::getattr( result, arg_name ); + } else{ return result; } + } inline boost::python::object get_out_argument( boost::python::object result, index_type index ){ - if( PySequence_Check( result.ptr() ) ){ - return result[ index ]; + if( !PySequence_Check( result.ptr() ) ){ + return result; } + boost::python::object cls = boost::python::getattr( result, "__class__" ); + boost::python::object cls_name = boost::python::getattr( cls, "__name__" ); + std::string name = boost::python::extract< std::string >( cls_name ); + if( "named_tuple" == name ){ + return result[ index ]; + } else{ return result; } Modified: pyplusplus_dev/pyplusplus/code_repository/named_tuple.py =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/named_tuple.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/pyplusplus/code_repository/named_tuple.py 2006-12-20 06:56:58 UTC (rev 805) @@ -12,31 +12,18 @@ # http://www.boost.org/LICENSE_1_0.txt) class named_tuple(tuple): - \"\"\"Creates tuple, which allows access to stored values by name and by index. + \"\"\"Creates tuple, which allows access to stored values by name and\\or by index. - named_tuple could be constructed exactly in the same way as Python dict. + Construction example: named_tuple( ('a',0), ('b',1) ) + 'a' and 'b' are names, while 0 and 1 are values \"\"\" - def __new__(cls, seq=None, **keywd): - if seq: - if isinstance( seq, dict ): - return tuple.__new__( cls, seq.values() ) - else: - return tuple.__new__( cls, [ val for name, val in seq] ) - else: - return tuple.__new__( cls, keywd.values() ) + def __new__(cls, *args): + return tuple.__new__( cls, [ val for name, val in args] ) - def __init__(self, seq=None, **keywd): - "named_tuple could be constructed exactly in the same way as Python dict." + def __init__(self, *args): tuple.__init__( self ) - if seq: - if isinstance( seq, dict ): - name2value = dict( seq.iteritems() ) - else: - name2value = dict( seq ) - else: - name2value = dict( keywd ) - self.__dict__[ '__name2value' ] = name2value + self.__dict__[ '__name2value' ] = dict( args ) def __getattr__(self, name): try: @@ -56,7 +43,7 @@ return super( named_tuple, self ).__getitem__( key ) if __name__ == '__main__': - nt = named_tuple( a=0, b=1) + nt = named_tuple( ('a',0), ('b',1) ) assert nt.a == 0 and nt.b == 1 a,b = nt assert a == 0 and b == 1 Modified: pyplusplus_dev/pyplusplus/file_writers/writer.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/writer.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/pyplusplus/file_writers/writer.py 2006-12-20 06:56:58 UTC (rev 805) @@ -50,12 +50,7 @@ for cr in code_repository.all: if self.__extmodule.is_system_header( cr.file_name ): self.write_file( os.path.join( dir, cr.file_name ), cr.code ) - #temporal patch: always write named_tuple.py file - f = file( os.path.join( dir, code_repository.named_tuple.file_name ), 'w+b' ) - f.write( code_repository.named_tuple.code ) - f.close() - @staticmethod def write_file( fpath, content ): """Write a source file. @@ -73,7 +68,10 @@ writer_t.logger.debug( 'write code to file "%s" - started' % fpath ) start_time = time.clock() fcontent_new = [] - fcontent_new.append( '// This file has been generated by Py++.' ) + if os.path.splitext( fpath )[1] == '.py': + fcontent_new.append( '# This file has been generated by Py++.' ) + else: + fcontent_new.append( '// This file has been generated by Py++.' ) fcontent_new.append( os.linesep * 2 ) fcontent_new.append( content ) fcontent_new.append( os.linesep ) #keep gcc happy Modified: pyplusplus_dev/pyplusplus/function_transformers/controllers.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/controllers.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/pyplusplus/function_transformers/controllers.py 2006-12-20 06:56:58 UTC (rev 805) @@ -1,3 +1,16 @@ +# Copyright 2006 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +"""defines controller classes which help to define the function transformation + +The idea behind implementation of "Function Transformation" functionality is simple: +Py++ defines few templates. Transformers are just editors for the templates. +In most cases, transformers don't directly edit the template, but use controller +classes for this purpose. Controller classes provide an abstraction of the templates. +""" + import string import templates from pygccxml import declarations @@ -3,5 +16,14 @@ class variable_t( object ): + """defines C++ variable""" def __init__( self, type, name, initialize_expr='' ): + """ + @param type: type of the variable + @type type: instance of L{pygccxml.declarations.type_t} + + @param name: name( str ) of the variable + + @param initialize_expr: an expression that initialize the variable + """ self.__name = name self.__type = type @@ -10,14 +32,17 @@ @property def name( self ): + "variable name" return self.__name @property def type( self ): + "variable type" return self.__type @property def initialize_expr( self ): + "inirialize expression" return self.__initialize_expr def declare_var_string( self ): @@ -27,6 +52,14 @@ , initialize_expr=self.initialize_expr ) class variables_manager_t( object ): + """function wrapper variables manager + + Almost every time we define new transformer, we need to define variables. + It is important to keep the variable names unique. This class will ensure this. + Every time you declare new variable, it will return the unique variable name. + The name will be built from the original variable name and some index, which + will make the variable to be unique. + """ def __init__( self ): object.__init__( self ) self.__variables = [] #variables @@ -34,14 +67,32 @@ @property def variables( self ): + "list of all declared variables" return self.__variables def declare_variable( self, type, name, initialize_expr='' ): + """declare variable + + @param type: type of the variable + @type type: instance of L{pygccxml.declarations.type_t} + + @param name: name( str ) of the variable + + @param initialize_expr: an expression that initialize the variable + + @return: the unique variable name + """ unique_name = self.__create_unique_var_name( name ) self.__variables.append( variable_t( type, unique_name, initialize_expr ) ) return unique_name def register_name( self, name ): + """register predefined variable name + + There are use cases, where it is convenience to define variables within + a template. In such cases, the only thing that should be done is registering + a unique name of the variable. + """ return self.__create_unique_var_name( name ) def __create_unique_var_name( self, name ): @@ -61,6 +112,8 @@ return vm class controller_base_t( object ): + """base class for all controller classes""" + def __init__( self, function ): self.__function = function @@ -69,10 +122,11 @@ return self.__function def apply( self, transformations ): + """asks all transformations to configure the controller""" raise NotImplementedError() class sealed_fun_controller_t( controller_base_t ): - #base class for free and member function controllers + """base class for free and member function controllers""" def __init__( self, function ): controller_base_t.__init__( self, function ) self.__vars_manager = create_variables_manager( function ) @@ -104,7 +158,7 @@ @property def wrapper_args( self ): - return self.__wrapper_args + return filter( None, self.__wrapper_args ) def find_wrapper_arg( self, name ): for arg in self.wrapper_args: @@ -116,7 +170,7 @@ arg = self.find_wrapper_arg( name ) if not arg: raise LookupError( "Unable to remove '%s' argument - not found!" % name ) - del self.wrapper_args[ self.wrapper_args.index(arg) ] + self.__wrapper_args[ self.__wrapper_args.index(arg) ] = None @property def arg_expressions( self ): Modified: pyplusplus_dev/pyplusplus/function_transformers/templates.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/templates.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/pyplusplus/function_transformers/templates.py 2006-12-20 06:56:58 UTC (rev 805) @@ -5,11 +5,12 @@ # Matthias Baas is an initial author of the templates. +"""defines few templates, which will be used to create a function-wrapper +definition.""" + import os from string import Template -#TODO: pre_call, post_call terminology should be changed. Use prefix and suffix -#instead: http://boost.org/libs/smart_ptr/sp_techniques.html#wrapper class sealed_fun: body = Template( os.linesep.join([ Modified: pyplusplus_dev/pyplusplus/function_transformers/transformer.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/transformer.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/pyplusplus/function_transformers/transformer.py 2006-12-20 06:56:58 UTC (rev 805) @@ -2,8 +2,6 @@ # 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 author: Matthias Baas """This module contains the class L{transformer_t}. """ @@ -12,23 +10,15 @@ from pygccxml import declarations, parser return_ = -1 +#return_ is a spacial const, which represent an index of return type class transformer_t: + """Base class for a function transformer.""" + USE_1_BASED_INDEXING = False - - """Base class for a function transformer. - - This class specifies the interface that a user written transformer - has to implement. It doesn't contain any actual functionality so - a user doesn't have to derive from this class. Methods that are not - implemented are treated as if they would do nothing and return None. - - @author: Matthias Baas - """ - + def __init__(self, function): - """Constructor. - """ + """@param function: reference to function declaration""" self.__function = function @property @@ -41,6 +31,10 @@ return [] def get_argument( self, reference ): + """returns reference to the desired argument + + @param reference: name( str ) or index( int ) of the argument + """ if isinstance( reference, str ): found = filter( lambda arg: arg.name == reference, self.function.arguments ) if len( found ) == 1: @@ -53,6 +47,10 @@ return self.function.arguments[ reference ] def get_type( self, reference ): + """returns type of the desired argument or return type of the function + + @param reference: name( str ) or index( int ) of the argument + """ global return_ if isinstance( reference, int ) and reference == return_: return self.function.return_type @@ -60,9 +58,26 @@ return self.get_argument( reference ).type def configure_mem_fun( self, controller ): + """Transformers should overridde the method, in order to define custom + transformation for non-virtual member function. + + @param controller: instance of L{mem_fun_controller_t} class + """ pass def configure_free_fun( self, controller ): + """Transformers should overridde the method, in order to define custom + transformation for free function. + + @param controller: instance of L{free_fun_controller_t} class + """ pass - \ No newline at end of file + def configure_virtual_mem_fun( self, controller ): + """Transformers should overridde the method, in order to define custom + transformation for virtual member function. + + @param controller: instance of L{virtual_mem_fun_controller_t} class + """ + pass + Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-12-20 06:56:58 UTC (rev 805) @@ -428,7 +428,10 @@ # Check if it is a header from the code repository if header in code_repository.headers: self.__extmodule.add_system_header( header ) - + + if not self.__extmodule.is_system_header( code_repository.named_tuple.file_name ): + self.__extmodule.add_system_header( code_repository.named_tuple.file_name ) + if self.curr_decl.has_static: #static_method should be created only once. found = filter( lambda creator: isinstance( creator, code_creators.static_method_t ) Modified: pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/unittests/data/function_transformations_to_be_exported.hpp 2006-12-20 06:56:58 UTC (rev 805) @@ -184,6 +184,13 @@ }; struct bug_render_target_t{ + + static float get_static_statistics( bug_render_target_t& inst ){ + float x,y; + inst.get_statistics( x, y ); + return x+y; + } + virtual void get_statistics( float& x, float& y ) const{ x = 1.1;; y = 1.2; Modified: pyplusplus_dev/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev/unittests/function_transformations_tester.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/unittests/function_transformations_tester.py 2006-12-20 06:56:58 UTC (rev 805) @@ -8,7 +8,6 @@ import math import unittest import fundamental_tester_base -from named_tuple import named_tuple from pyplusplus import function_transformers as ft from pyplusplus.module_builder import call_policies @@ -140,15 +139,16 @@ return self.m_height+1 def fixed_output_array(self): + from named_tuple import named_tuple # Produce a correct return value if self.fixed_output_array_mode==0: - return named_tuple( v=(2,5,7) ) + return named_tuple( ('v', (2,5,7)) ) # Produce the wrong type elif self.fixed_output_array_mode==1: return 5 # Produce a sequence with the wrong number of items elif self.fixed_output_array_mode==2: - return named_tuple( v=(2,5) ) + return named_tuple( ('v', (2,5)) ) pyimg1 = py_image1_t(3,7) @@ -202,6 +202,18 @@ cls = module.no_virtual_members_t() self.assertEqual(cls.member(), (True, 17)) + class py_bug_render_target_t( module.bug_render_target_t ): + def __init__( self ): + module.bug_render_target_t.__init__( self ) + + def get_statistics( self ): + from named_tuple import named_tuple + return named_tuple( ( 'x', 2.0 ), ( 'y', 3.0 ) ) + tmp = py_bug_render_target_t() + + tmp.get_statistics() + self.failUnless( 2.0 + 3.0 == module.bug_render_target_t.get_static_statistics( tmp ) ) + def create_suite(): suite = unittest.TestSuite() suite.addTest( unittest.makeSuite(tester_t)) Modified: pyplusplus_dev/unittests/temp/named_tuple.py =================================================================== --- pyplusplus_dev/unittests/temp/named_tuple.py 2006-12-18 08:36:12 UTC (rev 804) +++ pyplusplus_dev/unittests/temp/named_tuple.py 2006-12-20 06:56:58 UTC (rev 805) @@ -1,3 +1,5 @@ +# This file has been generated by Py++. + # Copyright 2004 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at @@ -4,31 +6,18 @@ # http://www.boost.org/LICENSE_1_0.txt) class named_tuple(tuple): - """Creates tuple, which allows access to stored values by name and by index. + """Creates tuple, which allows access to stored values by name and\or by index. - named_tuple could be constructed exactly in the same way as Python dict. + Construction example: named_tuple( ('a',0), ('b',1) ) + 'a' and 'b' are names, while 0 and 1 are values """ - def __new__(cls, seq=None, **keywd): - if seq: - if isinstance( seq, dict ): - return tuple.__new__( cls, seq.values() ) - else: - return tuple.__new__( cls, [ val for name, val in seq] ) - else: - return tuple.__new__( cls, keywd.values() ) + def __new__(cls, *args): + return tuple.__new__( cls, [ val for name, val in args] ) - def __init__(self, seq=None, **keywd): - "named_tuple could be constructed exactly in the same way as Python dict." + def __init__(self, *args): tuple.__init__( self ) - if seq: - if isinstance( seq, dict ): - name2value = dict( seq.iteritems() ) - else: - name2value = dict( seq ) - else: - name2value = dict( keywd ) - self.__dict__[ '__name2value' ] = name2value + self.__dict__[ '__name2value' ] = dict( args ) def __getattr__(self, name): try: @@ -48,9 +37,10 @@ return super( named_tuple, self ).__getitem__( key ) if __name__ == '__main__': - nt = named_tuple( a=0, b=1) + nt = named_tuple( ('a',0), ('b',1) ) assert nt.a == 0 and nt.b == 1 a,b = nt assert a == 0 and b == 1 assert nt[ "a" ] == 0 and nt[ "b" ] == 1 + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |