summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorDoug Hellmann <doug.hellmann@dreamhost.com>2012-04-25 17:02:35 -0400
committerDoug Hellmann <doug.hellmann@dreamhost.com>2012-04-25 17:02:35 -0400
commit63ff2dbdd1642fb4e44139accf3207f4988e81e7 (patch)
treee183e2393a95a52d62371f93da5172a2066c46c0 /docs
parent5a4fb0dbeaee31eee61ec0b181dbaf4b4b3191f3 (diff)
downloadcliff-tablib-63ff2dbdd1642fb4e44139accf3207f4988e81e7.tar.gz
add some real documentation
Diffstat (limited to 'docs')
-rw-r--r--docs/source/classes.rst39
-rw-r--r--docs/source/demoapp.rst217
-rw-r--r--docs/source/index.rst11
-rw-r--r--docs/source/introduction.rst55
-rw-r--r--docs/source/list_commands.rst52
5 files changed, 369 insertions, 5 deletions
diff --git a/docs/source/classes.rst b/docs/source/classes.rst
new file mode 100644
index 0000000..1777590
--- /dev/null
+++ b/docs/source/classes.rst
@@ -0,0 +1,39 @@
+===============
+ Cliff Classes
+===============
+
+App
+===
+
+.. autoclass:: cliff.app.App
+ :members:
+
+CommandManager
+==============
+
+.. autoclass:: cliff.commandmanager.CommandManager
+ :members:
+
+Command
+=======
+
+.. autoclass:: cliff.command.Command
+ :members:
+
+Lister
+======
+
+.. autoclass:: cliff.lister.Lister
+ :members:
+
+Formatter
+=========
+
+.. autoclass:: cliff.formatters.base.Formatter
+ :members:
+
+ListFormatter
+=============
+
+.. autoclass:: cliff.formatters.base.ListFormatter
+ :members:
diff --git a/docs/source/demoapp.rst b/docs/source/demoapp.rst
new file mode 100644
index 0000000..98242a3
--- /dev/null
+++ b/docs/source/demoapp.rst
@@ -0,0 +1,217 @@
+========================
+ Exploring the Demo App
+========================
+
+The cliff source package includes a ``demoapp`` directory containing
+an example main program with several command plugins.
+
+Setup
+=====
+
+To install and experiment with the demo app you should create a
+virtual environment and activate it. This will make it easy to remove
+the app later, since it doesn't do anything useful and you aren't
+likely to want to hang onto it after you understand how it works.
+
+::
+
+ $ pip install virtualenv
+ $ virtualenv .venv
+ $ . .venv/bin/activate
+ (.venv)$
+
+Next, install cliff in the same environment.
+
+::
+
+ (.venv)$ python setup.py install
+
+Finally, install the demo application into the virtual environment.
+
+::
+
+ (.venv)$ cd demoapp
+ (.venv)$ python setup.py install
+
+Usage
+=====
+
+Both cliff and the demo installed, you can now run the command
+``cliffdemo``.
+
+For basic command usage instructions, run::
+
+ (.venv)$ cliffdemo -h
+
+To see a list of commands availble from the plugins, run::
+
+ (.venv)$ cliffdemo --help
+
+Run the ``simple`` command by passing its name as argument to ``cliffdemo``.
+
+::
+
+ (.venv)$ cliffdemo simple
+
+The ``simple`` command prints this output to the console:
+
+::
+
+ sending greeting
+ hi!
+
+
+To see help for an individual command, include the command name on the
+command line::
+
+ (.venv)$ cliffdemo files --help
+
+The Source
+==========
+
+The ``cliffdemo`` application is defined in a ``cliffdemo`` package
+containing several modules.
+
+main.py
+-------
+
+The main application is defined in ``main.py``:
+
+.. literalinclude:: ../../demoapp/cliffdemo/main.py
+ :linenos:
+
+The :class:`DemoApp` class inherits from :class:`App` and overrides
+:func:`__init__` to set the program description and version number. It
+also passes a :class:`CommandManager` instance configured to look for
+plugins in the ``cliff.demo`` namespace.
+
+The :func:`prepare_to_run_command` method of :class:`DemoApp` will be
+invoked after the main program arguments are parsed and the command is
+identified, but before the command is given its arguments and
+run. This hook is intended for opening connections to remote web
+services, databases, etc. using arguments passed to the main
+application.
+
+The :func:`clean_up` method of :class:`DemoApp` is invoked after the
+command runs. If the command raised an exception, the exception object
+is passed to :func:`clean_up`. Otherwise the ``err`` argument is
+``None``.
+
+The :func:`main` function defined in ``main.py`` is registered as a
+console script entry point so that :class:`DemoApp` can be run from
+the command line (see the discussion of ``setup.py`` below).
+
+simple.py
+---------
+
+Two commands are defined in ``simple.py``:
+
+.. literalinclude:: ../../demoapp/cliffdemo/simple.py
+ :linenos:
+
+:class:`Simple` demonstrates using logging to emit messages on the
+console at different verbose levels.
+
+::
+
+ (.venv)$ cliffdemo simple
+ sending greeting
+ hi!
+
+ (.venv)$ cliffdemo -v simple
+ prepare_to_run_command Simple
+ sending greeting
+ debugging
+ hi!
+ clean_up Simple
+
+ (.venv)$ cliffdemo -q simple
+ hi!
+
+:class:`Error` always raises a :class:`RuntimeError` exception when it
+is invoked, and can be used to experiment with the error handling
+features of cliff.
+
+::
+
+ (.venv)$ cliffdemo error
+ causing error
+ ERROR: this is the expected exception
+
+ (.venv)$ cliffdemo -v error
+ prepare_to_run_command Error
+ causing error
+ ERROR: this is the expected exception
+ clean_up Error
+ got an error: this is the expected exception
+
+ (.venv)$ cliffdemo --debug error
+ causing error
+ this is the expected exception
+ Traceback (most recent call last):
+ File ".../cliff/app.py", line 148, in run
+ result = cmd.run(parsed_args)
+ File ".../demoapp/cliffdemo/simple.py", line 24, in run
+ raise RuntimeError('this is the expected exception')
+ RuntimeError: this is the expected exception
+ Traceback (most recent call last):
+ File "/Users/dhellmann/Envs/cliff/bin/cliffdemo", line 9, in <module>
+ load_entry_point('cliffdemo==0.1', 'console_scripts', 'cliffdemo')()
+ File ".../demoapp/cliffdemo/main.py", line 30, in main
+ return myapp.run(argv)
+ File ".../cliff/app.py", line 148, in run
+ result = cmd.run(parsed_args)
+ File ".../demoapp/cliffdemo/simple.py", line 24, in run
+ raise RuntimeError('this is the expected exception')
+ RuntimeError: this is the expected exception
+
+.. _demoapp-list:
+
+list.py
+-------
+
+``list.py`` includes a single command derived from
+:class:`cliff.lister.Lister` which prints a list of the files in the
+current directory.
+
+.. literalinclude:: ../../demoapp/cliffdemo/list.py
+ :linenos:
+
+:class:`Files` prepares the data, and :class:`Lister` manages the
+output formatter and printing the data to the console.
+
+::
+
+ (.venv)$ cliffdemo files
+ +---------------+------+
+ | Name | Size |
+ +---------------+------+
+ | build | 136 |
+ | cliffdemo.log | 2546 |
+ | Makefile | 5569 |
+ | source | 408 |
+ +---------------+------+
+
+ (.venv)$ cliffdemo files -f csv
+ "Name","Size"
+ "build",136
+ "cliffdemo.log",2690
+ "Makefile",5569
+ "source",408
+
+setup.py
+--------
+
+The demo application is packaged using distribute_, the modern
+implementation of setuptools.
+
+.. literalinclude:: ../../demoapp/setup.py
+ :linenos:
+
+The important parts of the packaging instructions are the
+``entry_points`` settings. All of the commands are registered in the
+``cliff.demo`` namespace. Each main program should define its own
+command namespace so that it only loads the command plugins that it
+should be managing.
+
+.. _distribute: http://packages.python.org/distribute/
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 39ac06a..c52580b 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -3,14 +3,18 @@
=======================================================
cliff is a framework for building command line programs. It uses
-setuptools `entry points`_ to provide subcommands, output formatters, and
-other extensions.
+plugins to define sub-commands, output formatters, and other
+extensions.
Contents:
.. toctree::
:maxdepth: 2
+ introduction
+ demoapp
+ list_commands
+ classes
Indices and tables
@@ -19,6 +23,3 @@ Indices and tables
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
-
-.. _entry points: http://packages.python.org/distribute/setuptools.html
-
diff --git a/docs/source/introduction.rst b/docs/source/introduction.rst
new file mode 100644
index 0000000..afef2bf
--- /dev/null
+++ b/docs/source/introduction.rst
@@ -0,0 +1,55 @@
+==============
+ Introduction
+==============
+
+The cliff framework is meant to be used to create multi-level commands
+such as subversion and git, where the main program handles some basic
+argument parsing and then invokes a sub-command to do the work.
+
+Command Plugins
+===============
+
+Cliff takes advantage of Python's ability to load code dynamically to
+allow the sub-commands of a main program to be implemented, packaged,
+and distributed separately from the main program. This organization
+provides a unified view of the command for *users*, while giving
+developers the opportunity organize source code in any way they see
+fit.
+
+Cliff Objects
+=============
+
+Cliff is organized around three objects that are combined to create a
+useful command line program.
+
+The Application
+---------------
+
+An :class:`cliff.app.App` is the main program that you run from the shell
+command prompt. It is responsible for global operations that apply to
+all of the commands, such as configuring logging and setting up I/O
+streams.
+
+The CommandManager
+------------------
+
+The :class:`cliff.commandmanager.CommandManager` knows how to load
+individual command plugins. The default implementation uses
+`setuptools entry points`_ but any mechanism for loading commands can
+be used by replacing the default :class:`CommandManager` when
+instantiating an :class:`App`.
+
+The Command
+-----------
+
+The :class:`cliff.command.Command` class is where the real work
+happens. The rest of the framework is present to help the user
+discover the command plugins and invoke them, and to provide runtime
+support for those plugins. Each :class:`Command` subclass is
+responsible for taking action based on instructions from the user. It
+defines its own local argument parser (usually using argparse_) and a
+:func:`run` method that does the appropriate work.
+
+.. _setuptools entry points: http://packages.python.org/distribute/setuptools.html
+
+.. _argparse: http://docs.python.org/library/argparse.html
diff --git a/docs/source/list_commands.rst b/docs/source/list_commands.rst
new file mode 100644
index 0000000..84dfe6e
--- /dev/null
+++ b/docs/source/list_commands.rst
@@ -0,0 +1,52 @@
+===============
+ List Commands
+===============
+
+One of the most common patterns with command line programs is the need
+to print lists of data. cliff provides a base class for commands of
+this type so that they only need to prepare the data, and the user can
+choose from one of several output formatter plugins to see the list of
+data in their preferred format.
+
+Lister
+======
+
+The :class:`cliff.lister.Lister` base class API extends
+:class:`Command` to add a :func:`get_data` method. Subclasses should
+provide a :func:`get_data` implementation that returns a two member
+tuple containing a tuple with the names of the columns in the dataset
+and an iterable that will yield the data to be output. See the
+description of :ref:`the files command in the demoapp <demoapp-list>`
+for details.
+
+List Output Formatters
+======================
+
+cliff is delivered with two output formatters for list
+commands. :class:`Lister` adds a command line switch to let the user
+specify the formatter they want, so you don't have to do any extra
+work in your application.
+
+csv
+---
+
+The ``csv`` formatter produces a comma-separated-values document as
+output. CSV data can be imported into a database or spreadsheet for
+further manipulation.
+
+PrettyTable
+-----------
+
+The ``PrettyTable`` formatter uses PrettyTable_ to produce output
+formatted for human consumption.
+
+.. _PrettyTable: http://code.google.com/p/prettytable/
+
+Creating Your Own Formatter
+---------------------------
+
+If the standard formatters do not meet your needs, you can bundle
+another formatter with your program by subclassing from
+:class:`cliff.formatters.base.ListFormatter` and registering the
+plugin in the ``cliff.formatter.list`` namespace.
+