[pygccxml-commit] SF.net SVN: pygccxml: [165] pygccxml_dev/docs
Brought to you by:
mbaas,
roman_yakovenko
From: <rom...@us...> - 2006-05-27 11:28:21
|
Revision: 165 Author: roman_yakovenko Date: 2006-05-27 04:28:07 -0700 (Sat, 27 May 2006) ViewCVS: http://svn.sourceforge.net/pygccxml/?rev=165&view=rev Log Message: ----------- improving documentation Modified Paths: -------------- pygccxml_dev/docs/query_interface.rest pygccxml_dev/docs/www_configuration.py pygccxml_dev/pygccxml/declarations/mdecl_wrapper.py Modified: pygccxml_dev/docs/query_interface.rest =================================================================== --- pygccxml_dev/docs/query_interface.rest 2006-05-25 08:05:00 UTC (rev 164) +++ pygccxml_dev/docs/query_interface.rest 2006-05-27 11:28:07 UTC (rev 165) @@ -9,7 +9,7 @@ ------------ You parsed the source files. Now you have to do some real work with the extracted information, right? `pygccxml`_ provides very powerful and simple interface to -query about extracted declrations. +query about extracted declarations. Just an example. I want to select all member functions, that have 2 arguments. I don't care about first argument type, but I do want second argument type to be @@ -23,7 +23,7 @@ query = query & ~declarations.access_type_matcher_t( 'public' ) global_ns.member_functions( function=query, arg_types=[None, 'int &'] ) -As for me, the example I gave was too complex. In many cases you will find your +The example is complex, but still readable. In many cases you will find your self looking for one or many declarations using one or two properties of that declaration(s). For example: :: @@ -34,141 +34,243 @@ -------------- User interface --------------- - -As you already know, ``pygccxml.declarations`` packages defines next classes: +-------------- +As you already know, ``pygccxml.declarations`` package defines next classes: + * ``scopedef_t`` - base class for all classes, that can contain other declarations * ``namespace_t`` - derives from ``scopedef_t`` class, represents C++ namespace -* ``class_t`` - derives from ``scopedef_t`` class, represents C++ class/struct. +* ``class_t`` - derives from ``scopedef_t`` class, represents C++ class/struct/union. -So, the query methods defined on ``scopedef_t`` class could be used on instances -of ``class_t`` and ``namespace_t`` classes. - -I will explain the usage of ``member_function`` and ``member_functions`` methods. -The usage of other methods is very similar to them. Here is definition of those -methods: -:: - - def member_function( self, - name=None, - function=None, - return_type=None, - arg_types=None, - header_dir=None, - header_file=None, - recursive=None ) - - - def member_functions( self, - name=None, - function=None, - return_type=None, - arg_types=None, - header_dir=None, - header_file=None, - recursive=None, - allow_empty=None ) - -As you can see, from the methods arguments you can search for member function -by: - - * ``name`` - - Python string, that contains member function name or full name. - - ``do_smth = my_class.member_function( 'do_smth' )`` - ``do_smth = my_class.member_function( 'my_namespace::my_class::do_smth' )`` - - * ``function`` - - Python callable object. You would use this functionality, if you need to - build custom query. This object will be called with one argument - declaration, - and it should return ``True`` or ``False``. - - ``impls = my_class.member_functions( lambda decl: decl.name.endswith( 'impl' ) )`` - - ``impls`` will contain all member functions, that thier name ends with "impl". - - * ``return_type`` - - Function return type. This argument can be Python string or an object that - describes C++ type. - - ``mem_funcs = my_class.member_functions( return_type='int' )`` - - ``i = declarations.int_t()`` - ``ref_i = declarations.reference_t( i )`` - ``const_ref_i = declarations.const_t( ref_i )`` - ``mem_funcs = my_class.member_functions( return_type=const_ref_int )`` - - * ``arg_types`` - - Python list that contains description of member function argument types. - This list could be a mix of Python strings and objects that describes C++ - type. Size of list says how many arguments function should have. If you want - to skip some argument type from within comparison, you put ``None``, into - relevant position within the list. - - ``mem_funcs = my_class.member_functions( arg_types=[ None, 'int'] )`` - - ``mem_funcs`` will contain all member functions, that have two arguments - and type of second argument is ``int``. - - * ``header_dir`` - - Python string, that contains full path to directory, which contains file, - which contains the function declaration - - ``mem_funcs = my_namespace.member_functions( header_dir='/home/roman/xyz' )`` - - * ``header_file`` - - Python string, that contains full path to file, which contains the function - declaration. - - ``mem_funcs = my_namespace.member_functions( header_dir='/home/roman/xyz/xyz.hpp' )`` - - * ``recursive`` - - Python boolean object. - - If ``recursive`` is ``True``, then member function will be also searched - within internal declarations. - - If ``recursive`` is ``False``, then member function will be searched only - within current scope. - - What happen if ``recursive`` is ``None``? Well. ``scopedef_t`` class defines - ``RECURSIVE_DEFAULT`` variable. It's initial value is ``True``. So, if you - don't pass ``recursive`` argument, the value of ``RECURSIVE_DEFAULT`` variable - will be used. This "yet another level of indirection" allows you to configure - `pygccxml`_ "select" functions in one place for all project. - - * ``allow_empty`` - - Python boolean object, it says `pygccxml`_ what to do if query returns empty. - - If ``allow_empty`` is ``False``, then exception - ``RuntimeError( "Multi declaration query returned 0 declarations." )`` - will be raised - - ``allow_empty`` uses same tehnique as ``recursive``, to allow you to customize - the behaviour project-wise. The relevant class variable name is - ``ALLOW_EMPTY_MDECL_WRAPPER``. It's initial value is ``False``. - -Now, when you understand, how to call those functions, I will explain what they -return. - -``member_function`` will always return reference to desired declaration. If -declaration could not be found or there are more then one declaration that -match query ``RuntimeError`` exception will be raised. - - - +So, the query methods defined on ``scopedef_t`` class could be used on instances +of ``class_t`` and ``namespace_t`` classes. I am sure you knew that. + +Usage examples +-------------- + +I will explain the usage of ``member_function`` and ``member_functions`` methods. +The usage of other methods is very similar to them. Here is definition of those +methods: +:: + + def member_function( self, + name=None, + function=None, + return_type=None, + arg_types=None, + header_dir=None, + header_file=None, + recursive=None ) + + + def member_functions( self, + name=None, + function=None, + return_type=None, + arg_types=None, + header_dir=None, + header_file=None, + recursive=None, + allow_empty=None ) + +As you can see, from the methods arguments you can search for member function +by: + + * ``name`` + + Python string, that contains member function name or full name. + :: + + do_smth = my_class.member_function( 'do_smth' ) + do_smth = my_class.member_function( 'my_namespace::my_class::do_smth' ) + + * ``function`` + + Python callable object. You would use this functionality, if you need to + build custom query. This object will be called with one argument - declaration, + and it should return ``True`` or ``False``. + :: + + impls = my_class.member_functions( lambda decl: decl.name.endswith( 'impl' ) ) + + ``impls`` will contain all member functions, that their name ends with "impl". + + * ``return_type`` + + Function return type. This argument can be Python string or an object that + describes C++ type. + :: + + mem_funcs = my_class.member_functions( return_type='int' ) + + i = declarations.int_t()`` + ref_i = declarations.reference_t( i ) + const_ref_i = declarations.const_t( ref_i ) + mem_funcs = my_class.member_functions( return_type=const_ref_int ) + + * ``arg_types`` + + Python list that contains description of member function argument types. + This list could be a mix of Python strings and objects that describes C++ + type. Size of list says how many arguments function should have. If you want + to skip some argument type from within comparison, you put ``None``, into + relevant position within the list. + :: + + mem_funcs = my_class.member_functions( arg_types=[ None, 'int'] ) + + ``mem_funcs`` will contain all member functions, that have two arguments + and type of second argument is ``int``. + + * ``header_dir`` + + Python string, that contains full path to directory, which contains file, + which contains the function declaration + + ``mem_funcs = my_namespace.member_functions( header_dir='/home/roman/xyz' )`` + + * ``header_file`` + + Python string, that contains full path to file, which contains the function + declaration. + + ``mem_funcs = my_namespace.member_functions( header_dir='/home/roman/xyz/xyz.hpp' )`` + + * ``recursive`` + + Python boolean object. + + If ``recursive`` is ``True``, then member function will be also searched + within internal declarations. + + If ``recursive`` is ``False``, then member function will be searched only + within current scope. + + What happen if ``recursive`` is ``None``? Well. ``scopedef_t`` class defines + ``RECURSIVE_DEFAULT`` variable. It's initial value is ``True``. So, if you + don't pass ``recursive`` argument, the value of ``RECURSIVE_DEFAULT`` variable + will be used. This "yet another level of indirection" allows you to configure + `pygccxml`_ "select" functions in one place for all project. + + * ``allow_empty`` + + Python boolean object, it says `pygccxml`_ what to do if query returns empty. + + If ``allow_empty`` is ``False``, then exception + ``RuntimeError( "Multi declaration query returned 0 declarations." )`` + will be raised + + ``allow_empty`` uses same technique as ``recursive``, to allow you to customize + the behaviour project-wise. The relevant class variable name is + ``ALLOW_EMPTY_MDECL_WRAPPER``. It's initial value is ``False``. + +Now, when you understand, how to call those functions, I will explain what they +return. + +``member_function`` will always return reference to desired declaration. If +declaration could not be found or there are more then one declaration that +match query ``RuntimeError`` exception will be raised. + +Return value of ``member_functions`` is not Python list or set, but instance +of ``mdecl_wrapper_t`` class. This class allows you to work on all selected +objects at once. I will give an example from another project - `pyplusplus`_. +In order to help `boost.python`_ to manage objects life time, all functions +should have `call policies`_. For example: +:: + + struct A{ + A* clone() const { return new A(); } + ... + }; + + struct B{ + B* clone() const { return new B(); } + ... + }; + +`Call policies`_ of the member function ``clone`` is ``return_value_policy<manage_new_object>()``. +Next code applies `call policies`_ on all ``clone`` member functions within the +project. +:: + + #global_ns - instance of namespace_t class, that contains reference to global namespace + clone = global_ns.member_functions( 'clone' ) + clone.call_policies = return_value_policy( manage_new_object ) + + +Another example, from `pyplusplus`_ project. Sometimes it is desirable to +exclude declaration, from being exported to Python. Next code will exclude +``clone`` member function from being exported: + + ``global_ns.member_functions( 'clone' ).exclude()`` + +As you can see this class allows you to write less code. Basically using this +class you don't have to write loops. If will do it for you. Also if you insist to +write loops, ``mdecl_wrapper_t`` class implements ``__len__``, ``__getitem__`` +and ``__iter__`` methods. So you can write next code: +:: + + for clone in global_ns.member_functions( 'clone' ): + print clone.parent.name + + +---------------------- +Implementation details +---------------------- + +Performance +----------- + +For big projects, performace is critical. When you finished to build/change +declarations tree, then you can call ``scopedef_t.init_optimizer`` method. +This method will initialize few data structures, that will help to minimize the +number of compared declarations. The price you are going to pay is memory usage. + +Data structures +~~~~~~~~~~~~~~~ +Here is a short explanation of what data structures is initialized. + +* ``scopedef_t._type2decls``, ``scopedef_t._type2decls_nr`` + + Python dictionary, that contains mapping between declaration type and + declarations in the current scope. + + ``scopedef_t.type2decls_nr`` contains only declaration from the current scope. + ``scopedef_t.type2decls`` contains declarations from the current scope and its children + +* ``scopedef_t._type2name2decls``, ``scopedef_t._type2name2decls_nr`` + + Python dictionary, that contains mapping between declaration type and + another dictionary. This second dictionary contains mapping between + a declaration name and declaration. + + ``scopedef_t.type2name2decls_nr`` contains only declaration from the current scope. + ``scopedef_t.type2name2decls`` contains declarations from the current scope and its children + +* ``scopedef_t._all_decls`` + + A flat list of all declarations, including declarations from the children scopes. + +Except ``scopedef_t.decl`` and ``scopedef_t.decls`` methods, all other queries +have information about declaration type. + +If you include ``name`` into your query, you will get the best performance. + +---------------- +More information +---------------- + +I think, I gave you all important information. If you need definition of some +query method, you can take a look on API documentation or into source code. + + +.. _`boost.python`: http://boost.org/libs/python/doc/tutorial/doc/html/index.html +.. _`call policies`: http://boost.org/libs/python/doc/tutorial/doc/html/python/functions.html#python.call_policies +.. _`Call policies`: http://boost.org/libs/python/doc/tutorial/doc/html/python/functions.html#python.call_policies .. _`pygccxml`: ./pygccxml.html +.. _`pyplusplus`: ./../pyplusplus/pyplusplus.html .. _`SourceForge`: http://sourceforge.net/index.php .. _`Python`: http://www.python.org .. _`GCC-XML`: http://www.gccxml.org Modified: pygccxml_dev/docs/www_configuration.py =================================================================== --- pygccxml_dev/docs/www_configuration.py 2006-05-25 08:05:00 UTC (rev 164) +++ pygccxml_dev/docs/www_configuration.py 2006-05-27 11:28:07 UTC (rev 165) @@ -1,3 +1,3 @@ name = 'pygccxml' files_to_skip = ['definition.rest'] -names = { 'query_api' : 'query interface' } \ No newline at end of file +names = { 'query_interface' : 'query interface' } \ No newline at end of file Modified: pygccxml_dev/pygccxml/declarations/mdecl_wrapper.py =================================================================== --- pygccxml_dev/pygccxml/declarations/mdecl_wrapper.py 2006-05-25 08:05:00 UTC (rev 164) +++ pygccxml_dev/pygccxml/declarations/mdecl_wrapper.py 2006-05-27 11:28:07 UTC (rev 165) @@ -46,6 +46,9 @@ def __getitem__( self, index ): """provides access to declaration""" return self.decls[index] + + def __iter__( self ): + return iter(self.decls) def __ensure_attribute( self, name ): invalid_decls = filter( lambda d: not hasattr( d, name ), self.decls ) @@ -64,4 +67,7 @@ def __getattr__( self, name ): """@param name: name of method """ - return call_redirector_t( name, self.decls ) \ No newline at end of file + return call_redirector_t( name, self.decls ) + + def __contains__( self, item ): + return item in self.decls This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |