|
|
|
=========================
|
|
|
|
Mitter Hacking Guidelines
|
|
|
|
=========================
|
|
|
|
|
|
|
|
First of all, Mitter is a Python project and it tries to follow PEP8_
|
|
|
|
as close as possible. Sometimes we fail, but we try to adhere to it
|
|
|
|
as much as possible. The Google Guidelines_ for Python are a good
|
|
|
|
summary about it, although we don't follow all their recommendations:
|
|
|
|
|
|
|
|
- We use PyFlakes instead of Pychecker. PyFlakes seems to be better in
|
|
|
|
finding unused imports. As usual, some files don't adhere to it,
|
|
|
|
mostly helper tools (Sphinx and the helper PEP8 checker, for
|
|
|
|
example.)
|
|
|
|
- Exceptions do not start with an Error class. Each module should have
|
|
|
|
its own Exception, e.g. NetworkError and all other exceptions
|
|
|
|
should use that as base, e.g. ::
|
|
|
|
|
|
|
|
class UnreachableNetworkError(NetworkError):
|
|
|
|
|
|
|
|
- Function parameters do not need to follow the break lines pointed,
|
|
|
|
but must follow the 80 columns rule.
|
|
|
|
|
|
|
|
Also, other rules we follow:
|
|
|
|
|
|
|
|
- All string formating must have the variables in parenthesis. In this
|
|
|
|
case, this is wrong::
|
|
|
|
|
|
|
|
text = '%d characters' % count
|
|
|
|
|
|
|
|
this is right::
|
|
|
|
|
|
|
|
text = '%d characters % (count)
|
|
|
|
|
|
|
|
- Unless it's a work in progress, do not leave code commented (or,
|
|
|
|
worse yet, inside a ``if 0:`` block.) If it's a WIP, be sure to
|
|
|
|
comment what it is (e.g. "Working on issue #X" or "Trying to make
|
|
|
|
the field count properly".)
|
|
|
|
|
|
|
|
|
|
|
|
Documentation
|
|
|
|
=============
|
|
|
|
All documentation (including this file!) follows the Sphinx_ format
|
|
|
|
(ReSTructured_ format). This includes docstrings and external files.
|
|
|
|
|
|
|
|
Creating Interfaces
|
|
|
|
===================
|
|
|
|
There is a couple of things you should take care when creating your
|
|
|
|
own interface.
|
|
|
|
|
|
|
|
Naming and Location
|
|
|
|
-------------------
|
|
|
|
Your file must have the prefix "ui\_". It must be installed in the
|
|
|
|
``mitterlib/ui`` directory.
|
|
|
|
|
|
|
|
class Interface
|
|
|
|
---------------
|
|
|
|
Inside your module, there should be at least one class called
|
|
|
|
``Interface``. It may inherit any other class (or ``object`` in case
|
|
|
|
you don't need anything).
|
|
|
|
|
|
|
|
__init__(self, connection, options)
|
|
|
|
-----------------------------------
|
|
|
|
The initialization will receive two parameters:
|
|
|
|
|
|
|
|
- connection: the network connection. Your interface will request any
|
|
|
|
network data with that object. You can check the ``Networks`` object
|
|
|
|
in the ``mitterlib/network/__init__.py`` for methods there (or read
|
|
|
|
the Sphinx documentation generated about it.)
|
|
|
|
|
|
|
|
- options: It's a ConfigOpt_ object, with all your interface options.
|
|
|
|
Use it for EVERTYHING that you'd hardcode.
|
|
|
|
|
|
|
|
__call__(self)
|
|
|
|
--------------
|
|
|
|
Once Mitter have everything set up, it will call your interface.
|
|
|
|
``__call__`` is to interfaces as ``run()`` is to threads.
|
|
|
|
|
|
|
|
options(self, options)
|
|
|
|
----------------------
|
|
|
|
``options`` is a ``@classmethod`` called by Mitter on the setting up
|
|
|
|
phase to populate the interface options. To add an option, use the
|
|
|
|
``add_option``; if your interface don't have any options, simply
|
|
|
|
return. Again, refer to the ConfigOpt_ documentation on how to use it.
|
|
|
|
|
|
|
|
Creating Networks
|
|
|
|
=================
|
|
|
|
Naming and Location
|
|
|
|
-------------------
|
|
|
|
Network reside in the ``mitterlib/network`` directory. Contrary to
|
|
|
|
interfaces, it doesn't require any special prefixes.
|
|
|
|
|
|
|
|
Base Class
|
|
|
|
----------
|
|
|
|
All networks must inherit from the :class:`NetworkBase` object, in
|
|
|
|
the module ``networkbase``. There is a couple of method you should
|
|
|
|
implement in case you want it to return any data. If the network
|
|
|
|
doesn't support some functionality (e.g. reposts), simply don't
|
|
|
|
declare the function. :class:`NetworkBase` offers good defaults to
|
|
|
|
all functions (basically, returning nothing.)
|
|
|
|
|
|
|
|
class Connection
|
|
|
|
----------------
|
|
|
|
Inside your module, you should have at least once class called
|
|
|
|
``Connection``. As pointed before, it should inherit from the
|
|
|
|
:class:`NetworkBase` clas.
|
|
|
|
|
|
|
|
Base Return Object
|
|
|
|
------------------
|
|
|
|
Most functions will return a :class:`NetworkData` object. It offers
|
|
|
|
an unified data format for every interface, so they don't need to
|
|
|
|
worry about each network data. It is wise to create your own
|
|
|
|
:class:`NetworkData`, inheriting from it, with its own ``__init__``
|
|
|
|
and setting the properties.
|
|
|
|
|
|
|
|
Mixing It All
|
|
|
|
=============
|
|
|
|
|
|
|
|
Creating New Elements
|
|
|
|
---------------------
|
|
|
|
In case you want to display/add a new element on your interface, you
|
|
|
|
need to add the element in :class:`NetworkData` with a default that
|
|
|
|
represents it better (for boolean values, set it to False; strings to
|
|
|
|
''; numbers to 0 or 0.0). Once your element is there, you can add it
|
|
|
|
in the networks (do not ignore other networks that may use that
|
|
|
|
information!) and then, finally, use it on your interface.
|
|
|
|
|
|
|
|
Creating New Request
|
|
|
|
--------------------
|
|
|
|
If you want to add a new functionality in the interfaces, you need do
|
|
|
|
to a couple of steps:
|
|
|
|
|
|
|
|
- First of all, you need to add the method in the :class:`Networks`.
|
|
|
|
Remember that this is the class that the interfaces receive to do
|
|
|
|
all the other calls. If the function doesn't exist there, it won't
|
|
|
|
be call it at all.
|
|
|
|
|
|
|
|
- Once the function is available to be called, you need to make it
|
|
|
|
available to the networks. For this, add the function in
|
|
|
|
:class:`NetworkBase` module, so calling it on networks that don't
|
|
|
|
have that method defined yet will still work. In this point, it
|
|
|
|
should return some sort of empty value (empty list, None).
|
|
|
|
|
|
|
|
- Finally, add the function on your network. Follow the same name in
|
|
|
|
the :class:`NetworkBase` and you should be fine.
|
|
|
|
|
|
|
|
Developer Discussion
|
|
|
|
====================
|
|
|
|
Mitter have an open developer discussion maillist. Join us on
|
|
|
|
Mitter-Dev_ if you have any suggestions/patches/questions.
|
|
|
|
|
|
|
|
(We had a massive problem with spammers in the recent days, so the
|
|
|
|
list is currently moderated. Your first message needs to be approved
|
|
|
|
and, after that, everything should be fine.)
|
|
|
|
|
|
|
|
Souce Code Repository
|
|
|
|
=====================
|
|
|
|
Mitter uses Git for SCM and Gitorious to host it. You can check the
|
|
|
|
Mitter_ project there, clone it and hack away! ;)
|
|
|
|
|
|
|
|
|
|
|
|
.. _PEP8: http://www.python.org/dev/peps/pep-0008/
|
|
|
|
|
|
|
|
.. _Guidelines: http://google-styleguide.googlecode.com/svn/trunk/pyguide.html
|
|
|
|
|
|
|
|
.. _Sphinx: http://sphinx.pocoo.org/
|
|
|
|
|
|
|
|
.. _ReSTRuctured: http://docutils.sourceforge.net/docs/user/rst/quickref.html
|
|
|
|
|
|
|
|
.. _ConfigOpt: http://deadbraincells.org/configopt/docs/configopt.html
|
|
|
|
|
|
|
|
.. _Mitter-Dev: http://groups.google.com/group/mitter-dev/
|
|
|
|
|
|
|
|
.. _Mitter: http://gitorious.org/projects/mitter
|