A micro-blogging tool with multiple interfaces.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

199 lines
7.1 KiB

=========================
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.
NAMESPACE
---------
The namespace is a class variable used to identify the name of the
network. It should also be used in the config as the group name.
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.
Proxy support
-------------
Mitter supports proxies. Its value is in the configuration manager, in
the ``NetworkManager`` section, ``proxy`` value. The network manager
itself will install a urllib2 proxy handler, so you don't need to
worry about manually installing a handler yourself if you use urllib2.
NAMESPACE
---------
The namespace is a class variable used to name the interface. It's
also used in the ``--interface`` so the user can name the interfaces
they want.
PRIORITY
--------
Interface priority, as a class variable. It's used by the interface
manager to select an interface in case the user doesn't have one. The
higher this value, the higher the priority. Be sure to put interfaces
with more dependencies with higher priorities, as those should be, in
theory, more full featured.
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