FLUMOTION STYLE GUIDE
---------------------

CODE
----

The style of all python code should honor the recommendations in the
Style Guide for Python Code [1] document.

In particular:
 - no space between the last comma and the closing parenthesis/brace in
   tuples or lists; examples:
   (1,)
   ['a', 'b',]

Other specific code guidelines:
- don't assert without having a message for the assertion

[1]: http://www.python.org/peps/pep-0008.html

ChangeLog
---------
All checkins should add an appropriate entry in the ChangeLog.
Exceptions for repository ignore files and metadata.

UI
--
- use kbit/s and Mbit/s; also note that we follow SI so these are powers of 10
- provide accelerators for controls

PUBLIC AND PRIVATE
------------------
Python is intended for consenting adults.  There is no explicit protection
mechanism for data access on objects.

As such, adults need to consent and communicate intent when programming.
If a variable/attribute/constant/method/function/... is meant to be private,
prefix it with an underscore.  This indicates that it is not part
of the public API and should not be relied on from the outside.

In contrast, if it is not prefixed with an underscore, this indicates that
it is part of the public API, and should be documented as such in the relevant
docstrings.

When in doubt, always err to making something private over public.  It's
cheaper to publicize something private than it is to privatize something public
(and usually not even possible in a stable series).

FIXME: There is a problem when something is meant to be used by subclasses of a
class, but not outside callers.  It would be great if we could make it clearly
understood when something should only be used by subclass implementations.
Possibly we should adopt something like:
- no underscore for public
- one underscore for external:private, but subclass:public
- two underscores for completely private, which corresponds to Python's
  attribute mangling behaviour.

API DOCS
--------
- We use epydoc and epydoc markup for API docs (see http://epydoc.sf.net/)

- all public methods should be documented, along with parameters and
  return values
  @param, @type, @returns, @rtype
- public instance vars should be documented
  @ivar, @type
- list @param before @type: what it actually does is more useful to know
  than the type
- align the var/param name:
  @param name:
  @type  name:
- align the content after the colons within a block
- types are "str" and "bool", not string or boolean
- separate @param from @rtype/@returns with an empty line
- .callRemote calls and similar are interfaces between processes.
  They should be documented with care, and it is good to add explain
  how they get received on the other side, linking to the receiving object
  base class
- defer_generator_method screws up the docs for public methods, leaving them
  without a docstring.  Avoid using defer_generator_method in public methods.
- defer_generator_method screws up the docs for private methods, causing
  private methods to be listed in the public API.  Avoid using
  defer_generator_method in private methods.

TESTS
-----
To be able to achieve good quality of the code, all major checkins
should also add an appropriate test in the testsuite. It's not okay
to have any tests in a non-working tests when checking in. The testsuite
should *always* run with no failing tests and ideally with no output.
This also makes it easier to refactor code.

If large changes are made over many places in the tree which can't make
the whole testsuite run, then it should be made on a separate branch and
not be merged with the main trunk before everything passes and it has been
reviewed.

Every source file should be tagged with a test case that tests the given file;
example:
# -*- Mode: Python; test-case-name: flumotion.test.test_manager_manager -*-

- If you use failIf, make sure you use the second argument to give an
  indication of what is wrong
- don't use failIf to do comparisons.  Instead, use assertEquals or
  failIfEquals

NAMING
------
- classes should be named with CapitalizedWords
- methods, functions and attributes should be named in the same style as the
  libraries on the same interface level
  e.g. GStreamer, GObject and GTK+ subclasses with underscore_method,
  but Twisted-style classes with lowerCamelCaseMethod
  When these two conflict:
  - prefer lowerCamelCaseMethod
  - prefer the outward interface you present
    (ie, if you use GStreamer internally, but present a GStreamer-agnostic
     abstraction to your users, then use the Twisted style)
  In general, Flumotion follows Twisted style: lowerCamelCaseMethod
  This goes for regular functions and variables too
- some Twisted-style methods have a special form of (action)_lowerCamelCase;
  e.g. perspective_, remote_, do_
  this also applies to tests; when testing the method formatTime, it is ok
  to write a test method called test_formatTime instead of changing it to
  testFormatTime
- Twisted coding standard:
  http://twistedmatrix.com/projects/core/documentation/howto/policy/coding-standard.html
- component properties and uiState keys should be named lowercase and
  hyphenated.

MODULES
-------
- the docstring should come before imports; otherwise it does not work

COMPONENTS
----------
- component types should always be lowercase, and consist of two
  dash-separated words.
  (FIXME: is there a need to have more than one word for the first part ?
   The last part should always be one word though)
  The first part should describe what medium or type it handles
  within the class, and distinguish from others within that class.
  e.g. firewire-producer, webcam-producer, tvcard-producer, loop-producer,
       ...
  The second part should be the class of component:
  producer, converter, consumer, muxer, encoder, bouncer, ...
- property names should always be lowercase and dash-separated.
  example: burst-on-connect, buffer-size, buffer-time
- property entries should have a full sentence describing them so
  flumotion-inspect can display this information
- directory layout:
  - components always go under flumotion/component
  - underneath that, they should go in a subdirectory according to class,
    or misc/
  - under that, they can go in files matching the first part of the type,
    or in a separate subdirectory for the component on its own

COMPONENT PROPERTIES
--------------------
- bitrate should always be in bps, and have as description
  Bitrate to encode at (in bps)
- byte properties should follow SI;
  - if you use a power of 2, use kibi, mebi, ...
  - default to using a power of 10, and kilo, mega, ...

PLUGS
-----
- component plugs should always be lowercase, and consist of two
  dash-separated words.
  The first part should describe the socket the plug goes into:
  adminaction, requestlogger, component, manager, ratecontroller, bouncer
  The second part should distinguish it from other plugs for the same socket:
  file, database, example, ...
  (this is the reverse from component naming, mostly done because not all
   socket types are verb-y)
- the socket should be named after the fully qualified class name of the Plug
  base class
- All plug class names should end in Plug
 
DEPRECATING
-----------
- all deprecated methods should be marked with a comment tag, so that they
  can later be removed; for example: # F0.8
- they should also contain a warnings.warn statement, and call through to
  the new version; for example:
	warnings.warn("Please call disconnectByFunction instead",
            DeprecationWarning, stacklevel=2)

REGISTRY
--------
- xml tags without data should be closed with a space before />

PYCHECKER
---------
Use pychecker to check for other style issues.
Run 'make pychecker' to check the whole codebase.
To check a single file the same way 'make pychecker' would, run e.g.
make pychecker PYCHECKER_WHITELIST=flumotion/common/common.py

