aboutsummaryrefslogblamecommitdiffstats
path: root/doc/hacking.txt
blob: 941dfde1e83292b4cded127bdf38f0d1f378b99e (plain) (tree)
1
2
3
4
5
6
7
8


          
 
               
               
 
                                                      


                                                                     
 








                                                                    


                  
                  


                                                                    






                                                                      


                      
                      
 



                                                               
 
 
       
       
 
                                   
 





                                           
                                                      
                                
 
                                                                 
                                                                      
 




                                                              




                                                                                                      





                                                                                                        
 

                                                                                
 
                                                       



                                                                                                        
**********
Hacking BE
**********

Adding commands
===============

To write a plugin, you simply create a new file in the
:file:`libbe/command/` directory.  Take a look at one of the simpler
plugins (e.g. :mod:`libbe.command.remove`) for an example of how that
looks, and to start getting a feel for the libbe interface.

See :mod:`libbe.command.base` for the definition of the important
classes :class:`~libbe.command.base.Option`,
:class:`~libbe.command.base.Argument`,
:class:`~libbe.command.base.Command`,
:class:`~libbe.command.base.InputOutput`,
:class:`~libbe.command.base.StorageCallbacks`, and
:class:`~libbe.command.base.UserInterface`.  You'll be subclassing
:class:`~libbe.command.base.Command` for your command, but all those
classes will be important.


Command completion
------------------

BE implements a general framework to make it easy to support command
completion for arbitrary plugins.  In order to support this system,
any of your completable :class:`~libbe.command.base.Argument`
instances (in your command's ``.options`` or ``.args``) should be
initialized with some valid completion_callback function.  Some common
cases are defined in :mod:`libbe.command.util`.  If you need more
flexibility, see :mod:`libbe.command.list`\'s ``--sort`` option for an
example of extensions via :class:`libbe.command.util.Completer`, or
write a custom completion function from scratch.


Adding user interfaces
======================

Take a look at :mod:`libbe.ui.command_line` for an example.
Basically you'll need to setup a
:class:`~libbe.command.base.UserInterface` instance for running
commands.  More details to come after I write an HTML UI...


Testing
=======

Run any tests in your module with::

    be$ python test.py <python.module.name>

for example:

    be$ python test.py libbe.command.merge

For a definition of "any tests", see :file:`test.py`'s
``add_module_tests()`` function.

Note that you will need to run ``make`` before testing a clean BE
branch to auto-generate required files like :file:`libbe/_version.py`.


Profiling
=========

Find out which 20 calls take the most cumulative time (time of
execution + childrens' times)::

    $ python -m cProfile -o profile be [command] [args]
    $ python -c "import pstats; p=pstats.Stats('profile'); p.sort_stats('cumulative').print_stats(20)"

If you want to find out who's calling your expensive function
(e.g. :func:`libbe.util.subproc.invoke`), try::

    $ python -c "import pstats; p=pstats.Stats('profile'); p.sort_stats('cumulative').print_callers(20)"

You can also toss::

    import sys, traceback
    print >> sys.stderr, '-'*60, '\n', '\n'.join(traceback.format_stack()[-10:])

into the function itself for a depth-first caller list.

For a more top-down approach, try::

    $ python -c "import pstats; p=pstats.Stats('profile'); p.sort_stats('cumulative').print_callees(20)"