=========
manage.py
=========

.. argparse::
    :ref: plainbox.provider_manager.get_parser_for_sphinx
    :manpage:
    :nodefault:

    This manual page documents the typical aspects of the manage.py file
    initially generated for each PlainBox provider by `plainbox startprovider`.
    It is not to be confused by `manage.py` files used by web applications
    written using the Django framework.

Working With Providers
======================

PlainBox is pretty flexible and allows developers and tests alike to work with
providers in several different ways. First of all, providers are typically
packaged into Debian packages. Such packages are installed in system-wide
locations (look at the output of ``./manage.py install --help``).

One particular file that is a part of such providers, that you don't typically
see in the source directory, is a file with the extension ``.provider``.
PlainBox looks for files like that in several places (see plainbox(1)
discussion of PROVIDERPATH). When working *on* a provider (either writing a new
provider from scratch or extending an existing provider) that would be a quite
tedious process to go through. For that you can use the ``manage.py develop``
command to create a ``.provider`` file in your
``$XDG_DATA_HOME/plainbox-providers-1/`` directory. PlainBox will automatically
pick it up and and you will be able to run jobs from it directly, without
having to reinstall.

Caveats
=======

The behavior of each management script may be different. PlainBox offers APIs
to extend or override available commands so this man page should be seen as a
spiritual intent rather than concrete behavior.

Building Provider-Specific Executables
======================================

PlainBox assists in building provider-specific executables. Those are
additional architecture-specific binary executables that can be used in job
scripts.

Typically such additional executables are written in C and built with make.  If
your provider doesn't require any sophisticated build system then all you need
to do is to create a src/ directory (alongside all the other provider
directories) and create at least the following files inside:

Makefile:
    The makefile that will build your executables. This assumes it is not
    generated (for example, with automake). It should place resulting
    executables int the *current directory*. It will be invoked from a
    different directory though, with ``make -f /path/to/Makefile``, so be aware
    of that when writing your rules. Fortunately makefiles tend to just work so
    this is not an issue in practice.
EXECUTABLES:
    This file lists all the executables (one per line) that will be built by
    the particular build system. It is used to ensure that PlainBox knows up
    front about executables built from source and to know which files to copy.
(sources):
    You obviously need to provide source files for your executables. Just add
    them alongside all the other files in the ``src/`` directory.

Once that is done, you should be able to run ``./manage.py build``. It will
attempt to identify the build system that is being used (it understands C, go
and autotools, to some extent) and then carry on to build everything as
expected.

Resulting executables will be placed in ``build/bin``. When working in
development mode (via ``manage.py develop``) that will all magically just work.
PlainBox will figure out where each executable is, coping with files both in
``build/bin`` and in ``bin/`` directories transparently. When installing
(``manage.py install``) either locally or as a part of the packaging step that
will also just work so you don't have do do anything else.

Overriding / Extending Commands
===============================

PlainBox offers a decorator that can be used to extend any of the manage.py
subcommands with additional functionality. The general syntax for extending
existing commands is (here illustrated by changes to the ``sdist`` command)::

    from plainbox.provider_manager import SourceDistributionCommand
    from plainbox.provider_manager import manage_py_extension

    @manage_py_extension
    class SourceDistributionCommandExt(SourceDistributionCommand):
        __doc__ = SourceDistributionCommand.__doc__

        def invoked(self, ns):
            super().invoked(ns)
            # Do something else as well


Note that in some cases you need to define the command name to match the
original command name (for example, the install command requires this).
Otherwise PlainBox will derive the command name from the class name which may
be not what you expected::

    from plainbox.provider_manager import InstallCommand
    from plainbox.provider_manager import manage_py_extension

    @manage_py_extension
    class InstallCommandExt(InstallCommand):
        __doc__ = InstallCommand.__doc__
        name = 'install'

Further Reading
===============

The Checkbox project comes with a number of providers that use various niche
and under-documented features. It's always good to learn from existing
examples.  Have a look at the project source directory, go to ``providers/``
and explore each provider there.
