pygccxml-commit Mailing List for C++ Python language bindings (Page 44)
Brought to you by:
mbaas,
roman_yakovenko
You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
(190) |
Apr
(166) |
May
(170) |
Jun
(75) |
Jul
(105) |
Aug
(131) |
Sep
(99) |
Oct
(84) |
Nov
(67) |
Dec
(54) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(66) |
Feb
(49) |
Mar
(25) |
Apr
(62) |
May
(21) |
Jun
(34) |
Jul
(9) |
Aug
(21) |
Sep
(5) |
Oct
|
Nov
(63) |
Dec
(34) |
2008 |
Jan
(10) |
Feb
(42) |
Mar
(26) |
Apr
(25) |
May
(6) |
Jun
(40) |
Jul
(18) |
Aug
(29) |
Sep
(6) |
Oct
(32) |
Nov
(14) |
Dec
(56) |
2009 |
Jan
(127) |
Feb
(52) |
Mar
(2) |
Apr
(10) |
May
(29) |
Jun
(3) |
Jul
|
Aug
(16) |
Sep
(4) |
Oct
(11) |
Nov
(8) |
Dec
(14) |
2010 |
Jan
(31) |
Feb
(1) |
Mar
(7) |
Apr
(9) |
May
(1) |
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2011 |
Jan
|
Feb
(8) |
Mar
(4) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2014 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <rom...@us...> - 2006-12-06 13:29:41
|
Revision: 783 http://svn.sourceforge.net/pygccxml/?rev=783&view=rev Author: roman_yakovenko Date: 2006-12-06 05:29:40 -0800 (Wed, 06 Dec 2006) Log Message: ----------- adding missing package Modified Paths: -------------- pyplusplus_dev/setup.py Modified: pyplusplus_dev/setup.py =================================================================== --- pyplusplus_dev/setup.py 2006-12-06 10:24:40 UTC (rev 782) +++ pyplusplus_dev/setup.py 2006-12-06 13:29:40 UTC (rev 783) @@ -107,6 +107,7 @@ 'pyplusplus.module_builder', 'pyplusplus.utils', 'pyplusplus.function_transformers', - 'pyplusplus._logging_'], + 'pyplusplus._logging_', + 'pyplusplus.messages'], cmdclass = {"doc" : doc_cmd} ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-06 10:24:41
|
Revision: 782 http://svn.sourceforge.net/pygccxml/?rev=782&view=rev Author: roman_yakovenko Date: 2006-12-06 02:24:40 -0800 (Wed, 06 Dec 2006) Log Message: ----------- updating documentation + small convenience function to disable warnings Modified Paths: -------------- pyplusplus_dev/docs/documentation/feedback.rest pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py pyplusplus_dev/pyplusplus/messages/__init__.py Property Changed: ---------------- pyplusplus_dev/pyplusplus/messages/ Modified: pyplusplus_dev/docs/documentation/feedback.rest =================================================================== --- pyplusplus_dev/docs/documentation/feedback.rest 2006-12-06 10:17:51 UTC (rev 781) +++ pyplusplus_dev/docs/documentation/feedback.rest 2006-12-06 10:24:40 UTC (rev 782) @@ -40,20 +40,34 @@ * .. code-block:: C++ - struct window{ - ... - void get_size( int& heght, int& widht ) const; - }; + struct window{ + ... + void get_size( int& heght, int& widht ) const; + }; Member function ``get_size`` can be exposed to Python, but it will not be callable because [FILL IN HERE]. * In order to expose free/member function that takes more than 10 arguments user should define ``BOOST_PYTHON_MAX_ARITY`` macro. - + +* + .. code-block:: C++ + + struct X{ + ... + }; + + void do_smth( X x ); + + If you expose ``do_smth`` function and don't expose struct ``X``, `Py++`_ + will tell you that struct ``X`` is used in exported declaration, but was not + exposed. + For these problems and many other `Py++`_ gives a nice explanation and sometimes a link to the relevant information on the Internet. -I hope, that from now you will find it helpful to read every `Py++`_ message :-). +I don't know what about you, but I found these messages pretty useful. They allow +me to deliver Python bindings with higher quality. ------------- How it works? @@ -68,10 +82,54 @@ default, messages with ``DEBUG`` level will be skipped, all other messages will be reported. +-------- +Warnings +-------- + +Example of the warning: +:: + + WARNING: containers::item_t [struct] + > warning W1020: Py++ will generate class wrapper - hand written code + > should be added to the wrapper class + +Almost every warning reported by `Py++`_ consists from 3 parts: + +* description of the declaration it refers to: "containers::item_t [struct]" + +* warning unique identifier: "W1020" + +* short explanation of the problem: "Py++ will generate class wrapper - hand + written code should be added to the wrapper class" + --------------- API Description --------------- +How to disable warning(s)? +-------------------------- + +Every warning has unique identifier. In the example I gave it was ``W1020``. + +.. code-block:: Python + + from pyplusplus import messages + from pyplusplus import module_builder + + mb = module_builder.module_builder_t( ... ) + xyz = mb.class_( XYZ ) + xyz.disable_warnings( messages.W1020 ) + +It is also possible to disable warnings for all declarations. ``pyplusplus.messages`` +package defines ``DISABLE_MESSAGES`` variable. This variable( ``list`` ) keeps +all warnings, which should not be reported. Use ``messages.disable`` function to +edit it: + +.. code-block:: Python + + messages.disable( messages.W1020 ) + + Logging API ----------- Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-12-06 10:17:51 UTC (rev 781) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-12-06 10:24:40 UTC (rev 782) @@ -153,7 +153,8 @@ return False type_no_ref = declarations.remove_reference( type_ ) return not declarations.is_const( type_no_ref ) \ - and python_traits.is_immutable( type_no_ref ) + and ( declarations.is_fundamental( type_no_ref ) + or declarations.is_enum( type_no_ref ) ) 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 Property changes on: pyplusplus_dev/pyplusplus/messages ___________________________________________________________________ Name: svn:ignore + *.pyc Modified: pyplusplus_dev/pyplusplus/messages/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/messages/__init__.py 2006-12-06 10:17:51 UTC (rev 781) +++ pyplusplus_dev/pyplusplus/messages/__init__.py 2006-12-06 10:24:40 UTC (rev 782) @@ -23,6 +23,8 @@ ] #Messages kept by DISABLE_MESSAGES list will not be reported +def disable( *args ): + DISABLE_MESSAGES.extend( args ) def filter_disabled_msgs( msgs, disable_messages=None ): report = [] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-06 10:17:50
|
Revision: 781 http://svn.sourceforge.net/pygccxml/?rev=781&view=rev Author: roman_yakovenko Date: 2006-12-06 02:17:51 -0800 (Wed, 06 Dec 2006) Log Message: ----------- small improvement for declaration description Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/calldef.py pygccxml_dev/pygccxml/declarations/declaration.py Modified: pygccxml_dev/pygccxml/declarations/calldef.py =================================================================== --- pygccxml_dev/pygccxml/declarations/calldef.py 2006-12-06 08:44:14 UTC (rev 780) +++ pygccxml_dev/pygccxml/declarations/calldef.py 2006-12-06 10:17:51 UTC (rev 781) @@ -312,6 +312,7 @@ cls = self.__class__.__name__ if cls[-2:]=="_t": cls = cls[:-2] + cls = cls.replace( '_', ' ' ) return "%s [%s]"%(res, cls) def _get__cmp__call_items(self): @@ -392,6 +393,7 @@ cls = self.__class__.__name__ if cls[-2:]=="_t": cls = cls[:-2] + cls = cls.replace( '_', ' ' ) return "%s [%s]"%(res, cls) def _get__cmp__call_items(self): Modified: pygccxml_dev/pygccxml/declarations/declaration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/declaration.py 2006-12-06 08:44:14 UTC (rev 780) +++ pygccxml_dev/pygccxml/declarations/declaration.py 2006-12-06 10:17:51 UTC (rev 781) @@ -95,6 +95,7 @@ cls = self.__class__.__name__ if cls[-2:]=="_t": cls = cls[:-2] + cls = cls.replace( '_', ' ' ) return "%s [%s]"%(name, cls) @staticmethod This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-06 08:44:15
|
Revision: 780 http://svn.sourceforge.net/pygccxml/?rev=780&view=rev Author: roman_yakovenko Date: 2006-12-06 00:44:14 -0800 (Wed, 06 Dec 2006) Log Message: ----------- adding missing module Added Paths: ----------- pyplusplus_dev/pyplusplus/messages/warnings_.py Added: pyplusplus_dev/pyplusplus/messages/warnings_.py =================================================================== --- pyplusplus_dev/pyplusplus/messages/warnings_.py (rev 0) +++ pyplusplus_dev/pyplusplus/messages/warnings_.py 2006-12-06 08:44:14 UTC (rev 780) @@ -0,0 +1,130 @@ +# 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) + +"""This package defines all user messages( warnings + errors ), which will be +reported to user. +""" + +W1000 = 'Py++, by default, does not expose internal compilers declarations.'\ + 'Names of those declarations usually start with "__".' + +W1001 = 'Py++, by default, does not expose internal declarations. ' \ + 'GCC-XML reports that these declaration belong to "<internal>" header.' + +W1002 = 'Py++, by default, does not expose compiler generated declarations.' + +W1003 = 'Virtual functions that returns const reference can not be overriden from Python. ' \ + 'Reason: boost::python::override::operator()(...) saves the result of the marshaling ' \ + '(from Python to C++) on the stack. Thus operator() returns reference ' \ + 'to a temporary variable. Consider to use "Function Transformation" functionality ' \ + 'to solve the problem.' + +W1004 = 'Boost.Python library can not expose function, which takes as argument/returns ' \ + 'pointer to function. ' \ + ' See http://www.boost.org/libs/python/doc/v2/faq.html#funcptr for more information.' + +W1005 = 'Py++ can not expose function that takes as argument/returns instance of non public class. ' \ + 'Generated code will not compile.' + +W1006 = 'Py++ need your help to expose function that takes as argument/returns C++ arrays. ' \ + 'Take a look on "Function Transformation" functionality and define the transformation.' + +W1007 = 'The function has more than %d arguments ( %d ). ' \ + 'You should adjust BOOST_PYTHON_MAX_ARITY macro. ' \ + 'For more information see: http://www.boost.org/libs/python/doc/v2/configuration.html' + +W1008 = 'The function returns non-const reference to "Python immutable" type. ' \ + 'The value can not be modified from Python. ' + +W1009 = 'The function takes as argument (name=%s, pos=%d ) non-const reference ' \ + 'to Python immutable type - function could not be called from Python. ' \ + 'Take a look on "Function Transformation" functionality and define the transformation.' + +W1010 = 'The function introduces registration order problem. ' \ + 'For more information about the problem read next document: ' \ + 'http://language-binding.net/pyplusplus/documentation/functions/registration_order.html ' \ + 'Problematic functions list: %s' + +W1011 = "Py++ doesn't export private not virtual functions." + +W1012 = 'Py++ does not exports compiler generated constructors.' + +W1013 = "Py++ doesn't export private constructor." + +W1014 = '"%s" is not supported. ' \ + 'See Boost.Python documentation: http://www.boost.org/libs/python/doc/v2/operators.html#introduction.' + +W1015 = "Py++ doesn't export private operators." + +W1016 = 'Py++ does not exports non-const casting operators with user defined type as return value. ' \ + 'This could be change in future.' + +W1017 = "Py++ doesn't export non-public casting operators." + +W1018 = 'Py++ can not expose unnamed classes.' + +W1019 = 'Py++ can not expose private class.' + +W1020 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class" + +W1021 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class null constructor body" + +W1022 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class copy constructor body" + +W1023 = "Py++ will generate class wrapper - there are few functions that should be redefined in class wrapper" + +W1024 = "Py++ will generate class wrapper - class contains bit field member variable" + +W1025 = "Py++ will generate class wrapper - class contains T* member variable" + +W1026 = "Py++ will generate class wrapper - class contains T& member variable" + +W1027 = "Py++ will generate class wrapper - class contains array member variable" + +W1028 = "Py++ will generate class wrapper - class contains definition of nested class that requires wrapper class" + +W1029 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class constructor body" + +W1030 = "Py++ will generate class wrapper - class contains definition of virtual or pure virtual member function" + +W1031 = "Py++ will generate class wrapper - user asked to expose non - public member function" + +W1032 = "Boost.Python library does not support enums with duplicate values. " \ + "You can read more about this here: " \ + "http://boost.org/libs/python/todo.html#support-for-enums-with-duplicate-values . " \ + "The quick work around is to add new class variable to the exported enum, from Python. " + +W1033 = "Py++ can not expose unnamed variables" + +W1034 = "Py++ can not expose alignement bit." + +W1035 = "Py++ can not expose static pointer member variables. This could be changed in future." + +W1036 = "Py++ can not expose pointer to Python immutable member variables. This could be changed in future." + +W1037 = "Boost.Python library can not expose variables, which are pointer to function." \ + " See http://www.boost.org/libs/python/doc/v2/faq.html#funcptr for more information." + +W1038 = "Py++ can not expose variables of with unnamed type." + +W1039 = "Py++ doesn't expose private or protected member variables." + +W1040 = 'The declaration is unexposed, but there are other declarations, which refer to it.' \ + 'This could cause "no to_python converter found" run time error.' \ + 'Declarations: %s' + + +warnings = globals() + +for identifier, explanation in warnings.items(): + globals()[ identifier ] = 'warning %s: %s' % ( identifier, explanation ) + +del warnings +del identifier +del explanation + + + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-06 07:27:03
|
Revision: 779 http://svn.sourceforge.net/pygccxml/?rev=779&view=rev Author: roman_yakovenko Date: 2006-12-05 23:27:03 -0800 (Tue, 05 Dec 2006) Log Message: ----------- adding new functionality - "pragma warning disable" :-) User now can filter messages, reported by Py++ per declaration basis Modified Paths: -------------- pyplusplus_dev/pyplusplus/__init__.py pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py pyplusplus_dev/pyplusplus/messages/__init__.py pyplusplus_dev/pyplusplus/module_creator/creator.py pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py pyplusplus_dev/unittests/smart_pointers_tester.py Modified: pyplusplus_dev/pyplusplus/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/__init__.py 2006-12-05 21:36:37 UTC (rev 778) +++ pyplusplus_dev/pyplusplus/__init__.py 2006-12-06 07:27:03 UTC (rev 779) @@ -30,6 +30,7 @@ import utils import decl_wrappers import module_builder +import messages from _logging_ import multi_line_formatter_t Modified: pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py 2006-12-05 21:36:37 UTC (rev 778) +++ pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py 2006-12-06 07:27:03 UTC (rev 779) @@ -148,18 +148,3 @@ def create_variable( self, *arguments, **keywords ): return variable_t(*arguments, **keywords) - - -skip_messages = [ - "Py++ does not exports compiler generated constructors" - , 'Py++, by default, does not expose internal compilers declarations. Names of those declarations usually start with "__".' - , 'Py++, by default, does not expose internal declarations (those that gccxml say belong to "<internal>" header).' - , 'Py++, by default, does not expose compiler generated declarations.' - , 'Py++ can not expose private class.' - , 'Py++ will generate class wrapper - class contains definition of virtual or pure virtual member function' - , "Py++ doesn't expose private or protected member variables." - , "Py++ doesn't export private not virtual functions." - , "Py++ doesn't export private constructor." - , "Py++ doesn't export private operators." -] -#Messages kept by skip_messages list will not be reported Modified: pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-12-05 21:36:37 UTC (rev 778) +++ pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-12-06 07:27:03 UTC (rev 779) @@ -28,6 +28,7 @@ self._exportable = None self._exportable_reason = None self._documentation = None + self.__msgs_to_ignore = set() @property def logger( self ): @@ -114,14 +115,34 @@ def _readme_impl( self ): return [] - def readme( self ): + + def readme( self, skip_ignored=True ): """This function will returns some hints/tips/description of problems that applied to the declarations. For example function that has argument reference to some fundamental type could be exported, but could not be called from Python + + @param skip_ignored: if True, messages that user asked to not reported + will not be returned """ - text = [] + msgs = [] if not self.exportable: - text.append( self.why_not_exportable() ) - text.extend( self._readme_impl() ) - return text + msgs.append( self.why_not_exportable() ) + msgs.extend( self._readme_impl() ) + return messages.filter_disabled_msgs( msgs, self.__msgs_to_ignore ) + + @property + def disabled_messaged( self ): + return self.__msgs_to_ignore + + def disable_messages( self, *args ): + """Using this method you can tell to Py++ to not report some specifiec warnings. + + Usage example: decl.ignore_warnings( messages.W1001, messages.W1040 ) + """ + for msg in args: + msg_id = messages.find_out_message_id( msg ) + if not msg_id: + raise RuntimeError( "Unable to find out message id. The message is: " + msg ) + self.__msgs_to_ignore.add( msg ) + disable_warnings = disable_messages Modified: pyplusplus_dev/pyplusplus/messages/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/messages/__init__.py 2006-12-05 21:36:37 UTC (rev 778) +++ pyplusplus_dev/pyplusplus/messages/__init__.py 2006-12-06 07:27:03 UTC (rev 779) @@ -6,122 +6,41 @@ """This package defines all user messages( warnings + errors ), which will be reported to user. """ +from warnings_ import * -W1000 = 'Py++, by default, does not expose internal compilers declarations.'\ - 'Names of those declarations usually start with "__".' +import re +__RE_GET_WARNING_ID = re.compile( r'warning\s(?P<id>W(\d){4})' ) +def find_out_message_id( msg ): + match_obj = __RE_GET_WARNING_ID.search(msg) + if not match_obj: + return None + else: + return match_obj.group( 'id' ) -W1001 = 'Py++, by default, does not expose internal declarations. ' \ - 'GCC-XML reports that these declaration belong to "<internal>" header.' -W1002 = 'Py++, by default, does not expose compiler generated declarations.' +DISABLE_MESSAGES = [ + W1000, W1001, W1002, W1011, W1012, W1013, W1015, W1019, W1030, W1034, W1039 +] +#Messages kept by DISABLE_MESSAGES list will not be reported -W1003 = 'Virtual functions that returns const reference can not be overriden from Python. ' \ - 'Reason: boost::python::override::operator()(...) saves the result of the marshaling ' \ - '(from Python to C++) on the stack. Thus operator() returns reference ' \ - 'to a temporary variable. Consider to use "Function Transformation" functionality ' \ - 'to solve the problem.' -W1004 = 'Boost.Python library can not expose function, which takes as argument/returns ' \ - 'pointer to function. ' \ - ' See http://www.boost.org/libs/python/doc/v2/faq.html#funcptr for more information.' +def filter_disabled_msgs( msgs, disable_messages=None ): + report = [] + + skip_them = DISABLE_MESSAGES[:] + if disable_messages: + skip_them.extend( disable_messages ) + + skip_them = filter( None, map( find_out_message_id, skip_them ) ) -W1005 = 'Py++ can not expose function that takes as argument/returns instance of non public class. ' \ - 'Generated code will not compile.' + for msg in msgs: + msg_id = find_out_message_id( msg ) + if msg_id and msg_id not in skip_them: + report.append( msg ) -W1006 = 'Py++ need your help to expose function that takes as argument/returns C++ arrays. ' \ - 'Take a look on "Function Transformation" functionality and define the transformation.' + return report -W1007 = 'The function has more than %d arguments ( %d ). ' \ - 'You should adjust BOOST_PYTHON_MAX_ARITY macro. ' \ - 'For more information see: http://www.boost.org/libs/python/doc/v2/configuration.html' -W1008 = 'The function returns non-const reference to "Python immutable" type. ' \ - 'The value can not be modified from Python. ' -W1009 = 'The function takes as argument (name=%s, pos=%d ) non-const reference ' \ - 'to Python immutable type - function could not be called from Python. ' \ - 'Take a look on "Function Transformation" functionality and define the transformation.' -W1010 = 'The function introduces registration order problem. ' \ - 'For more information about the problem read next document: ' \ - 'http://language-binding.net/pyplusplus/documentation/functions/registration_order.html ' \ - 'Problematic functions list: %s' -W1011 = "Py++ doesn't export private not virtual functions." - -W1012 = 'Py++ does not exports compiler generated constructors.' - -W1013 = "Py++ doesn't export private constructor." - -W1014 = '"%s" is not supported. ' \ - 'See Boost.Python documentation: http://www.boost.org/libs/python/doc/v2/operators.html#introduction.' - -W1015 = "Py++ doesn't export private operators." - -W1016 = 'Py++ does not exports non-const casting operators with user defined type as return value. ' \ - 'This could be change in future.' - -W1017 = "Py++ doesn't export non-public casting operators." - -W1018 = 'Py++ can not expose unnamed classes.' - -W1019 = 'Py++ can not expose private class.' - -W1020 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class" - -W1021 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class null constructor body" - -W1022 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class copy constructor body" - -W1023 = "Py++ will generate class wrapper - there are few functions that should be redefined in class wrapper" - -W1024 = "Py++ will generate class wrapper - class contains bit field member variable" - -W1025 = "Py++ will generate class wrapper - class contains T* member variable" - -W1026 = "Py++ will generate class wrapper - class contains T& member variable" - -W1027 = "Py++ will generate class wrapper - class contains array member variable" - -W1028 = "Py++ will generate class wrapper - class contains definition of nested class that requires wrapper class" - -W1029 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class constructor body" - -W1030 = "Py++ will generate class wrapper - class contains definition of virtual or pure virtual member function" - -W1031 = "Py++ will generate class wrapper - user asked to expose non - public member function" - -W1032 = "Boost.Python library does not support enums with duplicate values. " \ - "You can read more about this here: " \ - "http://boost.org/libs/python/todo.html#support-for-enums-with-duplicate-values . " \ - "The quick work around is to add new class variable to the exported enum, from Python. " - -W1033 = "Py++ can not expose unnamed variables" - -W1034 = "Py++ can not expose alignement bit." - -W1035 = "Py++ can not expose static pointer member variables. This could be changed in future." - -W1036 = "Py++ can not expose pointer to Python immutable member variables. This could be changed in future." - -W1037 = "Boost.Python library can not expose variables, which are pointer to function." \ - " See http://www.boost.org/libs/python/doc/v2/faq.html#funcptr for more information." - -W1038 = "Py++ can not expose variables of with unnamed type." - -W1039 = "Py++ doesn't expose private or protected member variables." - -W1040 = 'The declaration is unexposed, but there are other declarations, which refer to it.' \ - 'This could cause "no to_python converter found" run time error.' \ - 'Declarations: %s' - - - - - - - - - - - Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-12-05 21:36:37 UTC (rev 778) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-12-06 07:27:03 UTC (rev 779) @@ -152,7 +152,7 @@ if doc_extractor and decl.exportable: decl.documentation = doc_extractor( decl ) - readme = filter( lambda msg: msg not in decl_wrappers.skip_messages, decl.readme() ) + readme = decl.readme() if not readme: continue Modified: pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2006-12-05 21:36:37 UTC (rev 778) +++ pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2006-12-06 07:27:03 UTC (rev 779) @@ -71,7 +71,9 @@ if isinstance( depend_on_decl, declarations.class_types ) and depend_on_decl.opaque: continue if id( depend_on_decl ) not in exported_ids: - used_not_exported.append( dependency ) + report = messages.filter_disabled_msgs([messages.W1040], depend_on_decl.disabled_messaged ) + if report: + used_not_exported.append( dependency ) return used_not_exported def __group_by_unexposed( self, dependencies ): Modified: pyplusplus_dev/unittests/smart_pointers_tester.py =================================================================== --- pyplusplus_dev/unittests/smart_pointers_tester.py 2006-12-05 21:36:37 UTC (rev 778) +++ pyplusplus_dev/unittests/smart_pointers_tester.py 2006-12-06 07:27:03 UTC (rev 779) @@ -8,6 +8,7 @@ import unittest import fundamental_tester_base from pyplusplus import code_creators +from pyplusplus import messages class tester_t(fundamental_tester_base.fundamental_tester_base_t): EXTENSION_NAME = 'smart_pointers' @@ -20,7 +21,8 @@ def customize( self, mb ): base = mb.class_( 'base' ) - #base.held_type = '' + shared_ptrs = mb.decls( lambda decl: decl.name.startswith( 'shared_ptr<' ) ) + shared_ptrs.disable_warnings( messages.W1040 ) def create_py_derived( self, module ): class py_derived_t( module.base ): @@ -90,4 +92,4 @@ unittest.TextTestRunner(verbosity=2).run( create_suite() ) if __name__ == "__main__": - run_suite() \ No newline at end of file + run_suite() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-05 21:36:39
|
Revision: 778 http://svn.sourceforge.net/pygccxml/?rev=778&view=rev Author: roman_yakovenko Date: 2006-12-05 13:36:37 -0800 (Tue, 05 Dec 2006) Log Message: ----------- switching to use central repository for all messages. This refactoring will help users to define filter that will ignore selected messages Modified Paths: -------------- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py Added Paths: ----------- pyplusplus_dev/pyplusplus/messages/ pyplusplus_dev/pyplusplus/messages/__init__.py Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-12-05 21:34:41 UTC (rev 777) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-12-05 21:36:37 UTC (rev 778) @@ -9,6 +9,8 @@ import user_text import algorithm import decl_wrapper +import python_traits +from pyplusplus import messages from pygccxml import declarations from pyplusplus import function_transformers as ft @@ -88,15 +90,7 @@ and self.virtuality != declarations.VIRTUALITY_TYPES.NOT_VIRTUAL \ and declarations.is_reference( self.return_type ): self._overridable = False - self._non_overridable_reason = "Virtual functions that return "\ - "const reference can not be overriden from Python. "\ - "Ther is current no way for them to return a reference "\ - "to C++ code that calls them because in "\ - "boost::python::override::operator(...) the result of "\ - "marshaling (Python to C++) is saved on stack, after function "\ - "exit, thus the resulting reference would be a reference to "\ - "a temporary variable and would cause an access violation. "\ - "For an example of this see the temporary_variable_tester." + self._non_overridable_reason = messages.W1003 else: self._overridable = True self._non_overridable_reason = "" @@ -138,20 +132,19 @@ ptr2functions = filter( lambda unit: isinstance( unit, declarations.calldef_type_t ) , units ) if ptr2functions: - return "boost.python can not expose function, which takes as argument/returns pointer to function." \ - + " See http://www.boost.org/libs/python/doc/v2/faq.html#funcptr for more information." + return messages.W1004 #Function that take as agrument some instance of non public class #will not be exported. Same to the return variable if isinstance( units[-1], declarations.declarated_t ): dtype = units[-1] if isinstance( dtype.declaration.parent, declarations.class_t ): if dtype.declaration not in dtype.declaration.parent.public_members: - return "Py++ can not expose function that takes as argument/returns instance of non public class. Generated code will not compile." + return messages.W1005 no_ref = declarations.remove_reference( some_type ) no_ptr = declarations.remove_pointer( no_ref ) no_const = declarations.remove_const( no_ptr ) if declarations.is_array( no_const ): - return "Py++ can not expose function that takes as argument/returns C++ arrays. This will be changed in near future." + return messages.W1006 return self._exportable_impl_derived() def _readme_impl( self ): @@ -160,44 +153,34 @@ return False type_no_ref = declarations.remove_reference( type_ ) return not declarations.is_const( type_no_ref ) \ - and declarations.is_fundamental( type_no_ref ) + and python_traits.is_immutable( type_no_ref ) 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 = [ "The function has more than %d arguments ( %d ). " ] - tmp.append( "You should adjust BOOST_PYTHON_MAX_ARITY macro." ) - tmp.append( "For more information see: http://www.boost.org/libs/python/doc/v2/configuration.html" ) - tmp = ' '.join( tmp ) - msgs.append( tmp % ( calldef_t.BOOST_PYTHON_MAX_ARITY, len( self.arguments ) ) ) + msgs.append( messages.W1007 % ( calldef_t.BOOST_PYTHON_MAX_ARITY, len( self.arguments ) ) ) if self.transformations: #if user defined transformation, than I think it took care of the problems return msgs if suspicious_type( self.return_type ) and None is self.call_policies: - msgs.append( 'The function "%s" returns non-const reference to C++ fundamental type - value can not be modified from Python.' % str( self ) ) + msgs.append( messages.W1008 ) for index, arg in enumerate( self.arguments ): if suspicious_type( arg.type ): - tmpl = [ 'The function takes as argument (name=%s, pos=%d ) ' ] - tmpl.append( 'non-const reference to C++ fundamental type - ' ) - tmpl.append( 'function could not be called from Python.' ) - msgs.append( ''.join( tmpl ) % ( arg.name, index ) ) + msgs.append( messages.W1009 % ( arg.name, index ) ) if False == self.overridable: msgs.append( self._non_overridable_reason) problematics = algorithm.registration_order.select_problematics( self ) if problematics: - tmp = [ "The function introduces registration order problem. " ] - tmp.append( "For more information read next document: " - + "http://language-binding.net/pyplusplus/documentation/functions/registration_order.html" ) - tmp.append( "Problematic functions: " ) + tmp = [] for f in problematics: tmp.append( os.linesep + '\t' + str(f) ) - msgs.append( os.linesep.join( tmp ) ) + msgs.append( messages.W1010 % os.linesep.join( tmp ) ) return msgs class member_function_t( declarations.member_function_t, calldef_t ): @@ -218,7 +201,7 @@ def _exportable_impl_derived(self): if self.access_type == declarations.ACCESS_TYPES.PRIVATE \ and self.virtuality == declarations.VIRTUALITY_TYPES.NOT_VIRTUAL: - return "Py++ doesn't export private not virtual functions." + return messages.W1011 return '' class constructor_t( declarations.constructor_t, calldef_t ): @@ -238,9 +221,9 @@ def _exportable_impl_derived( self ): if self.is_artificial: - return 'Py++ does not exports compiler generated constructors' + return messages.W1012 if self.access_type == declarations.ACCESS_TYPES.PRIVATE: - return "Py++ doesn't export private constructor." + return messages.W1013 return '' def does_define_implicit_conversion( self ): @@ -304,9 +287,7 @@ if isinstance( oper, declarations.member_operator_t ) and oper.symbol in ( '()', '[]' ): return '' if not operators_helper.is_supported( oper ): - msg = [ '"%s" is not supported. ' % oper.name ] - msg.append( 'See Boost.Python documentation: http://www.boost.org/libs/python/doc/v2/operators.html#introduction.' ) - return ' '.join( msg ) + return messages.W1014 % oper.name return '' class member_operator_t( declarations.member_operator_t, calldef_t ): @@ -331,7 +312,7 @@ def _exportable_impl_derived( self ): if self.access_type == declarations.ACCESS_TYPES.PRIVATE \ and self.virtuality == declarations.VIRTUALITY_TYPES.NOT_VIRTUAL: - return "Py++ doesn't export private operators." + return messages.W1015 return operators_helper.exportable( self ) @@ -404,9 +385,9 @@ def _exportable_impl_derived( self ): if not declarations.is_fundamental( self.return_type ) and not self.has_const: - return 'Py++ does not exports non-const casting operators with user defined type as return value. This could be change in future.' + return messages.W1016 if self.access_type != declarations.ACCESS_TYPES.PUBLIC: - return "Py++ doesn't export non-public casting operators." + return messages.W1017 return '' Modified: pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2006-12-05 21:34:41 UTC (rev 777) +++ pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2006-12-05 21:36:37 UTC (rev 778) @@ -10,6 +10,7 @@ import properties import decl_wrapper import scopedef_wrapper +from pyplusplus import messages from pygccxml import declarations import indexing_suite1 as isuite1 import indexing_suite2 as isuite2 @@ -289,12 +290,12 @@ def _exportable_impl( self ): if not self.name: - return 'Py++ can not expose unnamed classes.' + return messages.W1018 #it is possible to do so, but not for unnamed classes defined under namespace. if isinstance( self.parent, declarations.namespace_t ): return '' if not self in self.parent.public_members: - return 'Py++ can not expose private class.' + return messages.W1019 return '' def get_exportable_members( self, sort=None ): @@ -433,40 +434,38 @@ """ explanation = [] if self.wrapper_code: - explanation.append( "Py++ will generate class wrapper - hand written code should be added to the wrapper class" ) + explanation.append( messages.W1020 ) if self.null_constructor_body: - explanation.append( "Py++ will generate class wrapper - hand written code should be added to the wrapper class null constructor body" ) + explanation.append( messages.W1021 ) if self.copy_constructor_body: - explanation.append( "Py++ will generate class wrapper - hand written code should be added to the wrapper class copy constructor body" ) + explanation.append( messages.W1022 ) if self.redefined_funcs(): - explanation.append( "Py++ will generate class wrapper - there are few functions that should be redefined in class wrapper" ) + explanation.append( messages.W1023 ) for member in self.get_exportable_members(): if isinstance( member, declarations.destructor_t ): continue if isinstance( member, declarations.variable_t ): if member.bits: - explanation.append( "Py++ will generate class wrapper - class contains bit field member variable" ) + explanation.append( messages.W1024 ) if declarations.is_pointer( member.type ): - explanation.append( "Py++ will generate class wrapper - class contains T* member variable" ) + explanation.append( messages.W1025 ) if declarations.is_reference( member.type ): - explanation.append( "Py++ will generate class wrapper - class contains T& member variable" ) + explanation.append( messages.W1026 ) if declarations.is_array( member.type ): - explanation.append( "Py++ will generate class wrapper - class contains array member variable" ) + explanation.append( messages.W1027 ) if isinstance( member, declarations.class_t ) and member.is_wrapper_needed(): - explanation.append( "Py++ will generate class wrapper - class contains definition of nested class that requires wrapper class" ) + explanation.append( messages.W1028 ) if isinstance( member, declarations.calldef_t ): if isinstance( member, declarations.constructor_t ) and member.body: - explanation.append( "Py++ will generate class wrapper - hand written code should be added to the wrapper class constructor body" ) + explanation.append( messages.W1029 ) if member.virtuality != VIRTUALITY_TYPES.NOT_VIRTUAL: - explanation.append( "Py++ will generate class wrapper - class contains definition of virtual or pure virtual member function" ) + explanation.append( messages.W1030 ) if member.access_type in ( ACCESS_TYPES.PROTECTED, ACCESS_TYPES.PRIVATE ): - explanation.append( "Py++ will generate class wrapper - user asked to expose non - public member function" ) - #if member.function_transformers: - # return True #function transformers require wrapper + explanation.append( messages.W1031 ) return explanation def _readme_impl( self ): Modified: pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-12-05 21:34:41 UTC (rev 777) +++ pyplusplus_dev/pyplusplus/decl_wrappers/decl_wrapper.py 2006-12-05 21:36:37 UTC (rev 778) @@ -9,6 +9,7 @@ import algorithm from pyplusplus import _logging_ from pygccxml import declarations +from pyplusplus import messages class decl_wrapper_t(object): """Declaration interface. @@ -38,7 +39,7 @@ def _set_documentation( self, value ): self._documentation = value documentation = property( _get_documentation, _set_documentation - , doc="Using this property you can set documentatio of exported declaration." ) + , doc="Using this property you can set documentation of the declaration." ) def _generate_valid_name(self, name=None): if name == None: @@ -94,12 +95,12 @@ def get_exportable( self ): if self._exportable is None: if self.name.startswith( '__' ): - self._exportable_reason = 'Py++, by default, does not expose internal compilers declarations. Names of those declarations usually start with "__".' + self._exportable_reason = messages.W1000 elif self.location and self.location.file_name == "<internal>": - self._exportable_reason = 'Py++, by default, does not expose internal declarations (those that gccxml say belong to "<internal>" header).' + self._exportable_reason = messages.W1001 elif self.is_artificial \ and not isinstance( self, ( declarations.class_t, declarations.enumeration_t ) ): - self._exportable_reason = 'Py++, by default, does not expose compiler generated declarations.' + self._exportable_reason = messages.W1002 else: self._exportable_reason = self._exportable_impl( ) self._exportable = not bool( self._exportable_reason ) Modified: pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py 2006-12-05 21:34:41 UTC (rev 777) +++ pyplusplus_dev/pyplusplus/decl_wrappers/enumeration_wrapper.py 2006-12-05 21:36:37 UTC (rev 778) @@ -5,8 +5,9 @@ """defines class that configure enumeration declaration exposing""" -from pygccxml import declarations import decl_wrapper +from pyplusplus import messages +from pygccxml import declarations class enumeration_t(decl_wrapper.decl_wrapper_t, declarations.enumeration_t): """defines a set of properties, that will instruct Py++ how to expose the enumeration @@ -72,7 +73,5 @@ if self.name: name2value = self.get_name2value_dict() if len( set( name2value.keys() ) ) != len( set( name2value.values() ) ): - msgs.append( "Boost.Python does not support enums with duplicate values. " - "You can read more about this here: http://boost.org/libs/python/todo.html#support-for-enums-with-duplicate-values . " - "The quick work around is to add new class variable to the exported enum, from Python. " ) + msgs.append( messages.W1032 ) return msgs Modified: pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py 2006-12-05 21:34:41 UTC (rev 777) +++ pyplusplus_dev/pyplusplus/decl_wrappers/variable_wrapper.py 2006-12-05 21:36:37 UTC (rev 778) @@ -6,6 +6,7 @@ """defines class that configure global and member variable exposing""" import decl_wrapper +from pyplusplus import messages from pygccxml import declarations from pyplusplus.decl_wrappers import python_traits @@ -43,29 +44,28 @@ def _exportable_impl( self ): if not self.name: - return "Py++ can not expose unnamed variables" + return messages.W1033 if self.bits == 0 and self.name == "": - return "Py++ can not expose alignement bit." + return messages.W1034 type_ = declarations.remove_alias( self.type ) type_ = declarations.remove_const( type_ ) if declarations.is_pointer( type_ ): if self.type_qualifiers.has_static: - return "Py++ can not expose static pointer member variables. This could be changed in future." + return messages.W1035 if python_traits.is_immutable( type_.base ): - return "Py++ can not expose pointer to Python immutable member variables. This could be changed in future." + return messages.W1036 units = declarations.decompose_type( type_ ) ptr2functions = filter( lambda unit: isinstance( unit, declarations.calldef_type_t ) , units ) if ptr2functions: - return "boost.python can not expose variables, which are pointer to function." \ - + " See http://www.boost.org/libs/python/doc/v2/faq.html#funcptr for more information." + return messages.W1037 type_ = declarations.remove_pointer( type_ ) if declarations.class_traits.is_my_case( type_ ): cls = declarations.class_traits.get_declaration( type_ ) if not cls.name: - return "Py++ can not expose variables of with unnamed type." + return messages.W1038 if isinstance( self.parent, declarations.class_t ): if self.access_type != declarations.ACCESS_TYPES.PUBLIC: - return "Py++ doesn't expose private or protected member variables." + return messages.W1039 return '' Added: pyplusplus_dev/pyplusplus/messages/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/messages/__init__.py (rev 0) +++ pyplusplus_dev/pyplusplus/messages/__init__.py 2006-12-05 21:36:37 UTC (rev 778) @@ -0,0 +1,127 @@ +# 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) + +"""This package defines all user messages( warnings + errors ), which will be +reported to user. +""" + +W1000 = 'Py++, by default, does not expose internal compilers declarations.'\ + 'Names of those declarations usually start with "__".' + +W1001 = 'Py++, by default, does not expose internal declarations. ' \ + 'GCC-XML reports that these declaration belong to "<internal>" header.' + +W1002 = 'Py++, by default, does not expose compiler generated declarations.' + +W1003 = 'Virtual functions that returns const reference can not be overriden from Python. ' \ + 'Reason: boost::python::override::operator()(...) saves the result of the marshaling ' \ + '(from Python to C++) on the stack. Thus operator() returns reference ' \ + 'to a temporary variable. Consider to use "Function Transformation" functionality ' \ + 'to solve the problem.' + +W1004 = 'Boost.Python library can not expose function, which takes as argument/returns ' \ + 'pointer to function. ' \ + ' See http://www.boost.org/libs/python/doc/v2/faq.html#funcptr for more information.' + +W1005 = 'Py++ can not expose function that takes as argument/returns instance of non public class. ' \ + 'Generated code will not compile.' + +W1006 = 'Py++ need your help to expose function that takes as argument/returns C++ arrays. ' \ + 'Take a look on "Function Transformation" functionality and define the transformation.' + +W1007 = 'The function has more than %d arguments ( %d ). ' \ + 'You should adjust BOOST_PYTHON_MAX_ARITY macro. ' \ + 'For more information see: http://www.boost.org/libs/python/doc/v2/configuration.html' + +W1008 = 'The function returns non-const reference to "Python immutable" type. ' \ + 'The value can not be modified from Python. ' + +W1009 = 'The function takes as argument (name=%s, pos=%d ) non-const reference ' \ + 'to Python immutable type - function could not be called from Python. ' \ + 'Take a look on "Function Transformation" functionality and define the transformation.' + +W1010 = 'The function introduces registration order problem. ' \ + 'For more information about the problem read next document: ' \ + 'http://language-binding.net/pyplusplus/documentation/functions/registration_order.html ' \ + 'Problematic functions list: %s' + +W1011 = "Py++ doesn't export private not virtual functions." + +W1012 = 'Py++ does not exports compiler generated constructors.' + +W1013 = "Py++ doesn't export private constructor." + +W1014 = '"%s" is not supported. ' \ + 'See Boost.Python documentation: http://www.boost.org/libs/python/doc/v2/operators.html#introduction.' + +W1015 = "Py++ doesn't export private operators." + +W1016 = 'Py++ does not exports non-const casting operators with user defined type as return value. ' \ + 'This could be change in future.' + +W1017 = "Py++ doesn't export non-public casting operators." + +W1018 = 'Py++ can not expose unnamed classes.' + +W1019 = 'Py++ can not expose private class.' + +W1020 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class" + +W1021 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class null constructor body" + +W1022 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class copy constructor body" + +W1023 = "Py++ will generate class wrapper - there are few functions that should be redefined in class wrapper" + +W1024 = "Py++ will generate class wrapper - class contains bit field member variable" + +W1025 = "Py++ will generate class wrapper - class contains T* member variable" + +W1026 = "Py++ will generate class wrapper - class contains T& member variable" + +W1027 = "Py++ will generate class wrapper - class contains array member variable" + +W1028 = "Py++ will generate class wrapper - class contains definition of nested class that requires wrapper class" + +W1029 = "Py++ will generate class wrapper - hand written code should be added to the wrapper class constructor body" + +W1030 = "Py++ will generate class wrapper - class contains definition of virtual or pure virtual member function" + +W1031 = "Py++ will generate class wrapper - user asked to expose non - public member function" + +W1032 = "Boost.Python library does not support enums with duplicate values. " \ + "You can read more about this here: " \ + "http://boost.org/libs/python/todo.html#support-for-enums-with-duplicate-values . " \ + "The quick work around is to add new class variable to the exported enum, from Python. " + +W1033 = "Py++ can not expose unnamed variables" + +W1034 = "Py++ can not expose alignement bit." + +W1035 = "Py++ can not expose static pointer member variables. This could be changed in future." + +W1036 = "Py++ can not expose pointer to Python immutable member variables. This could be changed in future." + +W1037 = "Boost.Python library can not expose variables, which are pointer to function." \ + " See http://www.boost.org/libs/python/doc/v2/faq.html#funcptr for more information." + +W1038 = "Py++ can not expose variables of with unnamed type." + +W1039 = "Py++ doesn't expose private or protected member variables." + +W1040 = 'The declaration is unexposed, but there are other declarations, which refer to it.' \ + 'This could cause "no to_python converter found" run time error.' \ + 'Declarations: %s' + + + + + + + + + + + Modified: pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2006-12-05 21:34:41 UTC (rev 777) +++ pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2006-12-05 21:36:37 UTC (rev 778) @@ -6,6 +6,7 @@ """defines class, which informs user about used, but unexposed declarations""" import os +from pyplusplus import messages from pygccxml import declarations from pyplusplus import decl_wrappers @@ -84,10 +85,10 @@ def __create_msg( self, dependencies ): depend_on_decl = dependencies[0].find_out_depend_on_declaration() - reason = [ 'There are declarations, which depend on the unexposed one:' ] + decls = [] for dependency in dependencies: - reason.append( ' ' + str( dependency.declaration ) ) - return "%s;%s" % ( depend_on_decl, os.linesep.join( reason ) ) + decls.append( os.linesep + ' ' + str( dependency.declaration ) ) + return "%s;%s" % ( depend_on_decl, messages.W1040 % ''.join( decls ) ) def inform_user( self ): used_not_exported_decls = self.__find_out_used_but_not_exported() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-05 21:34:42
|
Revision: 777 http://svn.sourceforge.net/pygccxml/?rev=777&view=rev Author: roman_yakovenko Date: 2006-12-05 13:34:41 -0800 (Tue, 05 Dec 2006) Log Message: ----------- updating documentation Modified Paths: -------------- pyplusplus_dev/docs/pyplusplus.rest Modified: pyplusplus_dev/docs/pyplusplus.rest =================================================================== --- pyplusplus_dev/docs/pyplusplus.rest 2006-12-05 10:52:14 UTC (rev 776) +++ pyplusplus_dev/docs/pyplusplus.rest 2006-12-05 21:34:41 UTC (rev 777) @@ -7,14 +7,15 @@ ------------- What is Py++? ------------- +Definition: + .. include:: ./definition.rest -.. include:: ./definition.rest -`Py++`_ is a powerful code generator that uses few different programming paradigms -to help you to expose C++ declarations to Python. This code generator will not -stand on your way. It will guide you through the whole process. It will raise -warnings in the case you are doing something wrong with a link to the explanation. -And the most important it will save your time - you will not have to update -code generator script every time you change source code. +`Py++`_ uses few different programming paradigms to help you to expose C++ +declarations to Python. This code generator will not stand on your way. It will +guide you through the whole process. It will raise warnings in the case you are +doing something wrong with a link to the explanation. And the most important it +will save your time - you will not have to update code generator script every +time source code is changed. ----------------------- Code generation process This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-05 10:52:19
|
Revision: 776 http://svn.sourceforge.net/pygccxml/?rev=776&view=rev Author: roman_yakovenko Date: 2006-12-05 02:52:14 -0800 (Tue, 05 Dec 2006) Log Message: ----------- editing ignore list Property Changed: ---------------- pygccxml_dev/unittests/data/ pyplusplus_dev/unittests/temp/ Property changes on: pygccxml_dev/unittests/data ___________________________________________________________________ Name: svn:ignore + *.cache Property changes on: pyplusplus_dev/unittests/temp ___________________________________________________________________ Name: svn:ignore - internal_classes.dll member_functions.dll member_variables.dll module_body.dll namespaces.dll noncopyable.dll operators.dll operators_bug.dll optional.dll optional_bug.dll pointer_as_arg.dll pointer_to_function_as_argument.dll private_assign.dll recursive.dll regression1.dll regression2.dll regression3.dll smart_pointers.dll special_operators.dll statics.dll temprorary_variable.dll unnamed_enums.dll user_text.dll abstract.cpp~ call_policies.cpp~ casting.cpp~ class_order2.cpp~ class_order3.cpp~ class_order4.cpp~ class_order.cpp~ classes.cpp~ enums.cpp~ factory.cpp~ finalizables.cpp~ free_functions.cpp~ free_operators.cpp~ global_variables.cpp~ index_operator.cpp~ internal_classes.cpp~ member_functions.cpp~ member_variables.cpp~ noncopyable.cpp~ operators_bug.cpp~ optional.cpp~ optional_bug.cpp~ pointer_as_arg.cpp~ pointer_to_function_as_argument.cpp~ private_assign.cpp~ recursive.cpp~ regression1.cpp~ regression2.cpp~ regression3.cpp~ smart_pointers.cpp~ special_operators.cpp~ statics.cpp~ temprorary_variable.cpp~ unnamed_enums.cpp~ user_text.cpp~ abstract.exp call_policies.exp casting.exp class_order2.exp class_order3.exp class_order4.exp class_order.exp classes.exp enums.exp factory.exp finalizables.exp free_function_ignore_bug.exp free_functions.exp free_operators.exp global_variables.exp index_operator.exp internal_classes.exp member_functions.exp member_variables.exp module_body.exp namespaces.exp noncopyable.exp operators.exp operators_bug.exp optional.exp optional_bug.exp pointer_as_arg.exp pointer_to_function_as_argument.exp private_assign.exp recursive.exp regression1.exp regression2.exp regression3.exp smart_pointers.exp special_operators.exp statics.exp temprorary_variable.exp unnamed_enums.exp user_text.exp abstract.lib call_policies.lib casting.lib class_order2.lib class_order3.lib class_order4.lib class_order.lib classes.lib enums.lib factory.lib finalizables.lib free_function_ignore_bug.lib free_functions.lib free_operators.lib global_variables.lib index_operator.lib internal_classes.lib member_functions.lib member_variables.lib module_body.lib namespaces.lib noncopyable.lib operators.lib operators_bug.lib optional.lib optional_bug.lib pointer_as_arg.lib pointer_to_function_as_argument.lib private_assign.lib recursive.lib regression1.lib regression2.lib regression3.lib smart_pointers.lib special_operators.lib statics.lib temprorary_variable.lib unnamed_enums.lib user_text.lib abstract.obj call_policies.obj casting.obj class_order2.obj class_order3.obj class_order4.obj class_order.obj classes.obj enums.obj factory.obj finalizables.obj free_function_ignore_bug.obj free_functions.obj free_operators.obj global_variables.obj index_operator.obj internal_classes.obj member_functions.obj member_variables.obj module_body.obj namespaces.obj noncopyable.obj operators.obj operators_bug.obj optional.obj optional_bug.obj pointer_as_arg.obj pointer_to_function_as_argument.obj private_assign.obj recursive.obj regression1.obj regression2.obj regression3.obj smart_pointers.obj special_operators.obj statics.obj temprorary_variable.obj unnamed_enums.obj user_text.obj abstract.scons call_policies.scons casting.scons class_order2.scons class_order3.scons class_order4.scons class_order.scons classes.scons enums.scons factory.scons finalizables.scons free_function_ignore_bug.scons free_functions.scons free_operators.scons global_variables.scons index_operator.scons internal_classes.scons member_functions.scons member_variables.scons module_body.scons namespaces.scons noncopyable.scons operators.scons operators_bug.scons optional.scons optional_bug.scons pointer_as_arg.scons pointer_to_function_as_argument.scons private_assign.scons recursive.scons regression1.scons regression2.scons regression3.scons smart_pointers.scons special_operators.scons statics.scons temprorary_variable.scons unnamed_enums.scons user_text.scons abstract.dll call_policies.dll casting.dll class_order2.dll class_order3.dll class_order4.dll class_order.dll classes.dll enums.dll factory.dll finalizables.dll free_function_ignore_bug.dll free_functions.dll free_operators.dll global_variables.dll index_operator.dll .sconsign.dblite __array_1.pypp.hpp classes.cpp enums.cpp free_functions.cpp module_body.cpp namespaces.cpp unnamed_enums.cpp abstract.cpp call_policies.cpp casting.cpp class_order.cpp class_order2.cpp class_order3.cpp class_order4.cpp factory.cpp finalizables.cpp free_function_ignore_bug.cpp free_operators.cpp global_variables.cpp index_operator.cpp internal_classes.cpp member_functions.cpp member_variables.cpp noncopyable.cpp operators.cpp operators_bug.cpp optional.cpp optional_bug.cpp pointer_as_arg.cpp pointer_to_function_as_argument.cpp private_assign.cpp protected.cpp recursive.cpp regression1.cpp regression2.cpp regression3.cpp smart_pointers.cpp special_operators.cpp statics.cpp temprorary_variable.cpp user_text.cpp protected.dll protected.exp protected.lib protected.obj protected.scons indexing_suites.cpp indexing_suites.cpp~ indexing_suites.dll indexing_suites.exp indexing_suites.lib indexing_suites.obj indexing_suites.scons + internal_classes.dll member_functions.dll member_variables.dll module_body.dll namespaces.dll noncopyable.dll operators.dll operators_bug.dll optional.dll optional_bug.dll pointer_as_arg.dll pointer_to_function_as_argument.dll private_assign.dll recursive.dll regression1.dll regression2.dll regression3.dll smart_pointers.dll special_operators.dll statics.dll temprorary_variable.dll unnamed_enums.dll user_text.dll abstract.cpp~ call_policies.cpp~ casting.cpp~ class_order2.cpp~ class_order3.cpp~ class_order4.cpp~ class_order.cpp~ classes.cpp~ enums.cpp~ factory.cpp~ finalizables.cpp~ free_functions.cpp~ free_operators.cpp~ global_variables.cpp~ index_operator.cpp~ internal_classes.cpp~ member_functions.cpp~ member_variables.cpp~ noncopyable.cpp~ operators_bug.cpp~ optional.cpp~ optional_bug.cpp~ pointer_as_arg.cpp~ pointer_to_function_as_argument.cpp~ private_assign.cpp~ recursive.cpp~ regression1.cpp~ regression2.cpp~ regression3.cpp~ smart_pointers.cpp~ special_operators.cpp~ statics.cpp~ temprorary_variable.cpp~ unnamed_enums.cpp~ user_text.cpp~ abstract.exp call_policies.exp casting.exp class_order2.exp class_order3.exp class_order4.exp class_order.exp classes.exp enums.exp factory.exp finalizables.exp free_function_ignore_bug.exp free_functions.exp free_operators.exp global_variables.exp index_operator.exp internal_classes.exp member_functions.exp member_variables.exp module_body.exp namespaces.exp noncopyable.exp operators.exp operators_bug.exp optional.exp optional_bug.exp pointer_as_arg.exp pointer_to_function_as_argument.exp private_assign.exp recursive.exp regression1.exp regression2.exp regression3.exp smart_pointers.exp special_operators.exp statics.exp temprorary_variable.exp unnamed_enums.exp user_text.exp abstract.lib call_policies.lib casting.lib class_order2.lib class_order3.lib class_order4.lib class_order.lib classes.lib enums.lib factory.lib finalizables.lib free_function_ignore_bug.lib free_functions.lib free_operators.lib global_variables.lib index_operator.lib internal_classes.lib member_functions.lib member_variables.lib module_body.lib namespaces.lib noncopyable.lib operators.lib operators_bug.lib optional.lib optional_bug.lib pointer_as_arg.lib pointer_to_function_as_argument.lib private_assign.lib recursive.lib regression1.lib regression2.lib regression3.lib smart_pointers.lib special_operators.lib statics.lib temprorary_variable.lib unnamed_enums.lib user_text.lib abstract.obj call_policies.obj casting.obj class_order2.obj class_order3.obj class_order4.obj class_order.obj classes.obj enums.obj factory.obj finalizables.obj free_function_ignore_bug.obj free_functions.obj free_operators.obj global_variables.obj index_operator.obj internal_classes.obj member_functions.obj member_variables.obj module_body.obj namespaces.obj noncopyable.obj operators.obj operators_bug.obj optional.obj optional_bug.obj pointer_as_arg.obj pointer_to_function_as_argument.obj private_assign.obj recursive.obj regression1.obj regression2.obj regression3.obj smart_pointers.obj special_operators.obj statics.obj temprorary_variable.obj unnamed_enums.obj user_text.obj abstract.scons call_policies.scons casting.scons class_order2.scons class_order3.scons class_order4.scons class_order.scons classes.scons enums.scons factory.scons finalizables.scons free_function_ignore_bug.scons free_functions.scons free_operators.scons global_variables.scons index_operator.scons internal_classes.scons member_functions.scons member_variables.scons module_body.scons namespaces.scons noncopyable.scons operators.scons operators_bug.scons optional.scons optional_bug.scons pointer_as_arg.scons pointer_to_function_as_argument.scons private_assign.scons recursive.scons regression1.scons regression2.scons regression3.scons smart_pointers.scons special_operators.scons statics.scons temprorary_variable.scons unnamed_enums.scons user_text.scons abstract.dll call_policies.dll casting.dll class_order2.dll class_order3.dll class_order4.dll class_order.dll classes.dll enums.dll factory.dll finalizables.dll free_function_ignore_bug.dll free_functions.dll free_operators.dll global_variables.dll index_operator.dll .sconsign.dblite __array_1.pypp.hpp classes.cpp enums.cpp free_functions.cpp module_body.cpp namespaces.cpp unnamed_enums.cpp abstract.cpp call_policies.cpp casting.cpp class_order.cpp class_order2.cpp class_order3.cpp class_order4.cpp factory.cpp finalizables.cpp free_function_ignore_bug.cpp free_operators.cpp global_variables.cpp index_operator.cpp internal_classes.cpp member_functions.cpp member_variables.cpp noncopyable.cpp operators.cpp operators_bug.cpp optional.cpp optional_bug.cpp pointer_as_arg.cpp pointer_to_function_as_argument.cpp private_assign.cpp protected.cpp recursive.cpp regression1.cpp regression2.cpp regression3.cpp smart_pointers.cpp special_operators.cpp statics.cpp temprorary_variable.cpp user_text.cpp protected.dll protected.exp protected.lib protected.obj protected.scons indexing_suites.cpp indexing_suites.cpp~ indexing_suites.dll indexing_suites.exp indexing_suites.lib indexing_suites.obj indexing_suites.scons *.pyd *.exp *.lib *.obj *.scons This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-05 10:50:34
|
Revision: 775 http://svn.sourceforge.net/pygccxml/?rev=775&view=rev Author: roman_yakovenko Date: 2006-12-05 02:50:33 -0800 (Tue, 05 Dec 2006) Log Message: ----------- Modified Paths: -------------- pygccxml_dev/unittests/autoconfig.py pyplusplus_dev/environment.py Property Changed: ---------------- pygccxml_dev/unittests/ Property changes on: pygccxml_dev/unittests ___________________________________________________________________ Name: svn:ignore - *.pyc + *.pyc temp Modified: pygccxml_dev/unittests/autoconfig.py =================================================================== --- pygccxml_dev/unittests/autoconfig.py 2006-12-03 21:55:33 UTC (rev 774) +++ pygccxml_dev/unittests/autoconfig.py 2006-12-05 10:50:33 UTC (rev 775) @@ -16,7 +16,7 @@ if 'roman' in getpass.getuser(): if sys.platform == 'win32': - gccxml_path = 'd:/gccxml_cvs/gccxml-build/bin/release/gccxml.exe' + gccxml_path = r'd:/dev/gccxml_cvs/gccxml-bin/bin/release/gccxml.exe' else: gccxml_path = '/home/roman/gccxml-build/bin/gccxml' Modified: pyplusplus_dev/environment.py =================================================================== --- pyplusplus_dev/environment.py 2006-12-03 21:55:33 UTC (rev 774) +++ pyplusplus_dev/environment.py 2006-12-05 10:50:33 UTC (rev 775) @@ -27,11 +27,11 @@ if sys.platform == 'win32': scons.suffix = '.pyd' scons.ccflags = ['/MD', '/EHsc', '/GR', '/Zc:wchar_t', '/Zc:forScope' ] - boost.libs = 'd:/boost_cvs/bin' - boost.include = 'd:/boost_cvs' + boost.libs = 'd:/dev/boost_cvs/bin' + boost.include = 'd:/dev/boost_cvs' python.libs = 'e:/python25/libs' python.include = 'e:/python25/include' - gccxml.executable = 'd:/gccxml_cvs/gccxml-build/bin/release/gccxml.exe' + gccxml.executable = r'd:/dev/gccxml_cvs/gccxml-bin/bin/release/gccxml.exe' else: scons.suffix = '.so' boost.libs = '/home/roman/boost_cvs/bin' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-03 21:55:34
|
Revision: 774 http://svn.sourceforge.net/pygccxml/?rev=774&view=rev Author: roman_yakovenko Date: 2006-12-03 13:55:33 -0800 (Sun, 03 Dec 2006) Log Message: ----------- updating docs and small change to dependencies manager Modified Paths: -------------- pygccxml_dev/docs/pygccxml.rest pygccxml_dev/docs/www_configuration.py pyplusplus_dev/docs/pyplusplus.rest pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py Modified: pygccxml_dev/docs/pygccxml.rest =================================================================== --- pygccxml_dev/docs/pygccxml.rest 2006-12-01 21:19:09 UTC (rev 773) +++ pygccxml_dev/docs/pygccxml.rest 2006-12-03 21:55:33 UTC (rev 774) @@ -16,19 +16,19 @@ ------------ .. include:: ./definition.rest ----------------------- -What can I do with it? ----------------------- +------------------------ +What can you do with it? +------------------------ Using `pygccxml`_ you can: * parse C++ source code -* build a code generator +* create a powerful code generator - + `Py++`_ is heavily based on `pygccxml`_ - + generate `WSDL`_ file from sources - + ... + + `Py++`_ is heavily based on `pygccxml`_ + + generate `WSDL`_ file from sources + + ... -* create UML diagrams +* generate UML diagrams * build code analyzer * ... @@ -50,22 +50,35 @@ Features -------- -Caching -------- +Query interface +--------------- +`pygccxml`_ provides simple and powerful API to query declarations tree. How many +lines is needed to write next query? +:: -Consider the following situation: you have to parse the same set of files every -day. There are 2 possible ways to complete the task: + select all free functions from the project + where + name equal to "do_smth" + return type is void + function has two arguments + second argument type is int -* create a header file that includes all files you need to parse +Only 1 ( one ) line of code is needed: -* parse each file separately and then join the results +.. code-block:: Python -The difference between these approaches is the caching algorithm used in the -second case. `pygccxml`_ supports both of them. + #global_ns is the reference to declarations, which describes global( :: ) namespace + global_ns.free_functions( "do_smth", return_type='void', arg_types=[None,'int'] ) +``None`` means "any type". In my opinion the code is prety clear and readable. + +If you want to know more about provided API read `query interface`__ document or +API documentation. + +.. __: ./query_interface.html + Type traits ----------- - `pygccxml`_ provides a lot of functionality to analyze C++ types and relationship between them. For more information please refer to `design`__ document or API documentation. Just a few names of algorithms: @@ -82,35 +95,27 @@ .. __: ./design.html -Query interface ---------------- +Declaration dependencies +------------------------ +You can query a declaration, about it dependencies - declarations it depends on. +This is very powerful and useful feature. `Py++`_, for example, uses this +functionality to check that user creates Python bindings for all relevant +declarations. -`pygccxml`_ provides simple and powerful API to query declarations tree. I will -try to give small example, that will prove my point. If you want to know more -about provided API please read `query interface`__ document or API documentation. -Examples: +Caching +------- +Consider the following situation: you have to parse the same set of files every +day. There are 2 possible ways to complete the task: -.. code-block:: Python +* create a header file that includes all files you need to parse - #global_ns is the reference to declarations that describes C++ namespace. - #In our case, instance of that declarations describes global ( :: ) namespace. - global_ns.free_functions( "do_smth", return_type='void', arg_types=[None,'int'] ) - +* parse each file separately and then join the results -Small explanation. Assume that ``None`` means "any type". Now the code is pretty -readable: +The difference between these approaches is the caching algorithm used in the +second case. `pygccxml`_ supports both of them. Actually `pygccxml`_ supports +more caching strategies, read the API documentation for more information. -:: - select all free functions from the project - where - name equal to "do_smth" - return type is void - function has two arguments - second argument type is int - -.. __: ./query_interface.html - ------- License ------- @@ -122,10 +127,9 @@ ----------------- `pygccxml`_ comes with comprehensive unit tests. It is running on Windows XP and -`Ubuntu`_. I am using `Python`_ 2.4 and `GCC-XML`_ CVS. -Right now I am running more then 150 tests. They test almost every piece of code. -Also I have performance tests. Most of the time I am using "white box" testing -strategy. +`Ubuntu`_. I am using `Python`_ 2.4\\2.5 and `GCC-XML`_ CVS. `pygccxml`_ has +more then 170 tests. They test almost every piece of code. It also has performance +tests. Most of the time I am using "white box" testing strategy. .. _`WSDL`: http://www.w3.org/TR/wsdl .. _`Py++`: ./../pyplusplus/pyplusplus.html Modified: pygccxml_dev/docs/www_configuration.py =================================================================== --- pygccxml_dev/docs/www_configuration.py 2006-12-01 21:19:09 UTC (rev 773) +++ pygccxml_dev/docs/www_configuration.py 2006-12-03 21:55:33 UTC (rev 774) @@ -1,3 +1,3 @@ name = 'pygccxml' files_to_skip = ['definition.rest'] -names = { 'query_interface' : 'query interface' } \ No newline at end of file +names = { 'query_interface' : 'query interface' } Modified: pyplusplus_dev/docs/pyplusplus.rest =================================================================== --- pyplusplus_dev/docs/pyplusplus.rest 2006-12-01 21:19:09 UTC (rev 773) +++ pyplusplus_dev/docs/pyplusplus.rest 2006-12-03 21:55:33 UTC (rev 774) @@ -9,23 +9,20 @@ ------------- .. include:: ./definition.rest +`Py++`_ is a powerful code generator that uses few different programming paradigms +to help you to expose C++ declarations to Python. This code generator will not +stand on your way. It will guide you through the whole process. It will raise +warnings in the case you are doing something wrong with a link to the explanation. +And the most important it will save your time - you will not have to update +code generator script every time you change source code. --------- -Preamble --------- - -This introduction will describe code generation process using Py++. -I hope, that after you finished to read it, you will understand how powerful -Py++ is. - ----------------------- Code generation process ----------------------- `Boost.Python`_ library allows you to expose C++ code to `Python`_ in quick and -elegant way. Almost the whole process of exposing declarations can be automated -by use of Py++. Code generation process, using Py++ consists -from few steps. Next paragraphs will tell you more about every step. +elegant way. Code generation process, using Py++ consists from few steps. +Next paragraphs will tell you more about every step. *"read declarations"* @@ -74,7 +71,7 @@ #will help you with code generation process mb.free_functions( arg_types=[ 'int &', None ] ) -An other example - the developer wants to exclude all protected functions from +Another example - the developer wants to exclude all protected functions from being exported: .. code-block:: Python @@ -128,64 +125,38 @@ Features list ------------- - * classes +* `Py++`_ support almost all features found in `Boost.Python`_ library - * class wrappers +* `Py++`_ generates code, which will help you to understand compiler generated + error messages - * two modes of code generation: +* `Py++`_ has few modes of writing code into files: + + * single file - * using scope - better error messages location from compiler + * multiple files - * no scope + * multiple files, where single class code is splitted to few files - * automatic detection of held type +* `Py++`_ will save your compilation time - it will rewrite a file, only in case + of change - * nested classes +* You have full control over generated code. Your code could be inserted almost + anywhere. - * implicit conversion +* Your license is written at the top of every file - * functions +* `Py++`_ will check the "completeness" of the bindings. It will check for you + that exposed declarations don't have references to unexposed ones. - * virtual methods +* `Py++`_ provides enough functionality to extract source code documentation + and write it as Python documentation string - * protected method, even non-virtual ones can be accessed from `Python`_. +* `Py++`_ provides simple and powerful framework to create wraper for functions, + which could not be exposed as is to `Python`_. - * overloading +* ... - * two modes of code generation: - - * with function type - good for exporting template instantiated - functions and overloaded ones. - - * without function type - - * static methods - - * code generated for wrapped methods takes into account types of arguments - - * operators, both free and member ones - - * call policies resolver - - * enumerations - - * variables, bit fields - - * namespace aliasing and using - - * writing multiple files - - * user code could be inserted almost any where - - * write code into file if there were changes - - * user license is written at the top of every file - - * extracting documentation from source files and integrating it with generated - source code - - * ... - ------- License ------- Modified: pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2006-12-01 21:19:09 UTC (rev 773) +++ pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2006-12-03 21:55:33 UTC (rev 774) @@ -3,6 +3,9 @@ # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) +"""defines class, which informs user about used, but unexposed declarations""" + +import os from pygccxml import declarations from pyplusplus import decl_wrappers @@ -70,12 +73,24 @@ used_not_exported.append( dependency ) return used_not_exported - def __create_msg( self, dependency ): - reason = 'The declaration depends on unexposed declaration "%s".' \ - % dependency.find_out_depend_on_declaration() - return "%s;%s" % ( dependency.declaration, reason ) + def __group_by_unexposed( self, dependencies ): + groups = {} + for dependency in dependencies: + depend_on_decl = dependency.find_out_depend_on_declaration() + if not groups.has_key( id( depend_on_decl ) ): + groups[ id( depend_on_decl ) ] = [] + groups[ id( depend_on_decl ) ].append( dependency ) + return groups + + def __create_msg( self, dependencies ): + depend_on_decl = dependencies[0].find_out_depend_on_declaration() + reason = [ 'There are declarations, which depend on the unexposed one:' ] + for dependency in dependencies: + reason.append( ' ' + str( dependency.declaration ) ) + return "%s;%s" % ( depend_on_decl, os.linesep.join( reason ) ) def inform_user( self ): used_not_exported_decls = self.__find_out_used_but_not_exported() - for used_not_exported in used_not_exported_decls: - self.__logger.warn( self.__create_msg( used_not_exported ) ) + groups = self.__group_by_unexposed( used_not_exported_decls ) + for group in groups.itervalues(): + self.__logger.warn( self.__create_msg( group ) ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-01 21:19:09
|
Revision: 773 http://svn.sourceforge.net/pygccxml/?rev=773&view=rev Author: roman_yakovenko Date: 2006-12-01 13:19:09 -0800 (Fri, 01 Dec 2006) Log Message: ----------- fixing dependency manager to not report missing declarations for implementation details of a class Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/calldef.py pygccxml_dev/pygccxml/declarations/class_declaration.py pygccxml_dev/pygccxml/declarations/declaration.py pygccxml_dev/pygccxml/declarations/enumeration.py pygccxml_dev/pygccxml/declarations/namespace.py pygccxml_dev/pygccxml/declarations/typedef.py pygccxml_dev/pygccxml/declarations/variable.py pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py Modified: pygccxml_dev/pygccxml/declarations/calldef.py =================================================================== --- pygccxml_dev/pygccxml/declarations/calldef.py 2006-12-01 19:47:39 UTC (rev 772) +++ pygccxml_dev/pygccxml/declarations/calldef.py 2006-12-01 21:19:09 UTC (rev 773) @@ -271,7 +271,7 @@ demangled_name = property( _get_demangled_name , doc="returns function demangled name. It can help you to deal with function template instantiations") - def i_depend_on_them( self ): + def i_depend_on_them( self, recursive=True ): report_dependency = lambda x: dependencies.dependency_info_t( self, x ) answer = [] map( lambda arg: answer.append( report_dependency( arg.type ) ) Modified: pygccxml_dev/pygccxml/declarations/class_declaration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/class_declaration.py 2006-12-01 19:47:39 UTC (rev 772) +++ pygccxml_dev/pygccxml/declarations/class_declaration.py 2006-12-01 21:19:09 UTC (rev 773) @@ -85,7 +85,7 @@ """implementation details""" return [] - def i_depend_on_them( self ): + def i_depend_on_them( self, recursive=True ): return [] class class_t( scopedef.scopedef_t ): @@ -337,21 +337,22 @@ def __find_out_member_dependencies( self, access_type ): members = self.get_members( access_type ) answer = [] - map( lambda mem: answer.extend( mem.i_depend_on_them() ), members ) + map( lambda mem: answer.extend( mem.i_depend_on_them(recursive=True) ), members ) member_ids = set( map( lambda m: id( m ), members ) ) for dependency in answer: if id( dependency.declaration ) in member_ids: dependency.access_type = access_type return answer - def i_depend_on_them( self ): + def i_depend_on_them( self, recursive=True ): report_dependency = lambda *args: dependencies.dependency_info_t( self, *args ) answer = [] map( lambda base: answer.append( report_dependency( base.related_class, base.access_type ) ) , self.bases ) - map( lambda access_type: answer.extend( self.__find_out_member_dependencies( access_type ) ) - , ACCESS_TYPES.ALL ) + if recursive: + map( lambda access_type: answer.extend( self.__find_out_member_dependencies( access_type ) ) + , ACCESS_TYPES.ALL ) return answer Modified: pygccxml_dev/pygccxml/declarations/declaration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/declaration.py 2006-12-01 19:47:39 UTC (rev 772) +++ pygccxml_dev/pygccxml/declarations/declaration.py 2006-12-01 21:19:09 UTC (rev 773) @@ -245,7 +245,7 @@ """ return self._cache - def i_depend_on_them( self ): + def i_depend_on_them( self, recursive=True ): #this method should return list of all types, declarations it depends on print self raise NotImplementedError() Modified: pygccxml_dev/pygccxml/declarations/enumeration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/enumeration.py 2006-12-01 19:47:39 UTC (rev 772) +++ pygccxml_dev/pygccxml/declarations/enumeration.py 2006-12-01 21:19:09 UTC (rev 773) @@ -114,5 +114,5 @@ x[val] = num return x - def i_depend_on_them( self ): + def i_depend_on_them( self, recursive=True ): return [] Modified: pygccxml_dev/pygccxml/declarations/namespace.py =================================================================== --- pygccxml_dev/pygccxml/declarations/namespace.py 2006-12-01 19:47:39 UTC (rev 772) +++ pygccxml_dev/pygccxml/declarations/namespace.py 2006-12-01 21:19:09 UTC (rev 773) @@ -135,7 +135,8 @@ , recursive=recursive , allow_empty=allow_empty) - def i_depend_on_them( self ): + def i_depend_on_them( self, recursive=True ): answer = [] - map( lambda decl: answer.extend( decl.i_depend_on_them() ), self.declarations ) + if recursive: + map( lambda decl: answer.extend( decl.i_depend_on_them() ), self.declarations ) return answer Modified: pygccxml_dev/pygccxml/declarations/typedef.py =================================================================== --- pygccxml_dev/pygccxml/declarations/typedef.py 2006-12-01 19:47:39 UTC (rev 772) +++ pygccxml_dev/pygccxml/declarations/typedef.py 2006-12-01 21:19:09 UTC (rev 773) @@ -34,5 +34,5 @@ type = property( _get_type, _set_type , doc="reference to the original L{type<type_t>}" ) - def i_depend_on_them( self ): + def i_depend_on_them( self, recursive=True ): return [ dependencies.dependency_info_t( self, self.type ) ] Modified: pygccxml_dev/pygccxml/declarations/variable.py =================================================================== --- pygccxml_dev/pygccxml/declarations/variable.py 2006-12-01 19:47:39 UTC (rev 772) +++ pygccxml_dev/pygccxml/declarations/variable.py 2006-12-01 21:19:09 UTC (rev 773) @@ -69,5 +69,5 @@ raise RuntimeError( "access_type functionality only available on member variables and not on global variables" ) return self.parent.find_out_member_access_type( self ) - def i_depend_on_them( self ): + def i_depend_on_them( self, recursive=True ): return [ dependencies.dependency_info_t( self, self.type ) ] Modified: pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2006-12-01 19:47:39 UTC (rev 772) +++ pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2006-12-01 21:19:09 UTC (rev 773) @@ -47,8 +47,13 @@ def __build_dependencies( self, decl ): if self.__is_std_decl( decl ): return [] #std declarations should be exported by Py++! - return decl.i_depend_on_them() + dependencies = decl.i_depend_on_them(recursive=False) + if isinstance( decl, declarations.class_t ): + dependencies = filter( lambda d: d.access_type != declarations.ACCESS_TYPES.PRIVATE + , dependencies ) + return dependencies + def __find_out_used_but_not_exported( self ): used_not_exported = [] exported_ids = set( map( lambda d: id( d ), self.__exported_decls ) ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-12-01 19:47:51
|
Revision: 772 http://svn.sourceforge.net/pygccxml/?rev=772&view=rev Author: roman_yakovenko Date: 2006-12-01 11:47:39 -0800 (Fri, 01 Dec 2006) Log Message: ----------- adding new question Modified Paths: -------------- pyplusplus_dev/docs/documentation/how_to.rest Modified: pyplusplus_dev/docs/documentation/how_to.rest =================================================================== --- pyplusplus_dev/docs/documentation/how_to.rest 2006-11-30 18:49:18 UTC (rev 771) +++ pyplusplus_dev/docs/documentation/how_to.rest 2006-12-01 19:47:39 UTC (rev 772) @@ -1,4 +1,4 @@ -============ +============ How to ... ? ============ @@ -28,6 +28,7 @@ .. code-block:: Python + mb = module_builder_t( ... ) mb.add_declaration_code( translate_code ) @@ -320,6 +321,61 @@ By the way, almost the same problem exists for template classes. But, in the classes use case `Py++`_ uses demangled name by default. + +------------------------------------- +Py++ generated file name is too long! +------------------------------------- +There are use cases, when `Py++`_ generated file name is too long. In some cases +the code generation process even fails because of this. What can you do in order +to eliminate the problem? + +First of all the problem arises when you expose template instantiated classes +and you did not set the class alias. + +Let me explain: + +.. code-block:: C++ + + template < class T> + struct holder{ ... }; + + +Lets say that you want to export ``holder< int >`` class. Class name in `Python`_ +has few `constraints`_. `Py++`_ is aware of the `constraints`_ and if you didn't +set an alias to the class, `Py++`_ will do it for you. In this case, +"holder_less_int_grate\_" is the generated alias. Obviously it is much longer +and not readable. + +.. _`constraints` : http://www.python.org/doc/current/ref/identifiers.html + +There are few pretty good reasons for this behavior: + +* when you just start to work on `Python`_ bindings concentrate your attention + on really important things + +* if you forgot to set the class alias your users still can use the class + functionality, however the class name will be a little bit ugly. + + +In this case the generate alias for ``holder`` instantiation is relatively short. +Imagine how long it could be for ``std::map`` instantiation. + +`Py++`_ uses class alias for the file name. So if you want to force `Py++`_ to +generate files with short name, you have to set class alias: + +.. code-block:: Python + + from pyplusplus import module_builder + + mb = module_builder_t( ... ) + holder = mb.class_( 'holder< int >' ) + holder.alias = 'IntHolder' + #next line has same effect as the previous one: + holder.rename( 'IntHolder' ) + +The nice thing about this approach is that now `Python`_ users have "normal" +class name and you have short file name. + .. _`Py++` : ./../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-11-30 18:49:19
|
Revision: 771 http://svn.sourceforge.net/pygccxml/?rev=771&view=rev Author: roman_yakovenko Date: 2006-11-30 10:49:18 -0800 (Thu, 30 Nov 2006) Log Message: ----------- fixing small bug Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py pyplusplus_dev/unittests/function_transformations_tester.py Added Paths: ----------- pyplusplus_dev/unittests/temp/named_tuple.py Modified: pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py 2006-11-30 13:56:21 UTC (rev 770) +++ pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py 2006-11-30 18:49:18 UTC (rev 771) @@ -253,20 +253,17 @@ def controller( self ): return self.ft.controller + @property + def function_type_alias( self ): + return 'default_' + self.alias + '_function_type' + def _get_alias_impl( self ): return self.wrapper.ft.alias def create_function_type_alias_code( self, exported_class_alias=None ): - result = [] + ftype = self.wrapper.default_function_type() + return 'typedef %s;' % ftype.create_typedef( self.function_type_alias ) - ftype = self.declaration.function_type() - result.append( 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) ) - if self.wrapper: - result.append( os.linesep ) - ftype = self.wrapper.function_type() - result.append( 'typedef %s;' % ftype.create_typedef( self.default_function_type_alias ) ) - return ''.join( result ) - def create_keywords_args(self): cntrl = self.controller.default_controller arg_utils = calldef_utils.argument_utils_t( self.declaration Modified: pyplusplus_dev/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev/unittests/function_transformations_tester.py 2006-11-30 13:56:21 UTC (rev 770) +++ pyplusplus_dev/unittests/function_transformations_tester.py 2006-11-30 18:49:18 UTC (rev 771) @@ -48,6 +48,7 @@ point3d.mem_fun( 'distance' ).add_transformation( ft.output(1) ) image = mb.class_( "image_t" ) + image.always_expose_using_scope = True image.member_function( "get_size" ) image.member_function( "get_size" ).add_transformation( ft.output(0), ft.output(1) ) image.member_function( "get_one_value" ).add_transformation( ft.output(0) ) Added: pyplusplus_dev/unittests/temp/named_tuple.py =================================================================== --- pyplusplus_dev/unittests/temp/named_tuple.py (rev 0) +++ pyplusplus_dev/unittests/temp/named_tuple.py 2006-11-30 18:49:18 UTC (rev 771) @@ -0,0 +1,56 @@ +# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +class named_tuple(tuple): + """Creates tuple, which allows access to stored values by name and by index. + + named_tuple could be constructed exactly in the same way as Python dict. + """ + + 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 __init__(self, seq=None, **keywd): + "named_tuple could be constructed exactly in the same way as Python dict." + 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 + + def __getattr__(self, name): + try: + return self.__dict__['__name2value'][ name ] + except KeyError: + raise AttributeError( "named_tuple has no attribute '%s'" % name ) + + def __setattr__(self, name, value): + raise AttributeError( "named_tuple has no attribute '%s'" % name ) + + def __getitem__( self, key ): + #TODO: it could be nice to support slicing. So the __getitem__ in case of + #slicing will return new named_tuple. + if isinstance( key, basestring ): + return self.__dict__['__name2value'][ key ] + else: + return super( named_tuple, self ).__getitem__( key ) + +if __name__ == '__main__': + 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. |
From: <rom...@us...> - 2006-11-30 13:56:26
|
Revision: 770 http://svn.sourceforge.net/pygccxml/?rev=770&view=rev Author: roman_yakovenko Date: 2006-11-30 05:56:21 -0800 (Thu, 30 Nov 2006) Log Message: ----------- adding dependencies manager Modified Paths: -------------- pyplusplus_dev/pyplusplus/module_creator/creator.py Added Paths: ----------- pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py Property Changed: ---------------- pyplusplus_dev/unittests/ Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-11-30 13:47:13 UTC (rev 769) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2006-11-30 13:56:21 UTC (rev 770) @@ -6,6 +6,7 @@ import types_database import creators_wizard import sort_algorithms +import dependencies_manager import opaque_types_manager import call_policies_resolver from pygccxml import declarations @@ -127,7 +128,9 @@ self.__exposed_free_fun_overloads = set() self.__opaque_types_manager = opaque_types_manager.manager_t( self.__extmodule ) self.__return_pointee_value_exists = False - + + self.__dependencies_manager = dependencies_manager.manager_t(self.decl_logger) + def _prepare_decls( self, decls, doc_extractor ): decls = declarations.make_flatten( decls ) @@ -181,6 +184,7 @@ and operator is creator.declaration , creator.creators ): #expose operator only once + self.__dependencies_manager.add_exported( operator ) creator.adopt_creator( code_creators.operator_t( operator=operator ) ) elif not creator: pass @@ -302,6 +306,7 @@ used_headers.add( isuite[ container_name ] ) cls_creator = create_cls_cc( cls ) + self.__dependencies_manager.add_exported( cls ) creators.append( cls_creator ) try: element_type = cls.indexing_suite.element_type @@ -370,6 +375,7 @@ creator.target_configuration = self.__target_configuration #last action. self._append_user_code() + self.__dependencies_manager.inform_user() return self.__extmodule def _create_includes(self): @@ -380,6 +386,7 @@ def visit_member_function( self ): fwrapper = None self.__types_db.update( self.curr_decl ) + self.__dependencies_manager.add_exported( self.curr_decl ) if None is self.curr_decl.call_policies: self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) self.__on_demand_include_call_policies( self.curr_decl.call_policies ) @@ -436,6 +443,7 @@ if self.curr_decl.is_copy_constructor: return self.__types_db.update( self.curr_decl ) + self.__dependencies_manager.add_exported( self.curr_decl ) if self.curr_decl.allow_implicit_conversion: maker = code_creators.casting_constructor_t( constructor=self.curr_decl ) self.__module_body.adopt_creator( maker ) @@ -461,8 +469,10 @@ self.__types_db.update( self.curr_decl ) maker = code_creators.operator_t( operator=self.curr_decl ) self.curr_code_creator.adopt_creator( maker ) + self.__dependencies_manager.add_exported( self.curr_decl ) def visit_casting_operator( self ): + self.__dependencies_manager.add_exported( self.curr_decl ) if None is self.curr_decl.call_policies: self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) self.__on_demand_include_call_policies( self.curr_decl.call_policies ) @@ -494,6 +504,7 @@ self.__exposed_free_fun_overloads.update( overloads ) for f in overloads: self.__types_db.update( f ) + self.__dependencies_manager.add_exported( f ) if None is f.call_policies: f.call_policies = self.__call_policies_resolver( f ) self.__on_demand_include_call_policies( f.call_policies ) @@ -514,6 +525,7 @@ overloads_reg.associated_decl_creators.extend( uc_creators ) else: self.__types_db.update( self.curr_decl ) + self.__dependencies_manager.add_exported( self.curr_decl ) if None is self.curr_decl.call_policies: self.curr_decl.call_policies = self.__call_policies_resolver( self.curr_decl ) self.__on_demand_include_call_policies( self.curr_decl.call_policies ) @@ -557,6 +569,7 @@ for f in overloads: self.__types_db.update( f ) + self.__dependencies_manager.add_exported( f ) if None is f.call_policies: f.call_policies = self.__call_policies_resolver( f ) self.__on_demand_include_call_policies( f.call_policies ) @@ -572,7 +585,7 @@ return exposed def visit_class(self ): - assert isinstance( self.curr_decl, declarations.class_t ) + self.__dependencies_manager.add_exported( self.curr_decl ) cls_decl = self.curr_decl cls_parent_cc = self.curr_code_creator exportable_members = self.curr_decl.get_exportable_members(sort_algorithms.sort) @@ -643,7 +656,7 @@ def visit_enumeration(self): - assert isinstance( self.curr_decl, declarations.enumeration_t ) + self.__dependencies_manager.add_exported( self.curr_decl ) maker = None if self.curr_decl.name: maker = code_creators.enum_t( enum=self.curr_decl ) @@ -667,7 +680,8 @@ def visit_variable(self): self.__types_db.update( self.curr_decl ) - + self.__dependencies_manager.add_exported( self.curr_decl ) + if declarations.is_array( self.curr_decl.type ): if not self.__cr_array_1_included: self.__extmodule.add_system_header( code_repository.array_1.file_name ) Added: pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py (rev 0) +++ pyplusplus_dev/pyplusplus/module_creator/dependencies_manager.py 2006-11-30 13:56:21 UTC (rev 770) @@ -0,0 +1,76 @@ +# 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) + +from pygccxml import declarations +from pyplusplus import decl_wrappers + +class manager_t( object ): + def __init__( self, logger ): + object.__init__( self ) + self.__exported_decls = [] + self.__logger = logger + + def add_exported( self, decl ): + self.__exported_decls.append( decl ) + + def __is_std_decl( self, decl ): + if not decl.parent: + return False + + if not isinstance( decl.parent, declarations.namespace_t ): + return False + + if 'std' != decl.parent.name: + return False + + ns_std = decl.parent + if not ns_std.parent: + return False + + if not isinstance( ns_std.parent, declarations.namespace_t ): + return False + + if '::' != ns_std.parent.name: + return False + + global_ns = ns_std.parent + if global_ns.parent: + return False + + if decl.name.startswith( 'pair<' ): + #special case + return False + return True + + def __build_dependencies( self, decl ): + if self.__is_std_decl( decl ): + return [] #std declarations should be exported by Py++! + return decl.i_depend_on_them() + + def __find_out_used_but_not_exported( self ): + used_not_exported = [] + exported_ids = set( map( lambda d: id( d ), self.__exported_decls ) ) + for decl in self.__exported_decls: + for dependency in self.__build_dependencies( decl ): + depend_on_decl = dependency.find_out_depend_on_declaration() + if None is depend_on_decl: + continue + if self.__is_std_decl( depend_on_decl ): + continue + if isinstance( depend_on_decl, declarations.class_types ) and depend_on_decl.opaque: + continue + if id( depend_on_decl ) not in exported_ids: + used_not_exported.append( dependency ) + return used_not_exported + + def __create_msg( self, dependency ): + reason = 'The declaration depends on unexposed declaration "%s".' \ + % dependency.find_out_depend_on_declaration() + return "%s;%s" % ( dependency.declaration, reason ) + + def inform_user( self ): + used_not_exported_decls = self.__find_out_used_but_not_exported() + for used_not_exported in used_not_exported_decls: + self.__logger.warn( self.__create_msg( used_not_exported ) ) Property changes on: pyplusplus_dev/unittests ___________________________________________________________________ Name: svn:ignore + *.pyc This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-11-30 13:47:14
|
Revision: 769 http://svn.sourceforge.net/pygccxml/?rev=769&view=rev Author: roman_yakovenko Date: 2006-11-30 05:47:13 -0800 (Thu, 30 Nov 2006) Log Message: ----------- adding missing dependencies tester adding find_out_depend_on_declaration functionality Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/__init__.py pygccxml_dev/pygccxml/declarations/dependencies.py Added Paths: ----------- pygccxml_dev/unittests/dependencies_tester.py Property Changed: ---------------- pygccxml_dev/unittests/ Modified: pygccxml_dev/pygccxml/declarations/__init__.py =================================================================== --- pygccxml_dev/pygccxml/declarations/__init__.py 2006-11-30 11:22:15 UTC (rev 768) +++ pygccxml_dev/pygccxml/declarations/__init__.py 2006-11-30 13:47:13 UTC (rev 769) @@ -19,6 +19,8 @@ from class_declaration import hierarchy_info_t from class_declaration import class_declaration_t +class_types = ( class_t, class_declaration_t ) + from typedef import typedef_t from cpptypes import type_t Modified: pygccxml_dev/pygccxml/declarations/dependencies.py =================================================================== --- pygccxml_dev/pygccxml/declarations/dependencies.py 2006-11-30 11:22:15 UTC (rev 768) +++ pygccxml_dev/pygccxml/declarations/dependencies.py 2006-11-30 13:47:13 UTC (rev 769) @@ -4,11 +4,17 @@ # http://www.boost.org/LICENSE_1_0.txt) """ +this module contains class that keeps dependency information of some declaration """ +import cpptypes + class dependency_info_t( object ): def __init__( self, declaration, depend_on_it, access_type=None ): object.__init__( self ) + #prevent recursive import + import class_declaration + assert isinstance( depend_on_it, ( class_declaration.class_t, cpptypes.type_t ) ) self._declaration = declaration self._depend_on_it = depend_on_it self._access_type = access_type @@ -32,3 +38,17 @@ def __str__( self ): return 'declaration "%s" depends( %s ) on "%s" ' \ % ( self.declaration, self.access_type, self.depend_on_it ) + + def find_out_depend_on_declaration( self ): + """if declaration depends on other declaration and not on some type + this function will return reference to it. Otherwise None will be returned + """ + #prevent recursive import + from pygccxml import declarations + + if isinstance( self.depend_on_it, declarations.declaration_t ): + return self.depend_on_it + base_type = declarations.base_type( declarations.remove_alias( self.depend_on_it ) ) + if isinstance( base_type, cpptypes.declarated_t ): + return base_type.declaration + return None Property changes on: pygccxml_dev/unittests ___________________________________________________________________ Name: svn:ignore + *.pyc Added: pygccxml_dev/unittests/dependencies_tester.py =================================================================== --- pygccxml_dev/unittests/dependencies_tester.py (rev 0) +++ pygccxml_dev/unittests/dependencies_tester.py 2006-11-30 13:47:13 UTC (rev 769) @@ -0,0 +1,95 @@ +# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import unittest +import autoconfig +import parser_test_case + +from pygccxml import utils +from pygccxml import parser +from pygccxml import declarations + +class tester_t( parser_test_case.parser_test_case_t ): + def __init__(self, *args ): + parser_test_case.parser_test_case_t.__init__( self, *args ) + self.header = 'include_all.hpp' + self.global_ns = None + + def setUp(self): + if not self.global_ns: + decls = parser.parse( [self.header], self.config ) + self.global_ns = declarations.get_global_namespace( decls ) + self.global_ns.init_optimizer() + + def test_variable( self ): + ns_vars = self.global_ns.namespace( '::declarations::variables' ) + static_var = ns_vars.variable( 'static_var' ) + dependencies = static_var.i_depend_on_them() + self.failUnless( len(dependencies) == 1 ) + self.failUnless( dependencies[0].declaration is static_var ) + self.failUnless( dependencies[0].depend_on_it.decl_string == 'int' ) + + m_mutable = ns_vars.variable( 'm_mutable' ) + dependencies = m_mutable.i_depend_on_them() + self.failUnless( len(dependencies) == 1 ) + self.failUnless( dependencies[0].declaration is m_mutable ) + self.failUnless( dependencies[0].depend_on_it.decl_string == 'int' ) + + def test_class( self ): + ns_vars = self.global_ns.namespace( '::declarations::variables' ) + + cls = ns_vars.class_( 'struct_variables_t' ) + dependencies = cls.i_depend_on_them() + self.failUnless( len(dependencies) == 2 ) #compiler generated copy constructor + + m_mutable = ns_vars.variable( 'm_mutable' ) + dependencies = filter( lambda dependency: dependency.declaration is m_mutable + , dependencies ) + self.failUnless( len(dependencies) == 1 ) + self.failUnless( dependencies[0].depend_on_it.decl_string == 'int' ) + self.failUnless( dependencies[0].access_type == 'public' ) + + ns_dh = self.global_ns.namespace( '::core::diamand_hierarchy' ) + fd_cls = ns_dh.class_( 'final_derived_t' ) + derived1_cls = ns_dh.class_( 'derived1_t' ) + dependencies = fd_cls.i_depend_on_them() + dependencies = filter( lambda dependency: dependency.depend_on_it is derived1_cls + , dependencies ) + self.failUnless( len(dependencies) == 1 ) + self.failUnless( dependencies[0].depend_on_it is derived1_cls) + self.failUnless( dependencies[0].access_type == 'public' ) + + def test_calldefs( self ): + ns = self.global_ns.namespace( '::declarations::calldef' ) + return_default_args = ns.calldef( 'return_default_args' ) + dependencies = return_default_args.i_depend_on_them() + self.failUnless( len(dependencies) == 3 ) + used_types = map( lambda dependency: dependency.depend_on_it.decl_string + , dependencies ) + + self.failUnless( used_types == [ 'int', 'bool', 'int' ] ) + + some_exception = ns.class_( 'some_exception_t' ) + other_exception = ns.class_( 'other_exception_t' ) + calldef_with_throw = ns.calldef( 'calldef_with_throw' ) + dependencies = calldef_with_throw.i_depend_on_them() + self.failUnless( len(dependencies) == 3 ) + dependencies = filter( lambda dependency: dependency.depend_on_it in ( some_exception, other_exception ) + , dependencies ) + self.failUnless( len(dependencies) == 2 ) + + def test_coverage( self ): + self.global_ns.i_depend_on_them() + +def create_suite(): + suite = unittest.TestSuite() + suite.addTest( unittest.makeSuite(tester_t)) + return suite + +def run_suite(): + unittest.TextTestRunner(verbosity=2).run( create_suite() ) + +if __name__ == "__main__": + run_suite() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-11-30 11:22:16
|
Revision: 768 http://svn.sourceforge.net/pygccxml/?rev=768&view=rev Author: roman_yakovenko Date: 2006-11-30 03:22:15 -0800 (Thu, 30 Nov 2006) Log Message: ----------- deleting pyplusplus_dev_ft branch Removed Paths: ------------- pyplusplus_dev_ft/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-11-30 11:20:24
|
Revision: 767 http://svn.sourceforge.net/pygccxml/?rev=767&view=rev Author: roman_yakovenko Date: 2006-11-30 03:20:24 -0800 (Thu, 30 Nov 2006) Log Message: ----------- merge of FT feature from pyplusplus_dev_ft branch Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/__init__.py pyplusplus_dev/pyplusplus/code_creators/algorithm.py pyplusplus_dev/pyplusplus/code_creators/calldef.py pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py pyplusplus_dev/pyplusplus/code_creators/declaration_based.py pyplusplus_dev/pyplusplus/code_repository/__init__.py pyplusplus_dev/pyplusplus/code_repository/call_policies.py pyplusplus_dev/pyplusplus/code_repository/convenience.py pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py pyplusplus_dev/pyplusplus/decl_wrappers/call_policies.py pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/properties.py pyplusplus_dev/pyplusplus/file_writers/writer.py pyplusplus_dev/pyplusplus/function_transformers/__init__.py pyplusplus_dev/pyplusplus/function_transformers/controllers.py pyplusplus_dev/pyplusplus/function_transformers/function_transformation.py pyplusplus_dev/pyplusplus/function_transformers/templates.py pyplusplus_dev/pyplusplus/function_transformers/transformer.py pyplusplus_dev/pyplusplus/function_transformers/transformers.py pyplusplus_dev/pyplusplus/module_builder/builder.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/test_all.py Added Paths: ----------- pyplusplus_dev/pyplusplus/code_repository/named_tuple.py Removed Paths: ------------- pyplusplus_dev/pyplusplus/function_transformers/code_manager.py pyplusplus_dev/pyplusplus/function_transformers/substitution_manager.py Modified: pyplusplus_dev/pyplusplus/code_creators/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_creators/__init__.py 2006-11-30 11:20:24 UTC (rev 767) @@ -78,6 +78,8 @@ from calldef_transformed import mem_fun_transformed_t from calldef_transformed import mem_fun_transformed_wrapper_t +from calldef_transformed import free_fun_transformed_t +from calldef_transformed import free_fun_transformed_wrapper_t from calldef_transformed import mem_fun_v_transformed_t from calldef_transformed import mem_fun_v_transformed_wrapper_t Modified: pyplusplus_dev/pyplusplus/code_creators/algorithm.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/algorithm.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_creators/algorithm.py 2006-11-30 11:20:24 UTC (rev 767) @@ -99,3 +99,6 @@ if recursive: search_area = make_flatten_generator( where ) return filter( lambda inst: isinstance( inst, what ), search_area ) + +def make_id_creator( code_creator ): + return lambda decl_string: create_identifier( code_creator, decl_string ) Modified: pyplusplus_dev/pyplusplus/code_creators/calldef.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_creators/calldef.py 2006-11-30 11:20:24 UTC (rev 767) @@ -19,9 +19,6 @@ #protected member functions - call, override #private - override -def make_id_creator( code_creator ): - return lambda decl_string: algorithm.create_identifier( code_creator, decl_string ) - class calldef_t( registration_based.registration_based_t , declaration_based.declaration_based_t ): def __init__(self, function, wrapper=None ): @@ -50,10 +47,15 @@ def param_sep(self): return os.linesep + self.indent( self.PARAM_SEPARATOR ) - def keywords_args(self): - arg_utils = calldef_utils.argument_utils_t( self.declaration, make_id_creator( self ) ) + def create_keywords_args(self): + arg_utils = calldef_utils.argument_utils_t( self.declaration, algorithm.make_id_creator( self ) ) return arg_utils.keywords_args() + def create_call_policies( self ): + if self.declaration.call_policies.is_default(): + return '' + return self.declaration.call_policies.create( self ) + def create_def_code( self ): if not self.works_on_instance: return '%s.def' % self.parent.class_var_name @@ -96,15 +98,16 @@ result.append( self.create_function_ref_code( not self.works_on_instance ) ) if self.declaration.use_keywords: - result.append( self.param_sep() ) - result.append( self.keywords_args() ) + keywd_args = self.create_keywords_args() + if keywd_args: + result.append( self.param_sep() ) + result.append( keywd_args ) if self.declaration.call_policies: - if not self.declaration.call_policies.is_default(): + c_p_code = self.create_call_policies() + if c_p_code: result.append( self.param_sep() ) - result.append( self.declaration.call_policies.create( self ) ) - else: - pass#don't generate default_call_policies + result.append( c_p_code ) else: result.append( os.linesep + self.indent( '/* undefined call policies */', 2 ) ) @@ -139,11 +142,11 @@ return algorithm.create_identifier( self, '::boost::python::override' ) def function_call_args( self ): - arg_utils = calldef_utils.argument_utils_t( self.declaration, make_id_creator( self ) ) + arg_utils = calldef_utils.argument_utils_t( self.declaration, algorithm.make_id_creator( self ) ) return arg_utils.call_args() def args_declaration( self ): - arg_utils = calldef_utils.argument_utils_t( self.declaration, make_id_creator( self ) ) + arg_utils = calldef_utils.argument_utils_t( self.declaration, algorithm.make_id_creator( self ) ) return arg_utils.args_declaration() def wrapped_class_identifier( self ): @@ -779,7 +782,7 @@ answer.append( '(' ) keywords_args = None if self.declaration.use_keywords: - keywords_args = self.keywords_args() + keywords_args = self.create_keywords_args() answer.append( '%s' % keywords_args ) if self.documentation: if keywords_args: @@ -841,7 +844,7 @@ def _create_constructor_call( self ): answer = [ algorithm.create_identifier( self, self.parent.declaration.decl_string ) ] answer.append( '( ' ) - arg_utils = calldef_utils.argument_utils_t( self.declaration, make_id_creator( self ) ) + arg_utils = calldef_utils.argument_utils_t( self.declaration, algorithm.make_id_creator( self ) ) params = arg_utils.call_args() answer.append( params ) if params: @@ -1177,7 +1180,7 @@ def create_end_def_code( self ): raise NotImplementedError() - def keywords_args(self): + def create_keywords_args(self): result = [ algorithm.create_identifier( self, '::boost::python::args' ) ] result.append( '( ' ) args = [] @@ -1199,7 +1202,7 @@ def create_overloads_cls( self ): result = [ self.overloads_class.name ] result.append( '( ' ) - result.append( os.linesep + self.indent( self.keywords_args(), 3 ) ) + result.append( os.linesep + self.indent( self.create_keywords_args(), 3 ) ) if self.overloads_class.max_function.documentation: result.append( os.linesep + self.indent( self.PARAM_SEPARATOR, 3 ) ) result.append( self.overloads_class.max_function.documentation ) Modified: pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_creators/calldef_transformed.py 2006-11-30 11:20:24 UTC (rev 767) @@ -4,482 +4,415 @@ # http://www.boost.org/LICENSE_1_0.txt) import os -#import algorithm -#import code_creator +import algorithm +import code_creator +import calldef_utils import class_declaration from pygccxml import declarations from calldef import calldef_t, calldef_wrapper_t import pyplusplus.function_transformers as function_transformers from pyplusplus import code_repository -###################################################################### +#TODO: constructors also can have transformation defined. We should use make _init +# function for this purpose -class mem_fun_transformed_t( calldef_t ): - """Creates code for public non-virtual member functions. - """ - +def remove_duplicate_linesep( code ): + lines = code.split( os.linesep ) + lines = filter( lambda line: line.strip(), lines ) + return os.linesep.join( lines ) + +class sealed_fun_transformed_t( calldef_t ): def __init__( self, function, wrapper=None ): calldef_t.__init__( self, function=function, wrapper=wrapper ) + @property + def ft( self ): #function transformation + return self.declaration.transformations[0] + + @property + def controller( self ): + return self.ft.controller + + def _get_alias_impl( self ): + return self.wrapper.ft.alias + def create_function_type_alias_code( self, exported_class_alias=None ): - if self.wrapper==None: - ftype = self.declaration.function_type() - else: - ftype = self.wrapper.function_type() - res = 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) - return res + ftype = self.wrapper.function_type() + return 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) def create_function_ref_code(self, use_function_alias=False): - if self.wrapper: - full_name = self.wrapper.full_name() - else: - full_name = declarations.full_name( self.declaration ) + full_name = self.wrapper.full_name() if use_function_alias: return '%s( &%s )' \ % ( self.function_type_alias, full_name ) elif self.declaration.create_with_signature: - if self.wrapper: - func_type = self.wrapper.function_type() - else: - func_type = self.declaration.function_type().decl_string - return '(%s)( &%s )' \ - % ( func_type, full_name ) + func_type = self.wrapper.function_type() + return '(%s)( &%s )' % ( func_type, full_name ) else: return '&%s' % full_name + def create_call_policies( self ): + return '' -class mem_fun_transformed_wrapper_t( calldef_wrapper_t ): - """Creates wrapper code for (public) non-virtual member functions. - - The generated function is either used as a static member inside the - wrapper class (when self.parent is not None) or as a free function - (when self.parent is None). - """ - +class sealed_fun_transformed_wrapper_t( calldef_wrapper_t ): def __init__( self, function ): - """Constructor. - - @param function: Function declaration - @type function: calldef_t - """ calldef_wrapper_t.__init__( self, function=function ) - # Create the substitution manager - sm = function_transformers.substitution_manager_t( function - , transformers=function.transformations[0].transformers) - sm.init_funcs() - self._subst_manager = sm + @property + def ft( self ): #function transformation + return self.declaration.transformations[0] - def function_type(self): - """Return the type of the wrapper function. + @property + def controller( self ): + return self.ft.controller - @rtype: type_t - """ - template = '$RET_TYPE' - rettype = self._subst_manager.subst_wrapper(template) - rettype = declarations.dummy_type_t(rettype) + def resolve_function_ref( self ): + raise NotImplementedError() - return declarations.free_function_type_t( - return_type=rettype - , arguments_types=map( lambda arg: arg.type, self.declaration.arguments ) ) + def create_fun_definition(self): + cntrl = self.controller - def wrapper_name(self): - """Return the name of the wrapper function. + make_object = algorithm.create_identifier( self, 'pyplusplus::call_policies::make_object' ) + make_tuple = algorithm.create_identifier( self, 'boost::python::make_tuple' ) + + tmpl_values = dict() - This is just the local name without any scope information. - """ - # A list with the individual components of the name - components = ["_py"] - # Is the wrapper placed outside a wrapper class? - if not isinstance(self.parent, class_declaration.class_wrapper_t): - # Incorporate the original class name into the name - components.append(self.declaration.parent.name) - components.append(self.declaration.alias) - return "_".join(components) + tmpl_values['unique_function_name'] = self.wrapper_name() + tmpl_values['return_type'] = self.controller.wrapper_return_type.decl_string + tmpl_values['arg_declarations'] = self.args_declaration() + + tmpl_values['declare_variables'] \ + = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string() ) + , cntrl.variables ) ) + + tmpl_values['pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.pre_call ) ) - def full_name(self): - """Return the full name of the wrapper function. + tmpl_values['save_result'] = '' + if not declarations.is_void( self.declaration.return_type ): + tmpl_values['save_result'] \ + = '%(type)s %(name)s = ' \ + % { 'type': cntrl.result_variable.type.decl_string + , 'name' : cntrl.result_variable.name } - The returned name also includes the class name (if there is any). + tmpl_values['function_name'] = self.resolve_function_ref() + tmpl_values['arg_expressions'] = self.PARAM_SEPARATOR.join( cntrl.arg_expressions ) + return_stmt_creator = calldef_utils.return_stmt_creator_t( self + , self.controller + , self.controller.result_variable + , self.controller.return_variables ) - @rtype: str - """ - if isinstance(self.parent, class_declaration.class_wrapper_t): - return self.parent.full_name + '::' + self.wrapper_name() - else: - return self.wrapper_name() - - def create_declaration(self, name): - """Create the function header. - """ - template = 'static $RET_TYPE %(name)s( $ARG_LIST_DEF ) %(throw)s' - - # Substitute the $-variables - template = self._subst_manager.subst_wrapper(template) - - return template % { - 'name' : self.wrapper_name() - , 'throw' : self.throw_specifier_code() - } - - def create_body(self): - body = os.linesep.join([ - '$DECLARATIONS' - , '$PRE_CALL' - , '$RESULT_VAR_ASSIGNMENT$CALL_FUNC_NAME($INPUT_PARAMS);' - , '$POST_CALL' - , '$RETURN_STMT' - ]) - - # Replace the $-variables - body = self._subst_manager.subst_wrapper(body) - - return body - - def create_function(self): - answer = [70*"/"] - answer.append("// Transformed wrapper function for:") - answer.append("// %s"%self.declaration) - answer.append(70*"/") - answer.append( self.create_declaration(self.declaration.alias) + '{') - answer.append( self.indent( self.create_body() ) ) - answer.append( '}' ) - return os.linesep.join( answer ) - + tmpl_values['post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.post_call ) ) + if return_stmt_creator.pre_return_code: + tmpl_values['post_call'] \ + = os.linesep.join([ tmpl_values['post_call'] + , self.indent( return_stmt_creator.pre_return_code )]) + tmpl_values['return'] = os.linesep + self.indent( return_stmt_creator.statement ) + + f_def = self.controller.template.substitute(tmpl_values) + return remove_duplicate_linesep( f_def ) + def _create_impl(self): - - answer = self.create_function() - - # Replace the argument list of the declaration so that in the - # case that keywords are created, the correct arguments will be - # picked up (i.e. the modified argument list and not the original - # argument list) - self.declaration.arguments = self._subst_manager.wrapper_func.arg_list - - return answer - -###################################################################### - -class mem_fun_v_transformed_t( calldef_t ): - """Creates code for (public) virtual member functions. + return self.create_fun_definition() + +class free_fun_transformed_t( sealed_fun_transformed_t ): + """Creates code for public non-virtual member functions. """ def __init__( self, function, wrapper=None ): - calldef_t.__init__( self, function=function, wrapper=wrapper ) - self.default_function_type_alias = 'default_' + self.function_type_alias + sealed_fun_transformed_t.__init__( self, function=function, wrapper=wrapper ) + self.works_on_instance = False - def create_function_type_alias_code( self, exported_class_alias=None ): - if self.wrapper==None: - ftype = self.declaration.function_type() - else: - ftype = self.wrapper.function_type() + def create_def_code( self ): + return self.def_identifier() - result = [] - result.append( 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) ) - return ''.join( result ) + def create_keywords_args(self): + arg_utils = calldef_utils.argument_utils_t( self.declaration + , algorithm.make_id_creator( self ) + , self.controller.wrapper_args ) + return arg_utils.keywords_args() - def create_doc(self): - return None - def create_function_ref_code(self, use_function_alias=False): - if self.wrapper: - full_name = self.wrapper.default_full_name() - else: - full_name = declarations.full_name( self.declaration ) - - result = [] - if use_function_alias: - result.append( '%s(&%s)' - % ( self.function_type_alias, full_name ) ) - elif self.declaration.create_with_signature: - if self.wrapper: - func_type = self.wrapper.function_type() - else: - func_type = self.declaration.function_type().decl_string - result.append( '(%s)(&%s)' - % ( func_type, full_name ) ) - else: - result.append( '&%s' % full_name ) - - return ''.join( result ) - - -class mem_fun_v_transformed_wrapper_t( calldef_wrapper_t ): - """Creates wrapper code for (public) virtual member functions. - - The generated code consists of two functions: the virtual function - and the 'default' function. - """ - +class free_fun_transformed_wrapper_t( sealed_fun_transformed_wrapper_t ): def __init__( self, function ): """Constructor. @param function: Function declaration @type function: calldef_t """ - calldef_wrapper_t.__init__( self, function=function ) - - # Create the substitution manager - sm = function_transformers.substitution_manager_t(function - , transformers=function.transformations[0].transformers ) + sealed_fun_transformed_wrapper_t .__init__( self, function=function ) - sm.init_funcs() - self._subst_manager = sm - - # Stores the name of the variable that holds the override - self._override_var \ - = sm.virtual_func.declare_variable(function.alias + "_callable", 'boost::python::override') - # Stores the name of the 'gstate' variable - self._gstate_var \ - = sm.virtual_func.declare_variable("gstate", 'pyplusplus::threading ::gil_guard_t' ) - - def default_name(self): - """Return the name of the 'default' function. - - @rtype: str - """ - return "default_" + self.declaration.alias - - def default_full_name(self): - """Return the full name of the 'default' function. - - The returned name also includes the class name. - - @rtype: str - """ - return self.parent.full_name + '::default_' + self.declaration.alias - - def virtual_name(self): - """Return the name of the 'virtual' function. - - @rtype: str - """ - return self.declaration.name - - def base_name(self): - """Return the name of the 'base' function. - - @rtype: str - """ - return "base_" + self.declaration.name - def function_type(self): - template = '$RET_TYPE' - rettype = self._subst_manager.subst_wrapper(template) - rettype = declarations.dummy_type_t(rettype) - return declarations.free_function_type_t( - return_type=rettype - , arguments_types=map( lambda arg: arg.type, self.declaration.arguments ) ) + return_type=self.controller.wrapper_return_type + , arguments_types=self.controller.wrapper_args ) - return declarations.member_function_type_t( - return_type=self.declaration.return_type - , class_inst=declarations.dummy_type_t( self.parent.full_name ) - , arguments_types=map( lambda arg: arg.type, self.declaration.arguments ) - , has_const=self.declaration.has_const ) + def wrapper_name( self ): + return self.ft.unique_name - def create_declaration(self, name, virtual=True): - """Create the function header. + def full_name(self): + return self.ft.unique_name - This method is used for the virtual function (and the base_ function), - but not for the default function. - """ - template = '%(virtual)s$RET_TYPE %(name)s( $ARG_LIST_DEF )%(constness)s %(throw)s' + def args_declaration( self ): + arg_utils = calldef_utils.argument_utils_t( + self.declaration + , algorithm.make_id_creator( self ) + , self.controller.wrapper_args ) + return arg_utils.args_declaration() - # Substitute the $-variables - template = self._subst_manager.subst_virtual(template) + def create_declaration(self, name): + template = 'static %(return_type)s %(name)s( %(args)s )' - virtualspec = '' - if virtual: - virtualspec = 'virtual ' - - constness = '' - if self.declaration.has_const: - constness = ' const ' - return template % { - 'virtual' : virtualspec - , 'name' : name - , 'constness' : constness - , 'throw' : self.throw_specifier_code() + 'return_type' : self.controller.wrapper_return_type.decl_string + , 'name' : self.wrapper_name() + , 'args' : self.args_declaration() } - def create_base_body(self): - body = "%(return_)s%(wrapped_class)s::%(name)s( %(args)s );" + def resolve_function_ref( self ): + return declarations.full_name( self.declaration ) - return_ = '' - if not declarations.is_void( self.declaration.return_type ): - return_ = 'return ' - return body % { - 'name' : self.declaration.name - , 'args' : self.function_call_args() - , 'return_' : return_ - , 'wrapped_class' : self.wrapped_class_identifier() - } +class mem_fun_transformed_t( sealed_fun_transformed_t ): + """Creates code for public non-virtual member functions. + """ + def __init__( self, function, wrapper=None ): + sealed_fun_transformed_t.__init__( self, function=function, wrapper=wrapper ) - def create_virtual_body(self): + def create_keywords_args(self): + args = self.controller.wrapper_args[:] + if self.controller.inst_arg: + args.insert( 0, self.controller.inst_arg ) - thread_safe = self.declaration.transformations[0].thread_safe + arg_utils = calldef_utils.argument_utils_t( self.declaration + , algorithm.make_id_creator( self ) + , args ) + return arg_utils.keywords_args() - if thread_safe: - body = """ -pyplusplus::threading::gil_guard_t %(gstate_var)s; +class mem_fun_transformed_wrapper_t( sealed_fun_transformed_wrapper_t ): + def __init__( self, function ): + """Constructor. -%(gstate_var)s.ensure(); -boost::python::override %(override_var)s = this->get_override( "%(alias)s" ); -%(gstate_var)s.release(); + @param function: Function declaration + @type function: calldef_t + """ + sealed_fun_transformed_wrapper_t.__init__( self, function=function ) -if( %(override_var)s ) -{ - // The corresponding release() is done in the destructor of %(gstate_var)s - %(gstate_var)s.ensure(); + def __is_global( self ): + return not isinstance( self.parent, class_declaration.class_wrapper_t ) - $DECLARATIONS + def function_type(self): + args = map( lambda arg: arg.type, self.controller.wrapper_args ) + if self.controller.inst_arg: + args.insert( 0, self.controller.inst_arg.type ) + return declarations.free_function_type_t( + return_type=self.controller.wrapper_return_type + , arguments_types=args ) - try { - $PRE_CALL + def wrapper_name( self ): + if self.__is_global(): + return self.ft.unique_name + else: + if self.declaration.overloads: + #it is possible that other functions will have same signature + return self.ft.unique_name + else: + return self.declaration.name - ${RESULT_VAR_ASSIGNMENT}boost::python::call<$RESULT_TYPE>($INPUT_PARAMS); + def full_name(self): + if self.__is_global(): + return self.ft.unique_name + else: + return self.parent.full_name + '::' + self.wrapper_name() - $POST_CALL + def args_declaration( self ): + args = self.controller.wrapper_args[:] + if self.controller.inst_arg: + args.insert( 0, self.controller.inst_arg ) + arg_utils = calldef_utils.argument_utils_t( + self.declaration + , algorithm.make_id_creator( self ) + , args ) + return arg_utils.args_declaration() - $RETURN_STMT - } - catch(...) - { - if (PyErr_Occurred()) - { - PyErr_Print(); - } + def resolve_function_ref( self ): + if self.controller.inst_arg: + return self.controller.inst_arg.name + '.' + self.declaration.name + else: + return declarations.full_name( self.declaration ) - $CLEANUP +class mem_fun_v_transformed_t( calldef_t ): + def __init__( self, function, wrapper=None ): + calldef_t.__init__( self, function=function, wrapper=wrapper ) - $EXCEPTION_HANDLER_EXIT - } -} -else -{ - %(inherited)s -} -""" + @property + def ft( self ): #function transformation + return self.declaration.transformations[0] - if not thread_safe: - body = """ -boost::python::override %(override_var)s = this->get_override( "%(alias)s" ); + @property + def controller( self ): + return self.ft.controller + + def _get_alias_impl( self ): + return self.wrapper.ft.alias + + def create_function_type_alias_code( self, exported_class_alias=None ): + result = [] -if( %(override_var)s ) -{ - $DECLARATIONS + ftype = self.declaration.function_type() + result.append( 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) ) + if self.wrapper: + result.append( os.linesep ) + ftype = self.wrapper.function_type() + result.append( 'typedef %s;' % ftype.create_typedef( self.default_function_type_alias ) ) + return ''.join( result ) - $PRE_CALL + def create_keywords_args(self): + cntrl = self.controller.default_controller + arg_utils = calldef_utils.argument_utils_t( self.declaration + , algorithm.make_id_creator( self ) + , [cntrl.inst_arg] + cntrl.wrapper_args ) + return arg_utils.keywords_args() - ${RESULT_VAR_ASSIGNMENT}boost::python::call<$RESULT_TYPE>($INPUT_PARAMS); + def create_function_ref_code(self, use_function_alias=False): + full_name = self.wrapper.default_full_name() + if use_function_alias: + return '%s( &%s )' % ( self.function_type_alias, full_name ) + elif self.declaration.create_with_signature: + func_type = self.wrapper.default_function_type() + return '(%s)( &%s )' % ( func_type, full_name ) + else: + return '&%s' % full_name - $POST_CALL +class mem_fun_v_transformed_wrapper_t( calldef_wrapper_t ): + def __init__( self, function ): + calldef_wrapper_t.__init__( self, function=function ) - $RETURN_STMT -} -else -{ - %(inherited)s -} -""" + @property + def ft( self ): #function transformation + return self.declaration.transformations[0] - vf = self._subst_manager.virtual_func - arg0 = "%s.ptr()"%self._override_var - if vf.INPUT_PARAMS=="": - vf.INPUT_PARAMS = arg0 + @property + def controller( self ): + return self.ft.controller + + def default_name(self): + if self.declaration.overloads: + #it is possible that other functions will have same signature + return 'default_' + self.ft.unique_name else: - vf.INPUT_PARAMS = arg0+", "+vf.INPUT_PARAMS + return 'default_' + self.declaration.alias - # Replace the $-variables - body = self._subst_manager.subst_virtual(body) + def default_full_name(self): + return self.parent.full_name + '::' + self.default_name() - return body % { - 'override_var' : self._override_var - , 'gstate_var' : self._gstate_var - , 'alias' : self.declaration.alias - , 'inherited' : self.create_base_body() - } + def args_override_declaration( self ): + return self.args_declaration() - def create_default_body(self): - cls_wrapper_type = self.parent.full_name - cls_wrapper = self._subst_manager.wrapper_func.declare_variable("cls_wrapper", cls_wrapper_type); - # The name of the 'self' variable (i.e. first argument) - selfname = self._subst_manager.wrapper_func.arg_list[0].name + def args_default_declaration( self ): + cntrl = self.controller.default_controller + arg_utils = calldef_utils.argument_utils_t( self.declaration + , algorithm.make_id_creator( self ) + , [cntrl.inst_arg] + cntrl.wrapper_args ) + return arg_utils.args_declaration() - body = """$DECLARATIONS + def default_function_type(self): + cntrl = self.controller.default_controller + args = [cntrl.inst_arg.type] + map( lambda arg: arg.type, cntrl.wrapper_args ) + return declarations.free_function_type_t( return_type=cntrl.wrapper_return_type + , arguments_types=args ) -$PRE_CALL + def create_default(self): + cntrl = self.controller.default_controller -%(cls_wrapper_type)s* %(cls_wrapper)s = dynamic_cast<%(cls_wrapper_type)s*>(boost::addressof(%(self)s)); -if (%(cls_wrapper)s==0) -{ - // The following call is done on an instance created in C++, - // so it won't invoke Python code. - $RESULT_VAR_ASSIGNMENT$CALL_FUNC_NAME($INPUT_PARAMS); -} -else -{ - // The following call is done on an instance created in Python, - // i.e. a wrapper instance. This call might invoke Python code. - $RESULT_VAR_ASSIGNMENT%(cls_wrapper)s->%(base_name)s($INPUT_PARAMS); -} + make_object = algorithm.create_identifier( self, 'pyplusplus::call_policies::make_object' ) + make_tuple = algorithm.create_identifier( self, 'boost::python::make_tuple' ) + + tmpl_values = dict() -$POST_CALL + tmpl_values['unique_function_name'] = self.default_name() + tmpl_values['return_type'] = cntrl.wrapper_return_type.decl_string + tmpl_values['arg_declarations'] = self.args_default_declaration() + tmpl_values['wrapper_class'] = self.parent.wrapper_alias + tmpl_values['wrapped_class'] = declarations.full_name( self.declaration.parent ) + tmpl_values['wrapped_inst'] = cntrl.inst_arg.name + + decl_vars = cntrl.variables[:] + if not declarations.is_void( self.declaration.return_type ): + decl_vars.append( cntrl.result_variable ) + tmpl_values['declare_variables'] \ + = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string() ) + , decl_vars ) ) + + tmpl_values['pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.pre_call ) ) -$RETURN_STMT -""" + tmpl_values['save_result'] = '' + if not declarations.is_void( self.declaration.return_type ): + tmpl_values['save_result'] = '%s = ' % cntrl.result_variable.name - # Replace the $-variables - body = self._subst_manager.subst_wrapper(body) + tmpl_values['function_name'] = self.declaration.name + tmpl_values['arg_expressions'] = self.PARAM_SEPARATOR.join( cntrl.arg_expressions ) + return_stmt_creator = calldef_utils.return_stmt_creator_t( self + , cntrl + , cntrl.result_variable + , cntrl.return_variables ) - # Replace the remaining parameters - body = body%{"cls_wrapper_type" : cls_wrapper_type, - "cls_wrapper" : cls_wrapper, - "self" : selfname, - "base_name" : self.base_name() } - return body + tmpl_values['post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.post_call ) ) + if return_stmt_creator.pre_return_code: + tmpl_values['post_call'] \ + = os.linesep.join([ tmpl_values['post_call'] + , self.indent( return_stmt_creator.pre_return_code )]) + tmpl_values['return'] = os.linesep + self.indent( return_stmt_creator.statement ) + + f_def = cntrl.template.substitute(tmpl_values) + return remove_duplicate_linesep( f_def ) - def create_function(self): - answer = [ self.create_declaration(self.declaration.name) + '{' ] - answer.append( self.indent( self.create_virtual_body() ) ) - answer.append( '}' ) - return os.linesep.join( answer ) + def wrapped_class_identifier( self ): + return algorithm.create_identifier( self, declarations.full_name( self.declaration.parent ) ) - def create_base_function( self ): - answer = [ self.create_declaration("base_"+self.declaration.name, False) + '{' ] - body = "%(return_)s%(wrapped_class)s::%(name)s( %(args)s );" - answer.append( self.indent( self.create_base_body() ) ) - answer.append( '}' ) - return os.linesep.join( answer ) + def create_override(self): + cntrl = self.controller.override_controller + + tmpl_values = dict() + tmpl_values['return_type' ] = self.declaration.return_type.decl_string + tmpl_values['function_name'] = self.declaration.name + tmpl_values['arg_declarations'] = self.args_override_declaration() + tmpl_values['constness'] = '' + if self.declaration.has_const: + tmpl_values['constness'] = ' const ' + tmpl_values['throw'] = self.throw_specifier_code() + tmpl_values['py_function_var'] = cntrl.py_function_var + tmpl_values['function_alias'] = self.declaration.alias + tmpl_values['declare_py_variables'] \ + = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string(), 2 ) + , cntrl.py_variables ) ) - def create_default_function( self ): + tmpl_values['py_pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.py_pre_call ), 2 ) + tmpl_values['py_post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.py_post_call ), 2 ) + tmpl_values['py_arg_expressions'] = '' + if cntrl.py_arg_expressions: + tmpl_values['py_arg_expressions'] \ + = ', ' + declarations.call_invocation.join( '', cntrl.py_arg_expressions ) + + tmpl_values['save_py_result'] = "bpl::object %s = " % cntrl.py_result_variable.name + tmpl_values['py_return'] = '' + tmpl_values['cpp_return'] = '' + if not declarations.is_void( self.declaration.return_type ): + tmpl_values['py_return'] \ + = 'return bpl::extract< %(type)s >( pyplus_conv::get_out_argument( %(py_result)s, 0 ) );' \ + % { 'type' : self.declaration.return_type.decl_string + , 'py_result' : cntrl.py_result_variable.name } + tmpl_values['cpp_return'] = 'return ' - header = 'static $RET_TYPE %s( $ARG_LIST_DEF ) {'%self.default_name() - header = self._subst_manager.subst_wrapper(header) + tmpl_values['wrapped_class'] = self.wrapped_class_identifier() - answer = [ header ] - answer.append( self.indent( self.create_default_body() ) ) - answer.append( '}' ) - return os.linesep.join( answer ) + arg_utils = calldef_utils.argument_utils_t( self.declaration + , algorithm.make_id_creator( self ) + , self.declaration.arguments ) + tmpl_values['cpp_arg_expressions'] = arg_utils.call_args() + f_def_code = cntrl.template.substitute(tmpl_values) + return remove_duplicate_linesep( f_def_code ) + def _create_impl(self): - - answer = [ self.create_function() ] - answer.append( os.linesep ) - answer.append( self.create_base_function() ) - answer.append( os.linesep ) - answer.append( self.create_default_function() ) - answer = os.linesep.join( answer ) - - # Replace the argument list of the declaration so that in the - # case that keywords are created, the correct arguments will be - # picked up (i.e. the modified argument list and not the original - # argument list) - self.declaration.arguments = self._subst_manager.wrapper_func.arg_list - - return answer - \ No newline at end of file + return os.linesep.join([ self.create_override(), '', self.create_default() ]) Modified: pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_creators/calldef_utils.py 2006-11-30 11:20:24 UTC (rev 767) @@ -3,6 +3,8 @@ # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) +import os +import algorithm import code_creator from pygccxml import declarations from pyplusplus import decl_wrappers @@ -39,6 +41,8 @@ return False def keywords_args(self): + if not self.__args: + return '' boost_arg = self.__id_creator( '::boost::python::arg' ) boost_obj = self.__id_creator( '::boost::python::object' ) result = ['( '] @@ -86,8 +90,66 @@ def call_args( self ): params = [] for index, arg in enumerate( self.__args ): - params.append( decl_wrappers.python_traits.call_traits( arg.type ) % self.argument_name( index ) ) + params.append( decl_wrappers.python_traits.call_traits( arg.type ) + % self.argument_name( index ) ) return ', '.join( params ) +class return_stmt_creator_t( object ): + def __init__( self, creator, controller, result_var, return_vars ): + object.__init__( self ) + self.__creator = creator + self.__controller = controller + self.__function = controller.function + self.__return_vars = return_vars[:] + self.__pre_return_code = None + self.__return_stmt = None + self.__result_var = result_var + self.__call_policy_alias = controller.register_variable_name( 'call_policies_t' ) + + @property + def pre_return_code( self ): + if None is self.__pre_return_code: + if not self.__controller.return_variables \ + or self.__function.call_policies.is_default() \ + or declarations.is_void( self.__function.return_type ): + self.__pre_return_code = '' + else: + c_p_typedef = 'typedef %s %s;' \ + % ( self.__function.call_policies.create_template_arg( self.__creator ) + , self.__call_policy_alias ) + self.__pre_return_code = c_p_typedef + return self.__pre_return_code + @property + def statement( self ): + if None is self.__return_stmt: + stmt = '' + bpl_object = algorithm.create_identifier( self.__creator, 'boost::python::object' ) + make_tuple = algorithm.create_identifier( self.__creator, 'boost::python::make_tuple' ) + make_object = algorithm.create_identifier( self.__creator, 'pyplusplus::call_policies::make_object' ) + if not declarations.is_void( self.__function.return_type ): + if self.__function.call_policies.is_default(): + self.__return_vars.insert( 0, self.__result_var.name ) + else: + self.__return_vars.insert( 0 + , declarations.call_invocation.join( + declarations.templates.join( make_object, [self.__call_policy_alias] ) + , [self.__result_var.name] ) ) + + if 0 == len( self.__return_vars ): + pass + elif 1 == len( self.__return_vars ): + stmt = bpl_object + '( %s )' % self.__return_vars[ 0 ] + else: # 1 < + stmt = declarations.call_invocation.join( make_tuple, self.__return_vars ) + if self.__creator.LINE_LENGTH < len( stmt ): + stmt = declarations.call_invocation.join( + make_tuple + , self.__return_vars + , os.linesep + self.__creator.indent( self.__creator.PARAM_SEPARATOR, 6 ) ) + + if stmt: + stmt = 'return ' + stmt + ';' + self.__return_stmt = stmt + return self.__return_stmt Modified: pyplusplus_dev/pyplusplus/code_creators/declaration_based.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/declaration_based.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_creators/declaration_based.py 2006-11-30 11:20:24 UTC (rev 767) @@ -30,9 +30,13 @@ doc="""The declaration this code creator is based on. @type: L{decl_wrapper_t<decl_wrappers.decl_wrapper_t>} """) + + def _get_alias_impl( self ): + return self.declaration.alias def _get_alias(self): - return self.declaration.alias + return self._get_alias_impl() + def _set_alias(self, alias): self.declaration.alias = alias alias = property( _get_alias, _set_alias ) Modified: pyplusplus_dev/pyplusplus/code_repository/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/__init__.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_repository/__init__.py 2006-11-30 11:20:24 UTC (rev 767) @@ -15,10 +15,11 @@ import array_1 import gil_guard +import named_tuple import convenience import call_policies -all = [ array_1, gil_guard, convenience, call_policies ] +all = [ array_1, gil_guard, convenience, call_policies, named_tuple ] headers = map( lambda f: f.file_name, all ) Modified: pyplusplus_dev/pyplusplus/code_repository/call_policies.py =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/call_policies.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_repository/call_policies.py 2006-11-30 11:20:24 UTC (rev 767) @@ -70,6 +70,14 @@ }; +template< typename CallPolicies, class T > +bpl::object make_object( T const & x ){ + //constructs object using CallPolicies result_converter + typedef BOOST_DEDUCED_TYPENAME CallPolicies::result_converter:: template apply< T >::type result_converter_t; + result_converter_t rc; + return bpl::object( bpl::handle<>( rc( x ) ) ); +} + } /*pyplusplus*/ } /*call_policies*/ Modified: pyplusplus_dev/pyplusplus/code_repository/convenience.py =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/convenience.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/code_repository/convenience.py 2006-11-30 11:20:24 UTC (rev 767) @@ -135,8 +135,29 @@ return array_inserter_t<T>( array, size ); } +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 ); + } + 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 ]; + } + else{ + return result; + } +} + } /*pyplusplus*/ } /*convenience*/ +namespace pyplus_conv = pyplusplus::convenience; #endif//__convenience_pyplusplus_hpp__ Copied: pyplusplus_dev/pyplusplus/code_repository/named_tuple.py (from rev 765, pyplusplus_dev_ft/pyplusplus/code_repository/named_tuple.py) =================================================================== --- pyplusplus_dev/pyplusplus/code_repository/named_tuple.py (rev 0) +++ pyplusplus_dev/pyplusplus/code_repository/named_tuple.py 2006-11-30 11:20:24 UTC (rev 767) @@ -0,0 +1,65 @@ +# 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) + +file_name = "named_tuple.py" + +code = \ +"""# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +class named_tuple(tuple): + \"\"\"Creates tuple, which allows access to stored values by name and by index. + + named_tuple could be constructed exactly in the same way as Python dict. + \"\"\" + + 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 __init__(self, seq=None, **keywd): + "named_tuple could be constructed exactly in the same way as Python dict." + 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 + + def __getattr__(self, name): + try: + return self.__dict__['__name2value'][ name ] + except KeyError: + raise AttributeError( "named_tuple has no attribute '%s'" % name ) + + def __setattr__(self, name, value): + raise AttributeError( "named_tuple has no attribute '%s'" % name ) + + def __getitem__( self, key ): + #TODO: it could be nice to support slicing. So the __getitem__ in case of + #slicing will return new named_tuple. + if isinstance( key, basestring ): + return self.__dict__['__name2value'][ key ] + else: + return super( named_tuple, self ).__getitem__( key ) + +if __name__ == '__main__': + 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 + +""" Modified: pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/decl_wrappers/__init__.py 2006-11-30 11:20:24 UTC (rev 767) @@ -98,6 +98,8 @@ from doc_extractor import doc_extractor_i from properties import property_t +from properties import property_recognizer_i +from properties import name_based_recognizer_t import python_traits @@ -147,3 +149,17 @@ def create_variable( self, *arguments, **keywords ): return variable_t(*arguments, **keywords) + +skip_messages = [ + "Py++ does not exports compiler generated constructors" + , 'Py++, by default, does not expose internal compilers declarations. Names of those declarations usually start with "__".' + , 'Py++, by default, does not expose internal declarations (those that gccxml say belong to "<internal>" header).' + , 'Py++, by default, does not expose compiler generated declarations.' + , 'Py++ can not expose private class.' + , 'Py++ will generate class wrapper - class contains definition of virtual or pure virtual member function' + , "Py++ doesn't expose private or protected member variables." + , "Py++ doesn't export private not virtual functions." + , "Py++ doesn't export private constructor." + , "Py++ doesn't export private operators." +] +#Messages kept by skip_messages list will not be reported Modified: pyplusplus_dev/pyplusplus/decl_wrappers/call_policies.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/call_policies.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/decl_wrappers/call_policies.py 2006-11-30 11:20:24 UTC (rev 767) @@ -38,6 +38,9 @@ code = code + '()' return code + def create_template_arg( self, function_creator ): + return self.create( function_creator, CREATION_POLICY.AS_TEMPLATE_ARGUMENT ) + def is_default( self ): """Returns True is self is instance of L{default_call_policies_t} class""" #Small hack that allows to write nicer code @@ -227,4 +230,4 @@ """returns True is policy represents return_value_policy<return_pointee_value>, False otherwise""" return isinstance( policy, return_value_policy_t ) \ and policy.result_converter_generator == return_pointee_value - \ No newline at end of file + Modified: pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/decl_wrappers/calldef_wrapper.py 2006-11-30 11:20:24 UTC (rev 767) @@ -168,10 +168,14 @@ if len( self.arguments ) > calldef_t.BOOST_PYTHON_MAX_ARITY: tmp = [ "The function has more than %d arguments ( %d ). " ] tmp.append( "You should adjust BOOST_PYTHON_MAX_ARITY macro." ) - tmp.append( "For more information see: http://mail.python.org/pipermail/c++-sig/2002-June/001554.html" ) + tmp.append( "For more information see: http://www.boost.org/libs/python/doc/v2/configuration.html" ) tmp = ' '.join( tmp ) msgs.append( tmp % ( calldef_t.BOOST_PYTHON_MAX_ARITY, len( self.arguments ) ) ) - + + if self.transformations: + #if user defined transformation, than I think it took care of the problems + return msgs + if suspicious_type( self.return_type ) and None is self.call_policies: msgs.append( 'The function "%s" returns non-const reference to C++ fundamental type - value can not be modified from Python.' % str( self ) ) Modified: pyplusplus_dev/pyplusplus/decl_wrappers/properties.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/properties.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/decl_wrappers/properties.py 2006-11-30 11:20:24 UTC (rev 767) @@ -58,11 +58,12 @@ class name_based_recognizer_t( property_recognizer_i ): def __init__( self ): property_recognizer_i.__init__( self ) - self.__prefixes = ( - ( 'is', 'set' ) - , ( 'get', 'set' ) - , ( 'has', 'set' ) - , ( '', 'set' ) ) + + def prefixes( self ): + return [ ( 'is', 'set' ) + , ( 'get', 'set' ) + , ( 'has', 'set' ) + , ( '', 'set' ) ] def check_prefix( self, name, prefix ): if not name.startswith( prefix ): @@ -105,7 +106,7 @@ , self.make_l_camel_convention ] for convention_maker in convention_makers: - for g, s in self.__prefixes: + for g, s in self.prefixes(): gc, sc = convention_maker( g, s ) if self.check_name_compatibility( gname, sname, gc, sc ): return ( gc, sc ) @@ -118,7 +119,7 @@ , self.make_l_camel_convention ] for convention_maker in convention_makers: - for g, unused in self.__prefixes: + for g, unused in self.prefixes(): if not g: continue gc, unused = convention_maker( g, 'set' ) Modified: pyplusplus_dev/pyplusplus/file_writers/writer.py =================================================================== --- pyplusplus_dev/pyplusplus/file_writers/writer.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/file_writers/writer.py 2006-11-30 11:20:24 UTC (rev 767) @@ -50,7 +50,12 @@ 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. @@ -91,4 +96,4 @@ f.write( fcontent_new ) f.close() writer_t.logger.info( 'file "%s" - updated( %f seconds )' % ( fname, time.clock() - start_time ) ) - \ No newline at end of file + Modified: pyplusplus_dev/pyplusplus/function_transformers/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/__init__.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/function_transformers/__init__.py 2006-11-30 11:20:24 UTC (rev 767) @@ -16,7 +16,6 @@ """ -from substitution_manager import substitution_manager_t from transformer import transformer_t import transformers from function_transformation import function_transformation_t Deleted: pyplusplus_dev/pyplusplus/function_transformers/code_manager.py =================================================================== --- pyplusplus_dev/pyplusplus/function_transformers/code_manager.py 2006-11-30 10:33:59 UTC (rev 766) +++ pyplusplus_dev/pyplusplus/function_transformers/code_manager.py 2006-11-30 11:20:24 UTC (rev 767) @@ -1,254 +0,0 @@ -# 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) -# -# Initial author: Matthias Baas - -"""This module contains the L{code_manager_t} and L{wrapper_code_manager_t} classes. -""" - -import os -import types -import string - -# code_manager_t -class code_manager_t: - """This class manages pieces of source code for a C++ function. - - The class mainly provides the interface for the code blocks to - manipulate a function and stores the actual substitution variables. - Each function has its own code manager instance. - - A code block can declare a local variable using L{declare_variable()} - and it can manipulate one of the attributes that are used to - initialize the final variables (see the documentation of the - instance variables below). The final variables (such as RET_TYPE, - FUNC_NAME, ARG_LIST, etc.) are stored as regular attributes of the - object. - - The functionality to perform a text substitution (using the - substitution() method) is inherited - from the class L{subst_t}. - - @ivar class_name: The name of the class of which the generated function is a member. A value of None or an empty string is used for free functions. This attribute is used for creating the CLASS_SPEC variable. - @type class_name: str - @ivar ret_type: Return type. The value may be any object where str(obj) is valid C++ code. The value None corresponds to void. This will be the value of the variable RET_TYPE. - @type ret_type: str - @ivar arg_list: The argument list. The items are pygccxml argument_t objects. This list will appear in the variables ARG_LIST, ARG_LIST_DEF and ARG_LIST_TYPES. - @type arg_list: list of L{argument_t<pygccxml.declarations.calldef.argument_t>} - @ivar input_params: A list of strings that contain the input parameter for the function call. This list is used for the INPUT_PARAMS variable. - @type input_params: list of str - @ivar result_var: The name of the variable that will receive the result of the function call. If None, th... [truncated message content] |
From: <rom...@us...> - 2006-11-30 10:34:04
|
Revision: 766 http://svn.sourceforge.net/pygccxml/?rev=766&view=rev Author: roman_yakovenko Date: 2006-11-30 02:33:59 -0800 (Thu, 30 Nov 2006) Log Message: ----------- adding new functionality: declarations will report declarations and types they depend on Modified Paths: -------------- pygccxml_dev/pygccxml/declarations/__init__.py pygccxml_dev/pygccxml/declarations/calldef.py pygccxml_dev/pygccxml/declarations/class_declaration.py pygccxml_dev/pygccxml/declarations/declaration.py pygccxml_dev/pygccxml/declarations/enumeration.py pygccxml_dev/pygccxml/declarations/namespace.py pygccxml_dev/pygccxml/declarations/scopedef.py pygccxml_dev/pygccxml/declarations/typedef.py pygccxml_dev/pygccxml/declarations/variable.py pygccxml_dev/unittests/test_all.py Added Paths: ----------- pygccxml_dev/pygccxml/declarations/dependencies.py Modified: pygccxml_dev/pygccxml/declarations/__init__.py =================================================================== --- pygccxml_dev/pygccxml/declarations/__init__.py 2006-11-29 20:10:52 UTC (rev 765) +++ pygccxml_dev/pygccxml/declarations/__init__.py 2006-11-30 10:33:59 UTC (rev 766) @@ -6,7 +6,7 @@ """ contains classes that describe different C++ declarations """ - +from dependencies import dependency_info_t from declaration import location_t from declaration import declaration_t from scopedef import scopedef_t Modified: pygccxml_dev/pygccxml/declarations/calldef.py =================================================================== --- pygccxml_dev/pygccxml/declarations/calldef.py 2006-11-29 20:10:52 UTC (rev 765) +++ pygccxml_dev/pygccxml/declarations/calldef.py 2006-11-30 10:33:59 UTC (rev 766) @@ -21,6 +21,7 @@ import algorithm import declaration import type_traits +import dependencies import call_invocation class VIRTUALITY_TYPES: @@ -270,6 +271,17 @@ demangled_name = property( _get_demangled_name , doc="returns function demangled name. It can help you to deal with function template instantiations") + def i_depend_on_them( self ): + report_dependency = lambda x: dependencies.dependency_info_t( self, x ) + answer = [] + map( lambda arg: answer.append( report_dependency( arg.type ) ) + , self.arguments ) + if self.return_type: + answer.append( report_dependency( self.return_type ) ) + map( lambda exception: answer.append( report_dependency( exception ) ) + , self.exceptions ) + return answer + #Second level in hierarchy of calldef class member_calldef_t( calldef_t ): """base class for "callable" declarations that defined within C++ class or struct""" Modified: pygccxml_dev/pygccxml/declarations/class_declaration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/class_declaration.py 2006-11-29 20:10:52 UTC (rev 765) +++ pygccxml_dev/pygccxml/declarations/class_declaration.py 2006-11-30 10:33:59 UTC (rev 766) @@ -15,6 +15,7 @@ import scopedef import algorithm import declaration +import dependencies class ACCESS_TYPES: """class that defines "access" constants""" @@ -83,7 +84,10 @@ def _get__cmp__items(self): """implementation details""" return [] - + + def i_depend_on_them( self ): + return [] + class class_t( scopedef.scopedef_t ): """describes class definition""" @@ -330,3 +334,24 @@ else: return member.cache.access_type + def __find_out_member_dependencies( self, access_type ): + members = self.get_members( access_type ) + answer = [] + map( lambda mem: answer.extend( mem.i_depend_on_them() ), members ) + member_ids = set( map( lambda m: id( m ), members ) ) + for dependency in answer: + if id( dependency.declaration ) in member_ids: + dependency.access_type = access_type + return answer + + def i_depend_on_them( self ): + report_dependency = lambda *args: dependencies.dependency_info_t( self, *args ) + answer = [] + + map( lambda base: answer.append( report_dependency( base.related_class, base.access_type ) ) + , self.bases ) + + map( lambda access_type: answer.extend( self.__find_out_member_dependencies( access_type ) ) + , ACCESS_TYPES.ALL ) + + return answer Modified: pygccxml_dev/pygccxml/declarations/declaration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/declaration.py 2006-11-29 20:10:52 UTC (rev 765) +++ pygccxml_dev/pygccxml/declarations/declaration.py 2006-11-30 10:33:59 UTC (rev 766) @@ -244,3 +244,8 @@ reference to instance of L{algorithms_cache.algorithms_cache_t} class. """ return self._cache + + def i_depend_on_them( self ): + #this method should return list of all types, declarations it depends on + print self + raise NotImplementedError() Added: pygccxml_dev/pygccxml/declarations/dependencies.py =================================================================== --- pygccxml_dev/pygccxml/declarations/dependencies.py (rev 0) +++ pygccxml_dev/pygccxml/declarations/dependencies.py 2006-11-30 10:33:59 UTC (rev 766) @@ -0,0 +1,34 @@ +# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +""" +""" + +class dependency_info_t( object ): + def __init__( self, declaration, depend_on_it, access_type=None ): + object.__init__( self ) + self._declaration = declaration + self._depend_on_it = depend_on_it + self._access_type = access_type + + @property + def declaration( self ): + return self._declaration + #short name + decl = declaration + + @property + def depend_on_it( self ): + return self._depend_on_it + + def _get_access_type( self ): + return self._access_type + def _set_access_type( self, access_type ): + self._access_type = access_type + access_type = property( _get_access_type, _set_access_type ) + + def __str__( self ): + return 'declaration "%s" depends( %s ) on "%s" ' \ + % ( self.declaration, self.access_type, self.depend_on_it ) Modified: pygccxml_dev/pygccxml/declarations/enumeration.py =================================================================== --- pygccxml_dev/pygccxml/declarations/enumeration.py 2006-11-29 20:10:52 UTC (rev 765) +++ pygccxml_dev/pygccxml/declarations/enumeration.py 2006-11-30 10:33:59 UTC (rev 766) @@ -113,3 +113,6 @@ for val, num in self._values: x[val] = num return x + + def i_depend_on_them( self ): + return [] Modified: pygccxml_dev/pygccxml/declarations/namespace.py =================================================================== --- pygccxml_dev/pygccxml/declarations/namespace.py 2006-11-29 20:10:52 UTC (rev 765) +++ pygccxml_dev/pygccxml/declarations/namespace.py 2006-11-30 10:33:59 UTC (rev 766) @@ -135,3 +135,7 @@ , recursive=recursive , allow_empty=allow_empty) + def i_depend_on_them( self ): + answer = [] + map( lambda decl: answer.extend( decl.i_depend_on_them() ), self.declarations ) + return answer Modified: pygccxml_dev/pygccxml/declarations/scopedef.py =================================================================== --- pygccxml_dev/pygccxml/declarations/scopedef.py 2006-11-29 20:10:52 UTC (rev 765) +++ pygccxml_dev/pygccxml/declarations/scopedef.py 2006-11-30 10:33:59 UTC (rev 766) @@ -625,6 +625,3 @@ - - - Modified: pygccxml_dev/pygccxml/declarations/typedef.py =================================================================== --- pygccxml_dev/pygccxml/declarations/typedef.py 2006-11-29 20:10:52 UTC (rev 765) +++ pygccxml_dev/pygccxml/declarations/typedef.py 2006-11-30 10:33:59 UTC (rev 766) @@ -8,6 +8,7 @@ """ import declaration +import dependencies class typedef_t( declaration.declaration_t ): """describes C++ typedef declaration""" @@ -32,3 +33,6 @@ self._type = type type = property( _get_type, _set_type , doc="reference to the original L{type<type_t>}" ) + + def i_depend_on_them( self ): + return [ dependencies.dependency_info_t( self, self.type ) ] Modified: pygccxml_dev/pygccxml/declarations/variable.py =================================================================== --- pygccxml_dev/pygccxml/declarations/variable.py 2006-11-29 20:10:52 UTC (rev 765) +++ pygccxml_dev/pygccxml/declarations/variable.py 2006-11-30 10:33:59 UTC (rev 766) @@ -8,6 +8,7 @@ """ import declaration +import dependencies import class_declaration class variable_t( declaration.declaration_t ): @@ -68,3 +69,5 @@ raise RuntimeError( "access_type functionality only available on member variables and not on global variables" ) return self.parent.find_out_member_access_type( self ) + def i_depend_on_them( self ): + return [ dependencies.dependency_info_t( self, self.type ) ] Modified: pygccxml_dev/unittests/test_all.py =================================================================== --- pygccxml_dev/unittests/test_all.py 2006-11-29 20:10:52 UTC (rev 765) +++ pygccxml_dev/unittests/test_all.py 2006-11-30 10:33:59 UTC (rev 766) @@ -39,6 +39,7 @@ import declarations_cache_tester import has_binary_operator_traits_tester import algorithms_cache_tester +import dependencies_tester def create_suite(): testers = [ @@ -77,6 +78,7 @@ , declarations_cache_tester , has_binary_operator_traits_tester , algorithms_cache_tester + , dependencies_tester ] main_suite = unittest.TestSuite() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-11-29 20:12:39
|
Revision: 765 http://svn.sourceforge.net/pygccxml/?rev=765&view=rev Author: roman_yakovenko Date: 2006-11-29 12:10:52 -0800 (Wed, 29 Nov 2006) Log Message: ----------- adding treatment for array transformers for virtual mem fun Modified Paths: -------------- pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py pyplusplus_dev_ft/unittests/data/function_transformations_to_be_exported.hpp pyplusplus_dev_ft/unittests/function_transformations_tester.py Modified: pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py 2006-11-29 15:05:10 UTC (rev 764) +++ pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py 2006-11-29 20:10:52 UTC (rev 765) @@ -384,9 +384,11 @@ tmpl_values['py_function_var'] = cntrl.py_function_var tmpl_values['function_alias'] = self.declaration.alias tmpl_values['declare_py_variables'] \ - = os.linesep.join( map( lambda var: var.declare_var_string(), cntrl.py_variables ) ) - tmpl_values['py_pre_call'] = os.linesep.join( cntrl.py_pre_call ) - tmpl_values['py_post_call'] = os.linesep.join( cntrl.py_post_call ) + = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string(), 2 ) + , cntrl.py_variables ) ) + + tmpl_values['py_pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.py_pre_call ), 2 ) + tmpl_values['py_post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.py_post_call ), 2 ) tmpl_values['py_arg_expressions'] = '' if cntrl.py_arg_expressions: tmpl_values['py_arg_expressions'] \ Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py 2006-11-29 15:05:10 UTC (rev 764) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py 2006-11-29 20:10:52 UTC (rev 765) @@ -137,6 +137,9 @@ w_arg = controller.find_wrapper_arg( self.arg.name ) w_arg.type = remove_ref_or_ptr( self.arg.type ) + def __configure_v_mem_fun_default( self, controller ): + self.__configure_sealed( controller ) + def configure_mem_fun( self, controller ): self.__configure_sealed( controller ) @@ -144,7 +147,7 @@ self.__configure_sealed( controller ) def configure_virtual_mem_fun( self, controller ): - self.__configure_sealed( controller.default_controller ) + self.__configure_v_mem_fun_default( controller.default_controller ) # inout_t class inout_t(transformer.transformer_t): @@ -177,7 +180,10 @@ w_arg.type = remove_ref_or_ptr( self.arg.type ) #adding the variable to return variables list controller.return_variable( w_arg.name ) - + + def __configure_v_mem_fun_default( self, controller ): + self.__configure_sealed( controller ) + def __configure_v_mem_fun_override( self, controller ): tmpl = string.Template( '$name = boost::python::extract< $type >( pyplus_conv::get_out_argument( $py_result, "$name" ) );' ) @@ -194,8 +200,16 @@ def configure_virtual_mem_fun( self, controller ): self.__configure_v_mem_fun_override( controller.override_controller ) - self.__configure_sealed( controller.default_controller ) + self.__configure_v_mem_fun_default( controller.default_controller ) + +_seq2arr = string.Template( os.linesep.join([ + 'pyplus_conv::ensure_uniform_sequence< $type >( $pylist, $array_size );' + , 'pyplus_conv::copy_sequence( $pylist, pyplus_conv::array_inserter( $native_array, $array_size ) );'])) + +_arr2seq = string.Template( + 'pyplus_conv::copy_container( $native_array, $native_array + $array_size, pyplus_conv::list_inserter( $pylist ) );' ) + class input_array_t(transformer.transformer_t): """Handles an input array with fixed size. @@ -228,14 +242,8 @@ """Returns list of header files that transformer generated code depends on.""" return [ code_repository.convenience.file_name ] - @property - def pre_call_tmpl( self ): - pre_call = [] - pre_call.append( 'pyplus_conv::ensure_uniform_sequence< $type >( $pylist, $array_size );' ) - pre_call.append( 'pyplus_conv::copy_sequence( $pylist, pyplus_conv::array_inserter( $native_array, $array_size ) );' ) - return string.Template( os.linesep.join( pre_call ) ) - def __configure_sealed(self, controller): + global _seq2arr w_arg = controller.find_wrapper_arg( self.arg.name ) w_arg.type = declarations.dummy_type_t( "boost::python::object" ) @@ -243,22 +251,41 @@ native_array = controller.declare_variable( self.array_item_type , "native_" + self.arg.name , '[%d]' % self.array_size ) + + copy_pylist2arr = _seq2arr.substitute( type=self.array_item_type + , pylist=w_arg.name + , array_size=self.array_size + , native_array=native_array ) - seq2arr = self.pre_call_tmpl.substitute( type=self.array_item_type - , pylist=w_arg.name - , array_size=self.array_size - , native_array=native_array ) + controller.add_pre_call_code( copy_pylist2arr ) - controller.add_pre_call_code( seq2arr ) - controller.modify_arg_expression( self.arg_index, native_array ) + def __configure_v_mem_fun_default( self, controller ): + self.__configure_sealed( controller ) + + def __configure_v_mem_fun_override( self, controller ): + global _arr2seq + pylist = controller.declare_py_variable( declarations.dummy_type_t( 'boost::python::list' ) + , 'py_' + self.arg.name ) + + copy_arr2pylist = _arr2seq.substitute( native_array=self.arg.name + , array_size=self.array_size + , pylist=pylist ) + + controller.add_py_pre_call_code( copy_arr2pylist ) + def configure_mem_fun( self, controller ): self.__configure_sealed( controller ) def configure_free_fun(self, controller ): self.__configure_sealed( controller ) + def configure_virtual_mem_fun( self, controller ): + self.__configure_v_mem_fun_override( controller.override_controller ) + self.__configure_v_mem_fun_default( controller.default_controller ) + + # output_array_t class output_array_t(transformer.transformer_t): """Handles an output array of a fixed size. @@ -293,11 +320,8 @@ """Returns list of header files that transformer generated code depends on.""" return [ code_repository.convenience.file_name ] - @property - def post_call_tmpl( self ): - return string.Template( 'pyplus_conv::copy_container( $native_array, $native_array + $array_size, pyplus_conv::list_inserter( $pylist ) );' ) - def __configure_sealed(self, controller): + global _arr2seq #removing arg from the function wrapper definition controller.remove_wrapper_arg( self.arg.name ) @@ -313,17 +337,41 @@ pylist = controller.declare_variable( declarations.dummy_type_t( "boost::python::list" ) , 'py_' + self.arg.name ) - arr2seq = self.post_call_tmpl.substitute( native_array=native_array - , array_size=self.array_size - , pylist=pylist ) + copy_arr2pylist = _arr2seq.substitute( native_array=native_array + , array_size=self.array_size + , pylist=pylist ) - controller.add_post_call_code( arr2seq ) + controller.add_post_call_code( copy_arr2pylist ) #adding the variable to return variables list controller.return_variable( pylist ) - + + def __configure_v_mem_fun_default( self, controller ): + self.__configure_sealed( controller ) + + def __configure_v_mem_fun_override( self, controller ): + global _seq2arr + seq = controller.declare_py_variable( declarations.dummy_type_t( 'boost::python::object' ) + , 'py_' + self.arg.name ) + controller.remove_py_arg( self.arg_index ) + tmpl = string.Template( '$seq = pyplus_conv::get_out_argument( $py_result, "$name" );' ) + get_ref_to_seq = tmpl.substitute( seq=seq + , py_result=controller.py_result_variable.name + , name=self.arg.name ) + controller.add_py_post_call_code( get_ref_to_seq ) + + copy_pylist2arr = _seq2arr.substitute( type=self.array_item_type + , pylist=seq + , array_size=self.array_size + , native_array=self.arg.name ) + controller.add_py_post_call_code( copy_pylist2arr ) + def configure_mem_fun( self, controller ): self.__configure_sealed( controller ) def configure_free_fun(self, controller ): self.__configure_sealed( controller ) + + def configure_virtual_mem_fun( self, controller ): + self.__configure_v_mem_fun_override( controller.override_controller ) + self.__configure_v_mem_fun_default( controller.default_controller ) Modified: pyplusplus_dev_ft/unittests/data/function_transformations_to_be_exported.hpp =================================================================== --- pyplusplus_dev_ft/unittests/data/function_transformations_to_be_exported.hpp 2006-11-29 15:05:10 UTC (rev 764) +++ pyplusplus_dev_ft/unittests/data/function_transformations_to_be_exported.hpp 2006-11-29 20:10:52 UTC (rev 765) @@ -125,17 +125,17 @@ return in; } - //~ // A method taking an input array of fixed size - //~ virtual int fixed_input_array(int v[3]) { - //~ return v[0]+v[1]+v[2]; - //~ } + // A method taking an input array of fixed size + virtual int fixed_input_array(int v[3]) { + return v[0]+v[1]+v[2]; + } - //~ // A method with a output array of fixed size - //~ virtual void fixed_output_array(int v[3]) { - //~ v[0] = 1; - //~ v[1] = 2; - //~ v[2] = 3; - //~ } + // A method with a output array of fixed size + virtual void fixed_output_array(int v[3]) { + v[0] = 1; + v[1] = 2; + v[2] = 3; + } unsigned int m_width; unsigned int m_height; @@ -161,13 +161,13 @@ return v; } -//~ // This is used for calling img.fixed_output_array() on an instance passed -//~ // in by Python. -//~ int image_fixed_output_array( image_t& img) { - //~ int v[3]; - //~ img.fixed_output_array(v); - //~ return v[0]+v[1]+v[2]; -//~ } +// This is used for calling img.fixed_output_array() on an instance passed +// in by Python. +int image_fixed_output_array( image_t& img) { + int v[3]; + img.fixed_output_array(v); + return v[0]+v[1]+v[2]; +} ////////////////////////////////////////////////////////////////////// Modified: pyplusplus_dev_ft/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev_ft/unittests/function_transformations_tester.py 2006-11-29 15:05:10 UTC (rev 764) +++ pyplusplus_dev_ft/unittests/function_transformations_tester.py 2006-11-29 20:10:52 UTC (rev 765) @@ -8,6 +8,7 @@ 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 @@ -52,8 +53,8 @@ image.member_function( "get_one_value" ).add_transformation( ft.output(0) ) image.member_function( "get_size2" ).add_transformation( ft.output(0), ft.output(1) ) image.member_function( "input_arg" ).add_transformation( ft.input(0) ) - #~ image.member_function( "fixed_input_array" ).add_transformation( ft.input_array(0,3) ) - #~ image.member_function( "fixed_output_array" ).add_transformation( ft.output_array(0,3) ) + image.member_function( "fixed_input_array" ).add_transformation( ft.input_array(0,3) ) + image.member_function( "fixed_output_array" ).add_transformation( ft.output_array(0,3) ) mb.free_function("get_cpp_instance").call_policies \ = call_policies.return_value_policy(call_policies.reference_existing_object) mb.variable( "cpp_instance" ).exclude() @@ -114,12 +115,12 @@ # Check the input_arg method self.assertEqual(img.input_arg(5), 5) - #~ # Check the fixed_input_array method - #~ self.assertEqual(img.fixed_input_array([1,2,3]), 6) - #~ self.assertEqual(img.fixed_input_array((1,2,3)), 6) + # Check the fixed_input_array method + self.assertEqual(img.fixed_input_array([1,2,3]), 6) + self.assertEqual(img.fixed_input_array((1,2,3)), 6) - #~ # Check the fixed_output_array method - #~ self.assertEqual(img.fixed_output_array(), [1,2,3]) + # Check the fixed_output_array method + self.assertEqual(img.fixed_output_array(), [1,2,3]) self.assertEqual(module.ft_private_destructor_t.get_value(), 21) @@ -134,16 +135,16 @@ def get_one_value(self): return self.m_height+1 - #~ def fixed_output_array(self): - #~ # Produce a correct return value - #~ if self.fixed_output_array_mode==0: - #~ return (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 (2,5) + def fixed_output_array(self): + # Produce a correct return value + if self.fixed_output_array_mode==0: + 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) ) pyimg1 = py_image1_t(3,7) @@ -156,12 +157,12 @@ # Check if the Python class can also be passed back to C++ self.assertEqual(module.get_image_one_value(pyimg1), 4) - #~ # Check if fixed_output_array() is correctly called from C++ - #~ self.assertEqual(module.image_fixed_output_array(pyimg1), 14) - #~ pyimg1.fixed_output_array_mode = 1 - #~ self.assertRaises(TypeError, lambda : module.image_fixed_output_array(pyimg1)) - #~ pyimg1.fixed_output_array_mode = 2 - #~ self.assertRaises(ValueError, lambda : module.image_fixed_output_array(pyimg1)) + # Check if fixed_output_array() is correctly called from C++ + self.assertEqual(module.image_fixed_output_array(pyimg1), 14) + pyimg1.fixed_output_array_mode = 1 + self.assertRaises(TypeError, lambda : module.image_fixed_output_array(pyimg1)) + pyimg1.fixed_output_array_mode = 2 + self.assertRaises(ValueError, lambda : module.image_fixed_output_array(pyimg1)) class py_image2_t(module.image_t): def __init__(self, h, w): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-11-29 15:05:14
|
Revision: 764 http://svn.sourceforge.net/pygccxml/?rev=764&view=rev Author: roman_yakovenko Date: 2006-11-29 07:05:10 -0800 (Wed, 29 Nov 2006) Log Message: ----------- adding support for almost all transformers for virtual member functions Modified Paths: -------------- pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py pyplusplus_dev_ft/unittests/data/function_transformations_to_be_exported.hpp pyplusplus_dev_ft/unittests/function_transformations_tester.py Modified: pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py 2006-11-29 12:24:50 UTC (rev 763) +++ pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py 2006-11-29 15:05:10 UTC (rev 764) @@ -267,32 +267,22 @@ result.append( 'typedef %s;' % ftype.create_typedef( self.default_function_type_alias ) ) return ''.join( result ) - def create_doc(self): - return None + def create_keywords_args(self): + cntrl = self.controller.default_controller + arg_utils = calldef_utils.argument_utils_t( self.declaration + , algorithm.make_id_creator( self ) + , [cntrl.inst_arg] + cntrl.wrapper_args ) + return arg_utils.keywords_args() def create_function_ref_code(self, use_function_alias=False): - result = [] + full_name = self.wrapper.default_full_name() if use_function_alias: - result.append( '%s(&%s)' - % ( self.function_type_alias, declarations.full_name( self.declaration ) ) ) - if self.wrapper: - result.append( self.param_sep() ) - result.append( '%s(&%s)' - % ( self.default_function_type_alias, self.wrapper.default_full_name() ) ) + return '%s( &%s )' % ( self.function_type_alias, full_name ) elif self.declaration.create_with_signature: - result.append( '(%s)(&%s)' - % ( self.declaration.function_type().decl_string - , declarations.full_name( self.declaration ) ) ) - if self.wrapper: - result.append( self.param_sep() ) - result.append( '(%s)(&%s)' - % ( self.wrapper.function_type().decl_string, self.wrapper.default_full_name() ) ) + func_type = self.wrapper.default_function_type() + return '(%s)( &%s )' % ( func_type, full_name ) else: - result.append( '&%s'% declarations.full_name( self.declaration ) ) - if self.wrapper: - result.append( self.param_sep() ) - result.append( '&%s' % self.wrapper.default_full_name() ) - return ''.join( result ) + return '&%s' % full_name class mem_fun_v_transformed_wrapper_t( calldef_wrapper_t ): def __init__( self, function ): @@ -306,34 +296,77 @@ def controller( self ): return self.ft.controller + def default_name(self): + if self.declaration.overloads: + #it is possible that other functions will have same signature + return 'default_' + self.ft.unique_name + else: + return 'default_' + self.declaration.alias + def default_full_name(self): - return self.parent.full_name + '::default_' + self.declaration.alias + return self.parent.full_name + '::' + self.default_name() def args_override_declaration( self ): return self.args_declaration() - def function_type(self): - return declarations.member_function_type_t( - return_type=self.declaration.return_type - , class_inst=declarations.dummy_type_t( self.parent.full_name ) - , arguments_types=map( lambda arg: arg.type, self.declaration.arguments ) - , has_const=self.declaration.has_const ) + def args_default_declaration( self ): + cntrl = self.controller.default_controller + arg_utils = calldef_utils.argument_utils_t( self.declaration + , algorithm.make_id_creator( self ) + , [cntrl.inst_arg] + cntrl.wrapper_args ) + return arg_utils.args_declaration() - def create_default_declaration(self): - template = '%(return_type)s %(name)s( %(args)s )%(constness)s %(throw)s' + def default_function_type(self): + cntrl = self.controller.default_controller + args = [cntrl.inst_arg.type] + map( lambda arg: arg.type, cntrl.wrapper_args ) + return declarations.free_function_type_t( return_type=cntrl.wrapper_return_type + , arguments_types=args ) - constness = '' - if self.declaration.has_const: - constness = ' const ' + def create_default(self): + cntrl = self.controller.default_controller - return template % { - 'return_type' : self.declaration.return_type.decl_string - , 'name' : 'default_' + self.declaration.alias - , 'args' : self.args_override_declaration() - , 'constness' : constness - , 'throw' : self.throw_specifier_code() - } + make_object = algorithm.create_identifier( self, 'pyplusplus::call_policies::make_object' ) + make_tuple = algorithm.create_identifier( self, 'boost::python::make_tuple' ) + + tmpl_values = dict() + tmpl_values['unique_function_name'] = self.default_name() + tmpl_values['return_type'] = cntrl.wrapper_return_type.decl_string + tmpl_values['arg_declarations'] = self.args_default_declaration() + tmpl_values['wrapper_class'] = self.parent.wrapper_alias + tmpl_values['wrapped_class'] = declarations.full_name( self.declaration.parent ) + tmpl_values['wrapped_inst'] = cntrl.inst_arg.name + + decl_vars = cntrl.variables[:] + if not declarations.is_void( self.declaration.return_type ): + decl_vars.append( cntrl.result_variable ) + tmpl_values['declare_variables'] \ + = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string() ) + , decl_vars ) ) + + tmpl_values['pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.pre_call ) ) + + tmpl_values['save_result'] = '' + if not declarations.is_void( self.declaration.return_type ): + tmpl_values['save_result'] = '%s = ' % cntrl.result_variable.name + + tmpl_values['function_name'] = self.declaration.name + tmpl_values['arg_expressions'] = self.PARAM_SEPARATOR.join( cntrl.arg_expressions ) + return_stmt_creator = calldef_utils.return_stmt_creator_t( self + , cntrl + , cntrl.result_variable + , cntrl.return_variables ) + + tmpl_values['post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.post_call ) ) + if return_stmt_creator.pre_return_code: + tmpl_values['post_call'] \ + = os.linesep.join([ tmpl_values['post_call'] + , self.indent( return_stmt_creator.pre_return_code )]) + tmpl_values['return'] = os.linesep + self.indent( return_stmt_creator.statement ) + + f_def = cntrl.template.substitute(tmpl_values) + return remove_duplicate_linesep( f_def ) + def wrapped_class_identifier( self ): return algorithm.create_identifier( self, declarations.full_name( self.declaration.parent ) ) @@ -379,22 +412,5 @@ f_def_code = cntrl.template.substitute(tmpl_values) return remove_duplicate_linesep( f_def_code ) - def create_default_body(self): - function_call = declarations.call_invocation.join( self.declaration.name - , [ self.function_call_args() ] ) - body = self.wrapped_class_identifier() + '::' + function_call + ';' - if not declarations.is_void( self.declaration.return_type ): - body = 'return ' + body - return body - - def create_default_function( self ): - answer = [ self.create_default_declaration() + '{' ] - answer.append( self.indent( self.create_default_body() ) ) - answer.append( '}' ) - return os.linesep.join( answer ) - def _create_impl(self): - answer = [ self.create_override() ] - answer.append( os.linesep ) - answer.append( self.create_default_function() ) - return os.linesep.join( answer ) + return os.linesep.join([ self.create_override(), '', self.create_default() ]) Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py 2006-11-29 12:24:50 UTC (rev 763) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py 2006-11-29 15:05:10 UTC (rev 764) @@ -203,7 +203,7 @@ @property def template( self ): - return templates.virtual_mem_fun.override_body + return templates.virtual_mem_fun.override @property def py_variables( self ): @@ -262,7 +262,11 @@ @property def inst_arg( self ): return self.__inst_arg - + + @property + def template( self ): + return templates.virtual_mem_fun.default + def __init__( self, function ): controller_base_t.__init__( self, function ) self.__override_cntrl = self.override_fun_controller_t( function ) Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py 2006-11-29 12:24:50 UTC (rev 763) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py 2006-11-29 15:05:10 UTC (rev 764) @@ -23,7 +23,7 @@ ])) class virtual_mem_fun: - override_body = Template( os.linesep.join([ + override = Template( os.linesep.join([ 'virtual $return_type $function_name( $arg_declarations )$constness $throw{' , ' namespace bpl = boost::python;' , ' if( bpl::override $py_function_var = this->get_override( "$function_alias" ) ){' @@ -39,12 +39,12 @@ , '}' ])) - default_body = Template( os.linesep.join([ - 'static $return_type $unique_function_name( $arg_declarations ){' + default = Template( os.linesep.join([ + 'static $return_type $unique_function_name( $arg_declarations ){' , ' $declare_variables' , ' $pre_call' - , ' if( $wrapper_class $py_wrapper_var = dynamic_cast< $wrapper_class >( boost::addressof( $wrapped_inst ) ) ){' - , ' $save_result$wrapped_inst->$wrapped_class::$function_name($arg_expressions);' + , ' if( dynamic_cast< $wrapper_class* >( boost::addressof( $wrapped_inst ) ) ){' + , ' $save_result$wrapped_inst.$wrapped_class::$function_name($arg_expressions);' , ' }' , ' else{' , ' $save_result$wrapped_inst.$function_name($arg_expressions);' Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py 2006-11-29 12:24:50 UTC (rev 763) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py 2006-11-29 15:05:10 UTC (rev 764) @@ -100,7 +100,6 @@ def configure_free_fun(self, controller ): self.__configure_sealed( controller ) - def configure_virtual_mem_fun( self, controller ): self.__configure_v_mem_fun_default( controller.default_controller ) self.__configure_v_mem_fun_override( controller.override_controller ) @@ -145,9 +144,7 @@ self.__configure_sealed( controller ) def configure_virtual_mem_fun( self, controller ): - pass #according to boost.python documentation, it will create a copy of - #the object by itself - + self.__configure_sealed( controller.default_controller ) # inout_t class inout_t(transformer.transformer_t): @@ -181,6 +178,14 @@ #adding the variable to return variables list controller.return_variable( w_arg.name ) + def __configure_v_mem_fun_override( self, controller ): + tmpl = string.Template( + '$name = boost::python::extract< $type >( pyplus_conv::get_out_argument( $py_result, "$name" ) );' ) + store_py_result_in_arg = tmpl.substitute( name=self.arg.name + , type=self.arg.type.decl_string + , py_result=controller.py_result_variable.name ) + controller.add_py_post_call_code( store_py_result_in_arg ) + def configure_mem_fun( self, controller ): self.__configure_sealed( controller ) @@ -188,13 +193,8 @@ self.__configure_sealed( controller ) def configure_virtual_mem_fun( self, controller ): - assert isinstance( controller, controllers.virtual_mem_fun_controller_t ) - tmpl = string.Template( - '$name = boost::python::extract< $type >( pyplus_conv::get_out_argument( $py_result, "$name" ) );' ) - store_py_result_in_arg = tmpl.substitute( name=self.arg.name - , type=self.arg.type.decl_string - , py_result=controller.py_result_variable.name ) - controller.add_py_post_call_code( store_py_result_in_arg ) + self.__configure_v_mem_fun_override( controller.override_controller ) + self.__configure_sealed( controller.default_controller ) class input_array_t(transformer.transformer_t): """Handles an input array with fixed size. Modified: pyplusplus_dev_ft/unittests/data/function_transformations_to_be_exported.hpp =================================================================== --- pyplusplus_dev_ft/unittests/data/function_transformations_to_be_exported.hpp 2006-11-29 12:24:50 UTC (rev 763) +++ pyplusplus_dev_ft/unittests/data/function_transformations_to_be_exported.hpp 2006-11-29 15:05:10 UTC (rev 764) @@ -102,28 +102,28 @@ // Made the method 'virtual' for now because func transformers // are currently only taken into account on virtual functions. - //~ virtual void get_size( unsigned int& h, unsigned int& w ){ - //~ h = m_height; - //~ w = m_width; - //~ } + virtual void get_size( unsigned int& h, unsigned int& w ){ + h = m_height; + w = m_width; + } // Return only one value virtual void get_one_value(unsigned int& h) { h = m_height; } - //~ // Like get_size() but with a return type and an additional argument - //~ // that has to be kept in the signature - //~ virtual int get_size2( unsigned int& h, unsigned int& w, int noref=0 ){ - //~ h = m_height; - //~ w = m_width; - //~ return noref; - //~ } + // Like get_size() but with a return type and an additional argument + // that has to be kept in the signature + virtual int get_size2( unsigned int& h, unsigned int& w, int noref=0 ){ + h = m_height; + w = m_width; + return noref; + } - //~ // A method with an input argument - //~ virtual int input_arg(int& in){ - //~ return in; - //~ } + // A method with an input argument + virtual int input_arg(int& in){ + return in; + } //~ // A method taking an input array of fixed size //~ virtual int fixed_input_array(int v[3]) { @@ -142,24 +142,24 @@ }; -//~ // Provide an instance created in C++ (i.e. this is not a wrapper instance) -//~ image_t cpp_instance(12,13); -//~ image_t& get_cpp_instance() { - //~ return cpp_instance; -//~ } +// Provide an instance created in C++ (i.e. this is not a wrapper instance) +image_t cpp_instance(12,13); +image_t& get_cpp_instance() { + return cpp_instance; +} -//~ inline void -//~ get_image_size( image_t& img, unsigned int& h, unsigned int& w ){ - //~ img.get_size( h, w ); -//~ } +inline void +get_image_size( image_t& img, unsigned int& h, unsigned int& w ){ + img.get_size( h, w ); +} -//~ // This is used for calling img.get_one_value() on an instance passed -//~ // in by Python. -//~ unsigned int get_image_one_value( image_t& img ) { - //~ unsigned int v; - //~ img.get_one_value(v); - //~ return v; -//~ } +// This is used for calling img.get_one_value() on an instance passed +// in by Python. +unsigned int get_image_one_value( image_t& img ) { + unsigned int v; + img.get_one_value(v); + return v; +} //~ // This is used for calling img.fixed_output_array() on an instance passed //~ // in by Python. @@ -169,19 +169,19 @@ //~ return v[0]+v[1]+v[2]; //~ } -//~ ////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// -//~ // A class without any virtual members -//~ struct no_virtual_members_t -//~ { - //~ bool member(int& v) { v=17; return true; } -//~ }; +// A class without any virtual members +struct no_virtual_members_t +{ + bool member(int& v) { v=17; return true; } +}; -//~ struct ft_private_destructor_t{ - //~ static void get_value( int& x ){ x = 21; } -//~ private: - //~ ~ft_private_destructor_t(){} -//~ }; +struct ft_private_destructor_t{ + static void get_value( int& x ){ x = 21; } +private: + ~ft_private_destructor_t(){} +}; } Modified: pyplusplus_dev_ft/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev_ft/unittests/function_transformations_tester.py 2006-11-29 12:24:50 UTC (rev 763) +++ pyplusplus_dev_ft/unittests/function_transformations_tester.py 2006-11-29 15:05:10 UTC (rev 764) @@ -47,27 +47,24 @@ point3d.mem_fun( 'distance' ).add_transformation( ft.output(1) ) image = mb.class_( "image_t" ) - image.include() - - #~ image.member_functions().exclude() - #~ image.member_function( "get_size" ).include() - #~ image.member_function( "get_size" ).add_transformation( ft.output(0), ft.output(1) ) + image.member_function( "get_size" ) + image.member_function( "get_size" ).add_transformation( ft.output(0), ft.output(1) ) image.member_function( "get_one_value" ).add_transformation( ft.output(0) ) - #~ image.member_function( "get_size2" ).add_transformation( ft.output(0), ft.output(1) ) - #~ image.member_function( "input_arg" ).add_transformation( ft.input(0) ) + image.member_function( "get_size2" ).add_transformation( ft.output(0), ft.output(1) ) + image.member_function( "input_arg" ).add_transformation( ft.input(0) ) #~ image.member_function( "fixed_input_array" ).add_transformation( ft.input_array(0,3) ) #~ image.member_function( "fixed_output_array" ).add_transformation( ft.output_array(0,3) ) - #~ mb.free_function("get_cpp_instance").call_policies \ - #~ = call_policies.return_value_policy(call_policies.reference_existing_object) - #~ mb.variable( "cpp_instance" ).exclude() + mb.free_function("get_cpp_instance").call_policies \ + = call_policies.return_value_policy(call_policies.reference_existing_object) + mb.variable( "cpp_instance" ).exclude() - #~ cls = mb.class_("no_virtual_members_t") - #~ cls.member_function("member").add_transformation( ft.output(0) ) + cls = mb.class_("no_virtual_members_t") + cls.member_function("member").add_transformation( ft.output(0) ) - #~ cls = mb.class_("ft_private_destructor_t") - #~ cls.member_function("get_value").add_transformation( ft.output(0) ) + cls = mb.class_("ft_private_destructor_t") + cls.member_function("get_value").add_transformation( ft.output(0) ) - #~ mb.decls(lambda decl: decl.name[0]=="_").exclude() + mb.decls(lambda decl: decl.name.startswith("_")).exclude() def run_tests(self, module): """Run the actual unit tests. @@ -99,23 +96,23 @@ self.failUnless( module.point3d_t.distance( point3d ) == math.sqrt( 1*1 + 2*2 + 3*3 ) ) self.failUnless( module.hello_world() == "hello world!" ) - #~ img = module.image_t( 2, 6) + img = module.image_t( 2, 6) # Check a method that returns two values by reference - #~ self.assertEqual(img.get_size(), (2,6)) + self.assertEqual(img.get_size(), (2,6)) - #~ # Check a method that only returns one value by reference - #~ self.assertEqual(img.get_one_value(), 2) + # Check a method that only returns one value by reference + self.assertEqual(img.get_one_value(), 2) - #~ # Check if the C++ class can also be passed back to C++ - #~ self.assertEqual(module.get_image_one_value(img), 2) + # Check if the C++ class can also be passed back to C++ + self.assertEqual(module.get_image_one_value(img), 2) - #~ # Check get_size2() - #~ self.assertEqual(img.get_size2(), (0,2,6)) - #~ self.assertEqual(img.get_size2(1), (1,2,6)) + # Check get_size2() + self.assertEqual(img.get_size2(), (0,2,6)) + self.assertEqual(img.get_size2(1), (1,2,6)) - #~ # Check the input_arg method - #~ self.assertEqual(img.input_arg(5), 5) + # Check the input_arg method + self.assertEqual(img.input_arg(5), 5) #~ # Check the fixed_input_array method #~ self.assertEqual(img.fixed_input_array([1,2,3]), 6) @@ -124,18 +121,18 @@ #~ # Check the fixed_output_array method #~ self.assertEqual(img.fixed_output_array(), [1,2,3]) - #~ self.assertEqual(module.ft_private_destructor_t.get_value(), 21) + self.assertEqual(module.ft_private_destructor_t.get_value(), 21) - #~ ####### Do the tests on a class derived in Python ######## + ####### Do the tests on a class derived in Python ######## - #~ class py_image1_t(module.image_t): - #~ def __init__(self, h, w): - #~ module.image_t.__init__(self, h, w) - #~ self.fixed_output_array_mode = 0 + class py_image1_t(module.image_t): + def __init__(self, h, w): + module.image_t.__init__(self, h, w) + self.fixed_output_array_mode = 0 - #~ # Override a virtual method - #~ def get_one_value(self): - #~ return self.m_height+1 + # Override a virtual method + def get_one_value(self): + return self.m_height+1 #~ def fixed_output_array(self): #~ # Produce a correct return value @@ -148,16 +145,16 @@ #~ elif self.fixed_output_array_mode==2: #~ return (2,5) - #~ pyimg1 = py_image1_t(3,7) + pyimg1 = py_image1_t(3,7) - #~ # Check a method that returns two values by reference - #~ self.assertEqual(pyimg1.get_size(), (3,7)) + # Check a method that returns two values by reference + self.assertEqual(pyimg1.get_size(), (3,7)) - #~ # Check a method that only returns one value by reference - #~ self.assertEqual(pyimg1.get_one_value(), 4) + # Check a method that only returns one value by reference + self.assertEqual(pyimg1.get_one_value(), 4) - #~ # Check if the Python class can also be passed back to C++ - #~ self.assertEqual(module.get_image_one_value(pyimg1), 4) + # Check if the Python class can also be passed back to C++ + self.assertEqual(module.get_image_one_value(pyimg1), 4) #~ # Check if fixed_output_array() is correctly called from C++ #~ self.assertEqual(module.image_fixed_output_array(pyimg1), 14) @@ -166,39 +163,39 @@ #~ pyimg1.fixed_output_array_mode = 2 #~ self.assertRaises(ValueError, lambda : module.image_fixed_output_array(pyimg1)) - #~ class py_image2_t(module.image_t): - #~ def __init__(self, h, w): - #~ module.image_t.__init__(self, h, w) + class py_image2_t(module.image_t): + def __init__(self, h, w): + module.image_t.__init__(self, h, w) - #~ # Override a virtual method and invoke the inherited method - #~ def get_one_value(self): - #~ return module.image_t.get_one_value(self)+2 + # Override a virtual method and invoke the inherited method + def get_one_value(self): + return module.image_t.get_one_value(self)+2 - #~ pyimg2 = py_image2_t(4,8) + pyimg2 = py_image2_t(4,8) - #~ # Check the derived get_one_value() method - #~ self.assertEqual(pyimg2.get_one_value(), 6) + # Check the derived get_one_value() method + self.assertEqual(pyimg2.get_one_value(), 6) - #~ # Check if the Python class can also be passed back to C++ - #~ self.assertEqual(module.get_image_one_value(pyimg2), 6) + # Check if the Python class can also be passed back to C++ + self.assertEqual(module.get_image_one_value(pyimg2), 6) - #~ ####### Do the tests on a class instantiated in C++ ######## + ####### Do the tests on a class instantiated in C++ ######## - #~ cppimg = module.get_cpp_instance() + cppimg = module.get_cpp_instance() - #~ # Check a method that returns two values by reference - #~ self.assertEqual(cppimg.get_size(), (12,13)) + # Check a method that returns two values by reference + self.assertEqual(cppimg.get_size(), (12,13)) - #~ # Check a method that only returns one value by reference - #~ self.assertEqual(cppimg.get_one_value(), 12) + # Check a method that only returns one value by reference + self.assertEqual(cppimg.get_one_value(), 12) - #~ # Check if the C++ class can also be passed back to C++ - #~ self.assertEqual(module.get_image_one_value(cppimg), 12) + # Check if the C++ class can also be passed back to C++ + self.assertEqual(module.get_image_one_value(cppimg), 12) - #~ ######### Test no_virtual_members_t ######## + ######### Test no_virtual_members_t ######## - #~ cls = module.no_virtual_members_t() - #~ self.assertEqual(cls.member(), (True, 17)) + cls = module.no_virtual_members_t() + self.assertEqual(cls.member(), (True, 17)) 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-11-29 12:24:55
|
Revision: 763 http://svn.sourceforge.net/pygccxml/?rev=763&view=rev Author: roman_yakovenko Date: 2006-11-29 04:24:50 -0800 (Wed, 29 Nov 2006) Log Message: ----------- templates.py file contains function definition too. Modified Paths: -------------- pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py Modified: pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py 2006-11-28 21:23:41 UTC (rev 762) +++ pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py 2006-11-29 12:24:50 UTC (rev 763) @@ -67,58 +67,54 @@ def controller( self ): return self.ft.controller - def create_declaration(self, name): - template = 'static %(return_type)s %(name)s( %(args)s )' - - return template % { - 'return_type' : self.controller.wrapper_return_type.decl_string - , 'name' : self.wrapper_name() - , 'args' : self.args_declaration() - } - def resolve_function_ref( self ): raise NotImplementedError() - def create_body(self): + def create_fun_definition(self): cntrl = self.controller make_object = algorithm.create_identifier( self, 'pyplusplus::call_policies::make_object' ) make_tuple = algorithm.create_identifier( self, 'boost::python::make_tuple' ) - result_var_assign = '' + tmpl_values = dict() + + tmpl_values['unique_function_name'] = self.wrapper_name() + tmpl_values['return_type'] = self.controller.wrapper_return_type.decl_string + tmpl_values['arg_declarations'] = self.args_declaration() + + tmpl_values['declare_variables'] \ + = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string() ) + , cntrl.variables ) ) + + tmpl_values['pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.pre_call ) ) + + tmpl_values['save_result'] = '' if not declarations.is_void( self.declaration.return_type ): - result_var_assign = '%(type)s %(name)s = ' \ - % { 'type': cntrl.result_variable.type.decl_string - , 'name' : cntrl.result_variable.name } + tmpl_values['save_result'] \ + = '%(type)s %(name)s = ' \ + % { 'type': cntrl.result_variable.type.decl_string + , 'name' : cntrl.result_variable.name } + tmpl_values['function_name'] = self.resolve_function_ref() + tmpl_values['arg_expressions'] = self.PARAM_SEPARATOR.join( cntrl.arg_expressions ) return_stmt_creator = calldef_utils.return_stmt_creator_t( self , self.controller , self.controller.result_variable , self.controller.return_variables ) - post_call = os.linesep.join( cntrl.post_call ) + tmpl_values['post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.post_call ) ) if return_stmt_creator.pre_return_code: - post_call = os.linesep.join( [post_call, return_stmt_creator.pre_return_code] ) + tmpl_values['post_call'] \ + = os.linesep.join([ tmpl_values['post_call'] + , self.indent( return_stmt_creator.pre_return_code )]) + tmpl_values['return'] = os.linesep + self.indent( return_stmt_creator.statement ) + + f_def = self.controller.template.substitute(tmpl_values) + return remove_duplicate_linesep( f_def ) - return cntrl.template.substitute({ - 'declare_variables' : os.linesep.join( map( lambda var: var.declare_var_string(), cntrl.variables ) ) - , 'pre_call' : os.linesep.join( cntrl.pre_call ) - , 'post_call' : post_call - , 'save_result' : result_var_assign - , 'function' : self.resolve_function_ref() - , 'arg_expressions' : self.PARAM_SEPARATOR.join( cntrl.arg_expressions ) - , 'return' : return_stmt_creator.statement - }) - def _create_impl(self): - answer = [ self.create_declaration(self.declaration.alias) + '{' ] - answer.append( self.indent( '// Transformed wrapper function for "%s"' % self.declaration ) ) - body = self.create_body() - body = remove_duplicate_linesep( body ) - answer.append( self.indent( body ) ) - answer.append( '}' ) - return os.linesep.join( answer ) - + return self.create_fun_definition() + class free_fun_transformed_t( sealed_fun_transformed_t ): """Creates code for public non-virtual member functions. """ @@ -313,6 +309,9 @@ def default_full_name(self): return self.parent.full_name + '::default_' + self.declaration.alias + def args_override_declaration( self ): + return self.args_declaration() + def function_type(self): return declarations.member_function_type_t( return_type=self.declaration.return_type @@ -320,22 +319,17 @@ , arguments_types=map( lambda arg: arg.type, self.declaration.arguments ) , has_const=self.declaration.has_const ) - def create_declaration(self, name, has_virtual=True): - template = '%(virtual)s%(return_type)s %(name)s( %(args)s )%(constness)s %(throw)s' + def create_default_declaration(self): + template = '%(return_type)s %(name)s( %(args)s )%(constness)s %(throw)s' - virtual = 'virtual ' - if not has_virtual: - virtual = '' - constness = '' if self.declaration.has_const: constness = ' const ' return template % { - 'virtual' : virtual - , 'return_type' : self.declaration.return_type.decl_string - , 'name' : name - , 'args' : self.args_declaration() + 'return_type' : self.declaration.return_type.decl_string + , 'name' : 'default_' + self.declaration.alias + , 'args' : self.args_override_declaration() , 'constness' : constness , 'throw' : self.throw_specifier_code() } @@ -343,10 +337,17 @@ def wrapped_class_identifier( self ): return algorithm.create_identifier( self, declarations.full_name( self.declaration.parent ) ) - def create_virtual_body(self): - cntrl = self.controller.override_controller + def create_override(self): + cntrl = self.controller.override_controller tmpl_values = dict() + tmpl_values['return_type' ] = self.declaration.return_type.decl_string + tmpl_values['function_name'] = self.declaration.name + tmpl_values['arg_declarations'] = self.args_override_declaration() + tmpl_values['constness'] = '' + if self.declaration.has_const: + tmpl_values['constness'] = ' const ' + tmpl_values['throw'] = self.throw_specifier_code() tmpl_values['py_function_var'] = cntrl.py_function_var tmpl_values['function_alias'] = self.declaration.alias tmpl_values['declare_py_variables'] \ @@ -369,15 +370,15 @@ tmpl_values['cpp_return'] = 'return ' tmpl_values['wrapped_class'] = self.wrapped_class_identifier() - tmpl_values['function_name'] = self.declaration.name arg_utils = calldef_utils.argument_utils_t( self.declaration , algorithm.make_id_creator( self ) , self.declaration.arguments ) tmpl_values['cpp_arg_expressions'] = arg_utils.call_args() - return cntrl.template.substitute(tmpl_values) - + f_def_code = cntrl.template.substitute(tmpl_values) + return remove_duplicate_linesep( f_def_code ) + def create_default_body(self): function_call = declarations.call_invocation.join( self.declaration.name , [ self.function_call_args() ] ) @@ -386,22 +387,14 @@ body = 'return ' + body return body - def create_function(self): - answer = [ self.create_declaration(self.declaration.name) + '{' ] - body = self.create_virtual_body() - body = remove_duplicate_linesep( body ) - answer.append( self.indent( body ) ) - answer.append( '}' ) - return os.linesep.join( answer ) - def create_default_function( self ): - answer = [ self.create_declaration('default_' + self.declaration.alias, False) + '{' ] + answer = [ self.create_default_declaration() + '{' ] answer.append( self.indent( self.create_default_body() ) ) answer.append( '}' ) return os.linesep.join( answer ) def _create_impl(self): - answer = [ self.create_function() ] + answer = [ self.create_override() ] answer.append( os.linesep ) answer.append( self.create_default_function() ) return os.linesep.join( answer ) Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py 2006-11-28 21:23:41 UTC (rev 762) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py 2006-11-29 12:24:50 UTC (rev 763) @@ -246,11 +246,27 @@ def modify_py_arg_expression( self, index, expression ): self.arg_expressions[ index ] = expression + + class default_fun_controller_t( sealed_fun_controller_t ): + def __init__( self, function ): + sealed_fun_controller_t.__init__( self, function ) + + inst_arg_type = declarations.declarated_t( self.function.parent ) + if self.function.has_const: + inst_arg_type = declarations.const_t( inst_arg_type ) + inst_arg_type = declarations.reference_t( inst_arg_type ) + + self.__inst_arg = declarations.argument_t( name=self.register_variable_name( 'inst' ) + , type=inst_arg_type ) - + @property + def inst_arg( self ): + return self.__inst_arg + def __init__( self, function ): controller_base_t.__init__( self, function ) self.__override_cntrl = self.override_fun_controller_t( function ) + self.__default_cntrl = self.default_fun_controller_t( function ) def apply( self, transformations ): map( lambda t: t.configure_virtual_mem_fun( self ), transformations ) @@ -258,3 +274,7 @@ @property def override_controller( self ): return self.__override_cntrl + + @property + def default_controller( self ): + return self.__default_cntrl Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py 2006-11-28 21:23:41 UTC (rev 762) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py 2006-11-29 12:24:50 UTC (rev 763) @@ -8,51 +8,50 @@ import os from string import Template -# function_name - C++ function name -# function_alias - function name that Python user will see - #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([ - '$declare_variables' - , '$pre_call' - , '$save_result$function($arg_expressions);' - , '$post_call' - , '$return' + 'static $return_type $unique_function_name( $arg_declarations ){' + , ' $declare_variables' + , ' $pre_call' + , ' $save_result$function_name($arg_expressions);' + , ' $post_call' + , ' $return' + , '}' ])) class virtual_mem_fun: override_body = Template( os.linesep.join([ - 'namespace bpl = boost::python;' - , 'if( bpl::override $py_function_var = this->get_override( "$function_alias" ) ){' - , ' $declare_py_variables' - , ' $py_pre_call' - , ' ${save_py_result}bpl::call<bpl::object>( $py_function_var.ptr()$py_arg_expressions );' - , ' $py_post_call' - , ' $py_return' + 'virtual $return_type $function_name( $arg_declarations )$constness $throw{' + , ' namespace bpl = boost::python;' + , ' if( bpl::override $py_function_var = this->get_override( "$function_alias" ) ){' + , ' $declare_py_variables' + , ' $py_pre_call' + , ' ${save_py_result}bpl::call<bpl::object>( $py_function_var.ptr()$py_arg_expressions );' + , ' $py_post_call' + , ' $py_return' + , ' }' + , ' else{' + , ' $cpp_return$wrapped_class::$function_name( $cpp_arg_expressions );' + , ' }' , '}' - , 'else{' - , ' $cpp_return$wrapped_class::$function_name( $cpp_arg_expressions );' - , '}' ])) default_body = Template( os.linesep.join([ - '$declare_variables' - , '$pre_call' - , 'if( $wrapper_class $py_wrapper_var = dynamic_cast< $wrapper_class >( boost::addressof( $wrapped_inst ) ) ){' - , ' // The following call is done on an instance created in Python i.e.' - , ' // a wrapper instance. this call might invoke python code.' - , ' $py_save_result$wrapped_inst->$wrapped_class::$function_name($py_arg_expressions);' + 'static $return_type $unique_function_name( $arg_declarations ){' + , ' $declare_variables' + , ' $pre_call' + , ' if( $wrapper_class $py_wrapper_var = dynamic_cast< $wrapper_class >( boost::addressof( $wrapped_inst ) ) ){' + , ' $save_result$wrapped_inst->$wrapped_class::$function_name($arg_expressions);' + , ' }' + , ' else{' + , ' $save_result$wrapped_inst.$function_name($arg_expressions);' + , ' }' + , ' $post_call' + , ' $return' , '}' - , 'else{' - , " // The following call is done on an instance created in C++, so it won't " - , ' // invoke python code.' - , ' $cpp_save_result$wrapped_inst.$function_name($cpp_arg_expressions);' - , '}' - , '$post_call' - , '$return' ])) Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py 2006-11-28 21:23:41 UTC (rev 762) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py 2006-11-29 12:24:50 UTC (rev 763) @@ -82,24 +82,30 @@ #adding the variable to return variables list controller.return_variable( var_name ) + def __configure_v_mem_fun_default( self, controller ): + self.__configure_sealed( controller ) + + def __configure_v_mem_fun_override( self, controller ): + controller.remove_py_arg( self.arg_index ) + tmpl = string.Template( + '$name = boost::python::extract< $type >( pyplus_conv::get_out_argument( $py_result, "$name" ) );' ) + store_py_result_in_arg = tmpl.substitute( name=self.arg.name + , type=remove_ref_or_ptr( self.arg.type ).decl_string + , py_result=controller.py_result_variable.name ) + controller.add_py_post_call_code( store_py_result_in_arg ) + def configure_mem_fun( self, controller ): self.__configure_sealed( controller ) def configure_free_fun(self, controller ): self.__configure_sealed( controller ) + def configure_virtual_mem_fun( self, controller ): - assert isinstance( controller, controllers.virtual_mem_fun_controller_t ) - override_cntrl = controller.override_controller - override_cntrl.remove_py_arg( self.arg_index ) - tmpl = string.Template( - '$name = boost::python::extract< $type >( pyplus_conv::get_out_argument( $py_result, "$name" ) );' ) - store_py_result_in_arg = tmpl.substitute( name=self.arg.name - , type=remove_ref_or_ptr( self.arg.type ).decl_string - , py_result=override_cntrl.py_result_variable.name ) - override_cntrl.add_py_post_call_code( store_py_result_in_arg ) + self.__configure_v_mem_fun_default( controller.default_controller ) + self.__configure_v_mem_fun_override( controller.override_controller ) + - # input_t class input_t(transformer.transformer_t): """Handles a single input variable. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-11-28 21:23:48
|
Revision: 762 http://svn.sourceforge.net/pygccxml/?rev=762&view=rev Author: roman_yakovenko Date: 2006-11-28 13:23:41 -0800 (Tue, 28 Nov 2006) Log Message: ----------- adding support for virtual function part of transformer Modified Paths: -------------- pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py pyplusplus_dev_ft/pyplusplus/code_creators/calldef_utils.py pyplusplus_dev_ft/pyplusplus/code_repository/convenience.py pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py pyplusplus_dev_ft/pyplusplus/function_transformers/function_transformation.py pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py pyplusplus_dev_ft/unittests/data/function_transformations_to_be_exported.hpp pyplusplus_dev_ft/unittests/function_transformations_tester.py Modified: pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py 2006-11-28 14:01:48 UTC (rev 761) +++ pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py 2006-11-28 21:23:41 UTC (rev 762) @@ -3,7 +3,6 @@ # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) -import re import os import algorithm import code_creator @@ -17,9 +16,10 @@ #TODO: constructors also can have transformation defined. We should use make _init # function for this purpose -__REMOVE_DUPLICAET_LINESEP = re.compile( '(%s){2,}' % os.linesep ) def remove_duplicate_linesep( code ): - return __REMOVE_DUPLICAET_LINESEP.sub( os.linesep, code ) + lines = code.split( os.linesep ) + lines = filter( lambda line: line.strip(), lines ) + return os.linesep.join( lines ) class sealed_fun_transformed_t( calldef_t ): def __init__( self, function, wrapper=None ): @@ -260,25 +260,44 @@ def _get_alias_impl( self ): return self.wrapper.ft.alias - def create_function_type_alias_code( self, exported_class_alias=None ): - ftype = self.wrapper.function_type() - return 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) + def create_function_type_alias_code( self, exported_class_alias=None ): + result = [] + ftype = self.declaration.function_type() + result.append( 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) ) + if self.wrapper: + result.append( os.linesep ) + ftype = self.wrapper.function_type() + result.append( 'typedef %s;' % ftype.create_typedef( self.default_function_type_alias ) ) + return ''.join( result ) + + def create_doc(self): + return None + def create_function_ref_code(self, use_function_alias=False): - full_name = self.wrapper.full_name() - + result = [] if use_function_alias: - return '%s( &%s )' \ - % ( self.function_type_alias, full_name ) + result.append( '%s(&%s)' + % ( self.function_type_alias, declarations.full_name( self.declaration ) ) ) + if self.wrapper: + result.append( self.param_sep() ) + result.append( '%s(&%s)' + % ( self.default_function_type_alias, self.wrapper.default_full_name() ) ) elif self.declaration.create_with_signature: - func_type = self.wrapper.function_type() - return '(%s)( &%s )' % ( func_type, full_name ) + result.append( '(%s)(&%s)' + % ( self.declaration.function_type().decl_string + , declarations.full_name( self.declaration ) ) ) + if self.wrapper: + result.append( self.param_sep() ) + result.append( '(%s)(&%s)' + % ( self.wrapper.function_type().decl_string, self.wrapper.default_full_name() ) ) else: - return '&%s' % full_name + result.append( '&%s'% declarations.full_name( self.declaration ) ) + if self.wrapper: + result.append( self.param_sep() ) + result.append( '&%s' % self.wrapper.default_full_name() ) + return ''.join( result ) - def create_call_policies( self ): - return '' - class mem_fun_v_transformed_wrapper_t( calldef_wrapper_t ): def __init__( self, function ): calldef_wrapper_t.__init__( self, function=function ) @@ -291,54 +310,98 @@ def controller( self ): return self.ft.controller - def create_declaration(self, name): - template = 'static %(return_type)s %(name)s( %(args)s )' + def default_full_name(self): + return self.parent.full_name + '::default_' + self.declaration.alias + def function_type(self): + return declarations.member_function_type_t( + return_type=self.declaration.return_type + , class_inst=declarations.dummy_type_t( self.parent.full_name ) + , arguments_types=map( lambda arg: arg.type, self.declaration.arguments ) + , has_const=self.declaration.has_const ) + + def create_declaration(self, name, has_virtual=True): + template = '%(virtual)s%(return_type)s %(name)s( %(args)s )%(constness)s %(throw)s' + + virtual = 'virtual ' + if not has_virtual: + virtual = '' + + constness = '' + if self.declaration.has_const: + constness = ' const ' + return template % { - 'return_type' : self.controller.wrapper_return_type.decl_string - , 'name' : self.wrapper_name() + 'virtual' : virtual + , 'return_type' : self.declaration.return_type.decl_string + , 'name' : name , 'args' : self.args_declaration() + , 'constness' : constness + , 'throw' : self.throw_specifier_code() } - def resolve_function_ref( self ): - raise NotImplementedError() + def wrapped_class_identifier( self ): + return algorithm.create_identifier( self, declarations.full_name( self.declaration.parent ) ) - def create_body(self): - cntrl = self.controller - - make_object = algorithm.create_identifier( self, 'pyplusplus::call_policies::make_object' ) - make_tuple = algorithm.create_identifier( self, 'boost::python::make_tuple' ) + def create_virtual_body(self): + cntrl = self.controller.override_controller - result_var_assign = '' + tmpl_values = dict() + tmpl_values['py_function_var'] = cntrl.py_function_var + tmpl_values['function_alias'] = self.declaration.alias + tmpl_values['declare_py_variables'] \ + = os.linesep.join( map( lambda var: var.declare_var_string(), cntrl.py_variables ) ) + tmpl_values['py_pre_call'] = os.linesep.join( cntrl.py_pre_call ) + tmpl_values['py_post_call'] = os.linesep.join( cntrl.py_post_call ) + tmpl_values['py_arg_expressions'] = '' + if cntrl.py_arg_expressions: + tmpl_values['py_arg_expressions'] \ + = ', ' + declarations.call_invocation.join( '', cntrl.py_arg_expressions ) + + tmpl_values['save_py_result'] = "bpl::object %s = " % cntrl.py_result_variable.name + tmpl_values['py_return'] = '' + tmpl_values['cpp_return'] = '' if not declarations.is_void( self.declaration.return_type ): - result_var_assign = '%(type)s %(name)s = ' \ - % { 'type': cntrl.result_variable.type.decl_string - , 'name' : cntrl.result_variable.name } + tmpl_values['py_return'] \ + = 'return bpl::extract< %(type)s >( pyplus_conv::get_out_argument( %(py_result)s, 0 ) );' \ + % { 'type' : self.declaration.return_type.decl_string + , 'py_result' : cntrl.py_result_variable.name } + tmpl_values['cpp_return'] = 'return ' - return_stmt_creator = calldef_utils.return_stmt_creator_t( self - , self.controller - , self.controller.result_variable - , self.controller.return_variables ) + tmpl_values['wrapped_class'] = self.wrapped_class_identifier() + tmpl_values['function_name'] = self.declaration.name - post_call = os.linesep.join( cntrl.post_call ) - if return_stmt_creator.pre_return_code: - post_call = os.linesep.join( [post_call, return_stmt_creator.pre_return_code] ) - - return cntrl.template.substitute({ - 'declare_variables' : os.linesep.join( map( lambda var: var.declare_var_string(), cntrl.variables ) ) - , 'pre_call' : os.linesep.join( cntrl.pre_call ) - , 'post_call' : post_call - , 'save_result' : result_var_assign - , 'function' : self.resolve_function_ref() - , 'arg_expressions' : self.PARAM_SEPARATOR.join( cntrl.arg_expressions ) - , 'return' : return_stmt_creator.statement - }) - - def _create_impl(self): - answer = [ self.create_declaration(self.declaration.alias) + '{' ] - answer.append( self.indent( '// Transformed wrapper function for "%s"' % self.declaration ) ) - body = self.create_body() + arg_utils = calldef_utils.argument_utils_t( self.declaration + , algorithm.make_id_creator( self ) + , self.declaration.arguments ) + tmpl_values['cpp_arg_expressions'] = arg_utils.call_args() + + return cntrl.template.substitute(tmpl_values) + + def create_default_body(self): + function_call = declarations.call_invocation.join( self.declaration.name + , [ self.function_call_args() ] ) + body = self.wrapped_class_identifier() + '::' + function_call + ';' + if not declarations.is_void( self.declaration.return_type ): + body = 'return ' + body + return body + + def create_function(self): + answer = [ self.create_declaration(self.declaration.name) + '{' ] + body = self.create_virtual_body() body = remove_duplicate_linesep( body ) answer.append( self.indent( body ) ) answer.append( '}' ) return os.linesep.join( answer ) + + def create_default_function( self ): + answer = [ self.create_declaration('default_' + self.declaration.alias, False) + '{' ] + answer.append( self.indent( self.create_default_body() ) ) + answer.append( '}' ) + return os.linesep.join( answer ) + + def _create_impl(self): + answer = [ self.create_function() ] + answer.append( os.linesep ) + answer.append( self.create_default_function() ) + return os.linesep.join( answer ) Modified: pyplusplus_dev_ft/pyplusplus/code_creators/calldef_utils.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/code_creators/calldef_utils.py 2006-11-28 14:01:48 UTC (rev 761) +++ pyplusplus_dev_ft/pyplusplus/code_creators/calldef_utils.py 2006-11-28 21:23:41 UTC (rev 762) @@ -90,7 +90,8 @@ def call_args( self ): params = [] for index, arg in enumerate( self.__args ): - params.append( decl_wrappers.python_traits.call_traits( arg.type ) % self.argument_name( index ) ) + params.append( decl_wrappers.python_traits.call_traits( arg.type ) + % self.argument_name( index ) ) return ', '.join( params ) class return_stmt_creator_t( object ): Modified: pyplusplus_dev_ft/pyplusplus/code_repository/convenience.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/code_repository/convenience.py 2006-11-28 14:01:48 UTC (rev 761) +++ pyplusplus_dev_ft/pyplusplus/code_repository/convenience.py 2006-11-28 21:23:41 UTC (rev 762) @@ -145,6 +145,16 @@ } } +inline boost::python::object +get_out_argument( boost::python::object result, index_type index ){ + if( PySequence_Check( result.ptr() ) ){ + return result[ index ]; + } + else{ + return result; + } +} + } /*pyplusplus*/ } /*convenience*/ namespace pyplus_conv = pyplusplus::convenience; Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py 2006-11-28 14:01:48 UTC (rev 761) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py 2006-11-28 21:23:41 UTC (rev 762) @@ -100,7 +100,7 @@ @property def template( self ): - return templates.mem_fun.body + return templates.sealed_fun.body @property def wrapper_args( self ): @@ -188,58 +188,73 @@ class virtual_mem_fun_controller_t( controller_base_t ): - def __init__( self, function ): - controller_base_t.__init__( self, function ) - self.__py_vars_manager = create_variables_manager( function ) - self.__py_function_var \ - = self.__py_vars_manager.register_name( 'func_' + function.alias ) - self.__py_pre_call = [] - self.__py_post_call = [] - self.__py_result_var = variable_t( declarations.dummy_type_t( 'boost::python::object' ) - , self.register_py_variable_name( 'py_result' ) ) + class override_fun_controller_t( controller_base_t ): + def __init__( self, function ): + controller_base_t.__init__( self, function ) + self.__py_vars_manager = create_variables_manager( function ) + self.__py_function_var \ + = self.__py_vars_manager.register_name( 'func_' + function.alias ) + self.__py_pre_call = [] + self.__py_post_call = [] + self.__py_result_var = variable_t( declarations.dummy_type_t( 'boost::python::object' ) + , self.register_py_variable_name( 'py_result' ) ) + + self.__py_arg_expressions = [ arg.name for arg in function.arguments ] - self.__py_arg_expressions = [ arg.name for arg in function.arguments ] - - @property - def py_variables( self ): - return self.__py_vars_manager.variables + @property + def template( self ): + return templates.virtual_mem_fun.override_body + + @property + def py_variables( self ): + return self.__py_vars_manager.variables + + def declare_py_variable( self, type, name, initialize_expr='' ): + return self.__py_vars_manager.declare_variable( type, name, initialize_expr) - def declare_py_variable( self, type, name, initialize_expr='' ): - return self.__py_vars_manager.declare_variable( type, name, initialize_expr) - - def register_py_variable_name( self, name ): - return self.__py_vars_manager.register_name( name ) + def register_py_variable_name( self, name ): + return self.__py_vars_manager.register_name( name ) + + @property + def py_function_var( self ): + return self.__py_function_var - @property - def py_function_var( self ): - return self.__py_function_var + @property + def py_pre_call( self ): + return self.__py_pre_call + + def add_py_pre_call_code( self, code ): + self.__py_pre_call.append( code ) + + @property + def py_post_call( self ): + return self.__py_post_call + + def add_py_post_call_code( self, code ): + self.__py_post_call.append( code ) - @property - def py_pre_call( self ): - return self.__py_pre_call + @property + def py_result_variable( self ): + return self.__py_result_var - def add_py_pre_call_code( self, code ): - self.__py_pre_call.append( code ) - - @property - def py_post_call( self ): - return self.__py_post_call + @property + def py_arg_expressions( self ): + return filter( None, self.__py_arg_expressions ) - def add_py_post_call_code( self, code ): - self.__py_post_call.append( code ) + def remove_py_arg( self, index ): + self.__py_arg_expressions[ index ] = None + + def modify_py_arg_expression( self, index, expression ): + self.arg_expressions[ index ] = expression - @property - def py_result_variable( self ): - return self.__py_result_var - @property - def py_arg_expressions( self ): - return filter( None, self.__py_arg_expressions ) + def __init__( self, function ): + controller_base_t.__init__( self, function ) + self.__override_cntrl = self.override_fun_controller_t( function ) - def remove_py_arg( self, index ): - self.__py_arg_expressions[ index ] = None - - def modify_py_arg_expression( self, index, expression ): - self.arg_expressions[ index ] = expression + def apply( self, transformations ): + map( lambda t: t.configure_virtual_mem_fun( self ), transformations ) - + @property + def override_controller( self ): + return self.__override_cntrl Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/function_transformation.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/function_transformation.py 2006-11-28 14:01:48 UTC (rev 761) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/function_transformation.py 2006-11-28 21:23:41 UTC (rev 762) @@ -16,7 +16,10 @@ self.__function = function self.__controller = None if isinstance( function.parent, declarations.class_t ): - self.__controller = controllers.mem_fun_controller_t( function ) + if declarations.VIRTUALITY_TYPES.NOT_VIRTUAL == function.virtuality: + self.__controller = controllers.mem_fun_controller_t( function ) + else: + self.__controller = controllers.virtual_mem_fun_controller_t( function ) else: self.__controller = controllers.free_fun_controller_t( function ) self.__transformers = map( lambda tr_creator: tr_creator( function ), transformer_creator ) Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py 2006-11-28 14:01:48 UTC (rev 761) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py 2006-11-28 21:23:41 UTC (rev 762) @@ -11,17 +11,10 @@ # function_name - C++ function name # function_alias - function name that Python user will see -class free_fun: - body = Template( os.linesep.join([ - '$declare_variables' - , '$pre_call' - , '$save_result$function($arg_expressions);' - , '$post_call' - , '$return' - ])) +#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 mem_fun: +class sealed_fun: body = Template( os.linesep.join([ '$declare_variables' , '$pre_call' @@ -32,15 +25,16 @@ class virtual_mem_fun: override_body = Template( os.linesep.join([ - 'if( boost::python::override $py_function_var = this->get_override( "$function_alias" ) ){' + 'namespace bpl = boost::python;' + , 'if( bpl::override $py_function_var = this->get_override( "$function_alias" ) ){' , ' $declare_py_variables' , ' $py_pre_call' - , ' ${save_py_result}boost::python::call<$py_return_type>( $py_function_var$py_arg_expressions );' + , ' ${save_py_result}bpl::call<bpl::object>( $py_function_var.ptr()$py_arg_expressions );' , ' $py_post_call' , ' $py_return' , '}' , 'else{' - , ' $cpp_return$wrapped_class::%function_name( $cpp_arg_expressions );' + , ' $cpp_return$wrapped_class::$function_name( $cpp_arg_expressions );' , '}' ])) @@ -50,7 +44,6 @@ , 'if( $wrapper_class $py_wrapper_var = dynamic_cast< $wrapper_class >( boost::addressof( $wrapped_inst ) ) ){' , ' // The following call is done on an instance created in Python i.e.' , ' // a wrapper instance. this call might invoke python code.' - , ' // a wrapper instance. this call might invoke python code.' , ' $py_save_result$wrapped_inst->$wrapped_class::$function_name($py_arg_expressions);' , '}' , 'else{' Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py 2006-11-28 14:01:48 UTC (rev 761) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py 2006-11-28 21:23:41 UTC (rev 762) @@ -72,8 +72,7 @@ """Returns list of header files that transformer generated code depends on.""" return [ code_repository.convenience.file_name ] - - def __configure_non_virtual( self, controller ): + def __configure_sealed( self, controller ): #removing arg from the function wrapper definition controller.remove_wrapper_arg( self.arg.name ) #declaring new variable, which will keep result @@ -84,21 +83,21 @@ controller.return_variable( var_name ) def configure_mem_fun( self, controller ): - self.__configure_non_virtual( controller ) + self.__configure_sealed( controller ) def configure_free_fun(self, controller ): - self.__configure_non_virtual( controller ) + self.__configure_sealed( controller ) def configure_virtual_mem_fun( self, controller ): assert isinstance( controller, controllers.virtual_mem_fun_controller_t ) - #removing arg from the function wrapper definition - controller.remove_py_arg( self.arg_index ) + override_cntrl = controller.override_controller + override_cntrl.remove_py_arg( self.arg_index ) tmpl = string.Template( '$name = boost::python::extract< $type >( pyplus_conv::get_out_argument( $py_result, "$name" ) );' ) store_py_result_in_arg = tmpl.substitute( name=self.arg.name - , type=self.arg.type.decl_string - , py_result=controller.py_result_variable.name ) - controller.add_py_post_call_code( store_py_result_in_arg ) + , type=remove_ref_or_ptr( self.arg.type ).decl_string + , py_result=override_cntrl.py_result_variable.name ) + override_cntrl.add_py_post_call_code( store_py_result_in_arg ) # input_t @@ -129,15 +128,15 @@ def __str__(self): return "input(%d)"%(self.idx) - def __configure_non_virtual( self, controller ): + def __configure_sealed( self, controller ): w_arg = controller.find_wrapper_arg( self.arg.name ) w_arg.type = remove_ref_or_ptr( self.arg.type ) def configure_mem_fun( self, controller ): - self.__configure_non_virtual( controller ) + self.__configure_sealed( controller ) def configure_free_fun(self, controller ): - self.__configure_non_virtual( controller ) + self.__configure_sealed( controller ) def configure_virtual_mem_fun( self, controller ): pass #according to boost.python documentation, it will create a copy of @@ -170,17 +169,17 @@ def __str__(self): return "inout(%d)"%(self.arg_index) - def __configure_non_virtual(self, controller): + def __configure_sealed(self, controller): w_arg = controller.find_wrapper_arg( self.arg.name ) w_arg.type = remove_ref_or_ptr( self.arg.type ) #adding the variable to return variables list controller.return_variable( w_arg.name ) def configure_mem_fun( self, controller ): - self.__configure_non_virtual( controller ) + self.__configure_sealed( controller ) def configure_free_fun(self, controller ): - self.__configure_non_virtual( controller ) + self.__configure_sealed( controller ) def configure_virtual_mem_fun( self, controller ): assert isinstance( controller, controllers.virtual_mem_fun_controller_t ) @@ -230,7 +229,7 @@ pre_call.append( 'pyplus_conv::copy_sequence( $pylist, pyplus_conv::array_inserter( $native_array, $array_size ) );' ) return string.Template( os.linesep.join( pre_call ) ) - def __configure_non_virtual(self, controller): + def __configure_sealed(self, controller): w_arg = controller.find_wrapper_arg( self.arg.name ) w_arg.type = declarations.dummy_type_t( "boost::python::object" ) @@ -249,10 +248,10 @@ controller.modify_arg_expression( self.arg_index, native_array ) def configure_mem_fun( self, controller ): - self.__configure_non_virtual( controller ) + self.__configure_sealed( controller ) def configure_free_fun(self, controller ): - self.__configure_non_virtual( controller ) + self.__configure_sealed( controller ) # output_array_t class output_array_t(transformer.transformer_t): @@ -292,7 +291,7 @@ def post_call_tmpl( self ): return string.Template( 'pyplus_conv::copy_container( $native_array, $native_array + $array_size, pyplus_conv::list_inserter( $pylist ) );' ) - def __configure_non_virtual(self, controller): + def __configure_sealed(self, controller): #removing arg from the function wrapper definition controller.remove_wrapper_arg( self.arg.name ) @@ -318,7 +317,7 @@ controller.return_variable( pylist ) def configure_mem_fun( self, controller ): - self.__configure_non_virtual( controller ) + self.__configure_sealed( controller ) def configure_free_fun(self, controller ): - self.__configure_non_virtual( controller ) + self.__configure_sealed( controller ) Modified: pyplusplus_dev_ft/unittests/data/function_transformations_to_be_exported.hpp =================================================================== --- pyplusplus_dev_ft/unittests/data/function_transformations_to_be_exported.hpp 2006-11-28 14:01:48 UTC (rev 761) +++ pyplusplus_dev_ft/unittests/data/function_transformations_to_be_exported.hpp 2006-11-28 21:23:41 UTC (rev 762) @@ -91,26 +91,26 @@ } -//~ namespace ft{ +namespace ft{ -//~ struct image_t{ +struct image_t{ - //~ image_t( unsigned int h, unsigned int w ) - //~ : m_height( h ) - //~ , m_width( w ) - //~ {} + image_t( unsigned int h, unsigned int w ) + : m_height( h ) + , m_width( w ) + {} - //~ // Made the method 'virtual' for now because func transformers - //~ // are currently only taken into account on virtual functions. - //~ void get_size( unsigned int& h, unsigned int& w ){ + // Made the method 'virtual' for now because func transformers + // are currently only taken into account on virtual functions. + //~ virtual void get_size( unsigned int& h, unsigned int& w ){ //~ h = m_height; //~ w = m_width; //~ } - //~ // Return only one value - //~ virtual void get_one_value(unsigned int& h) { - //~ h = m_height; - //~ } + // Return only one value + virtual void get_one_value(unsigned int& h) { + h = m_height; + } //~ // Like get_size() but with a return type and an additional argument //~ // that has to be kept in the signature @@ -137,10 +137,10 @@ //~ v[2] = 3; //~ } - //~ unsigned int m_width; - //~ unsigned int m_height; + unsigned int m_width; + unsigned int m_height; -//~ }; +}; //~ // Provide an instance created in C++ (i.e. this is not a wrapper instance) //~ image_t cpp_instance(12,13); @@ -183,6 +183,6 @@ //~ ~ft_private_destructor_t(){} //~ }; -//~ } +} #endif//__function_transformations_to_be_exported_hpp__ Modified: pyplusplus_dev_ft/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev_ft/unittests/function_transformations_tester.py 2006-11-28 14:01:48 UTC (rev 761) +++ pyplusplus_dev_ft/unittests/function_transformations_tester.py 2006-11-28 21:23:41 UTC (rev 762) @@ -46,13 +46,13 @@ point3d.mem_fun( 'position' ).add_transformation( ft.output_array(0, size=3) ) point3d.mem_fun( 'distance' ).add_transformation( ft.output(1) ) - #~ image = mb.class_( "image_t" ) - #~ image.include() - #~ image.add_wrapper_code( '' ) + image = mb.class_( "image_t" ) + image.include() + #~ image.member_functions().exclude() #~ image.member_function( "get_size" ).include() #~ image.member_function( "get_size" ).add_transformation( ft.output(0), ft.output(1) ) - #~ image.member_function( "get_one_value" ).add_transformation( ft.output(0) ) + image.member_function( "get_one_value" ).add_transformation( ft.output(0) ) #~ image.member_function( "get_size2" ).add_transformation( ft.output(0), ft.output(1) ) #~ image.member_function( "input_arg" ).add_transformation( ft.input(0) ) #~ image.member_function( "fixed_input_array" ).add_transformation( ft.input_array(0,3) ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-11-28 14:01:53
|
Revision: 761 http://svn.sourceforge.net/pygccxml/?rev=761&view=rev Author: roman_yakovenko Date: 2006-11-28 06:01:48 -0800 (Tue, 28 Nov 2006) Log Message: ----------- initial implementation of transformers for virtual functions Modified Paths: -------------- pyplusplus_dev_ft/pyplusplus/code_repository/convenience.py pyplusplus_dev_ft/pyplusplus/function_transformers/__init__.py pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py Removed Paths: ------------- pyplusplus_dev_ft/pyplusplus/function_transformers/code_manager.py pyplusplus_dev_ft/pyplusplus/function_transformers/substitution_manager.py Modified: pyplusplus_dev_ft/pyplusplus/code_repository/convenience.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/code_repository/convenience.py 2006-11-28 08:27:48 UTC (rev 760) +++ pyplusplus_dev_ft/pyplusplus/code_repository/convenience.py 2006-11-28 14:01:48 UTC (rev 761) @@ -135,6 +135,16 @@ return array_inserter_t<T>( array, size ); } +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 ); + } + else{ + return result; + } +} + } /*pyplusplus*/ } /*convenience*/ namespace pyplus_conv = pyplusplus::convenience; Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/__init__.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/__init__.py 2006-11-28 08:27:48 UTC (rev 760) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/__init__.py 2006-11-28 14:01:48 UTC (rev 761) @@ -16,7 +16,6 @@ """ -from substitution_manager import substitution_manager_t from transformer import transformer_t import transformers from function_transformation import function_transformation_t @@ -44,4 +43,4 @@ def output_array( *args, **keywd ): def creator( function ): return transformers.output_array_t( function, *args, **keywd ) - return creator \ No newline at end of file + return creator Deleted: pyplusplus_dev_ft/pyplusplus/function_transformers/code_manager.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/code_manager.py 2006-11-28 08:27:48 UTC (rev 760) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/code_manager.py 2006-11-28 14:01:48 UTC (rev 761) @@ -1,254 +0,0 @@ -# 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) -# -# Initial author: Matthias Baas - -"""This module contains the L{code_manager_t} and L{wrapper_code_manager_t} classes. -""" - -import os -import types -import string - -# code_manager_t -class code_manager_t: - """This class manages pieces of source code for a C++ function. - - The class mainly provides the interface for the code blocks to - manipulate a function and stores the actual substitution variables. - Each function has its own code manager instance. - - A code block can declare a local variable using L{declare_variable()} - and it can manipulate one of the attributes that are used to - initialize the final variables (see the documentation of the - instance variables below). The final variables (such as RET_TYPE, - FUNC_NAME, ARG_LIST, etc.) are stored as regular attributes of the - object. - - The functionality to perform a text substitution (using the - substitution() method) is inherited - from the class L{subst_t}. - - @ivar class_name: The name of the class of which the generated function is a member. A value of None or an empty string is used for free functions. This attribute is used for creating the CLASS_SPEC variable. - @type class_name: str - @ivar ret_type: Return type. The value may be any object where str(obj) is valid C++ code. The value None corresponds to void. This will be the value of the variable RET_TYPE. - @type ret_type: str - @ivar arg_list: The argument list. The items are pygccxml argument_t objects. This list will appear in the variables ARG_LIST, ARG_LIST_DEF and ARG_LIST_TYPES. - @type arg_list: list of L{argument_t<pygccxml.declarations.calldef.argument_t>} - @ivar input_params: A list of strings that contain the input parameter for the function call. This list is used for the INPUT_PARAMS variable. - @type input_params: list of str - @ivar result_var: The name of the variable that will receive the result of the function call. If None, the return value is ignored. This attribute will be used for the variable RESULT_VAR_ASSIGNMENT. - @type result_var: str - @ivar result_type: The type of the variable 'result_var' - @type result_type: str - @ivar result_expr: A string containing the expression that will be put after the "return" statement. This expression is used for the variable RETURN_STMT. - @type result_expr: str - @ivar exception_handler_exit: The C++ code that is executed at the end of the main exception handler (default: "throw;"). - @type exception_handler_exit: str - - @author: Matthias Baas - """ - - def __init__(self): - """Constructor.""" - # The name of the class of which the generated function is a member - # (pass None or an empty string if the function is a free function) - self.class_name = None - - # Return type (the value may be any object where str(obj) is valid - # C++ code. The value None corresponds to "void"). - self.ret_type = None - # The argument list. The items are argument_t objects. - self.arg_list = [] - - # A list of strings that contain the input parameter for the - # function call - self.input_params = [] - - # The name of the variable that will receive the result of the - # function call. If None, the return value is ignored. - self.result_var = None - - # The type of 'result_var' - self.result_type = "void" - - # A string containing the expression that will be put after - # the "return" statement. - self.result_expr = None - - # The C++ code that is executed at the end of the main - # exception handler. - self.exception_handler_exit = "throw;" - - # Key:Variable name / Value:(type,size,default) - self._declared_vars = {} - - def substitute( self, template_code ): - tmpl = string.Template(template_code) - return tmpl.safe_substitute(self.__dict__) - - # declare_variable - def declare_variable(self, name, type, initialize_expr=''): - """Declare a local variable and return its final name. - - @param name: The desired variable name - @type name: str - @param type: The type of the variable (must be valid C++ code) - @type type: str - @param size: The array length or None - @type size: int - @param default: The default value (must be valid C++ code) or None - @type default: str - @return: The assigned variable name (which is guaranteed to be unique) - @rtype: str - """ - name = self._make_name_unique(name) - self._declared_vars[name] = (type, initialize_expr) - return name - - def init_variables(self): - """Initialize the substitution variables. - - Based on the (lowercase) attributes, the final (uppercase) - variables are created. Those variables are regular string - attributes. - """ - - # CLASS_SPEC - if (self.class_name in [None, ""]): - self.CLASS_SPEC = "" - else: - self.CLASS_SPEC = "%s::"%self.class_name - - # RET_TYPE - if self.ret_type==None: - self.RET_TYPE = "void" - else: - self.RET_TYPE = str(self.ret_type) - - # ARG_LIST_DEF - args = map(lambda a: str(a), self.arg_list) - self.ARG_LIST_DEF = ", ".join(args) - - # ARG_LIST - args = map(lambda s: s.split("=")[0], args) - self.ARG_LIST = ", ".join(args) - - # ARG_LIST_TYPES - args = map(lambda a: str(a.type), self.arg_list) - self.ARG_LIST_TYPES = ", ".join(args) - - # Create the declaration block -> DECLARATIONS - vardecls = [] - for name, (type, initialize_expr) in self._declared_vars.iteritems(): - tmpl = "%(type)s %(name)s%(initialize_expr)s;" - vardecls.append( tmpl % { 'type' : type - , 'name' : name - , 'initialize_expr' : initialize_expr } ) - self.DECLARATIONS = os.linesep.join(vardecls) - - # RESULT_VAR_ASSIGNMENT - if self.result_var!=None: - self.RESULT_VAR_ASSIGNMENT = "%s = "%self.result_var - else: - self.RESULT_VAR_ASSIGNMENT = "" - - # RESULT_TYPE - if self.result_type!=None: - self.RESULT_TYPE = str(self.result_type) - else: - self.RESULT_TYPE = "" - - # INPUT_PARAMS - self.INPUT_PARAMS = ", ".join(self.input_params) - - # RETURN_STMT - if self.result_expr!=None: - self.RETURN_STMT = "return %s;"%self.result_expr - else: - self.RETURN_STMT = "" - - # EXCEPTION_HANDLER_EXIT - if self.exception_handler_exit!=None: - self.EXCEPTION_HANDLER_EXIT = self.exception_handler_exit - else: - self.EXCEPTION_HANDLER_EXIT = "" - - # _make_name_unique - def _make_name_unique(self, name): - """Make a variable name unique so that there's no clash with other names. - - @param name: The variable name that should be unique - @type name: str - @return: A unique name based on the input name - @rtype: str - """ - n = 2 - newname = name - while 1: - if not self._declared_vars.has_key( newname ): - return newname - newname = "%s_%d"%(name, n) - n += 1 - -# wrapper_code_manager_t -class wrapper_code_manager_t(code_manager_t): - """The CodeManager class for the wrapper function. - - In contrast to a regular C++ function a Python function can return - several values, so this class provides the extra attribute "result_exprs" - which is a list of individual expressions. Apart from that this - class is identical to L{code_manager_t}. - - @ivar result_exprs: Similar to result_expr but this list variable can contain more than just one result. The items can be either strings containing the variable names (or expressions) that should be returned or it can be an L{argument_t<pygccxml.declarations.calldef.argument_t>} object (usually from the argument list of the virtual function) whose name attribute will be used. This attribute only exists on the code manager for the wrapper function (the virtual function cannot return several values, use result_expr instead). - @type result_exprs: list of str or L{argument_t<pygccxml.declarations.calldef.argument_t>} - """ - - def __init__(self): - """Constructor. - """ - code_manager_t.__init__(self) - - # Similar to result_expr but now there can be more than just one result - # The items can be either strings containing the variable names (or - # expressions) that should be returned or it can be an argument_t - # object (usually from the argument list of the virtual function) - # whose name attribute will be used. - self.result_exprs = [] - - def init_variables(self): - """Initialize the substitution variables. - """ - - # Prepare the variables for RET_TYPE and RETURN_STMT... - - # Convert all items into strings - result_exprs = [] - for re in self.result_exprs: - # String? - if isinstance(re, types.StringTypes): - result_exprs.append(re) - # argument_t - else: - result_exprs.append(re.name) - - if self.result_expr==None: - # No output values? - if len(result_exprs)==0: - self.ret_type = None - self.result_expr = None - # Exactly one output value? - elif len(result_exprs)==1: - self.ret_type = "boost::python::object" - self.result_expr = "boost::python::object(%s)"%result_exprs[0] - # More than one output value... - else: - self.ret_type = "boost::python::object" - self.result_expr = "boost::python::make_tuple(%s)"%(", ".join(result_exprs)) - - # Invoke the inherited method that sets the actual variables - code_manager_t.init_variables(self) - - Deleted: pyplusplus_dev_ft/pyplusplus/function_transformers/substitution_manager.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/substitution_manager.py 2006-11-28 08:27:48 UTC (rev 760) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/substitution_manager.py 2006-11-28 14:01:48 UTC (rev 761) @@ -1,511 +0,0 @@ -# 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) -# -# Initial author: Matthias Baas - -"""This module contains the L{substitution_manager_t} class. -""" - -import os -from pygccxml import declarations -from code_manager import code_manager_t, wrapper_code_manager_t -from transformer import transformer_t -from transformer import return_ - -# substitution_manager_t -class substitution_manager_t: - """Helper class for creating C++ source code for wrapper functions. - - The class does not create the entire function source code itself - but it maintains the individual parts that can be composed by the - user of the class. Those individual parts are stored inside - variables which can be used to perform text substitutions. - - Doing substitutions - =================== - - Here is an example that demonstrates the usage of the class. The - user creates a template string that contains the layout of the - entire wrapper function. Such a template string may look like - this:: - - $RET_TYPE $CLASS_SPEC$FUNC_NAME($ARG_LIST) - { - $DECLARATIONS - - $PRE_CALL - - $RESULT_VAR_ASSIGNMENT$CALL_FUNC_NAME($INPUT_PARAMS); - - $POST_CALL - - $RETURN_STMT - } - - Any part of the function that is not fixed, i.e. that can be - modified by argument policies, is specified via a variable. The - substitution manager can now be used to substitute the variables with - their actual value. There are actually two sets of identical - variables, one for the wrapper function and one for the virtual - function. You choose a set either by using the L{subst_wrapper()} or - L{subst_virtual()} method for doing the substitution. For example, - performing a "wrapper" substitution on the above template string - might result in the following code:: - - boost::python::object Spam_wrapper::foo_wrapper(Spam& self, int mode) - { - int result; - int w; - int h; - - result = self.foo(w, &h, mode); - - return boost::python::make_tuple(result, w, h); - } - - In this example, the individual variables have the following values: - - - RET_TYPE = C{boost::python::object} - - CLASS_SPEC = C{Spam_wrapper::} - - FUNC_NAME = C{foo_wrapper} - - ARG_LIST = C{Spam& self, int mode} - - DECLARATIONS = C{int result;\\nint w;\\nint h;} - - PRE_CALL = <empty> - - RESULT_VAR_ASSIGNMENT = C{result =} - - CALL_FUNC_NAME = C{self.foo} - - INPUT_PARAMS = C{w, &h, mode} - - POST_CALL = <empty> - - RETURN_STMT = C{return boost::python::make_tuple(result, w, h);} - - - Modifying the variables - ======================= - - In addition to the actual user of the class (who wants to do text - substitutions), the class is also used by the arg policies (code blocks) - to modify the variables. - There are two attributes L{wrapper_func} and L{virtual_func} that are - used to modify either the wrapper or the virtual function. If the - signature of the wrapper needs modification this should be done via - the methods L{remove_arg()} and L{insert_arg()} and not via the - wrapper_func or virtual_func attributes because this affects the - virtual function as well (because the virtual function makes a call - to the Python function). - - Variables - ========= - - - - RET_TYPE: The return type (e.g. "void", "int", "boost::python::object") - - - CLASS_SPEC: "<classname>::" or empty - - - FUNC_NAME: The name of the wrapper or virtual function. - - - ARG_LIST: The parameters for $FUNC_NAME (including self if required) - - - ARG_LIST_DEF: Like ARG_LIST, but including default values (if there are any) - - - ARG_LIST_TYPES: Like ARG_LIST but the variable names are left out and only the types are listed (this can identify a particular signature). - - - DECLARATIONS: The declaration block - - - PRE_CALL:: - - +--------------------------+ - | [try {] | - +--------------------------+ - | Pre-call code block 1 | - +--------------------------+ - | Pre-call code block 2 | - +--------------------------+ - | ... | - +--------------------------+ - | Pre-call code block n | - +--------------------------+ - - - RESULT_VAR_ASSIGNMENT: "<varname> = " or empty - - - RESULT_TYPE: The type of the result variable - - - CALL_FUNC_NAME: The name of the function that should be invoked (self?). - - - INPUT_PARAMS: The values or variables that will be passed to $FUNC_NAME, - e.g. "a, b" or "0.5, 1.5" etc - - - POST_CALL:: - - +--------------------------+ - | Post-call code block n | - +--------------------------+ - | ... | - +--------------------------+ - | Post-call code block 2 | - +--------------------------+ - | Post-call code block 1 | - +--------------------------+ - | [} catch(...) {...}] | - +--------------------------+ - - - CLEANUP: The cleanup code blocks of all function transformers. - - - RETURN_STMT: "return <varname>" or "return boost::python::make_tuple(...)" - - - EXCEPTION_HANDLER_EXIT: The C++ code that is executed at the end of the main exception handler (default: "throw;") - - - @ivar wrapper_func: The L{code manager<code_manager_t>} object that manages the wrapper function. This is used by the arg policies to modify the wrapper function. - @type wrapper_func: L{wrapper_code_manager_t} - @ivar virtual_func: The L{code manager<code_manager_t>} object that manages the virtual function. This is used by the arg policies to modify the virtual function. - @type virtual_func: L{code_manager_t} - - @group Methods called by the user of the class: append_code_block, subst_wrapper, subst_virtual - @group Methods called by the function transformers: remove_arg, insert_arg, py_result_expr - - @author: Matthias Baas - """ - - def __init__(self, decl, wrapper_class=None, transformers=None): - """Constructor. - - @param decl: calldef declaration - @type decl: calldef_t - @param wrapper_class: The name of the class the generated function should belong to (or None if the generated function should be a free function) - @type wrapper_class: str - @param transformers: Function transformer objects - @type transformers: list of transformer_t - """ - #prevent recursive import - from pyplusplus import decl_wrappers - # Code manager for the virtual function - self.virtual_func = code_manager_t() - # Code manager for the wrapper function - self.wrapper_func = wrapper_code_manager_t() - - # The declaration that represents the original C++ function - self.decl = decl - - # The function transformers - if transformers==None: - transformers = [] - self.transformers = transformers - - self.wrapper_class = wrapper_class - - # Initialize the code managers... - - self.virtual_func.arg_list = decl.arguments[:] - self.virtual_func.class_name = wrapper_class - self.virtual_func.FUNC_NAME = decl.name - self.virtual_func.CALL_FUNC_NAME = decl.name - self.virtual_func.input_params \ - = map( lambda arg: decl_wrappers.python_traits.call_traits( arg.type ) % arg.name - , decl.arguments ) - - self.wrapper_func.arg_list = decl.arguments[:] - self.wrapper_func.class_name = wrapper_class - self.wrapper_func.FUNC_NAME = "%s_wrapper"%decl.alias - self.wrapper_func.CALL_FUNC_NAME = decl.name - self.wrapper_func.input_params = map(lambda a: a.name, decl.arguments) - - if str(decl.return_type)=="void": - ret_type = None - else: - ret_type = decl.return_type - self.wrapper_func.result_type = str(declarations.type_traits.remove_reference(ret_type)) - self.wrapper_func.result_var = self.wrapper_func.declare_variable("result", self.wrapper_func.result_type) - self.wrapper_func.result_exprs = [self.wrapper_func.result_var] - - self.virtual_func.ret_type = ret_type - - self.wrapper_func.ret_type = ret_type - - # The offset that is added to the index in insert_arg() - # This index is either 0 for free functions or 1 for member functions - # because the "self" argument is not a regular argument. - self._insert_arg_idx_offset = 0 - - # Check if we're dealing with a member function... - if isinstance( decl.parent, declarations.class_t ): - if decl.has_static: - self.wrapper_func.CALL_FUNC_NAME \ - = "%s::%s" % (declarations.full_name(decl.parent), self.wrapper_func.CALL_FUNC_NAME) - else: - selfname = self.wrapper_func._make_name_unique("self") - selfarg = declarations.argument_t(selfname, declarations.dummy_type_t("%s&"%declarations.full_name(decl.parent))) - self.wrapper_func.arg_list.insert(0, selfarg) - self.wrapper_func.CALL_FUNC_NAME = "%s.%s"%(selfname, self.wrapper_func.CALL_FUNC_NAME) - self._insert_arg_idx_offset = 1 - - # Argument index map - # Original argument index ---> Input arg index (indices are 0-based!) - # Initial state is the identity: f(x) = x - # The argument index map represents a function that maps the argument - # index of the original C++ function to the index of the corresponding - # parameter in the input parameter list for the Python call. - self.argidxmap = range(len(decl.arguments)) - - - # Flag that is set after the functions were initialized - self._funcs_initialized = False - - # init_funcs - def init_funcs(self): - """Initialize the virtual function and the wrapper function. - - After this method has been called, the substitution variables - are ready for usage. - - It is not necessary to call this method manually, it is - automatically called at the time a substitution is requested. - """ - - # Append the default return_virtual_result_t code modifier - transformers = self.transformers+[return_virtual_result_t(self.decl)] - - for cb in transformers: - if hasattr(cb, "init_funcs"): - cb.init_funcs(self) - - # Create a variable that will hold the result of the Python call - # inside the virtual function. - if len(self.wrapper_func.result_exprs)>0: - self.virtual_func.result_type = "boost::python::object" - self.virtual_func.result_var = self.virtual_func.declare_variable("pyresult", self.virtual_func.result_type) - - self.wrapper_func.init_variables() - self.virtual_func.init_variables() - - self._funcs_initialized = True - - block_sep = os.linesep * 2 - # Create the wrapper function pre-call block... - tmp = filter(None, map(lambda cb: cb.wrapper_pre_call(self), transformers) ) - self.wrapper_func.PRE_CALL = block_sep.join( tmp ) - - # Create the wrapper function post-call block... - tmp = filter(None, map(lambda cb: cb.wrapper_post_call(self), transformers) ) - self.wrapper_func.POST_CALL = block_sep.join( tmp ) - - # Create the wrapper function cleanup block... - tmp = filter(None, map(lambda cb: cb.wrapper_cleanup(self), transformers) ) - self.wrapper_func.CLEANUP = block_sep.join( tmp ) - - # Create the virtual function pre-call block... - tmp = filter(None, map(lambda cb: cb.virtual_pre_call(self), transformers) ) - self.virtual_func.PRE_CALL = block_sep.join( tmp ) - - # Create the virtual function post-call block... - tmp = filter(None, map(lambda cb: cb.virtual_post_call(self), transformers) ) - self.virtual_func.POST_CALL = block_sep.join( tmp ) - - # Create the virtual function cleanup block... - tmp = filter(None, map(lambda cb: cb.virtual_cleanup(self), transformers) ) - self.virtual_func.CLEANUP = block_sep.join( tmp ) - - # remove_arg - def remove_arg(self, idx): - """Remove an argument from the wrapper function. - - This function can also be used to remove the original return value - (idx=0). - - The function is supposed to be called by function transformer - objects. - - @param idx: Argument index of the original function (may be negative) - @type idx: int - @returns: Returns the argument_t object that was removed (or None - if idx is 0 and the function has no return type). You must not - modify this object as it may still be in use on the virtual - function. - @rtype: L{argument_t<pygccxml.declarations.calldef.argument_t>} - """ - if self._funcs_initialized: - raise ValueError, "remove_arg() may only be called before function initialization." - if idx<0: - idx += len(self.virtual_func.arg_list)+1 - if idx>=len(self.virtual_func.arg_list)+1: - raise IndexError, "Index (%d) out of range."%idx - - # Remove original return type? - if idx==0: - if id(self.wrapper_func.ret_type)==id(self.wrapper_func.ret_type): - self.wrapper_func.ret_type = None - self.wrapper_func.result_exprs.remove(self.wrapper_func.result_var) - else: - raise ValueError, 'Argument %d not found on the wrapper function'%(idx) - # Remove argument... - else: - # Get the original argument... - arg = self.virtual_func.arg_list[idx-1] - # ...and remove it from the wrapper - try: - self.wrapper_func.arg_list.remove(arg) - except ValueError: - msg = str(self.decl)+"\n" - msg += 'Argument %d ("%s") not found on the wrapper function'%(idx, arg.name) - raise ValueError, msg - - # Remove the input parameter on the Python call in the - # virtual function. - paramidx = self.argidxmap[idx-1] - if paramidx==None: - raise ValueError, "Argument was already removed" - del self.virtual_func.input_params[paramidx] - self.argidxmap[idx-1] = None - for i in range(idx,len(self.argidxmap)): - if self.argidxmap[i]!=None: - self.argidxmap[i] -= 1 - - return arg - - - # insert_arg - def insert_arg(self, idx, arg, inputexpr): - """Insert a new argument into the argument list of the wrapper function. - - This function is supposed to be called by function transformer - objects. - - @param idx: New argument index (may be negative) - @type idx: int - @param arg: New argument object - @type arg: L{argument_t<pygccxml.declarations.calldef.argument_t>} - @param inputexpr: The expression that is used as input parameter for the Python function call inside the virtual function - @type inputexpr: str - """ - if self._funcs_initialized: - raise ValueError, "insert_arg() may only be called before function initialization." - if idx==0: - pass - else: - if idx<0: - idx += len(self.wrapper_func.arg_list)+2 - - idx += self._insert_arg_idx_offset - self.wrapper_func.arg_list.insert(idx-1, arg) - - # What to insert? - self.virtual_func.input_params.insert(idx-1, inputexpr) - # Adjust the argument index map - for i in range(idx-1,len(self.argidxmap)): - if self.argidxmap[i]!=None: - self.argidxmap[i] += 1 - - # py_result_expr - def py_result_expr(self, local_wrapper_var): - """Return a C++ expression that references one particular item of the result tuple in the virtual function. - - This method is supposed to be used in the virtual_post_call() method - of function transformers when the result object of the Python call - is required. It relieves the transformer from having to check whether - its value is the only output value or not (in the former case the - value is an arbitrary Python object, in the latter case it is always - a tuple). - - For example, if a function transformer allocates a variable and - adds it to the result expressions of the wrapper function (so that - the wrapper function returns the value of this variable) then - the corresponding virtual function has to receive this value - and convert it to a C++ value. Suppose the result of invoking - the Python function inside the virtual function is stored in - the variable "pyresult" (which is of type "object"). The transformer - object that has to access its output value has to distinguish - two cases: - - - Its output value was the only output, then it references the - output value simply with "pyresult". - - There are also other output values, then it references its - output value with "pyresult[n]" where n is the position of - the output variable in the result tuple. - - To relieve the transformer from the burden of having to perform - this test, py_result_expr() can be used which generates the - appropriate expression. - - @param local_wrapper_var: The name of the local variable inside the wrapper that is part of the result tuple - @type local_wrapper_var: str - @return: The C++ expression that references the result item - @rtype: str - """ - # Get the name of the result variable - pyresult = self.virtual_func.result_var - # Determine the index of the requested local wrapper variable - try: - idx = self.wrapper_func.result_exprs.index(local_wrapper_var) - except ValueError: - raise ValueError, "The local variable '%s' is not returned by the wrapper function." - - # Return the C++ expression - if len(self.wrapper_func.result_exprs)==1: - return pyresult - else: - return "%s[%d]"%(pyresult, idx) - - # subst_virtual - def subst_virtual(self, template): - """Perform a text substitution using the "virtual" variable set. - - @return: Returns the input string that has all variables substituted. - @rtype: str - """ - if not self._funcs_initialized: - self.init_funcs() - return self.virtual_func.substitute(template) - - # subst_wrapper - def subst_wrapper(self, template): - """Perform a text substitution using the "wrapper" variable set. - - @return: Returns the input string that has all variables substituted. - @rtype: str - """ - if not self._funcs_initialized: - self.init_funcs() - return self.wrapper_func.substitute(template) - - - -# return_virtual_result_t -class return_virtual_result_t(transformer_t): - """Extract and return the result value of the virtual function. - - This is an internal code block object that is automatically appended - to the list of code blocks inside the substitution_manager_t class. - """ - - def __init__(self, function): - transformer_t.__init__(self, function) - self.result_var = "<not initialized>" - - def __str__(self): - return "ReturnVirtualResult()"%(self.idx) - - def init_funcs(self, sm): - if sm.virtual_func.ret_type==None: - return - - # Declare the local variable that will hold the return value - # for the virtual function - self.result_var = sm.virtual_func.declare_variable("result", sm.virtual_func.ret_type) - # Replace the result expression if there is still the default - # result expression (which will not work anyway) - if sm.virtual_func.result_expr==sm.virtual_func.result_var: - sm.virtual_func.result_expr = self.result_var - - def virtual_post_call(self, sm): - # Search the result tuple of the wrapper function for the return - # value of the C++ function call. If the value exists it is extracted - # from the Python result tuple, converted to C++ and returned from - # the virtual function. If it does not exist, do nothing. - try: - resexpr = sm.py_result_expr(self.result_var) - except ValueError: - return - - res = "// Extract the C++ return value\n" - res += "%s = boost::python::extract<%s>(%s);"%(self.result_var, sm.virtual_func.ret_type, resexpr) - return res Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py 2006-11-28 08:27:48 UTC (rev 760) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py 2006-11-28 14:01:48 UTC (rev 761) @@ -68,6 +68,11 @@ def __str__(self): return "output(%d)"%(self.arg_index) + def required_headers( self ): + """Returns list of header files that transformer generated code depends on.""" + return [ code_repository.convenience.file_name ] + + def __configure_non_virtual( self, controller ): #removing arg from the function wrapper definition controller.remove_wrapper_arg( self.arg.name ) @@ -88,6 +93,12 @@ assert isinstance( controller, controllers.virtual_mem_fun_controller_t ) #removing arg from the function wrapper definition controller.remove_py_arg( self.arg_index ) + tmpl = string.Template( + '$name = boost::python::extract< $type >( pyplus_conv::get_out_argument( $py_result, "$name" ) );' ) + store_py_result_in_arg = tmpl.substitute( name=self.arg.name + , type=self.arg.type.decl_string + , py_result=controller.py_result_variable.name ) + controller.add_py_post_call_code( store_py_result_in_arg ) # input_t @@ -128,6 +139,11 @@ def configure_free_fun(self, controller ): self.__configure_non_virtual( controller ) + def configure_virtual_mem_fun( self, controller ): + pass #according to boost.python documentation, it will create a copy of + #the object by itself + + # inout_t class inout_t(transformer.transformer_t): """Handles a single input/output variable. @@ -166,6 +182,14 @@ def configure_free_fun(self, controller ): self.__configure_non_virtual( controller ) + def configure_virtual_mem_fun( self, controller ): + assert isinstance( controller, controllers.virtual_mem_fun_controller_t ) + tmpl = string.Template( + '$name = boost::python::extract< $type >( pyplus_conv::get_out_argument( $py_result, "$name" ) );' ) + store_py_result_in_arg = tmpl.substitute( name=self.arg.name + , type=self.arg.type.decl_string + , py_result=controller.py_result_variable.name ) + controller.add_py_post_call_code( store_py_result_in_arg ) class input_array_t(transformer.transformer_t): """Handles an input array with fixed size. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-11-28 08:27:49
|
Revision: 760 http://svn.sourceforge.net/pygccxml/?rev=760&view=rev Author: roman_yakovenko Date: 2006-11-28 00:27:48 -0800 (Tue, 28 Nov 2006) Log Message: ----------- adding named_tuple class. It will be used for FT feature Modified Paths: -------------- pyplusplus_dev_ft/pyplusplus/code_repository/__init__.py pyplusplus_dev_ft/pyplusplus/decl_wrappers/__init__.py pyplusplus_dev_ft/pyplusplus/decl_wrappers/properties.py pyplusplus_dev_ft/pyplusplus/file_writers/writer.py pyplusplus_dev_ft/pyplusplus/module_creator/creator.py Added Paths: ----------- pyplusplus_dev_ft/pyplusplus/code_repository/named_tuple.py Modified: pyplusplus_dev_ft/pyplusplus/code_repository/__init__.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/code_repository/__init__.py 2006-11-27 21:12:53 UTC (rev 759) +++ pyplusplus_dev_ft/pyplusplus/code_repository/__init__.py 2006-11-28 08:27:48 UTC (rev 760) @@ -15,10 +15,11 @@ import array_1 import gil_guard +import named_tuple import convenience import call_policies -all = [ array_1, gil_guard, convenience, call_policies ] +all = [ array_1, gil_guard, convenience, call_policies, named_tuple ] headers = map( lambda f: f.file_name, all ) Added: pyplusplus_dev_ft/pyplusplus/code_repository/named_tuple.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/code_repository/named_tuple.py (rev 0) +++ pyplusplus_dev_ft/pyplusplus/code_repository/named_tuple.py 2006-11-28 08:27:48 UTC (rev 760) @@ -0,0 +1,65 @@ +# 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) + +file_name = "named_tuple.py" + +code = \ +"""# Copyright 2004 Roman Yakovenko. +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +class named_tuple(tuple): + \"\"\"Creates tuple, which allows access to stored values by name and by index. + + named_tuple could be constructed exactly in the same way as Python dict. + \"\"\" + + 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 __init__(self, seq=None, **keywd): + "named_tuple could be constructed exactly in the same way as Python dict." + 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 + + def __getattr__(self, name): + try: + return self.__dict__['__name2value'][ name ] + except KeyError: + raise AttributeError( "named_tuple has no attribute '%s'" % name ) + + def __setattr__(self, name, value): + raise AttributeError( "named_tuple has no attribute '%s'" % name ) + + def __getitem__( self, key ): + #TODO: it could be nice to support slicing. So the __getitem__ in case of + #slicing will return new named_tuple. + if isinstance( key, basestring ): + return self.__dict__['__name2value'][ key ] + else: + return super( named_tuple, self ).__getitem__( key ) + +if __name__ == '__main__': + 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 + +""" Modified: pyplusplus_dev_ft/pyplusplus/decl_wrappers/__init__.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/decl_wrappers/__init__.py 2006-11-27 21:12:53 UTC (rev 759) +++ pyplusplus_dev_ft/pyplusplus/decl_wrappers/__init__.py 2006-11-28 08:27:48 UTC (rev 760) @@ -149,3 +149,17 @@ def create_variable( self, *arguments, **keywords ): return variable_t(*arguments, **keywords) + +skip_messages = [ + "Py++ does not exports compiler generated constructors" + , 'Py++, by default, does not expose internal compilers declarations. Names of those declarations usually start with "__".' + , 'Py++, by default, does not expose internal declarations (those that gccxml say belong to "<internal>" header).' + , 'Py++, by default, does not expose compiler generated declarations.' + , 'Py++ can not expose private class.' + , 'Py++ will generate class wrapper - class contains definition of virtual or pure virtual member function' + , "Py++ doesn't expose private or protected member variables." + , "Py++ doesn't export private not virtual functions." + , "Py++ doesn't export private constructor." + , "Py++ doesn't export private operators." +] +#Messages kept by skip_messages list will not be reported Modified: pyplusplus_dev_ft/pyplusplus/decl_wrappers/properties.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/decl_wrappers/properties.py 2006-11-27 21:12:53 UTC (rev 759) +++ pyplusplus_dev_ft/pyplusplus/decl_wrappers/properties.py 2006-11-28 08:27:48 UTC (rev 760) @@ -106,7 +106,7 @@ , self.make_l_camel_convention ] for convention_maker in convention_makers: - for g, s in self.__prefixes: + for g, s in self.prefixes(): gc, sc = convention_maker( g, s ) if self.check_name_compatibility( gname, sname, gc, sc ): return ( gc, sc ) Modified: pyplusplus_dev_ft/pyplusplus/file_writers/writer.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/file_writers/writer.py 2006-11-27 21:12:53 UTC (rev 759) +++ pyplusplus_dev_ft/pyplusplus/file_writers/writer.py 2006-11-28 08:27:48 UTC (rev 760) @@ -50,7 +50,12 @@ 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. @@ -91,4 +96,4 @@ f.write( fcontent_new ) f.close() writer_t.logger.info( 'file "%s" - updated( %f seconds )' % ( fname, time.clock() - start_time ) ) - \ No newline at end of file + Modified: pyplusplus_dev_ft/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/module_creator/creator.py 2006-11-27 21:12:53 UTC (rev 759) +++ pyplusplus_dev_ft/pyplusplus/module_creator/creator.py 2006-11-28 08:27:48 UTC (rev 760) @@ -47,19 +47,6 @@ INDEXING_SUITE_2_MAIN_HEADER = "boost/python/suite/indexing/container_suite.hpp" -DO_NOT_REPORT_MSGS = [ - "Py++ does not exports compiler generated constructors" - , 'Py++, by default, does not expose internal compilers declarations. Names of those declarations usually start with "__".' - , 'Py++, by default, does not expose internal declarations (those that gccxml say belong to "<internal>" header).' - , 'Py++, by default, does not expose compiler generated declarations.' - , 'Py++ can not expose private class.' - , 'Py++ will generate class wrapper - class contains definition of virtual or pure virtual member function' - , "Py++ doesn't expose private or protected member variables." - , "Py++ doesn't export private not virtual functions." - , "Py++ doesn't export private constructor." - , "Py++ doesn't export private operators." -] - class creator_t( declarations.decl_visitor_t ): """Creating code creators. @@ -142,8 +129,6 @@ self.__return_pointee_value_exists = False def _prepare_decls( self, decls, doc_extractor ): - global DO_NOT_REPORT_MSGS - decls = declarations.make_flatten( decls ) for decl in decls: @@ -164,7 +149,7 @@ if doc_extractor and decl.exportable: decl.documentation = doc_extractor( decl ) - readme = filter( lambda msg: msg not in DO_NOT_REPORT_MSGS, decl.readme() ) + readme = filter( lambda msg: msg not in decl_wrappers.skip_messages, decl.readme() ) if not readme: continue This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <rom...@us...> - 2006-11-27 21:12:54
|
Revision: 759 http://svn.sourceforge.net/pygccxml/?rev=759&view=rev Author: roman_yakovenko Date: 2006-11-27 13:12:53 -0800 (Mon, 27 Nov 2006) Log Message: ----------- adding virtual mem fun controller Modified Paths: -------------- pyplusplus_dev_ft/pyplusplus/code_creators/__init__.py pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py pyplusplus_dev_ft/pyplusplus/code_creators/calldef_utils.py pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py pyplusplus_dev_ft/unittests/function_transformations_tester.py Modified: pyplusplus_dev_ft/pyplusplus/code_creators/__init__.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/code_creators/__init__.py 2006-11-27 10:23:04 UTC (rev 758) +++ pyplusplus_dev_ft/pyplusplus/code_creators/__init__.py 2006-11-27 21:12:53 UTC (rev 759) @@ -80,10 +80,9 @@ from calldef_transformed import mem_fun_transformed_wrapper_t from calldef_transformed import free_fun_transformed_t from calldef_transformed import free_fun_transformed_wrapper_t +from calldef_transformed import mem_fun_v_transformed_t +from calldef_transformed import mem_fun_v_transformed_wrapper_t -#~ from calldef_transformed import mem_fun_v_transformed_t -#~ from calldef_transformed import mem_fun_v_transformed_wrapper_t - from global_variable import global_variable_base_t from global_variable import global_variable_t from global_variable import array_gv_t Modified: pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py 2006-11-27 10:23:04 UTC (rev 758) +++ pyplusplus_dev_ft/pyplusplus/code_creators/calldef_transformed.py 2006-11-27 21:12:53 UTC (rev 759) @@ -21,7 +21,7 @@ def remove_duplicate_linesep( code ): return __REMOVE_DUPLICAET_LINESEP.sub( os.linesep, code ) -class non_virtual_fun_transformed_t( calldef_t ): +class sealed_fun_transformed_t( calldef_t ): def __init__( self, function, wrapper=None ): calldef_t.__init__( self, function=function, wrapper=wrapper ) @@ -53,12 +53,9 @@ return '&%s' % full_name def create_call_policies( self ): - if self.controller.wrapper_call_policies.is_default(): - return '' - else: - return super( non_virtual_fun_transformed_t, self ).create_call_policies() + return '' -class non_virtual_fun_transformed_wrapper_t( calldef_wrapper_t ): +class sealed_fun_transformed_wrapper_t( calldef_wrapper_t ): def __init__( self, function ): calldef_wrapper_t.__init__( self, function=function ) @@ -115,19 +112,19 @@ def _create_impl(self): answer = [ self.create_declaration(self.declaration.alias) + '{' ] - answer.append( '// Transformed wrapper function for "%s"' % self.declaration ) + answer.append( self.indent( '// Transformed wrapper function for "%s"' % self.declaration ) ) body = self.create_body() body = remove_duplicate_linesep( body ) answer.append( self.indent( body ) ) answer.append( '}' ) return os.linesep.join( answer ) -class free_fun_transformed_t( non_virtual_fun_transformed_t ): +class free_fun_transformed_t( sealed_fun_transformed_t ): """Creates code for public non-virtual member functions. """ def __init__( self, function, wrapper=None ): - non_virtual_fun_transformed_t.__init__( self, function=function, wrapper=wrapper ) + sealed_fun_transformed_t.__init__( self, function=function, wrapper=wrapper ) self.works_on_instance = False def create_def_code( self ): @@ -140,14 +137,14 @@ return arg_utils.keywords_args() -class free_fun_transformed_wrapper_t( non_virtual_fun_transformed_wrapper_t ): +class free_fun_transformed_wrapper_t( sealed_fun_transformed_wrapper_t ): def __init__( self, function ): """Constructor. @param function: Function declaration @type function: calldef_t """ - non_virtual_fun_transformed_wrapper_t .__init__( self, function=function ) + sealed_fun_transformed_wrapper_t .__init__( self, function=function ) def function_type(self): return declarations.free_function_type_t( @@ -180,11 +177,11 @@ return declarations.full_name( self.declaration ) -class mem_fun_transformed_t( non_virtual_fun_transformed_t ): +class mem_fun_transformed_t( sealed_fun_transformed_t ): """Creates code for public non-virtual member functions. """ def __init__( self, function, wrapper=None ): - non_virtual_fun_transformed_t.__init__( self, function=function, wrapper=wrapper ) + sealed_fun_transformed_t.__init__( self, function=function, wrapper=wrapper ) def create_keywords_args(self): args = self.controller.wrapper_args[:] @@ -196,14 +193,14 @@ , args ) return arg_utils.keywords_args() -class mem_fun_transformed_wrapper_t( non_virtual_fun_transformed_wrapper_t ): +class mem_fun_transformed_wrapper_t( sealed_fun_transformed_wrapper_t ): def __init__( self, function ): """Constructor. @param function: Function declaration @type function: calldef_t """ - non_virtual_fun_transformed_wrapper_t.__init__( self, function=function ) + sealed_fun_transformed_wrapper_t.__init__( self, function=function ) def __is_global( self ): return not isinstance( self.parent, class_declaration.class_wrapper_t ) @@ -247,3 +244,101 @@ return self.controller.inst_arg.name + '.' + self.declaration.name else: return declarations.full_name( self.declaration ) + +class mem_fun_v_transformed_t( calldef_t ): + def __init__( self, function, wrapper=None ): + calldef_t.__init__( self, function=function, wrapper=wrapper ) + + @property + def ft( self ): #function transformation + return self.declaration.transformations[0] + + @property + def controller( self ): + return self.ft.controller + + def _get_alias_impl( self ): + return self.wrapper.ft.alias + + def create_function_type_alias_code( self, exported_class_alias=None ): + ftype = self.wrapper.function_type() + return 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias ) + + def create_function_ref_code(self, use_function_alias=False): + full_name = self.wrapper.full_name() + + if use_function_alias: + return '%s( &%s )' \ + % ( self.function_type_alias, full_name ) + elif self.declaration.create_with_signature: + func_type = self.wrapper.function_type() + return '(%s)( &%s )' % ( func_type, full_name ) + else: + return '&%s' % full_name + + def create_call_policies( self ): + return '' + +class mem_fun_v_transformed_wrapper_t( calldef_wrapper_t ): + def __init__( self, function ): + calldef_wrapper_t.__init__( self, function=function ) + + @property + def ft( self ): #function transformation + return self.declaration.transformations[0] + + @property + def controller( self ): + return self.ft.controller + + def create_declaration(self, name): + template = 'static %(return_type)s %(name)s( %(args)s )' + + return template % { + 'return_type' : self.controller.wrapper_return_type.decl_string + , 'name' : self.wrapper_name() + , 'args' : self.args_declaration() + } + + def resolve_function_ref( self ): + raise NotImplementedError() + + def create_body(self): + cntrl = self.controller + + make_object = algorithm.create_identifier( self, 'pyplusplus::call_policies::make_object' ) + make_tuple = algorithm.create_identifier( self, 'boost::python::make_tuple' ) + + result_var_assign = '' + if not declarations.is_void( self.declaration.return_type ): + result_var_assign = '%(type)s %(name)s = ' \ + % { 'type': cntrl.result_variable.type.decl_string + , 'name' : cntrl.result_variable.name } + + return_stmt_creator = calldef_utils.return_stmt_creator_t( self + , self.controller + , self.controller.result_variable + , self.controller.return_variables ) + + post_call = os.linesep.join( cntrl.post_call ) + if return_stmt_creator.pre_return_code: + post_call = os.linesep.join( [post_call, return_stmt_creator.pre_return_code] ) + + return cntrl.template.substitute({ + 'declare_variables' : os.linesep.join( map( lambda var: var.declare_var_string(), cntrl.variables ) ) + , 'pre_call' : os.linesep.join( cntrl.pre_call ) + , 'post_call' : post_call + , 'save_result' : result_var_assign + , 'function' : self.resolve_function_ref() + , 'arg_expressions' : self.PARAM_SEPARATOR.join( cntrl.arg_expressions ) + , 'return' : return_stmt_creator.statement + }) + + def _create_impl(self): + answer = [ self.create_declaration(self.declaration.alias) + '{' ] + answer.append( self.indent( '// Transformed wrapper function for "%s"' % self.declaration ) ) + body = self.create_body() + body = remove_duplicate_linesep( body ) + answer.append( self.indent( body ) ) + answer.append( '}' ) + return os.linesep.join( answer ) Modified: pyplusplus_dev_ft/pyplusplus/code_creators/calldef_utils.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/code_creators/calldef_utils.py 2006-11-27 10:23:04 UTC (rev 758) +++ pyplusplus_dev_ft/pyplusplus/code_creators/calldef_utils.py 2006-11-27 21:12:53 UTC (rev 759) @@ -123,29 +123,31 @@ def statement( self ): if None is self.__return_stmt: stmt = '' + bpl_object = algorithm.create_identifier( self.__creator, 'boost::python::object' ) make_tuple = algorithm.create_identifier( self.__creator, 'boost::python::make_tuple' ) make_object = algorithm.create_identifier( self.__creator, 'pyplusplus::call_policies::make_object' ) - if self.__return_vars: - if not declarations.is_void( self.__function.return_type ): - if self.__function.call_policies.is_default(): - self.__return_vars.insert( 0, self.__result_var.name ) - else: - self.__return_vars.insert( 0 - , declarations.call_invocation.join( - declarations.templates.join( make_object, [self.__call_policy_alias] ) - , [self.__result_var.name] ) ) - + if not declarations.is_void( self.__function.return_type ): + if self.__function.call_policies.is_default(): + self.__return_vars.insert( 0, self.__result_var.name ) + else: + self.__return_vars.insert( 0 + , declarations.call_invocation.join( + declarations.templates.join( make_object, [self.__call_policy_alias] ) + , [self.__result_var.name] ) ) + + if 0 == len( self.__return_vars ): + pass + elif 1 == len( self.__return_vars ): + stmt = bpl_object + '( %s )' % self.__return_vars[ 0 ] + else: # 1 < stmt = declarations.call_invocation.join( make_tuple, self.__return_vars ) if self.__creator.LINE_LENGTH < len( stmt ): stmt = declarations.call_invocation.join( - make_tuple - , self.__return_vars - , os.linesep + self.__creator.indent( self.__creator.PARAM_SEPARATOR, 6 ) ) - elif not declarations.is_void( self.__function.return_type ): - stmt = self.__result_var.name - else: - pass + make_tuple + , self.__return_vars + , os.linesep + self.__creator.indent( self.__creator.PARAM_SEPARATOR, 6 ) ) + if stmt: stmt = 'return ' + stmt + ';' self.__return_stmt = stmt Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py 2006-11-27 10:23:04 UTC (rev 758) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/controllers.py 2006-11-27 21:12:53 UTC (rev 759) @@ -25,18 +25,13 @@ , name=self.name , type=self.type , initialize_expr=self.initialize_expr ) - -class controller_base_t( object ): - def __init__( self, function ): + +class variables_manager_t( object ): + def __init__( self ): object.__init__( self ) - self.__function = function self.__variables = [] #variables - self.__names_in_use = set( map( lambda arg: arg.name, self.function.arguments ) ) + self.__names_in_use = set() - @property - def function( self ): - return self.__function - @property def variables( self ): return self.__variables @@ -46,7 +41,7 @@ self.__variables.append( variable_t( type, unique_name, initialize_expr ) ) return unique_name - def register_variable_name( self, name ): + def register_name( self, name ): return self.__create_unique_var_name( name ) def __create_unique_var_name( self, name ): @@ -60,13 +55,27 @@ self.__names_in_use.add( unique_name ) return unique_name +def create_variables_manager( function ): + vm = variables_manager_t() + map( lambda arg: vm.register_name( arg.name ) , function.arguments ) + return vm + +class controller_base_t( object ): + def __init__( self, function ): + self.__function = function + + @property + def function( self ): + return self.__function + def apply( self, transformations ): raise NotImplementedError() -class non_virtual_fun_controller_t( controller_base_t ): +class sealed_fun_controller_t( controller_base_t ): #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 ) self.__wrapper_args = [ arg.clone() for arg in function.arguments ] self.__result_var = variable_t( self.function.return_type , self.register_variable_name( 'result' ) ) @@ -74,7 +83,17 @@ self.__pre_call = [] self.__post_call = [] self.__arg_expressions = [ arg.name for arg in function.arguments ] + + @property + def variables( self ): + return self.__vars_manager.variables + def declare_variable( self, type, name, initialize_expr='' ): + return self.__vars_manager.declare_variable( type, name, initialize_expr) + + def register_variable_name( self, name ): + return self.__vars_manager.register_name( name ) + @property def result_variable( self ): return self.__result_var @@ -103,26 +122,22 @@ def arg_expressions( self ): return self.__arg_expressions - def modify_argument_expression( self, index, expression ): + def modify_arg_expression( self, index, expression ): self.arg_expressions[ index ] = expression @property def wrapper_return_type( self ): - if len( self.return_variables ): + return_vars_count = len( self.return_variables ) + if not declarations.is_void( self.function.return_type ): + return_vars_count += 1 + if 0 == return_vars_count: + return self.function.return_type #return type is void + elif 1 == return_vars_count: + return declarations.dummy_type_t( 'boost::python::object' ) + else: return declarations.dummy_type_t( 'boost::python::tuple' ) - else: - return self.function.return_type - + @property - def wrapper_call_policies( self ): - #prevent recursive import - from pyplusplus import decl_wrappers - if 'boost::python::tuple' == self.wrapper_return_type.decl_string: - return decl_wrappers.default_call_policies() - else: - return self.function.call_policies - - @property def return_variables( self ): return self.__return_variables @@ -143,13 +158,9 @@ def add_post_call_code( self, code ): self.__post_call.append( code ) - def set_input_param( self, index, var_name_or_expr ): - self.__input_params[ index ] = var_name_or_expr - - -class mem_fun_controller_t( non_virtual_fun_controller_t ): +class mem_fun_controller_t( sealed_fun_controller_t ): def __init__( self, function ): - non_virtual_fun_controller_t.__init__( self, function ) + sealed_fun_controller_t.__init__( self, function ) inst_arg_type = declarations.declarated_t( self.function.parent ) if self.function.has_const: @@ -168,10 +179,67 @@ def inst_arg( self ): return self.__inst_arg -class free_fun_controller_t( non_virtual_fun_controller_t ): +class free_fun_controller_t( sealed_fun_controller_t ): def __init__( self, function ): - non_virtual_fun_controller_t.__init__( self, function ) + sealed_fun_controller_t.__init__( self, function ) def apply( self, transformations ): map( lambda t: t.configure_free_fun( self ), transformations ) + +class virtual_mem_fun_controller_t( controller_base_t ): + def __init__( self, function ): + controller_base_t.__init__( self, function ) + self.__py_vars_manager = create_variables_manager( function ) + self.__py_function_var \ + = self.__py_vars_manager.register_name( 'func_' + function.alias ) + self.__py_pre_call = [] + self.__py_post_call = [] + self.__py_result_var = variable_t( declarations.dummy_type_t( 'boost::python::object' ) + , self.register_py_variable_name( 'py_result' ) ) + + self.__py_arg_expressions = [ arg.name for arg in function.arguments ] + + @property + def py_variables( self ): + return self.__py_vars_manager.variables + + def declare_py_variable( self, type, name, initialize_expr='' ): + return self.__py_vars_manager.declare_variable( type, name, initialize_expr) + + def register_py_variable_name( self, name ): + return self.__py_vars_manager.register_name( name ) + + @property + def py_function_var( self ): + return self.__py_function_var + + @property + def py_pre_call( self ): + return self.__py_pre_call + + def add_py_pre_call_code( self, code ): + self.__py_pre_call.append( code ) + + @property + def py_post_call( self ): + return self.__py_post_call + + def add_py_post_call_code( self, code ): + self.__py_post_call.append( code ) + + @property + def py_result_variable( self ): + return self.__py_result_var + + @property + def py_arg_expressions( self ): + return filter( None, self.__py_arg_expressions ) + + def remove_py_arg( self, index ): + self.__py_arg_expressions[ index ] = None + + def modify_py_arg_expression( self, index, expression ): + self.arg_expressions[ index ] = expression + + Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py 2006-11-27 10:23:04 UTC (rev 758) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/templates.py 2006-11-27 21:12:53 UTC (rev 759) @@ -30,7 +30,7 @@ , '$return' ])) -class mem_fun_v: +class virtual_mem_fun: override_body = Template( os.linesep.join([ 'if( boost::python::override $py_function_var = this->get_override( "$function_alias" ) ){' , ' $declare_py_variables' Modified: pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py =================================================================== --- pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py 2006-11-27 10:23:04 UTC (rev 758) +++ pyplusplus_dev_ft/pyplusplus/function_transformers/transformers.py 2006-11-27 21:12:53 UTC (rev 759) @@ -74,7 +74,7 @@ #declaring new variable, which will keep result var_name = controller.declare_variable( remove_ref_or_ptr( self.arg.type ), self.arg.name ) #adding just declared variable to the original function call expression - controller.modify_argument_expression( self.arg_index, var_name ) + controller.modify_arg_expression( self.arg_index, var_name ) #adding the variable to return variables list controller.return_variable( var_name ) @@ -84,6 +84,12 @@ def configure_free_fun(self, controller ): self.__configure_non_virtual( controller ) + def configure_virtual_mem_fun( self, controller ): + assert isinstance( controller, controllers.virtual_mem_fun_controller_t ) + #removing arg from the function wrapper definition + controller.remove_py_arg( self.arg_index ) + + # input_t class input_t(transformer.transformer_t): """Handles a single input variable. @@ -216,7 +222,7 @@ controller.add_pre_call_code( seq2arr ) - controller.modify_argument_expression( self.arg_index, native_array ) + controller.modify_arg_expression( self.arg_index, native_array ) def configure_mem_fun( self, controller ): self.__configure_non_virtual( controller ) @@ -272,7 +278,7 @@ , '[%d]' % self.array_size ) #adding just declared variable to the original function call expression - controller.modify_argument_expression( self.arg_index, native_array ) + controller.modify_arg_expression( self.arg_index, native_array ) # Declare a Python list which will receive the output... pylist = controller.declare_variable( declarations.dummy_type_t( "boost::python::list" ) @@ -292,4 +298,3 @@ def configure_free_fun(self, controller ): self.__configure_non_virtual( controller ) - Modified: pyplusplus_dev_ft/unittests/function_transformations_tester.py =================================================================== --- pyplusplus_dev_ft/unittests/function_transformations_tester.py 2006-11-27 10:23:04 UTC (rev 758) +++ pyplusplus_dev_ft/unittests/function_transformations_tester.py 2006-11-27 21:12:53 UTC (rev 759) @@ -95,10 +95,10 @@ point3d = module.point3d_t() result = point3d.initialize( [ 1,2,3 ] ) self.failUnless( result== 1*2*3 and point3d.x == 1 and point3d.y==2 and point3d.z==3 ) - self.failUnless( [1,2,3] == point3d.position()[0] ) - self.failUnless( module.point3d_t.distance( point3d )[0] == math.sqrt( 1*1 + 2*2 + 3*3 ) ) + self.failUnless( [1,2,3] == point3d.position() ) + self.failUnless( module.point3d_t.distance( point3d ) == math.sqrt( 1*1 + 2*2 + 3*3 ) ) - self.failUnless( module.hello_world()[0] == "hello world!" ) + self.failUnless( module.hello_world() == "hello world!" ) #~ img = module.image_t( 2, 6) # Check a method that returns two values by reference This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |