summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoug Hellmann <doug.hellmann@dreamhost.com>2012-04-28 19:11:25 -0400
committerDoug Hellmann <doug.hellmann@dreamhost.com>2012-04-28 19:37:49 -0400
commitab200eb50513f5bf900cc066bd59ad964b0ab86e (patch)
treedf3f9073f94f2bd17e1e8fa41a149762e7ef3b6b
parent0fba7287795eba5a1d7bd6e5d30ef6ce0e91efdb (diff)
downloadcliff-tablib-ab200eb50513f5bf900cc066bd59ad964b0ab86e.tar.gz
documentation improvements
-rw-r--r--cliff/app.py46
-rw-r--r--cliff/command.py3
-rw-r--r--cliff/commandmanager.py4
-rw-r--r--cliff/interactive.py23
-rw-r--r--docs/source/classes.rst6
-rw-r--r--docs/source/demoapp.rst16
-rw-r--r--docs/source/history.rst2
-rw-r--r--docs/source/index.rst3
-rw-r--r--docs/source/interactive_mode.rst94
-rw-r--r--docs/source/introduction.rst11
10 files changed, 189 insertions, 19 deletions
diff --git a/cliff/app.py b/cliff/app.py
index bd42477..6b1a851 100644
--- a/cliff/app.py
+++ b/cliff/app.py
@@ -15,6 +15,21 @@ LOG = logging.getLogger(__name__)
class App(object):
"""Application base class.
+
+ :param description: one-liner explaining the program purpose
+ :paramtype description: str
+ :param version: application version number
+ :paramtype version: str
+ :param command_manager: plugin loader
+ :paramtype command_manager: cliff.commandmanager.CommandManager
+ :param stdin: Standard input stream
+ :paramtype stdin: readable I/O stream
+ :param stdout: Standard output stream
+ :paramtype stdout: writable I/O stream
+ :param stderr: Standard error output stream
+ :paramtype stderr: writable I/O stream
+ :param interactive_app_factory: callable to create an interactive application
+ :paramtype interactive_app_factory: cliff.interactive.InteractiveApp
"""
NAME = os.path.splitext(os.path.basename(sys.argv[0]))[0]
@@ -24,21 +39,16 @@ class App(object):
DEFAULT_VERBOSE_LEVEL = 1
def __init__(self, description, version, command_manager,
- stdin=None, stdout=None, stderr=None):
+ stdin=None, stdout=None, stderr=None,
+ interactive_app_factory=InteractiveApp):
"""Initialize the application.
-
- :param description: One liner explaining the program purpose
- :param version: String containing the application version number
- :param command_manager: A CommandManager instance
- :param stdin: Standard input stream
- :param stdout: Standard output stream
- :param stderr: Standard error output stream
"""
self.command_manager = command_manager
self.command_manager.add_command('help', HelpCommand)
self.stdin = stdin or sys.stdin
self.stdout = stdout or sys.stdout
self.stderr = stderr or sys.stderr
+ self.interactive_app_factory = interactive_app_factory
self.parser = self.build_option_parser(description, version)
self.interactive_mode = False
@@ -47,6 +57,11 @@ class App(object):
Subclasses may override this method to extend
the parser with more global options.
+
+ :param description: full description of the application
+ :paramtype description: str
+ :param version: version number for the application
+ :paramtype version: str
"""
parser = argparse.ArgumentParser(
description=description,
@@ -116,6 +131,9 @@ class App(object):
def run(self, argv):
"""Equivalent to the main program for the application.
+
+ :param argv: input arguments and options
+ :paramtype argv: list of str
"""
self.options, remainder = self.parser.parse_known_args(argv)
self.configure_logging()
@@ -138,17 +156,27 @@ class App(object):
def prepare_to_run_command(self, cmd):
"""Perform any preliminary work needed to run a command.
+
+ :param cmd: command processor being invoked
+ :paramtype cmd: cliff.command.Command
"""
return
def clean_up(self, cmd, result, err):
"""Hook run after a command is done to shutdown the app.
+
+ :param cmd: command processor being invoked
+ :paramtype cmd: cliff.command.Command
+ :param result: return value of cmd
+ :paramtype result: int
+ :param err: exception or None
+ :paramtype err: Exception
"""
return
def interact(self):
self.interactive_mode = True
- interpreter = InteractiveApp(self, self.command_manager, self.stdin, self.stdout)
+ interpreter = self.interactive_app_factory(self, self.command_manager, self.stdin, self.stdout)
interpreter.prompt = '(%s) ' % self.NAME
interpreter.cmdloop()
return 0
diff --git a/cliff/command.py b/cliff/command.py
index 94c8e8e..7ff526e 100644
--- a/cliff/command.py
+++ b/cliff/command.py
@@ -6,6 +6,9 @@ import inspect
class Command(object):
"""Base class for command plugins.
+
+ :param app: Application instance invoking the command.
+ :paramtype app: cliff.app.App
"""
__metaclass__ = abc.ABCMeta
diff --git a/cliff/commandmanager.py b/cliff/commandmanager.py
index bb8bfe2..135714a 100644
--- a/cliff/commandmanager.py
+++ b/cliff/commandmanager.py
@@ -23,6 +23,10 @@ class EntryPointWrapper(object):
class CommandManager(object):
"""Discovers commands and handles lookup based on argv data.
+
+ :param namespace: String containing the setuptools entrypoint namespace
+ for the plugins to be loaded. For example,
+ ``'cliff.formatter.list'``.
"""
def __init__(self, namespace):
self.commands = {}
diff --git a/cliff/interactive.py b/cliff/interactive.py
index 33aefc6..493235c 100644
--- a/cliff/interactive.py
+++ b/cliff/interactive.py
@@ -12,6 +12,20 @@ LOG = logging.getLogger(__name__)
class InteractiveApp(cmd2.Cmd):
+ """Provides "interactive mode" features.
+
+ Refer to the cmd2_ and cmd_ documentation for details
+ about subclassing and configuring this class.
+
+ .. _cmd2: http://packages.python.org/cmd2/index.html
+ .. _cmd: http://docs.python.org/library/cmd.html
+
+ :param parent_app: The calling application (expected to be derived
+ from :class:`cliff.main.App`).
+ :param command_manager: A :class:`cliff.commandmanager.CommandManager` instance.
+ :param stdin: Standard input stream
+ :param stdout: Standard output stream
+ """
use_rawinput = True
doc_header = "Shell commands (type help <topic>):"
@@ -32,10 +46,8 @@ class InteractiveApp(cmd2.Cmd):
self.parent_app.run_subcommand(line_parts)
def completedefault(self, text, line, begidx, endidx):
- """Tab-completion for commands known to the command manager.
-
- Does not handle options on the commands.
- """
+ # Tab-completion for commands known to the command manager.
+ # Does not handle options on the commands.
if not text:
completions = sorted(n for n, v in self.command_manager)
else:
@@ -75,6 +87,9 @@ class InteractiveApp(cmd2.Cmd):
return
def get_names(self):
+ # Override the base class version to filter out
+ # things that look like they should be hidden
+ # from the user.
return [n
for n in cmd2.Cmd.get_names(self)
if not n.startswith('do__')
diff --git a/docs/source/classes.rst b/docs/source/classes.rst
index a1cadbb..65abd4e 100644
--- a/docs/source/classes.rst
+++ b/docs/source/classes.rst
@@ -8,6 +8,12 @@ App
.. autoclass:: cliff.app.App
:members:
+InteractiveApp
+==============
+
+.. autoclass:: cliff.interactive.InteractiveApp
+ :members:
+
CommandManager
==============
diff --git a/docs/source/demoapp.rst b/docs/source/demoapp.rst
index 1832077..84ca5d3 100644
--- a/docs/source/demoapp.rst
+++ b/docs/source/demoapp.rst
@@ -85,14 +85,20 @@ The :class:`DemoApp` class inherits from :class:`App` and overrides
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
+The :func:`initialize_app` method of :class:`DemoApp` will be invoked
+after the main program arguments are parsed, but before any command
+processing is performed and before the application enters interactive
+mode. 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
+The :func:`prepare_to_run_command` method of :class:`DemoApp` will be
+invoked after a command is identified, but before the command is given
+its arguments and run. This hook is intended for pre-command
+validation or setup that must be repeated and cannot be handled by
+:func:`initialize_app`.
+
+The :func:`clean_up` method of :class:`DemoApp` is invoked after a
command runs. If the command raised an exception, the exception object
is passed to :func:`clean_up`. Otherwise the ``err`` argument is
``None``.
diff --git a/docs/source/history.rst b/docs/source/history.rst
index 303b9cd..58b5fb3 100644
--- a/docs/source/history.rst
+++ b/docs/source/history.rst
@@ -5,6 +5,8 @@
dev
- Add shell formatter for single objects.
+ - Add interactive mode.
+ - Expand documentation.
0.3
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 8994669..0a13664 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -15,6 +15,7 @@ Contents:
demoapp
list_commands
show_commands
+ interactive_mode
classes
install
developers
@@ -27,3 +28,5 @@ Indices and tables
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
+
+.. todolist::
diff --git a/docs/source/interactive_mode.rst b/docs/source/interactive_mode.rst
new file mode 100644
index 0000000..519e89a
--- /dev/null
+++ b/docs/source/interactive_mode.rst
@@ -0,0 +1,94 @@
+==================
+ Interactive Mode
+==================
+
+In addition to running single commands from the command line, cliff
+supports an interactive mode in which the user is presented with a
+separate command shell. All of the command plugins available from the
+command line are automatically configured as commands within the
+shell.
+
+Refer to the cmd2_ documentation for more details about features of
+the shell.
+
+.. _cmd2: http://packages.python.org/cmd2/index.html
+
+.. todo:: Add details about configuring and interacting with the shell (copy from cmd2 docs)
+
+Example
+=======
+
+The ``cliffdemo`` application enters interactive mode if no command is
+specified on the command line.
+
+::
+
+ (.venv)$ cliffdemo
+ (cliffdemo) help
+
+ Shell commands (type help <topic>):
+ ===================================
+ cmdenvironment edit hi l list pause r save shell show
+ ed help history li load py run set shortcuts
+
+ Undocumented commands:
+ ======================
+ EOF eof exit q quit
+
+ Application commands (type help <topic>):
+ =========================================
+ files help simple file error two part
+
+To obtain instructions for a built-in or application command, use the
+``help`` command:
+
+::
+
+ (cliffdemo) help simple
+ usage: simple [-h]
+
+ A simple command that prints a message.
+
+ optional arguments:
+ -h, --help show this help message and exit
+
+The commands can be run, including options and arguments, as on the
+regular command line:
+
+::
+
+ (cliffdemo) simple
+ sending greeting
+ hi!
+ (cliffdemo) files
+ +----------------------+-------+
+ | Name | Size |
+ +----------------------+-------+
+ | .git | 578 |
+ | .gitignore | 268 |
+ | .tox | 238 |
+ | .venv | 204 |
+ | announce.rst | 1015 |
+ | announce.rst~ | 708 |
+ | cliff | 884 |
+ | cliff.egg-info | 340 |
+ | cliffdemo.log | 2193 |
+ | cliffdemo.log.1 | 10225 |
+ | demoapp | 408 |
+ | dist | 136 |
+ | distribute_setup.py | 15285 |
+ | distribute_setup.pyc | 15196 |
+ | docs | 238 |
+ | LICENSE | 11358 |
+ | Makefile | 376 |
+ | Makefile~ | 94 |
+ | MANIFEST.in | 186 |
+ | MANIFEST.in~ | 344 |
+ | README.rst | 1063 |
+ | setup.py | 5855 |
+ | setup.py~ | 8128 |
+ | tests | 204 |
+ | tox.ini | 76 |
+ | tox.ini~ | 421 |
+ +----------------------+-------+
+ (cliffdemo)
diff --git a/docs/source/introduction.rst b/docs/source/introduction.rst
index afef2bf..0951f19 100644
--- a/docs/source/introduction.rst
+++ b/docs/source/introduction.rst
@@ -19,7 +19,7 @@ fit.
Cliff Objects
=============
-Cliff is organized around three objects that are combined to create a
+Cliff is organized around four objects that are combined to create a
useful command line program.
The Application
@@ -50,6 +50,15 @@ 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.
+The Interactive Application
+---------------------------
+
+The main program uses an :class:`cliff.interactive.InteractiveApp`
+instance to provide a command-shell mode in which the user can type
+multiple commands before the program exits. Many cliff-based
+applications will be able to use the default implementation of
+:class:`InteractiveApp` without subclassing it.
+
.. _setuptools entry points: http://packages.python.org/distribute/setuptools.html
.. _argparse: http://docs.python.org/library/argparse.html