[pygccxml-commit] SF.net SVN: pygccxml: [1372] pyplusplus_dev
Brought to you by:
mbaas,
roman_yakovenko
From: <rom...@us...> - 2008-07-14 18:58:35
|
Revision: 1372 http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1372&view=rev Author: roman_yakovenko Date: 2008-07-14 11:58:40 -0700 (Mon, 14 Jul 2008) Log Message: ----------- adding ablity to generate class wrapper destructor Modified Paths: -------------- pyplusplus_dev/pyplusplus/code_creators/__init__.py pyplusplus_dev/pyplusplus/code_creators/calldef.py pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py pyplusplus_dev/pyplusplus/messages/warnings_.py pyplusplus_dev/pyplusplus/module_creator/creator.py pyplusplus_dev/unittests/transfer_ownership_tester.py Modified: pyplusplus_dev/pyplusplus/code_creators/__init__.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/__init__.py 2008-07-14 18:14:53 UTC (rev 1371) +++ pyplusplus_dev/pyplusplus/code_creators/__init__.py 2008-07-14 18:58:40 UTC (rev 1372) @@ -68,6 +68,7 @@ from calldef import casting_operator_t from calldef import mem_fun_overloads_t from calldef import free_fun_overloads_t +from calldef import destructor_wrapper_t from calldef import casting_constructor_t from calldef import constructor_wrapper_t from calldef import mem_fun_overloads_class_t Modified: pyplusplus_dev/pyplusplus/code_creators/calldef.py =================================================================== --- pyplusplus_dev/pyplusplus/code_creators/calldef.py 2008-07-14 18:14:53 UTC (rev 1371) +++ pyplusplus_dev/pyplusplus/code_creators/calldef.py 2008-07-14 18:58:40 UTC (rev 1372) @@ -1157,7 +1157,25 @@ def _get_system_headers_impl( self ): return [] +class destructor_wrapper_t( code_creator.code_creator_t + , declaration_based.declaration_based_t ): + """ + Creates class wrapper destructor from the code provided by the user + """ + def __init__( self, class_ ): + code_creator.code_creator_t.__init__( self ) + declaration_based.declaration_based_t.__init__( self, declaration=class_ ) + def _create_impl(self): + answer = [ 'virtual ~%s(){' % self.declaration.wrapper_alias ] + answer.append( self.indent( os.linesep.join( self.declaration.destructor_code ) ) ) + answer.append( '}' ) + return os.linesep.join( answer ) + + def _get_system_headers_impl( self ): + return [] + + class calldef_overloads_class_t( code_creator.code_creator_t ): def __init__( self, functions ): #precondition: all member functions belong to same class and Modified: pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2008-07-14 18:14:53 UTC (rev 1371) +++ pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2008-07-14 18:58:40 UTC (rev 1372) @@ -76,8 +76,8 @@ @property def indexing_suite( self ): - """reference to indexing suite configuration class. - + """reference to indexing suite configuration class. + If the class is not STD container, this property will contain None" """ if self._indexing_suite is None: @@ -105,7 +105,7 @@ else: self._always_expose_using_scope = False return self._always_expose_using_scope - + def _set_always_expose_using_scope( self, value ): self._always_expose_using_scope = value always_expose_using_scope = property( _get_always_expose_using_scope, _set_always_expose_using_scope @@ -134,12 +134,12 @@ less_than_comparable = property( _get_less_than_comparable, _set_less_than_comparable , doc="indicates existence of public operator<. " \ +"Default value is calculated, based on information presented in the declarations tree" ) - + def _get_opaque( self ): return self._opaque def _set_opaque( self, value ): - self._opaque = value + self._opaque = value self.ignore = value #don't expose opaque type opaque = property( _get_opaque, _set_opaque @@ -163,12 +163,12 @@ class class_t( class_common_details_t , scopedef_wrapper.scopedef_t , declarations.class_t): - + class EXPOSED_CLASS_TYPE: DECLARED = 'declared' WRAPPER = 'wrapper' ALL = ( DECLARED, WRAPPER ) - + def __init__(self, *arguments, **keywords): class_common_details_t.__init__( self ) declarations.class_t.__init__(self, *arguments, **keywords ) @@ -177,19 +177,20 @@ self._redefine_operators = False self._held_type = None self._noncopyable = None - self._wrapper_alias = None + self._wrapper_alias = None self._registration_code_head = [] self._registration_code_tail = [] self._declaration_code = [] self._wrapper_code = [] self._null_constructor_body = '' self._copy_constructor_body = '' + self._destructor_code = [] self._exception_translation_code = None self._properties = [] self._redefined_funcs = None self._require_self_reference = False self._exposed_class_type = self.EXPOSED_CLASS_TYPE.DECLARED - + def _get_redefine_operators( self ): return self._redefine_operators def _set_redefine_operators( self, new_value ): @@ -288,6 +289,15 @@ , doc="copy constructor code, that will be added as is to the copy constructor of class-wrapper") @property + def destructor_code(self): + """list of code to be added to wrapper destructor""" + return self._destructor_code + + def add_destructor_code(self, code): + """adds code to the class-wrapper destructor""" + self._destructor_code.append( code ) + + @property def exception_argument_name( self ): """exception argument name for translate exception function @@ -341,7 +351,7 @@ self.registration_code_tail.append( user_text.class_user_text_t( code, works_on_instance ) ) else: self.registration_code_head.append( user_text.class_user_text_t( code, works_on_instance ) ) - + #preserving backward computability add_code = add_registration_code @@ -385,7 +395,7 @@ vfunction_selector = lambda member: isinstance( member, declarations.member_function_t ) \ and member.virtuality == declarations.VIRTUALITY_TYPES.PURE_VIRTUAL members.extend( filter( vfunction_selector, self.private_members ) ) - + def is_exportable( decl ): #filter out non-public member operators - Py++ does not support them right now if isinstance( decl, declarations.member_operator_t ) \ @@ -396,7 +406,7 @@ return False if decl.ignore == True or decl.exportable == False: return False - return True + return True #-#if declarations.has_destructor( self ) \ #-# and not declarations.has_public_destructor( self ): members = filter( is_exportable, members ) @@ -425,7 +435,7 @@ def add_properties( self, recognizer=None, exclude_accessors=False ): props = properties.find_properties( self, recognizer, exclude_accessors ) self.properties.extend( props ) - + def add_static_property( self, name, fget, fset=None, doc='' ): """adds new static property to the class""" self._properties.append( properties.property_t( name, fget, fset, doc, True ) ) @@ -456,14 +466,14 @@ all_included = declarations.custom_matcher_t( lambda decl: decl.ignore == False and decl.exportable ) all_protected = declarations.access_type_matcher_t( 'protected' ) & all_included - all_pure_virtual = declarations.virtuality_type_matcher_t( VIRTUALITY_TYPES.PURE_VIRTUAL ) + all_pure_virtual = declarations.virtuality_type_matcher_t( VIRTUALITY_TYPES.PURE_VIRTUAL ) all_virtual = declarations.virtuality_type_matcher_t( VIRTUALITY_TYPES.VIRTUAL ) \ & ( declarations.access_type_matcher_t( 'public' ) \ - | declarations.access_type_matcher_t( 'protected' )) + | declarations.access_type_matcher_t( 'protected' )) all_not_pure_virtual = ~all_pure_virtual - query = all_protected | all_pure_virtual - mf_query = query | all_virtual + query = all_protected | all_pure_virtual + mf_query = query | all_virtual relevant_opers = declarations.custom_matcher_t( lambda decl: decl.symbol in ('()', '[]') ) funcs = [] defined_funcs = [] @@ -493,7 +503,7 @@ if declarations.is_base_and_derived( f_impl.parent, f.parent ): #add function from the most derived class not_reimplemented_funcs.remove( f_impl ) - not_reimplemented_funcs.add( f ) + not_reimplemented_funcs.add( f ) break else: #should test whether this function is implemented in base class @@ -504,18 +514,18 @@ if is_same_function( f, f_defined ): break else: - not_reimplemented_funcs.add( f ) + not_reimplemented_funcs.add( f ) functions = filter( lambda f: ( False == f.ignore and True == f.exportable ) or all_pure_virtual( f ) , list( not_reimplemented_funcs ) ) - + #Boost.Python is not able to call for non-virtual function, from the base #class if there is a virtual function with the same within base class #See override_bug tester for more information def buggy_bpl_filter( f ): - if f.parent is self: + if f.parent is self: return False if f.access_type != ACCESS_TYPES.PUBLIC: return False @@ -564,6 +574,9 @@ if self.copy_constructor_body: explanation.append( messages.W1022 ) + if self.destructor_code: + explanation.append( messages.W1055 ) + redefined_funcs = self.redefined_funcs() if redefined_funcs: funcs = map( lambda f: f.name, redefined_funcs ) @@ -607,7 +620,7 @@ #MSVC 7.1 has problem with taking reference to operator= if self.member_operators( is_assign, allow_empty=True, recursive=False ): return impl_details.GUESS_VALUES.ALWAYS_TRUE - return super(class_t, self).guess_always_expose_using_scope_value() + return super(class_t, self).guess_always_expose_using_scope_value() def _get_require_self_reference(self): return self._require_self_reference Modified: pyplusplus_dev/pyplusplus/messages/warnings_.py =================================================================== --- pyplusplus_dev/pyplusplus/messages/warnings_.py 2008-07-14 18:14:53 UTC (rev 1371) +++ pyplusplus_dev/pyplusplus/messages/warnings_.py 2008-07-14 18:58:40 UTC (rev 1372) @@ -3,7 +3,7 @@ # 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 +"""This package defines all user messages (warnings + errors), which will be reported to user. """ @@ -11,13 +11,13 @@ """implementation details""" def __new__(self, value, identifier=None): return str.__new__(self, value ) - + def __init__(self, value, identifier=None): - self.__identifier = identifier - + self.__identifier = identifier + @property def identifier( self ): - return self.__identifier + return self.__identifier def __mod__( self, values ): str_value = super( message_type, self ).__str__() @@ -34,55 +34,55 @@ W0000 = warning( '%s' ) #general message, usefull in few cases -W1000 = compilation_error( +W1000 = compilation_error( 'Py++, by default, does not expose internal compilers declarations. ' 'Names of those declarations usually start with "__".' ) -W1001 = compilation_error( +W1001 = compilation_error( 'Py++, by default, does not expose internal declarations. ' 'GCC-XML reports that these declaration belong to "<internal>" header.' ) -W1002 = compilation_error( +W1002 = compilation_error( 'Py++, by default, does not expose compiler generated declarations.' ) -W1003 = warning( - 'Virtual functions that returns const reference cannot be overridden 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 ' +W1003 = warning( + 'Virtual functions that returns const reference cannot be overridden 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 = compilation_error( - 'Boost.Python library can not expose function, which takes as argument/returns ' - 'pointer to function. ' +W1004 = compilation_error( + '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 = compilation_error( - 'Py++ cannot expose function that takes as argument/returns instance of non-public class. ' +W1005 = compilation_error( + 'Py++ cannot expose function that takes as argument/returns instance of non-public class. ' 'Generated code will not compile.' ) -W1006 = compilation_error( +W1006 = compilation_error( '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 = warning( - 'The function has more than %d arguments ( %d ). ' - 'You should adjust BOOST_PYTHON_MAX_ARITY macro. ' +W1007 = warning( + '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 = warning( - 'The function returns non-const reference to "Python immutable" type. ' +W1008 = warning( + 'The function returns non-const reference to "Python immutable" type. ' 'The value cannot be modified from Python. ' ) -W1009 = execution_error( - 'The function takes as argument (name=%s, pos=%d) non-const reference ' - 'to Python immutable type - function could not be called from Python. ' +W1009 = execution_error( + '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 = execution_error( - '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 ' + '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 = warning( "Py++ doesn't export private not virtual functions." ) @@ -91,14 +91,14 @@ W1013 = compilation_error( "Py++ doesn't export private constructor." ) -W1014 = compilation_error( +W1014 = compilation_error( '"%s" is not supported. ' 'See Boost.Python documentation: http://www.boost.org/libs/python/doc/v2/operators.html#introduction.' ) W1015 = compilation_error( "Py++ doesn't export private operators." ) -W1016 = warning( - 'Py++ does not exports non-const casting operators with user defined type as return value. ' +W1016 = warning( + 'Py++ does not exports non-const casting operators with user defined type as return value. ' 'This could be change in future.' ) W1017 = compilation_error( "Py++ doesn't export non-public casting operators." ) @@ -113,7 +113,7 @@ W1022 = warning( "Py++ will generate class wrapper - hand written code should be added to the wrapper class copy constructor body" ) -W1023 = warning( +W1023 = warning( "Py++ will generate class wrapper - there are few functions that should be redefined in class wrapper. " "The functions are: %s." ) @@ -133,10 +133,10 @@ W1031 = warning( 'Py++ will generate class wrapper - user asked to expose non - public member function "%s"' ) -W1032 = execution_error( - "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 . " +W1032 = execution_error( + "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 = compilation_error( "Py++ can not expose unnamed variables" ) @@ -147,21 +147,21 @@ W1036 = compilation_error( "Py++ can not expose pointer to Python immutable member variables. This could be changed in future." ) -W1037 = compilation_error( - "Boost.Python library can not expose variables, which are pointer to function." +W1037 = compilation_error( + "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 = compilation_error( "Py++ can not expose variables of with unnamed type." ) W1039 = compilation_error( "Py++ doesn't expose private or protected member variables." ) -W1040 = execution_error( +W1040 = execution_error( 'The declaration is unexposed, but there are other declarations, which refer to it. ' - 'This could cause "no to_python converter found" run time error. ' + 'This could cause "no to_python converter found" run time error. ' 'Declarations: %s' ) -W1041 = warning( - 'Property "%s" could not be created. There is another exposed declaration with the same name( alias )." ' +W1041 = warning( + 'Property "%s" could not be created. There is another exposed declaration with the same name( alias )." ' 'The property will make it inaccessible.' ) W1042 = warning( @@ -175,15 +175,15 @@ W1044 = warning( 'Py++ created an ugly alias ("%s") for function wrapper.' ) -W1045 = compilation_error( +W1045 = compilation_error( 'Py++ does not expose static arrays with unknown size. ' 'You can fix this by setting array size to the actual one.' 'For more information see "array_t" class documentation.' ) -W1046 = warning( - 'The virtual function was declared with empty throw. ' - 'Adding the ability to override the function from Python breaks the exception specification. ' - 'The function wrapper can throw any exception. ' +W1046 = warning( + 'The virtual function was declared with empty throw. ' + 'Adding the ability to override the function from Python breaks the exception specification. ' + 'The function wrapper can throw any exception. ' 'In case of exception in run-time, the behaviour of the program is undefined! ' ) W1047 = warning( @@ -192,32 +192,34 @@ 'of the classes will not be exposed to Python.' 'Other classes : %s' ) -W1048 = warning( +W1048 = warning( 'There are two or more aliases within "pyplusplus::aliases" namespace for ' 'the class. Py++ selected "%s" as class alias. Other aliases: %s' ) -W1049 = warning( - 'This method could not be overriden in Python - method returns reference ' +W1049 = warning( + 'This method could not be overriden in Python - method returns reference ' 'to local variable!' ) W1050 = compilation_error( - 'The function returns "%s" type. You have to specify a call policies.' - 'Be sure to take a look on Py++ defined call policies: ' + 'The function returns "%s" type. You have to specify a call policies.' + 'Be sure to take a look on Py++ defined call policies: ' 'http://language-binding.net/pyplusplus/documentation/functions/call_policies.html#py-defined-call-policies' ) -W1051 = warning( +W1051 = warning( 'The function takes as argument (name=%s, pos=%d) "%s" type. ' 'You have to specify a call policies or to use "Function Transformation" ' 'functionality.' ) -W1052 = warning( +W1052 = warning( 'Py++ will not expose free operator "%s" - all classes, this operator works on, are excluded.' ) -W1053 = warning( +W1053 = warning( 'Py++ will not expose function "%s" - the function has variable-argument list, spicified by ellipsis (...).' ) W1054 = compilation_error( 'Py++ can not expose unions.' ) +W1055 = warning( "Py++ will generate class wrapper - hand written code should be added to the wrapper class destructor body" ) + warnings = globals() all_warning_msgs = [] @@ -230,13 +232,13 @@ try: int( identifier[1:] ) except: - continue - msg = '%s %s: %s' % ( explanation.__class__.prefix, identifier, str(explanation) ) + continue + msg = '%s %s: %s' % ( explanation.__class__.prefix, identifier, str(explanation) ) msg_inst = explanation.__class__( msg, identifier ) globals()[ identifier ] = msg_inst all_warning_msgs.append( msg_inst ) - + del warnings del identifier del explanation Modified: pyplusplus_dev/pyplusplus/module_creator/creator.py =================================================================== --- pyplusplus_dev/pyplusplus/module_creator/creator.py 2008-07-14 18:14:53 UTC (rev 1371) +++ pyplusplus_dev/pyplusplus/module_creator/creator.py 2008-07-14 18:58:40 UTC (rev 1372) @@ -624,6 +624,10 @@ for property_def in cls_decl.properties: cls_cc.adopt_creator( code_creators.property_t(property_def) ) + if wrapper and cls_decl.destructor_code: + destructor = code_creators.destructor_wrapper_t( class_=cls_decl ) + wrapper.adopt_creator( destructor ) + self.curr_decl = cls_decl self.curr_code_creator = cls_parent_cc Modified: pyplusplus_dev/unittests/transfer_ownership_tester.py =================================================================== --- pyplusplus_dev/unittests/transfer_ownership_tester.py 2008-07-14 18:14:53 UTC (rev 1371) +++ pyplusplus_dev/unittests/transfer_ownership_tester.py 2008-07-14 18:58:40 UTC (rev 1372) @@ -12,14 +12,10 @@ from pyplusplus.module_builder import call_policies decref_code = \ -""" - virtual ~%(cls)s(){ - if (this->m_pyobj) { - //Py_DECREF(this->m_pyobj); - this->m_pyobj = 0; - } - } -""" +"""if (this->m_pyobj) { + //Py_DECREF(this->m_pyobj); + this->m_pyobj = 0; +}""" incref_code = \ """ @@ -36,9 +32,9 @@ class tester_t(fundamental_tester_base.fundamental_tester_base_t): EXTENSION_NAME = 'transfer_ownership' - + def __init__( self, *args ): - fundamental_tester_base.fundamental_tester_base_t.__init__( + fundamental_tester_base.fundamental_tester_base_t.__init__( self , tester_t.EXTENSION_NAME , *args ) @@ -46,12 +42,12 @@ def customize( self, mb ): event_clss = mb.classes( lambda cls: cls.name in ( 'event_t', 'do_nothing_t' ) ) for cls in event_clss: - cls.add_wrapper_code( decref_code % { 'cls' : cls.wrapper_alias } ) + cls.add_destructor_code( decref_code ) cls.add_wrapper_code( 'PyObject* m_pyobj;' ) cls.set_constructors_body( 'm_pyobj=0;' ) cls.mem_fun( 'notify' ).add_override_precall_code( incref_code ) cls.mem_fun( 'notify' ).add_default_precall_code( incref_code ) - + cls.held_type = 'std::auto_ptr< %s >' % cls.wrapper_alias cls.add_registration_code( impl_conv_code % { 'from' : cls.wrapper_alias , 'to' : cls.decl_string } @@ -62,7 +58,7 @@ impl_conv_code % { 'from' : cls.decl_string , 'to' : base.related_class.decl_string } , False) - + cls.add_registration_code( #from wrapper to clas base class impl_conv_code % { 'from' : cls.wrapper_alias , 'to' : base.related_class.decl_string } @@ -73,16 +69,16 @@ simulator = mb.class_( 'simulator_t' ) simulator.mem_fun( 'get_event' ).call_policies \ = call_policies.return_internal_reference() - + def run_tests( self, module): class py_event_t( module.event_t ): def __init__( self, container ): module.event_t.__init__( self ) self.container = container - + def notify( self ): self.container.append( 1 ) - + print '1' notify_data = [] simulator = module.simulator_t() @@ -97,9 +93,9 @@ simulator.run() print '6' self.failUnless( notify_data[0] == 1 ) - + def create_suite(): - suite = unittest.TestSuite() + suite = unittest.TestSuite() suite.addTest( unittest.makeSuite(tester_t)) return suite This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |