In Flumotion, the illusion is created that pieces of the import space
are merged together so that all import statements for flumotion modules
"just work".

There are a number of use cases for this:
- bundles - a way of transferring code from a process to another, so that
  the second process can transparently run this code
- running uninstalled stacks:
  - consider a new user interface project that you want to run uninstalled,
    and also run against an uninstalled flumotion
    the depending project sets up everything so that its own part of the
    flumotion import space is mapped onto the existing one
  - consider a new component project that you want to run uninstalled,
    against an uninstalled flumotion
    flumotion should set up everything, based on an env var, so that this
    new project's flumotion import space is overlapped onto the existing one
- running installed-but-in-different-prefix-stacks

TERMS
-----
- module:
  - something that can be imported
  - has a __file__ attribute that points to the file this module is
    represented by
  - A/__init__.py represents the module A
    A/B/__init__.py represents the module A.B
    A/B/C/.py represents the module A.B.C
- package:
  - a module that has modules underneath itself, and is thus not an end module
  - has a __path__ attribute that is a list of paths to look for child
    modules
  - A/B/__init__.py contains the package A.B
- end module:
  - a module that is not a package; represented by a file.py
  - thus it has __file__ but not __path__
  - A/B/C.py contains the end module A.B.C

REGISTRY
--------
The registry serves two tasks:
  - list of components, and their config syntax
  - list of bundles, and files they contain

PROCEDURE
---------
- at the start of any application that needs additional projects:
  - bootstrapping is necessary to get at registerPackagePath method
    from the package module
  - so sys.path is set to point at the main flumotion location
  - registerPackagePath on the main flumotion location, either installed
    or uninstalled
  - registerPackagePath on all dirs listed in an env var, so other
    (uninstalled, or installed in different prefix) projects' import space
    is added

- when a bundle needs to be registered:
  - unpack the bundle
  - registerPackagePath for the bundle
    - if this bundle was registered before with a different packagepath:
      - remove all old paths for this bundle from everywhere
      - insert new path for this bundle everywhere relevant
      - mark the modules in this bundle as needing a rebuild.rebuild

- importhooks:
  every time a package gets imported, there's a new module loaded in python,
  which will have a __path__ attribute, set to a list with one item:
  the location where it was found first underneath its parent package.
  At that point, __path__ needs to be added to, since we could have
  project1/package/A/B/C.py
  and
  project2/package/A/B/D.py
  where import package.A will end up

PROBLEMS
--------
doing "from twisted.internet import reactor" should be done before doing
"from flumotion.common import setup; setup.setup()"

The reason is that reactor immediately del's itself from the global modules
list, and the subsequent imports it does breaks in the import code:
    from twisted.internet import reactor
  File "/usr/lib/python2.4/ihooks.py", line 409, in import_module
    self.ensure_fromlist(m, fromlist)
  File "/usr/lib/python2.4/ihooks.py", line 474, in ensure_fromlist
    submod = self.import_it(sub, subname, m)
  File "/usr/lib/python2.4/ihooks.py", line 495, in import_it
    m = self.loader.load_module(fqname, stuff)
  File "/usr/lib/python2.4/ihooks.py", line 270, in load_module
    m = self.hooks.load_source(name, filename, file)
  File "/usr/lib/python2.4/ihooks.py", line 168, in load_source
    return imp.load_source(name, filename, file)
  File "/usr/lib/python2.4/site-packages/twisted/internet/reactor.py", line 21, in ?
    from twisted.python import runtime
  File "/usr/lib/python2.4/ihooks.py", line 403, in import_module
    parent = self.determine_parent(globals)
  File "/usr/lib/python2.4/ihooks.py", line 420, in determine_parent
    if '.' in pname:
TypeError: iterable argument required

FIXME: This seems to have been a bug with gst-python
(http://bugzilla.gnome.org/show_bug.cgi?id=357310) uninstalled and pygtk, and
I'm not sure this still applies to the case mentioned above now.
I could only reproduce it without the bug fixed, and with also "import gtk"
at the top

TODO
----
- it would be very nice if any flumotion module can be run against any
  flumotion base.  Right now, running configure determines which flumotion
  you run against, making it harder to run a module against a different
  flumotion branch.
- to do this:
  - PYTHONPATH should point to core flumotion as the first directory "flumotion"
    can be imported from, always
  - this probably means we should start installing core flumotion in the
    normal python directories instead of our own tree; right now it is
    hardcoded at configure-time (that makes installed and uninstalled work
    the same way again)
  - from the original flumotion dir, we can then do
    from flumotion.common import setup; setup.setup() to trampoline the other
    project flumotion import spaces

- Some notes about sys.path:
  - whatever dir you run from, or the script that you run lives in, is
    prepended to sys.path as the first item
    - create /tmp/test.py
      import sys; print sys.path
      and run it
  - sys.path contains the usual suspects, as well as entries from .pth files
    (see gst, pygtk, ...)
  - if PYTHONPATH is set, but to an empty variable, then the cwd gets added
    after the first one, but before the usual suspects
    compared to LD_LIBRARY_PATH and similar's behaviour, this can be
    considered a bug
  - if PYTHONPATH contains leading or trailing :, this will also be seen
    as '' (empty string) and thus bring in cwd
    [thomas@otto trunk]$ PYTHONPATH=/tmp/tmp: python /tmp/test.py
['/tmp', '/tmp/tmp', '/home/thomas/flu/svn/flumotion-template/trunk', ...
  - this may be a problem; if you're in a project directory, you have
    'flumotion' in your cwd, and you want to avoid loading this one first;
    instead you want to find anything in your sys.path pointing to flumotion
    *without* cwd.
- NOTE: having PYTHONPATH end in ':' makes it import from current directory
        as well
- QUESTION: if flumotion is in system path, does PYTHONPATH take precedence ?
            this is necessary to develop/run uninstalled
  ANSWER: according to the docs, PYTHONPATH entries are prepended to sys.path
