[pygccxml-commit] SF.net SVN: pygccxml: [613] pyplusplus_dev
Brought to you by:
mbaas,
roman_yakovenko
From: <rom...@us...> - 2006-10-04 01:40:24
|
Revision: 613 http://svn.sourceforge.net/pygccxml/?rev=613&view=rev Author: roman_yakovenko Date: 2006-10-02 13:45:21 -0700 (Mon, 02 Oct 2006) Log Message: ----------- adding small algorithm that will discover class properties Modified Paths: -------------- pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py pyplusplus_dev/pyplusplus/decl_wrappers/properties.py pyplusplus_dev/unittests/data/properties_to_be_exported.hpp pyplusplus_dev/unittests/properties_tester.py Modified: pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2006-10-01 19:49:39 UTC (rev 612) +++ pyplusplus_dev/pyplusplus/decl_wrappers/class_wrapper.py 2006-10-02 20:45:21 UTC (rev 613) @@ -333,6 +333,10 @@ """ self._properties.append( properties.property_t( name, fget, fset, doc ) ) + 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 ) ) Modified: pyplusplus_dev/pyplusplus/decl_wrappers/properties.py =================================================================== --- pyplusplus_dev/pyplusplus/decl_wrappers/properties.py 2006-10-01 19:49:39 UTC (rev 612) +++ pyplusplus_dev/pyplusplus/decl_wrappers/properties.py 2006-10-02 20:45:21 UTC (rev 613) @@ -43,15 +43,224 @@ desc.append( 'fset=%s' % declarations.full_name( self.fset ) ) return "property [%s]"% ''.join( desc ) -def find_properties( cls ): - """this function should return a list of possible properties for the class""" - #get* set* - #get_* set_* - #*, set* - #*, set_* - #get defined on [derived|base], set defined on [base|derived] - raise NotImplemented() +class property_recognizer_i(object): + def __init__( self ): + object.__init__( self ) + + def create_property( self, fget, fset ): + raise NotImplementedError() + def create_read_only_property( sefl, fget ): + raise NotImplementedError() + +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 check_prefix( self, name, prefix ): + if len( prefix ) >= len( name ): + return False + if not name.startswith( prefix ): + return False + return True + + def check_name_compatibility( self, gname, sname, gprefix, sprefix ): + if not self.check_prefix( gname, gprefix ): + return False + if not self.check_prefix( sname, sprefix ): + return False + if gname[ len( gprefix ): ] != sname[ len( sprefix ): ]: + return False + return True + def make_std_convention( self, gprefix, sprefix ): + convert = lambda x: x + '_' + if gprefix: + gprefix = convert( gprefix ) + return ( gprefix, convert( sprefix ) ) + + def make_u_camel_convention( self, gprefix, sprefix ): + convert = lambda x: x[0].upper() + x[1:] + if gprefix: + gprefix = convert( gprefix ) + return ( gprefix, convert( sprefix ) ) + + def make_l_camel_convention( self, gprefix, sprefix ): + convert = lambda x: x[0].lower() + x[1:] + if gprefix: + gprefix = convert( gprefix ) + return ( gprefix, convert( sprefix ) ) + + def find_out_prefixes( self, gname, sname ): + convention_makers = [ + self.make_std_convention #longest first + , self.make_u_camel_convention + , self.make_l_camel_convention ] + + for convention_maker in convention_makers: + for g, s in self.__prefixes: + gc, sc = convention_maker( g, s ) + if self.check_name_compatibility( gname, sname, gc, sc ): + return ( gc, sc ) + return None + + def find_out_ro_prefixes( self, gname ): + convention_makers = [ + self.make_std_convention #longest first + , self.make_u_camel_convention + , self.make_l_camel_convention ] + + for convention_maker in convention_makers: + for g, unused in self.__prefixes: + gc, unused = convention_maker( g, 'set' ) + if self.check_prefix( gname, gc ): + return gc + return None + + def check_type_compatibility( self, fget, fset ): + #algorithms allows "const" differences between types + t1 = fget.return_type + t2 = fset.arguments[0].type + + if declarations.is_same( t1, t2 ): + return True + elif declarations.is_pointer( t1 ) and declarations.is_pointer( t2 ): + t1 = declarations.remove_cv( declarations.remove_pointer( t1 ) ) + t2 = declarations.remove_cv( declarations.remove_pointer( t2 ) ) + return declarations.is_same( t1, t2 ) + elif declarations.is_reference( t1 ) and declarations.is_reference( t2 ): + t1 = declarations.remove_cv( declarations.remove_reference( t1 ) ) + t2 = declarations.remove_cv( declarations.remove_reference( t2 ) ) + return declarations.is_same( t1, t2 ) + else: + return False + + def create_property( self, fget, fset ): + if not self.check_type_compatibility( fget, fset ): + return None + found = self.find_out_prefixes( fget.name, fset.name ) + if not found: + return None + return property_t( fget.name[len(found[0]):], fget, fset ) + + def create_read_only_property( self, fget ): + found = self.find_out_ro_prefixes( fget.name ) + if found: + return property_t( fget.name[len(found[0]):], fget ) + else: + return None + +class properties_finder_t: + def __init__( self, cls, recognizer=None, exclude_accessors=False ): + self.cls = cls + if None is recognizer: + recognizer = name_based_recognizer_t() + self.recognizer = recognizer + self.exclude_accessors = exclude_accessors + self.getters, self.setters \ + = self.__get_accessors( cls.member_functions( recursive=False, allow_empty=True ) ) + + inherted_mem_funs = [] + for hierarchy_info in cls.recursive_bases: + if hierarchy_info.related_class.ignore: #don't scan excluded classes + continue + if 'public' != hierarchy_info.access_type: #don't scan non public hierarchy + continue + base_cls = hierarchy_info.related_class + inherted_mem_funs.extend( base_cls.member_functions( recursive=False, allow_empty=True ) ) + + self.inherited_getters, self.inherited_setters \ + = self.__get_accessors( inherted_mem_funs ) + + def __is_getter( self, mem_fun ): + if mem_fun.arguments: + return False + if declarations.is_void( mem_fun.return_type ): + return False + if not mem_fun.has_const: + return False + return True + + def __is_setter( self, mem_fun ): + if len( mem_fun.arguments ) != 1: + return False + if not declarations.is_void( mem_fun.return_type ): + return False + if mem_fun.has_const: + return False + return True + + def __get_accessors( self, mem_funs ): + getters = [] + setters = [] + for mem_fun in mem_funs: + if mem_fun.ignore: + continue + elif mem_fun.access_type != 'public': + continue + elif mem_fun.has_static: + continue #TODO: should be supported + elif mem_fun.virtuality == declarations.VIRTUALITY_TYPES.PURE_VIRTUAL: + continue + elif self.__is_getter( mem_fun ): + getters.append( mem_fun ) + elif self.__is_setter( mem_fun ): + setters.append( mem_fun ) + else: + continue + return ( getters, setters ) + + def find_properties( self, getters, setters, used_getters, used_setters ): + properties = [] + for fget in getters: + if fget in used_getters: + continue + for fset in setters: + if fset in used_setters: + continue + property_ = self.recognizer.create_property( fget, fset ) + if property_: + used_getters.add( fget ) + used_setters.add( fset ) + properties.append( property_ ) + break + return properties + + def __call__( self ): + used_getters = set() + used_setters = set() + properties = [] + #this get, this set + properties.extend( + self.find_properties( self.getters, self.setters, used_getters, used_setters ) ) + #this get, base set + properties.extend( + self.find_properties( self.getters, self.inherited_setters, used_getters, used_setters ) ) + #base get, this set + properties.extend( + self.find_properties( self.inherited_getters, self.setters, used_getters, used_setters ) ) + + for fget in self.getters: + if fget in used_getters: + continue + property_ = self.recognizer.create_read_only_property( fget ) + if property_: + used_getters.add( fget ) + properties.append( property_ ) + + if self.exclude_accessors: + map( lambda accessor: accessor.exclude(), used_getters ) + map( lambda accessor: accessor.exclude(), used_setters ) + + return properties + +def find_properties( cls, recognizer=None, exclude_accessors=False ): + pf = properties_finder_t( cls, recognizer, exclude_accessors ) + properties = pf() + return properties \ No newline at end of file Modified: pyplusplus_dev/unittests/data/properties_to_be_exported.hpp =================================================================== --- pyplusplus_dev/unittests/data/properties_to_be_exported.hpp 2006-10-01 19:49:39 UTC (rev 612) +++ pyplusplus_dev/unittests/data/properties_to_be_exported.hpp 2006-10-02 20:45:21 UTC (rev 613) @@ -24,16 +24,31 @@ void set_count( int x ) { m_count = x; } - nested& get_nested() + const nested& get_nested() const { return m_nested; } void set_nested( nested x ) { m_nested = x; } - + int m_count; nested m_nested; }; +struct properties_finder_tester_t{ + + int count() const { return 0; } + void set_count( int ){} + + int get_size() const { return 0; } + void set_size( int ){} + + int getWidth() const { return 0; } + void setWidth(int) {} + + int GetHeight() const { return 0; } + void SetHeight(int){} + +}; } Modified: pyplusplus_dev/unittests/properties_tester.py =================================================================== --- pyplusplus_dev/unittests/properties_tester.py 2006-10-01 19:49:39 UTC (rev 612) +++ pyplusplus_dev/unittests/properties_tester.py 2006-10-02 20:45:21 UTC (rev 613) @@ -33,6 +33,10 @@ cls.add_property( "nested_", get_nested, set_nested ) cls.add_property( "nested_ro", get_nested ) + + cls = mb.class_( 'properties_finder_tester_t' ) + cls.add_properties( exclude_accessors=True ) + self.failUnless( 4 == len( cls.properties ) ) def run_tests(self, module): pt = module.properties_tester_t() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |