documentation improvements
This commit is contained in:
parent
0fba728779
commit
ab200eb505
46
cliff/app.py
46
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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 = {}
|
||||
|
|
|
@ -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__')
|
||||
|
|
|
@ -8,6 +8,12 @@ App
|
|||
.. autoclass:: cliff.app.App
|
||||
:members:
|
||||
|
||||
InteractiveApp
|
||||
==============
|
||||
|
||||
.. autoclass:: cliff.interactive.InteractiveApp
|
||||
:members:
|
||||
|
||||
CommandManager
|
||||
==============
|
||||
|
||||
|
|
|
@ -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``.
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
dev
|
||||
|
||||
- Add shell formatter for single objects.
|
||||
- Add interactive mode.
|
||||
- Expand documentation.
|
||||
|
||||
0.3
|
||||
|
||||
|
|
|
@ -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::
|
||||
|
|
|
@ -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)
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue