Doc updates for API changes.

Clean up docstrings.
Bump version to 1.0.

Change-Id: I1047c637ffed4ffac8bffbdaa1bddc56895716d9
This commit is contained in:
Doug Hellmann 2012-06-20 17:27:08 -04:00
parent 9bb0a4a13a
commit 83469ad81a
12 changed files with 70 additions and 31 deletions

View File

@ -11,9 +11,15 @@ other extensions.
What's New In This Release? What's New In This Release?
=========================== ===========================
- Clean up interactive mode flag settting. - Add trailing newlines after output from tablib-based formatters
- Add support for Python 2.6, contributed by heavenshell. (JSON, YAML, and HTML). Contributed by Matt Joyce.
- Fix multi-word commands in interactive mode. - Some PEP-8 fixes.
- Refactor the API in ``Command`` to add ``take_action()``
and make ``run()`` a concrete method. Existing users should only
need to rename ``run()`` to ``take_action()`` since the function
signatures have not changed.
- In ``Lister`` and ``ShowOne`` use ``take_action()`` instead of
``get_data()``.
Documentation Documentation
============= =============

View File

@ -143,7 +143,11 @@ class App(object):
self.interactive_mode = not remainder self.interactive_mode = not remainder
self.initialize_app(remainder) self.initialize_app(remainder)
except Exception as err: except Exception as err:
if self.options.debug: if hasattr(self, 'options'):
debug = self.options.debug
else:
debug = True
if debug:
LOG.exception(err) LOG.exception(err)
raise raise
else: else:

View File

@ -23,7 +23,7 @@ class Command(object):
return inspect.getdoc(self.__class__) or '' return inspect.getdoc(self.__class__) or ''
def get_parser(self, prog_name): def get_parser(self, prog_name):
"""Return an argparse.ArgumentParser. """Return an :class:`argparse.ArgumentParser`.
""" """
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description=self.get_description(), description=self.get_description(),
@ -33,12 +33,18 @@ class Command(object):
@abc.abstractmethod @abc.abstractmethod
def take_action(self, parsed_args): def take_action(self, parsed_args):
"""Return a two-part tuple with a tuple of column names """Override to do something useful.
and a tuple of values.
""" """
def run(self, parsed_args): def run(self, parsed_args):
"""Do something useful. """Invoked by the application when the command is run.
Developers implementing commands should override
:meth:`take_action`.
Developers creating new command base classes (such as
:class:`Lister` and :class:`ShowOne`) should override this
method to wrap :meth:`take_action`.
""" """
self.take_action(parsed_args) self.take_action(parsed_args)
return 0 return 0

View File

@ -1,4 +1,5 @@
import argparse import argparse
import logging
import sys import sys
from .command import Command from .command import Command
@ -12,13 +13,22 @@ class HelpAction(argparse.Action):
instance, passed in as the "default" value for the action. instance, passed in as the "default" value for the action.
""" """
def __call__(self, parser, namespace, values, option_string=None): def __call__(self, parser, namespace, values, option_string=None):
log = logging.getLogger(__name__)
app = self.default app = self.default
parser.print_help(app.stdout) parser.print_help(app.stdout)
app.stdout.write('\nCommands:\n') app.stdout.write('\nCommands:\n')
command_manager = app.command_manager command_manager = app.command_manager
for name, ep in sorted(command_manager): for name, ep in sorted(command_manager):
factory = ep.load() try:
cmd = factory(self, None) factory = ep.load()
except Exception as err:
app.stdout.write('Could not load %r\n' % ep)
continue
try:
cmd = factory(self, None)
except Exception as err:
app.stdout.write('Could not instantiate %r: %s\n' % (ep, err))
continue
one_liner = cmd.get_description().split('\n')[0] one_liner = cmd.get_description().split('\n')[0]
app.stdout.write(' %-13s %s\n' % (name, one_liner)) app.stdout.write(' %-13s %s\n' % (name, one_liner))
sys.exit(0) sys.exit(0)

View File

@ -8,7 +8,7 @@ class Simple(Command):
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def run(self, parsed_args): def take_action(self, parsed_args):
self.log.info('sending greeting') self.log.info('sending greeting')
self.log.debug('debugging') self.log.debug('debugging')
self.app.stdout.write('hi!\n') self.app.stdout.write('hi!\n')
@ -19,6 +19,6 @@ class Error(Command):
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def run(self, parsed_args): def take_action(self, parsed_args):
self.log.info('causing error') self.log.info('causing error')
raise RuntimeError('this is the expected exception') raise RuntimeError('this is the expected exception')

View File

@ -48,7 +48,7 @@ copyright = u'2012, Doug Hellmann'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '0.7' version = '1.0'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = version release = version

View File

@ -155,19 +155,25 @@ features of cliff.
causing error causing error
this is the expected exception this is the expected exception
Traceback (most recent call last): Traceback (most recent call last):
File ".../cliff/app.py", line 148, in run File ".../cliff/app.py", line 218, in run_subcommand
result = cmd.run(parsed_args) result = cmd.run(parsed_args)
File ".../demoapp/cliffdemo/simple.py", line 24, in run File ".../cliff/command.py", line 43, in run
self.take_action(parsed_args)
File ".../demoapp/cliffdemo/simple.py", line 24, in take_action
raise RuntimeError('this is the expected exception') raise RuntimeError('this is the expected exception')
RuntimeError: this is the expected exception RuntimeError: this is the expected exception
Traceback (most recent call last): Traceback (most recent call last):
File "/Users/dhellmann/Envs/cliff/bin/cliffdemo", line 9, in <module> File "/Users/dhellmann/Envs/cliff/bin/cliffdemo", line 9, in <module>
load_entry_point('cliffdemo==0.1', 'console_scripts', 'cliffdemo')() load_entry_point('cliffdemo==0.1', 'console_scripts', 'cliffdemo')()
File ".../demoapp/cliffdemo/main.py", line 30, in main File ".../demoapp/cliffdemo/main.py", line 33, in main
return myapp.run(argv) return myapp.run(argv)
File ".../cliff/app.py", line 148, in run File ".../cliff/app.py", line 160, in run
result = self.run_subcommand(remainder)
File ".../cliff/app.py", line 218, in run_subcommand
result = cmd.run(parsed_args) result = cmd.run(parsed_args)
File ".../demoapp/cliffdemo/simple.py", line 24, in run File ".../cliff/command.py", line 43, in run
self.take_action(parsed_args)
File ".../demoapp/cliffdemo/simple.py", line 24, in take_action
raise RuntimeError('this is the expected exception') raise RuntimeError('this is the expected exception')
RuntimeError: this is the expected exception RuntimeError: this is the expected exception

View File

@ -2,11 +2,17 @@
Release History Release History
================= =================
dev 1.0
- Add trailing newlines after output from tablib-based formatters - Add trailing newlines after output from tablib-based formatters
(JSON, YAML, and HTML). Contributed by Matt Joyce. (JSON, YAML, and HTML). Contributed by Matt Joyce.
- Some :pep:`8` fixes. - Some :pep:`8` fixes.
- Refactor the API in :class:`Command` to add :func:`take_action`
and make :func:`run` a concrete method. Existing users should only
need to rename :func:`run()` to :func:`take_action()` since the
function signatures have not changed.
- In :class:`Lister` and :class:`ShowOne` use :func:`take_action`
instead of :func:`get_data`.
0.7 0.7

View File

@ -48,7 +48,7 @@ discover the command plugins and invoke them, and to provide runtime
support for those plugins. Each :class:`Command` subclass is support for those plugins. Each :class:`Command` subclass is
responsible for taking action based on instructions from the user. It responsible for taking action based on instructions from the user. It
defines its own local argument parser (usually using argparse_) and a defines its own local argument parser (usually using argparse_) and a
:func:`run` method that does the appropriate work. :func:`take_action` method that does the appropriate work.
The Interactive Application The Interactive Application
--------------------------- ---------------------------

View File

@ -12,12 +12,12 @@ Lister
====== ======
The :class:`cliff.lister.Lister` base class API extends The :class:`cliff.lister.Lister` base class API extends
:class:`Command` to add a :func:`get_data` method. Subclasses should :class:`Command` to allow :func:`take_action` to return data to be
provide a :func:`get_data` implementation that returns a two member formatted using a user-selectable formatter. Subclasses should provide
tuple containing a tuple with the names of the columns in the dataset a :func:`take_action` implementation that returns a two member tuple
and an iterable that will yield the data to be output. See the containing a tuple with the names of the columns in the dataset and an
description of :ref:`the files command in the demoapp <demoapp-list>` iterable that will yield the data to be output. See the description of
for details. :ref:`the files command in the demoapp <demoapp-list>` for details.
List Output Formatters List Output Formatters
====================== ======================

View File

@ -12,10 +12,11 @@ ShowOne
======= =======
The :class:`cliff.show.ShowOne` base class API extends The :class:`cliff.show.ShowOne` base class API extends
:class:`Command` to add a :func:`get_data` method. Subclasses should :class:`Command` to allow :func:`take_action` to return data to be
provide a :func:`get_data` implementation that returns a two member formatted using a user-selectable formatter. Subclasses should provide
tuple containing a tuple with the names of the columns in the dataset a :func:`take_action` implementation that returns a two member tuple
and an iterable that contains the data values associated with those containing a tuple with the names of the columns in the dataset and an
iterable that contains the data values associated with those
names. See the description of :ref:`the file command in the demoapp names. See the description of :ref:`the file command in the demoapp
<demoapp-show>` for details. <demoapp-show>` for details.

View File

@ -3,7 +3,7 @@
PROJECT = 'cliff' PROJECT = 'cliff'
# Change docs/source/conf.py too! # Change docs/source/conf.py too!
VERSION = '0.7' VERSION = '1.0'
# Bootstrap installation of Distribute # Bootstrap installation of Distribute
import distribute_setup import distribute_setup