cliff-1.4.5/0000755000101700007650000000000012220116306014524 5ustar dhellmanndhellmann00000000000000cliff-1.4.5/.gitignore0000644000101700007650000000041411747077561016541 0ustar dhellmanndhellmann00000000000000*.py[co] # Packages *.egg *.egg-info dist build eggs parts bin var sdist develop-eggs .installed.cfg .venv # Installer logs pip-log.txt # Unit test / coverage reports .coverage .tox #Translations *.mo #Mr Developer .mr.developer.cfg #sample output *.log *.log.* cliff-1.4.5/.travis.yml0000644000101700007650000000017412220115753016644 0ustar dhellmanndhellmann00000000000000language: python python: - 2.7 - 3.2 - 3.3 - pypy install: pip install -r test-requirements.txt script: nosetests -dcliff-1.4.5/announce.rst0000644000101700007650000000173112220116130017061 0ustar dhellmanndhellmann00000000000000======================================================================== cliff -- Command Line Interface Formulation Framework -- version 1.4.5 ======================================================================== .. tags:: python cliff release DreamHost cliff is a framework for building command line programs. It uses setuptools entry points to provide subcommands, output formatters, and other extensions. What's New In This Release? =========================== - Update the pyparsing dependency to a version that supports both Python 2 and Python 3. - Add PyPy testing. Documentation ============= `Documentation for cliff`_ is hosted on `readthedocs.org`_ .. _Documentation for cliff: http://readthedocs.org/docs/cliff/en/latest/ .. _readthedocs.org: http://readthedocs.org Installation ============ Use pip:: $ pip install cliff See `the installation guide`_ for more details. .. _the installation guide: http://cliff.readthedocs.org/en/latest/install.html cliff-1.4.5/cliff/0000755000101700007650000000000012220116306015607 5ustar dhellmanndhellmann00000000000000cliff-1.4.5/cliff/__init__.py0000644000101700007650000000000012007313741017713 0ustar dhellmanndhellmann00000000000000cliff-1.4.5/cliff/app.py0000644000101700007650000002457412207671670016774 0ustar dhellmanndhellmann00000000000000"""Application base class. """ import argparse import codecs import locale import logging import logging.handlers import os import sys from .help import HelpAction, HelpCommand from .interactive import InteractiveApp # Make sure the cliff library has a logging handler # in case the app developer doesn't set up logging. # For py26 compat, create a NullHandler if hasattr(logging, 'NullHandler'): NullHandler = logging.NullHandler else: class NullHandler(logging.Handler): def handle(self, record): pass def emit(self, record): pass def createLock(self): self.lock = None logging.getLogger('cliff').addHandler(NullHandler()) 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] CONSOLE_MESSAGE_FORMAT = '%(message)s' LOG_FILE_MESSAGE_FORMAT = \ '[%(asctime)s] %(levelname)-8s %(name)s %(message)s' DEFAULT_VERBOSE_LEVEL = 1 DEFAULT_OUTPUT_ENCODING = 'utf-8' def __init__(self, description, version, command_manager, stdin=None, stdout=None, stderr=None, interactive_app_factory=InteractiveApp): """Initialize the application. """ self.command_manager = command_manager self.command_manager.add_command('help', HelpCommand) self._set_streams(stdin, stdout, stderr) self.interactive_app_factory = interactive_app_factory self.parser = self.build_option_parser(description, version) self.interactive_mode = False self.interpreter = None def _set_streams(self, stdin, stdout, stderr): locale.setlocale(locale.LC_ALL, '') if sys.version_info[:2] == (2, 6): # Configure the input and output streams. If a stream is # provided, it must be configured correctly by the # caller. If not, make sure the versions of the standard # streams used by default are wrapped with encodings. This # works around a problem with Python 2.6 fixed in 2.7 and # later (http://hg.python.org/cpython/rev/e60ef17561dc/). lang, encoding = locale.getdefaultlocale() encoding = (getattr(sys.stdout, 'encoding', None) or encoding or self.DEFAULT_OUTPUT_ENCODING ) self.stdin = stdin or codecs.getreader(encoding)(sys.stdin) self.stdout = stdout or codecs.getwriter(encoding)(sys.stdout) self.stderr = stderr or codecs.getwriter(encoding)(sys.stderr) else: self.stdin = stdin or sys.stdin self.stdout = stdout or sys.stdout self.stderr = stderr or sys.stderr def build_option_parser(self, description, version, argparse_kwargs=None): """Return an argparse option parser for this application. 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 :param argparse_kwargs: extra keyword argument passed to the ArgumentParser constructor :paramtype extra_kwargs: dict """ argparse_kwargs = argparse_kwargs or {} parser = argparse.ArgumentParser( description=description, add_help=False, **argparse_kwargs ) parser.add_argument( '--version', action='version', version='%(prog)s {0}'.format(version), ) parser.add_argument( '-v', '--verbose', action='count', dest='verbose_level', default=self.DEFAULT_VERBOSE_LEVEL, help='Increase verbosity of output. Can be repeated.', ) parser.add_argument( '--log-file', action='store', default=None, help='Specify a file to log output. Disabled by default.', ) parser.add_argument( '-q', '--quiet', action='store_const', dest='verbose_level', const=0, help='suppress output except warnings and errors', ) parser.add_argument( '-h', '--help', action=HelpAction, nargs=0, default=self, # tricky help="show this help message and exit", ) parser.add_argument( '--debug', default=False, action='store_true', help='show tracebacks on errors', ) return parser def configure_logging(self): """Create logging handlers for any log output. """ root_logger = logging.getLogger('') root_logger.setLevel(logging.DEBUG) # Set up logging to a file if self.options.log_file: file_handler = logging.FileHandler( filename=self.options.log_file, ) formatter = logging.Formatter(self.LOG_FILE_MESSAGE_FORMAT) file_handler.setFormatter(formatter) root_logger.addHandler(file_handler) # Always send higher-level messages to the console via stderr console = logging.StreamHandler(self.stderr) console_level = {0: logging.WARNING, 1: logging.INFO, 2: logging.DEBUG, }.get(self.options.verbose_level, logging.DEBUG) console.setLevel(console_level) formatter = logging.Formatter(self.CONSOLE_MESSAGE_FORMAT) console.setFormatter(formatter) root_logger.addHandler(console) return def run(self, argv): """Equivalent to the main program for the application. :param argv: input arguments and options :paramtype argv: list of str """ try: self.options, remainder = self.parser.parse_known_args(argv) self.configure_logging() self.interactive_mode = not remainder self.initialize_app(remainder) except Exception as err: if hasattr(self, 'options'): debug = self.options.debug else: debug = True if debug: LOG.exception(err) raise else: LOG.error(err) return 1 result = 1 if self.interactive_mode: result = self.interact() else: result = self.run_subcommand(remainder) return result # FIXME(dhellmann): Consider moving these command handling methods # to a separate class. def initialize_app(self, argv): """Hook for subclasses to take global initialization action after the arguments are parsed but before a command is run. Invoked only once, even in interactive mode. :param argv: List of arguments, including the subcommand to run. Empty for interactive mode. """ return 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.interpreter = self.interactive_app_factory(self, self.command_manager, self.stdin, self.stdout, ) self.interpreter.cmdloop() return 0 def run_subcommand(self, argv): try: subcommand = self.command_manager.find_command(argv) except ValueError as err: if self.options.debug: raise else: LOG.error(err) return 2 cmd_factory, cmd_name, sub_argv = subcommand cmd = cmd_factory(self, self.options) err = None result = 1 try: self.prepare_to_run_command(cmd) full_name = (cmd_name if self.interactive_mode else ' '.join([self.NAME, cmd_name]) ) cmd_parser = cmd.get_parser(full_name) parsed_args = cmd_parser.parse_args(sub_argv) result = cmd.run(parsed_args) except Exception as err: if self.options.debug: LOG.exception(err) else: LOG.error(err) try: self.clean_up(cmd, result, err) except Exception as err2: if self.options.debug: LOG.exception(err2) else: LOG.error('Could not clean up: %s', err2) if self.options.debug: raise else: try: self.clean_up(cmd, result, None) except Exception as err3: if self.options.debug: LOG.exception(err3) else: LOG.error('Could not clean up: %s', err3) return result cliff-1.4.5/cliff/command.py0000644000101700007650000000241312121131171017574 0ustar dhellmanndhellmann00000000000000 import abc import argparse 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 def __init__(self, app, app_args): self.app = app self.app_args = app_args return def get_description(self): """Return the command description. """ return inspect.getdoc(self.__class__) or '' def get_parser(self, prog_name): """Return an :class:`argparse.ArgumentParser`. """ parser = argparse.ArgumentParser( description=self.get_description(), prog=prog_name, ) return parser @abc.abstractmethod def take_action(self, parsed_args): """Override to do something useful. """ def run(self, parsed_args): """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) return 0 cliff-1.4.5/cliff/commandmanager.py0000644000101700007650000000444212121131216021133 0ustar dhellmanndhellmann00000000000000"""Discover and lookup command plugins. """ import logging import pkg_resources LOG = logging.getLogger(__name__) class EntryPointWrapper(object): """Wrap up a command class already imported to make it look like a plugin. """ def __init__(self, name, command_class): self.name = name self.command_class = command_class def load(self): return self.command_class 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'``. :param convert_underscores: Whether cliff should convert underscores to to spaces in entry_point commands. """ def __init__(self, namespace, convert_underscores=True): self.commands = {} self.namespace = namespace self.convert_underscores = convert_underscores self._load_commands() def _load_commands(self): for ep in pkg_resources.iter_entry_points(self.namespace): LOG.debug('found command %r', ep.name) cmd_name = (ep.name.replace('_', ' ') if self.convert_underscores else ep.name) self.commands[cmd_name] = ep return def __iter__(self): return iter(self.commands.items()) def add_command(self, name, command_class): self.commands[name] = EntryPointWrapper(name, command_class) def find_command(self, argv): """Given an argument list, find a command and return the processor and any remaining arguments. """ search_args = argv[:] name = '' while search_args: if search_args[0].startswith('-'): raise ValueError('Invalid command %r' % search_args[0]) next_val = search_args.pop(0) name = '%s %s' % (name, next_val) if name else next_val if name in self.commands: cmd_ep = self.commands[name] cmd_factory = cmd_ep.load() return (cmd_factory, name, search_args) else: raise ValueError('Unknown command %r' % (argv,)) cliff-1.4.5/cliff/display.py0000644000101700007650000000551512121131250017627 0ustar dhellmanndhellmann00000000000000"""Application base class for displaying data. """ import abc import logging import pkg_resources from .command import Command LOG = logging.getLogger(__name__) class DisplayCommandBase(Command): """Command base class for displaying data about a single object. """ __metaclass__ = abc.ABCMeta def __init__(self, app, app_args): super(DisplayCommandBase, self).__init__(app, app_args) self.load_formatter_plugins() @abc.abstractproperty def formatter_namespace(self): "String specifying the namespace to use for loading formatter plugins." @abc.abstractproperty def formatter_default(self): "String specifying the name of the default formatter." def load_formatter_plugins(self): self.formatters = {} for ep in pkg_resources.iter_entry_points(self.formatter_namespace): try: self.formatters[ep.name] = ep.load()() except Exception as err: LOG.error(err) if self.app_args.debug: raise return def get_parser(self, prog_name): parser = super(DisplayCommandBase, self).get_parser(prog_name) formatter_group = parser.add_argument_group( title='output formatters', description='output formatter options', ) formatter_choices = sorted(self.formatters.keys()) formatter_default = self.formatter_default if formatter_default not in formatter_choices: formatter_default = formatter_choices[0] formatter_group.add_argument( '-f', '--format', dest='formatter', action='store', choices=formatter_choices, default=formatter_default, help='the output format, defaults to %s' % formatter_default, ) formatter_group.add_argument( '-c', '--column', action='append', default=[], dest='columns', metavar='COLUMN', help='specify the column(s) to include, can be repeated', ) for name, formatter in sorted(self.formatters.items()): formatter.add_argument_group(parser) return parser @abc.abstractmethod def produce_output(self, parsed_args, column_names, data): """Use the formatter to generate the output. :param parsed_args: argparse.Namespace instance with argument values :param column_names: sequence of strings containing names of output columns :param data: iterable with values matching the column names """ def run(self, parsed_args): self.formatter = self.formatters[parsed_args.formatter] column_names, data = self.take_action(parsed_args) self.produce_output(parsed_args, column_names, data) return 0 cliff-1.4.5/cliff/formatters/0000755000101700007650000000000012220116306017775 5ustar dhellmanndhellmann00000000000000cliff-1.4.5/cliff/formatters/__init__.py0000644000101700007650000000000011745104456022112 0ustar dhellmanndhellmann00000000000000cliff-1.4.5/cliff/formatters/base.py0000644000101700007650000000272711747346251021312 0ustar dhellmanndhellmann00000000000000"""Base classes for formatters. """ import abc class Formatter(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def add_argument_group(self, parser): """Add any options to the argument parser. Should use our own argument group. """ class ListFormatter(Formatter): """Base class for formatters that know how to deal with multiple objects. """ __metaclass__ = abc.ABCMeta @abc.abstractmethod def emit_list(self, column_names, data, stdout, parsed_args): """Format and print the list from the iterable data source. :param column_names: names of the columns :param data: iterable data source, one tuple per object with values in order of column names :param stdout: output stream where data should be written :param parsed_args: argparse namespace from our local options """ class SingleFormatter(Formatter): """Base class for formatters that work with single objects. """ __metaclass__ = abc.ABCMeta @abc.abstractmethod def emit_one(self, column_names, data, stdout, parsed_args): """Format and print the values associated with the single object. :param column_names: names of the columns :param data: iterable data source with values in order of column names :param stdout: output stream where data should be written :param parsed_args: argparse namespace from our local options """ cliff-1.4.5/cliff/formatters/commaseparated.py0000644000101700007650000000170312121131340023330 0ustar dhellmanndhellmann00000000000000"""Output formatters using csv format. """ import csv from .base import ListFormatter class CSVLister(ListFormatter): QUOTE_MODES = { 'all': csv.QUOTE_ALL, 'minimal': csv.QUOTE_MINIMAL, 'nonnumeric': csv.QUOTE_NONNUMERIC, 'none': csv.QUOTE_NONE, } def add_argument_group(self, parser): group = parser.add_argument_group('CSV Formatter') group.add_argument( '--quote', choices=sorted(self.QUOTE_MODES.keys()), dest='quote_mode', default='nonnumeric', help='when to include quotes, defaults to nonnumeric', ) def emit_list(self, column_names, data, stdout, parsed_args): writer = csv.writer(stdout, quoting=self.QUOTE_MODES[parsed_args.quote_mode], ) writer.writerow(column_names) for row in data: writer.writerow(row) return cliff-1.4.5/cliff/formatters/shell.py0000644000101700007650000000232312121131351021453 0ustar dhellmanndhellmann00000000000000"""Output formatters using shell syntax. """ from .base import SingleFormatter class ShellFormatter(SingleFormatter): def add_argument_group(self, parser): group = parser.add_argument_group( title='shell formatter', description='a format a UNIX shell can parse (variable="value")', ) group.add_argument( '--variable', action='append', default=[], dest='variables', metavar='VARIABLE', help='specify the variable(s) to include, can be repeated', ) group.add_argument( '--prefix', action='store', default='', dest='prefix', help='add a prefix to all variable names', ) def emit_one(self, column_names, data, stdout, parsed_args): variable_names = [c.lower().replace(' ', '_') for c in column_names ] desired_columns = parsed_args.variables for name, value in zip(variable_names, data): if name in desired_columns or not desired_columns: stdout.write('%s%s="%s"\n' % (parsed_args.prefix, name, value)) return cliff-1.4.5/cliff/formatters/table.py0000644000101700007650000000356212202717230021447 0ustar dhellmanndhellmann00000000000000"""Output formatters using prettytable. """ import prettytable from .base import ListFormatter, SingleFormatter class TableFormatter(ListFormatter, SingleFormatter): ALIGNMENTS = { int: 'r', str: 'l', float: 'r', } try: ALIGNMENTS[unicode] = 'l' except NameError: pass def add_argument_group(self, parser): pass def emit_list(self, column_names, data, stdout, parsed_args): x = prettytable.PrettyTable( column_names, print_empty=False, ) x.padding_width = 1 # Figure out the types of the columns in the # first row and set the alignment of the # output accordingly. data_iter = iter(data) try: first_row = next(data_iter) except StopIteration: pass else: for value, name in zip(first_row, column_names): alignment = self.ALIGNMENTS.get(type(value), 'l') x.align[name] = alignment # Now iterate over the data and add the rows. x.add_row(first_row) for row in data_iter: x.add_row(row) formatted = x.get_string(fields=column_names) stdout.write(formatted) stdout.write('\n') return def emit_one(self, column_names, data, stdout, parsed_args): x = prettytable.PrettyTable(field_names=('Field', 'Value'), print_empty=False) x.padding_width = 1 # Align all columns left because the values are # not all the same type. x.align['Field'] = 'l' x.align['Value'] = 'l' for name, value in zip(column_names, data): x.add_row((name, value)) formatted = x.get_string(fields=('Field', 'Value')) stdout.write(formatted) stdout.write('\n') return cliff-1.4.5/cliff/help.py0000644000101700007650000000530112121131257017112 0ustar dhellmanndhellmann00000000000000import argparse import sys from .command import Command class HelpAction(argparse.Action): """Provide a custom action so the -h and --help options to the main app will print a list of the commands. The commands are determined by checking the CommandManager instance, passed in as the "default" value for the action. """ def __call__(self, parser, namespace, values, option_string=None): app = self.default parser.print_help(app.stdout) app.stdout.write('\nCommands:\n') command_manager = app.command_manager for name, ep in sorted(command_manager): try: 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] app.stdout.write(' %-13s %s\n' % (name, one_liner)) sys.exit(0) class HelpCommand(Command): """print detailed help for another command """ def get_parser(self, prog_name): parser = super(HelpCommand, self).get_parser(prog_name) parser.add_argument('cmd', nargs='*', help='name of the command', ) return parser def take_action(self, parsed_args): if parsed_args.cmd: try: the_cmd = self.app.command_manager.find_command( parsed_args.cmd, ) cmd_factory, cmd_name, search_args = the_cmd except ValueError: # Did not find an exact match cmd = parsed_args.cmd[0] fuzzy_matches = [k[0] for k in self.app.command_manager if k[0].startswith(cmd) ] if not fuzzy_matches: raise self.app.stdout.write('Command "%s" matches:\n' % cmd) for fm in fuzzy_matches: self.app.stdout.write(' %s\n' % fm) return cmd = cmd_factory(self.app, search_args) full_name = (cmd_name if self.app.interactive_mode else ' '.join([self.app.NAME, cmd_name]) ) cmd_parser = cmd.get_parser(full_name) else: cmd_parser = self.get_parser(' '.join([self.app.NAME, 'help'])) cmd_parser.print_help(self.app.stdout) return 0 cliff-1.4.5/cliff/interactive.py0000644000101700007650000001012312121131324020470 0ustar dhellmanndhellmann00000000000000"""Application base class. """ import itertools import logging import logging.handlers import shlex import cmd2 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 ):" app_cmd_header = "Application commands (type help ):" def __init__(self, parent_app, command_manager, stdin, stdout): self.parent_app = parent_app self.prompt = '(%s) ' % parent_app.NAME self.command_manager = command_manager cmd2.Cmd.__init__(self, 'tab', stdin=stdin, stdout=stdout) def default(self, line): # Tie in the the default command processor to # dispatch commands known to the command manager. # We send the message through our parent app, # since it already has the logic for executing # the subcommand. line_parts = shlex.split(line.parsed.raw) 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. if not text: completions = sorted(n for n, v in self.command_manager) else: completions = sorted(n for n, v in self.command_manager if n.startswith(text) ) return completions def help_help(self): # Use the command manager to get instructions for "help" self.default('help help') def do_help(self, arg): if arg: # Check if the arg is a builtin command or something # coming from the command manager arg_parts = shlex.split(arg) method_name = '_'.join( itertools.chain( ['do'], itertools.takewhile(lambda x: not x.startswith('-'), arg_parts) ) ) # Have the command manager version of the help # command produce the help text since cmd and # cmd2 do not provide help for "help" if hasattr(self, method_name): return cmd2.Cmd.do_help(self, arg) # Dispatch to the underlying help command, # which knows how to provide help for extension # commands. self.default(self.parsed('help ' + arg)) else: cmd2.Cmd.do_help(self, arg) cmd_names = sorted([n for n, v in self.command_manager]) self.print_topics(self.app_cmd_header, cmd_names, 15, 80) 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__') ] def precmd(self, statement): # Pre-process the parsed command in case it looks like one of # our subcommands, since cmd2 does not handle multi-part # command names by default. line_parts = shlex.split(statement.parsed.raw) try: the_cmd = self.command_manager.find_command(line_parts) cmd_factory, cmd_name, sub_argv = the_cmd except ValueError: # Not a plugin command pass else: statement.parsed.command = cmd_name statement.parsed.args = ' '.join(sub_argv) return statement cliff-1.4.5/cliff/lister.py0000644000101700007650000000412112020117332017457 0ustar dhellmanndhellmann00000000000000"""Application base class for providing a list of data as output. """ import abc try: from itertools import compress except ImportError: # for py26 compat from itertools import izip def compress(data, selectors): return (d for d, s in izip(data, selectors) if s) import logging from .display import DisplayCommandBase LOG = logging.getLogger(__name__) class Lister(DisplayCommandBase): """Command base class for providing a list of data as output. """ __metaclass__ = abc.ABCMeta @property def formatter_namespace(self): return 'cliff.formatter.list' @property def formatter_default(self): return 'table' @abc.abstractmethod def take_action(self, parsed_args): """Return a tuple containing the column names and an iterable containing the data to be listed. """ def produce_output(self, parsed_args, column_names, data): if not parsed_args.columns: columns_to_include = column_names data_gen = data else: columns_to_include = [c for c in column_names if c in parsed_args.columns ] if not columns_to_include: raise ValueError('No recognized column names in %s' % str(parsed_args.columns)) # Set up argument to compress() selector = [(c in columns_to_include) for c in column_names] # Generator expression to only return the parts of a row # of data that the user has expressed interest in # seeing. We have to convert the compress() output to a # list so the table formatter can ask for its length. data_gen = (list(compress(row, selector)) for row in data) self.formatter.emit_list(columns_to_include, data_gen, self.app.stdout, parsed_args, ) return 0 cliff-1.4.5/cliff/show.py0000644000101700007650000000314312173731250017152 0ustar dhellmanndhellmann00000000000000"""Application base class for displaying data about a single object. """ import abc import itertools import logging from .display import DisplayCommandBase LOG = logging.getLogger(__name__) class ShowOne(DisplayCommandBase): """Command base class for displaying data about a single object. """ __metaclass__ = abc.ABCMeta @property def formatter_namespace(self): return 'cliff.formatter.show' @property def formatter_default(self): return 'table' @abc.abstractmethod def take_action(self, parsed_args): """Return a two-part tuple with a tuple of column names and a tuple of values. """ def produce_output(self, parsed_args, column_names, data): if not parsed_args.columns: columns_to_include = column_names else: columns_to_include = [c for c in column_names if c in parsed_args.columns] # Set up argument to compress() selector = [(c in columns_to_include) for c in column_names] data = list(itertools.compress(data, selector)) self.formatter.emit_one(columns_to_include, data, self.app.stdout, parsed_args) return 0 def dict2columns(self, data): """Implement the common task of converting a dict-based object to the two-column output that ShowOne expects. """ if not data: return ({}, {}) else: return zip(*sorted(data.items())) cliff-1.4.5/cliff/tests/0000755000101700007650000000000012220116306016751 5ustar dhellmanndhellmann00000000000000cliff-1.4.5/cliff/tests/__init__.py0000644000101700007650000000000012202717230021053 0ustar dhellmanndhellmann00000000000000cliff-1.4.5/cliff/tests/test_app.py0000644000101700007650000002710212207671670021163 0ustar dhellmanndhellmann00000000000000# -*- encoding: utf-8 -*- from argparse import ArgumentError try: from StringIO import StringIO except ImportError: # Probably python 3, that test won't be run so ignore the error pass import sys import nose import mock from cliff.app import App from cliff.command import Command from cliff.commandmanager import CommandManager def make_app(): cmd_mgr = CommandManager('cliff.tests') # Register a command that succeeds command = mock.MagicMock(spec=Command) command_inst = mock.MagicMock(spec=Command) command_inst.run.return_value = 0 command.return_value = command_inst cmd_mgr.add_command('mock', command) # Register a command that fails err_command = mock.Mock(name='err_command', spec=Command) err_command_inst = mock.Mock(spec=Command) err_command_inst.run = mock.Mock( side_effect=RuntimeError('test exception') ) err_command.return_value = err_command_inst cmd_mgr.add_command('error', err_command) app = App('testing interactive mode', '1', cmd_mgr, stderr=mock.Mock(), # suppress warning messages ) return app, command def test_no_args_triggers_interactive_mode(): app, command = make_app() app.interact = mock.MagicMock(name='inspect') app.run([]) app.interact.assert_called_once_with() def test_interactive_mode_cmdloop(): app, command = make_app() app.interactive_app_factory = mock.MagicMock( name='interactive_app_factory' ) assert app.interpreter is None app.run([]) assert app.interpreter is not None app.interactive_app_factory.return_value.cmdloop.assert_called_once_with() def test_initialize_app(): app, command = make_app() app.initialize_app = mock.MagicMock(name='initialize_app') app.run(['mock']) app.initialize_app.assert_called_once_with(['mock']) def test_prepare_to_run_command(): app, command = make_app() app.prepare_to_run_command = mock.MagicMock(name='prepare_to_run_command') app.run(['mock']) app.prepare_to_run_command.assert_called_once_with(command()) def test_clean_up_success(): app, command = make_app() app.clean_up = mock.MagicMock(name='clean_up') app.run(['mock']) app.clean_up.assert_called_once_with(command.return_value, 0, None) def test_clean_up_error(): app, command = make_app() app.clean_up = mock.MagicMock(name='clean_up') app.run(['error']) app.clean_up.assert_called_once() call_args = app.clean_up.call_args_list[0] assert call_args == mock.call(mock.ANY, 1, mock.ANY) args, kwargs = call_args assert isinstance(args[2], RuntimeError) assert args[2].args == ('test exception',) def test_clean_up_error_debug(): app, command = make_app() app.clean_up = mock.MagicMock(name='clean_up') try: app.run(['--debug', 'error']) except RuntimeError as err: assert app.clean_up.call_args_list[0][0][2] is err else: assert False, 'Should have had an exception' app.clean_up.assert_called_once() call_args = app.clean_up.call_args_list[0] assert call_args == mock.call(mock.ANY, 1, mock.ANY) args, kwargs = call_args assert isinstance(args[2], RuntimeError) assert args[2].args == ('test exception',) def test_error_handling_clean_up_raises_exception(): app, command = make_app() app.clean_up = mock.MagicMock( name='clean_up', side_effect=RuntimeError('within clean_up'), ) app.run(['error']) app.clean_up.assert_called_once() call_args = app.clean_up.call_args_list[0] assert call_args == mock.call(mock.ANY, 1, mock.ANY) args, kwargs = call_args assert isinstance(args[2], RuntimeError) assert args[2].args == ('test exception',) def test_error_handling_clean_up_raises_exception_debug(): app, command = make_app() app.clean_up = mock.MagicMock( name='clean_up', side_effect=RuntimeError('within clean_up'), ) try: app.run(['--debug', 'error']) except RuntimeError as err: if not hasattr(err, '__context__'): # The exception passed to clean_up is not the exception # caused *by* clean_up. This test is only valid in python # 2 because under v3 the original exception is re-raised # with the new one as a __context__ attribute. assert app.clean_up.call_args_list[0][0][2] is not err else: assert False, 'Should have had an exception' app.clean_up.assert_called_once() call_args = app.clean_up.call_args_list[0] assert call_args == mock.call(mock.ANY, 1, mock.ANY) args, kwargs = call_args assert isinstance(args[2], RuntimeError) assert args[2].args == ('test exception',) def test_normal_clean_up_raises_exception(): app, command = make_app() app.clean_up = mock.MagicMock( name='clean_up', side_effect=RuntimeError('within clean_up'), ) app.run(['mock']) app.clean_up.assert_called_once() call_args = app.clean_up.call_args_list[0] assert call_args == mock.call(mock.ANY, 0, None) def test_normal_clean_up_raises_exception_debug(): app, command = make_app() app.clean_up = mock.MagicMock( name='clean_up', side_effect=RuntimeError('within clean_up'), ) app.run(['--debug', 'mock']) app.clean_up.assert_called_once() call_args = app.clean_up.call_args_list[0] assert call_args == mock.call(mock.ANY, 0, None) def test_build_option_parser_conflicting_option_should_throw(): class MyApp(App): def __init__(self): super(MyApp, self).__init__( description='testing', version='0.1', command_manager=CommandManager('tests'), ) def build_option_parser(self, description, version): parser = super(MyApp, self).build_option_parser(description, version) parser.add_argument( '-h', '--help', default=self, # tricky help="show this help message and exit", ) # TODO: tests should really use unittest2. try: MyApp() except ArgumentError: pass else: raise Exception('Exception was not thrown') def test_option_parser_conflicting_option_custom_arguments_should_not_throw(): class MyApp(App): def __init__(self): super(MyApp, self).__init__( description='testing', version='0.1', command_manager=CommandManager('tests'), ) def build_option_parser(self, description, version): argparse_kwargs = {'conflict_handler': 'resolve'} parser = super(MyApp, self).build_option_parser( description, version, argparse_kwargs=argparse_kwargs) parser.add_argument( '-h', '--help', default=self, # tricky help="show this help message and exit", ) MyApp() def test_output_encoding_default(): # The encoding should come from getdefaultlocale() because # stdout has no encoding set. if sys.version_info[:2] != (2, 6): raise nose.SkipTest('only needed for python 2.6') data = '\xc3\xa9' u_data = data.decode('utf-8') class MyApp(App): def __init__(self): super(MyApp, self).__init__( description='testing', version='0.1', command_manager=CommandManager('tests'), ) stdout = StringIO() getdefaultlocale = lambda: ('ignored', 'utf-8') with mock.patch('sys.stdout', stdout): with mock.patch('locale.getdefaultlocale', getdefaultlocale): app = MyApp() app.stdout.write(u_data) actual = stdout.getvalue() assert data == actual def test_output_encoding_cliff_default(): # The encoding should come from cliff.App.DEFAULT_OUTPUT_ENCODING # because the other values are missing or None if sys.version_info[:2] != (2, 6): raise nose.SkipTest('only needed for python 2.6') data = '\xc3\xa9' u_data = data.decode('utf-8') class MyApp(App): def __init__(self): super(MyApp, self).__init__( description='testing', version='0.1', command_manager=CommandManager('tests'), ) stdout = StringIO() getdefaultlocale = lambda: ('ignored', None) with mock.patch('sys.stdout', stdout): with mock.patch('locale.getdefaultlocale', getdefaultlocale): app = MyApp() app.stdout.write(u_data) actual = stdout.getvalue() assert data == actual def test_output_encoding_sys(): # The encoding should come from sys.stdout because it is set # there. if sys.version_info[:2] != (2, 6): raise nose.SkipTest('only needed for python 2.6') data = '\xc3\xa9' u_data = data.decode('utf-8') class MyApp(App): def __init__(self): super(MyApp, self).__init__( description='testing', version='0.1', command_manager=CommandManager('tests'), ) stdout = StringIO() stdout.encoding = 'utf-8' getdefaultlocale = lambda: ('ignored', 'utf-16') with mock.patch('sys.stdout', stdout): with mock.patch('locale.getdefaultlocale', getdefaultlocale): app = MyApp() app.stdout.write(u_data) actual = stdout.getvalue() assert data == actual def test_error_encoding_default(): # The encoding should come from getdefaultlocale() because # stdout has no encoding set. if sys.version_info[:2] != (2, 6): raise nose.SkipTest('only needed for python 2.6') data = '\xc3\xa9' u_data = data.decode('utf-8') class MyApp(App): def __init__(self): super(MyApp, self).__init__( description='testing', version='0.1', command_manager=CommandManager('tests'), ) stderr = StringIO() getdefaultlocale = lambda: ('ignored', 'utf-8') with mock.patch('sys.stderr', stderr): with mock.patch('locale.getdefaultlocale', getdefaultlocale): app = MyApp() app.stderr.write(u_data) actual = stderr.getvalue() assert data == actual def test_error_encoding_sys(): # The encoding should come from sys.stdout (not sys.stderr) # because it is set there. if sys.version_info[:2] != (2, 6): raise nose.SkipTest('only needed for python 2.6') data = '\xc3\xa9' u_data = data.decode('utf-8') class MyApp(App): def __init__(self): super(MyApp, self).__init__( description='testing', version='0.1', command_manager=CommandManager('tests'), ) stdout = StringIO() stdout.encoding = 'utf-8' stderr = StringIO() getdefaultlocale = lambda: ('ignored', 'utf-16') with mock.patch('sys.stdout', stdout): with mock.patch('sys.stderr', stderr): with mock.patch('locale.getdefaultlocale', getdefaultlocale): app = MyApp() app.stderr.write(u_data) actual = stderr.getvalue() assert data == actual def test_unknown_cmd(): app, command = make_app() assert app.run(['hell']) == 2 def test_unknown_cmd_debug(): app, command = make_app() try: app.run(['--debug', 'hell']) == 2 except ValueError as err: assert "['hell']" in ('%s' % err) cliff-1.4.5/cliff/tests/test_command.py0000644000101700007650000000066412174545363022027 0ustar dhellmanndhellmann00000000000000 from cliff.command import Command class TestCommand(Command): """Description of command. """ def take_action(self, parsed_args): return def test_get_description(): cmd = TestCommand(None, None) desc = cmd.get_description() assert desc == "Description of command.\n " def test_get_parser(): cmd = TestCommand(None, None) parser = cmd.get_parser('NAME') assert parser.prog == 'NAME' cliff-1.4.5/cliff/tests/test_commandmanager.py0000644000101700007650000000666712174545363023373 0ustar dhellmanndhellmann00000000000000 import mock from cliff.commandmanager import CommandManager class TestCommand(object): @classmethod def load(cls): return cls def __init__(self): return class TestCommandManager(CommandManager): def _load_commands(self): self.commands = { 'one': TestCommand, 'two words': TestCommand, 'three word command': TestCommand, } def test_lookup_and_find(): def check(mgr, argv): cmd, name, remaining = mgr.find_command(argv) assert cmd assert name == ' '.join(argv) assert not remaining mgr = TestCommandManager('test') for expected in [['one'], ['two', 'words'], ['three', 'word', 'command'], ]: yield check, mgr, expected return def test_lookup_with_remainder(): def check(mgr, argv): cmd, name, remaining = mgr.find_command(argv) assert cmd assert remaining == ['--opt'] mgr = TestCommandManager('test') for expected in [['one', '--opt'], ['two', 'words', '--opt'], ['three', 'word', 'command', '--opt'], ]: yield check, mgr, expected return def test_find_invalid_command(): mgr = TestCommandManager('test') def check_one(argv): try: mgr.find_command(argv) except ValueError as err: assert '-b' in ('%s' % err) else: assert False, 'expected a failure' for argv in [['a', '-b'], ['-b'], ]: yield check_one, argv def test_find_unknown_command(): mgr = TestCommandManager('test') try: mgr.find_command(['a', 'b']) except ValueError as err: assert "['a', 'b']" in ('%s' % err) else: assert False, 'expected a failure' def test_add_command(): mgr = TestCommandManager('test') mock_cmd = mock.Mock() mgr.add_command('mock', mock_cmd) found_cmd, name, args = mgr.find_command(['mock']) assert found_cmd is mock_cmd def test_load_commands(): testcmd = mock.Mock(name='testcmd') testcmd.name.replace.return_value = 'test' mock_pkg_resources = mock.Mock(return_value=[testcmd]) with mock.patch('pkg_resources.iter_entry_points', mock_pkg_resources) as iter_entry_points: mgr = CommandManager('test') assert iter_entry_points.called_once_with('test') names = [n for n, v in mgr] assert names == ['test'] def test_load_commands_keep_underscores(): testcmd = mock.Mock() testcmd.name = 'test_cmd' mock_pkg_resources = mock.Mock(return_value=[testcmd]) with mock.patch('pkg_resources.iter_entry_points', mock_pkg_resources) as iter_entry_points: mgr = CommandManager('test', convert_underscores=False) assert iter_entry_points.called_once_with('test') names = [n for n, v in mgr] assert names == ['test_cmd'] def test_load_commands_replace_underscores(): testcmd = mock.Mock() testcmd.name = 'test_cmd' mock_pkg_resources = mock.Mock(return_value=[testcmd]) with mock.patch('pkg_resources.iter_entry_points', mock_pkg_resources) as iter_entry_points: mgr = CommandManager('test', convert_underscores=True) assert iter_entry_points.called_once_with('test') names = [n for n, v in mgr] assert names == ['test cmd'] cliff-1.4.5/cliff/tests/test_help.py0000644000101700007650000000643612174545363021344 0ustar dhellmanndhellmann00000000000000try: from StringIO import StringIO except: from io import StringIO import mock from cliff.app import App from cliff.command import Command from cliff.commandmanager import CommandManager from cliff.help import HelpCommand class TestParser(object): def print_help(self, stdout): stdout.write('TestParser') class TestCommand(Command): @classmethod def load(cls): return cls def get_parser(self, ignore): # Make it look like this class is the parser # so parse_args() is called. return TestParser() def take_action(self, args): return class TestCommandManager(CommandManager): def _load_commands(self): self.commands = { 'one': TestCommand, 'two words': TestCommand, 'three word command': TestCommand, } def test_show_help_for_command(): # FIXME(dhellmann): Are commands tied too closely to the app? Or # do commands know too much about apps by using them to get to the # command manager? stdout = StringIO() app = App('testing', '1', TestCommandManager('cliff.test'), stdout=stdout) app.NAME = 'test' help_cmd = HelpCommand(app, mock.Mock()) parser = help_cmd.get_parser('test') parsed_args = parser.parse_args(['one']) try: help_cmd.run(parsed_args) except SystemExit: pass assert stdout.getvalue() == 'TestParser' def test_list_matching_commands(): # FIXME(dhellmann): Are commands tied too closely to the app? Or # do commands know too much about apps by using them to get to the # command manager? stdout = StringIO() app = App('testing', '1', TestCommandManager('cliff.test'), stdout=stdout) app.NAME = 'test' help_cmd = HelpCommand(app, mock.Mock()) parser = help_cmd.get_parser('test') parsed_args = parser.parse_args(['t']) try: help_cmd.run(parsed_args) except SystemExit: pass help_output = stdout.getvalue() assert 'Command "t" matches:' in help_output assert 'two' in help_output assert 'three' in help_output def test_list_matching_commands_no_match(): # FIXME(dhellmann): Are commands tied too closely to the app? Or # do commands know too much about apps by using them to get to the # command manager? stdout = StringIO() app = App('testing', '1', TestCommandManager('cliff.test'), stdout=stdout) app.NAME = 'test' help_cmd = HelpCommand(app, mock.Mock()) parser = help_cmd.get_parser('test') parsed_args = parser.parse_args(['z']) try: help_cmd.run(parsed_args) except SystemExit: pass except ValueError: pass else: assert False, 'Should have seen a ValueError' def test_show_help_for_help(): # FIXME(dhellmann): Are commands tied too closely to the app? Or # do commands know too much about apps by using them to get to the # command manager? stdout = StringIO() app = App('testing', '1', TestCommandManager('cliff.test'), stdout=stdout) app.NAME = 'test' help_cmd = HelpCommand(app, mock.Mock()) parser = help_cmd.get_parser('test') parsed_args = parser.parse_args([]) try: help_cmd.run(parsed_args) except SystemExit: pass help_text = stdout.getvalue() assert 'usage: test help [-h]' in help_text cliff-1.4.5/cliff/tests/test_lister.py0000644000101700007650000000231012174545363021701 0ustar dhellmanndhellmann00000000000000#!/usr/bin/env python from cliff.lister import Lister import mock class FauxFormatter(object): def __init__(self): self.args = [] def emit_list(self, columns, data, stdout, args): self.args.append((columns, data)) class ExerciseLister(Lister): def load_formatter_plugins(self): self.formatters = { 'test': FauxFormatter(), } return def take_action(self, parsed_args): return ( parsed_args.columns, [('a', 'A'), ('b', 'B')], ) # def run(self, parsed_args): # self.formatter = self.formatters[parsed_args.formatter] # column_names, data = self.take_action(parsed_args) # self.produce_output(parsed_args, column_names, data) # return 0 def test_formatter_args(): app = mock.Mock() test_lister = ExerciseLister(app, []) parsed_args = mock.Mock() parsed_args.columns = ('Col1', 'Col2') parsed_args.formatter = 'test' test_lister.run(parsed_args) f = test_lister.formatters['test'] assert len(f.args) == 1 args = f.args[0] assert args[0] == list(parsed_args.columns) data = list(args[1]) assert data == [['a', 'A'], ['b', 'B']] cliff-1.4.5/cliff/tests/test_show.py0000644000101700007650000000236112174545423021362 0ustar dhellmanndhellmann00000000000000#!/usr/bin/env python from cliff.show import ShowOne import mock class FauxFormatter(object): def __init__(self): self.args = [] def emit_list(self, columns, data, stdout, args): self.args.append((columns, data)) class ExerciseShowOne(ShowOne): def load_formatter_plugins(self): self.formatters = { 'test': FauxFormatter(), } return def take_action(self, parsed_args): return ( parsed_args.columns, [('a', 'A'), ('b', 'B')], ) # def test_formatter_args(): # app = mock.Mock() # test_lister = ExerciseLister(app, []) # parsed_args = mock.Mock() # parsed_args.columns = ('Col1', 'Col2') # parsed_args.formatter = 'test' # test_lister.run(parsed_args) # f = test_lister.formatters['test'] # assert len(f.args) == 1 # args = f.args[0] # assert args[0] == list(parsed_args.columns) # data = list(args[1]) # assert data == [['a', 'A'], ['b', 'B']] def test_dict2columns(): app = mock.Mock() test_show = ExerciseShowOne(app, []) d = {'a': 'A', 'b': 'B', 'c': 'C'} expected = [('a', 'b', 'c'), ('A', 'B', 'C')] actual = list(test_show.dict2columns(d)) assert expected == actual cliff-1.4.5/cliff.egg-info/0000755000101700007650000000000012220116306017301 5ustar dhellmanndhellmann00000000000000cliff-1.4.5/cliff.egg-info/dependency_links.txt0000644000101700007650000000000112220116305023346 0ustar dhellmanndhellmann00000000000000 cliff-1.4.5/cliff.egg-info/entry_points.txt0000644000101700007650000000035212220116305022576 0ustar dhellmanndhellmann00000000000000[cliff.formatter.list] table = cliff.formatters.table:TableFormatter csv = cliff.formatters.commaseparated:CSVLister [cliff.formatter.show] table = cliff.formatters.table:TableFormatter shell = cliff.formatters.shell:ShellFormatter cliff-1.4.5/cliff.egg-info/namespace_packages.txt0000644000101700007650000000000112220116305023622 0ustar dhellmanndhellmann00000000000000 cliff-1.4.5/cliff.egg-info/not-zip-safe0000644000101700007650000000000112152152421021531 0ustar dhellmanndhellmann00000000000000 cliff-1.4.5/cliff.egg-info/PKG-INFO0000644000101700007650000000266512220116305020406 0ustar dhellmanndhellmann00000000000000Metadata-Version: 1.1 Name: cliff Version: 1.4.5 Summary: Command Line Interface Formulation Framework Home-page: https://github.com/dreamhost/cliff Author: Doug Hellmann Author-email: doug.hellmann@gmail.com License: UNKNOWN Download-URL: https://github.com/dreamhost/cliff/tarball/master Description: ======================================================= cliff -- Command Line Interface Formulation Framework ======================================================= .. image:: https://secure.travis-ci.org/dhellmann/cliff.png?branch=master cliff is a framework for building command line programs. It uses setuptools entry points to provide subcommands, output formatters, and other extensions. Documentation ============= Documentation for cliff is hosted on readthedocs.org at http://readthedocs.org/docs/cliff/en/latest/ Platform: Any Classifier: Development Status :: 5 - Production/Stable Classifier: License :: OSI Approved :: Apache Software License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Intended Audience :: Developers Classifier: Environment :: Console Provides: cliff cliff-1.4.5/cliff.egg-info/requires.txt0000644000101700007650000000006212220116305021676 0ustar dhellmanndhellmann00000000000000PrettyTable>=0.6,<0.8 pyparsing>=2.0.1 cmd2>=0.6.7cliff-1.4.5/cliff.egg-info/SOURCES.txt0000644000101700007650000000601512220116305021166 0ustar dhellmanndhellmann00000000000000.gitignore .travis.yml LICENSE MANIFEST.in Makefile README.rst announce.rst setup.py test-requirements.txt tox.ini cliff/__init__.py cliff/app.py cliff/command.py cliff/commandmanager.py cliff/display.py cliff/help.py cliff/interactive.py cliff/lister.py cliff/show.py cliff.egg-info/PKG-INFO cliff.egg-info/SOURCES.txt cliff.egg-info/dependency_links.txt cliff.egg-info/entry_points.txt cliff.egg-info/namespace_packages.txt cliff.egg-info/not-zip-safe cliff.egg-info/requires.txt cliff.egg-info/top_level.txt cliff/formatters/__init__.py cliff/formatters/base.py cliff/formatters/commaseparated.py cliff/formatters/shell.py cliff/formatters/table.py cliff/tests/__init__.py cliff/tests/test_app.py cliff/tests/test_command.py cliff/tests/test_commandmanager.py cliff/tests/test_help.py cliff/tests/test_lister.py cliff/tests/test_show.py demoapp/README.rst demoapp/setup.py demoapp/build/lib/cliffdemo/__init__.py demoapp/build/lib/cliffdemo/encoding.py demoapp/build/lib/cliffdemo/list.py demoapp/build/lib/cliffdemo/main.py demoapp/build/lib/cliffdemo/show.py demoapp/build/lib/cliffdemo/simple.py demoapp/cliffdemo/__init__.py demoapp/cliffdemo/encoding.py demoapp/cliffdemo/list.py demoapp/cliffdemo/main.py demoapp/cliffdemo/show.py demoapp/cliffdemo/simple.py docs/Makefile docs/requirements.txt docs/build/html/classes.html docs/build/html/demoapp.html docs/build/html/developers.html docs/build/html/genindex.html docs/build/html/history.html docs/build/html/index.html docs/build/html/install.html docs/build/html/interactive_mode.html docs/build/html/introduction.html docs/build/html/list_commands.html docs/build/html/search.html docs/build/html/searchindex.js docs/build/html/show_commands.html docs/build/html/_sources/classes.txt docs/build/html/_sources/demoapp.txt docs/build/html/_sources/developers.txt docs/build/html/_sources/history.txt docs/build/html/_sources/index.txt docs/build/html/_sources/install.txt docs/build/html/_sources/interactive_mode.txt docs/build/html/_sources/introduction.txt docs/build/html/_sources/list_commands.txt docs/build/html/_sources/show_commands.txt docs/build/html/_static/basic.css docs/build/html/_static/comment-bright.png docs/build/html/_static/comment-close.png docs/build/html/_static/comment.png docs/build/html/_static/default.css docs/build/html/_static/doctools.js docs/build/html/_static/down-pressed.png docs/build/html/_static/down.png docs/build/html/_static/file.png docs/build/html/_static/jquery.js docs/build/html/_static/minus.png docs/build/html/_static/plus.png docs/build/html/_static/pygments.css docs/build/html/_static/searchtools.js docs/build/html/_static/sidebar.js docs/build/html/_static/underscore.js docs/build/html/_static/up-pressed.png docs/build/html/_static/up.png docs/build/html/_static/websupport.js docs/source/classes.rst docs/source/conf.py docs/source/demoapp.rst docs/source/developers.rst docs/source/history.rst docs/source/index.rst docs/source/install.rst docs/source/interactive_mode.rst docs/source/introduction.rst docs/source/list_commands.rst docs/source/show_commands.rstcliff-1.4.5/cliff.egg-info/top_level.txt0000644000101700007650000000000612220116305022026 0ustar dhellmanndhellmann00000000000000cliff cliff-1.4.5/demoapp/0000755000101700007650000000000012220116306016151 5ustar dhellmanndhellmann00000000000000cliff-1.4.5/demoapp/build/0000755000101700007650000000000012220116306017250 5ustar dhellmanndhellmann00000000000000cliff-1.4.5/demoapp/build/lib/0000755000101700007650000000000012220116306020016 5ustar dhellmanndhellmann00000000000000cliff-1.4.5/demoapp/build/lib/cliffdemo/0000755000101700007650000000000012220116306021746 5ustar dhellmanndhellmann00000000000000cliff-1.4.5/demoapp/build/lib/cliffdemo/__init__.py0000644000101700007650000000000011744324650024062 0ustar dhellmanndhellmann00000000000000cliff-1.4.5/demoapp/build/lib/cliffdemo/encoding.py0000644000101700007650000000071112202717230024110 0ustar dhellmanndhellmann00000000000000# -*- encoding: utf-8 -*- import logging from cliff.lister import Lister class Encoding(Lister): """Show some unicode text """ log = logging.getLogger(__name__) def take_action(self, parsed_args): messages = [ u'pi: Ï€', u'GB18030:鼀丅ã€Ù¸à½á §êŒ¢â‚¬', ] return ( ('UTF-8', 'Unicode'), [(repr(t.encode('utf-8')), t) for t in messages], ) cliff-1.4.5/demoapp/build/lib/cliffdemo/list.py0000644000101700007650000000061211770433433023306 0ustar dhellmanndhellmann00000000000000import logging import os from cliff.lister import Lister class Files(Lister): """Show a list of files in the current directory. The file name and size are printed by default. """ log = logging.getLogger(__name__) def take_action(self, parsed_args): return (('Name', 'Size'), ((n, os.stat(n).st_size) for n in os.listdir('.')) ) cliff-1.4.5/demoapp/build/lib/cliffdemo/main.py0000644000101700007650000000156011753012445023257 0ustar dhellmanndhellmann00000000000000import logging import sys from cliff.app import App from cliff.commandmanager import CommandManager class DemoApp(App): log = logging.getLogger(__name__) def __init__(self): super(DemoApp, self).__init__( description='cliff demo app', version='0.1', command_manager=CommandManager('cliff.demo'), ) def initialize_app(self, argv): self.log.debug('initialize_app') def prepare_to_run_command(self, cmd): self.log.debug('prepare_to_run_command %s', cmd.__class__.__name__) def clean_up(self, cmd, result, err): self.log.debug('clean_up %s', cmd.__class__.__name__) if err: self.log.debug('got an error: %s', err) def main(argv=sys.argv[1:]): myapp = DemoApp() return myapp.run(argv) if __name__ == '__main__': sys.exit(main(sys.argv[1:])) cliff-1.4.5/demoapp/build/lib/cliffdemo/show.py0000644000101700007650000000145411770433433023320 0ustar dhellmanndhellmann00000000000000import logging import os from cliff.show import ShowOne class File(ShowOne): "Show details about a file" log = logging.getLogger(__name__) def get_parser(self, prog_name): parser = super(File, self).get_parser(prog_name) parser.add_argument('filename', nargs='?', default='.') return parser def take_action(self, parsed_args): stat_data = os.stat(parsed_args.filename) columns = ('Name', 'Size', 'UID', 'GID', 'Modified Time', ) data = (parsed_args.filename, stat_data.st_size, stat_data.st_uid, stat_data.st_gid, stat_data.st_mtime, ) return (columns, data) cliff-1.4.5/demoapp/build/lib/cliffdemo/simple.py0000644000101700007650000000104711770434662023634 0ustar dhellmanndhellmann00000000000000import logging from cliff.command import Command class Simple(Command): "A simple command that prints a message." log = logging.getLogger(__name__) def take_action(self, parsed_args): self.log.info('sending greeting') self.log.debug('debugging') self.app.stdout.write('hi!\n') class Error(Command): "Always raises an error" log = logging.getLogger(__name__) def take_action(self, parsed_args): self.log.info('causing error') raise RuntimeError('this is the expected exception') cliff-1.4.5/demoapp/cliffdemo/0000755000101700007650000000000012220116306020101 5ustar dhellmanndhellmann00000000000000cliff-1.4.5/demoapp/cliffdemo/__init__.py0000644000101700007650000000000011744324650022215 0ustar dhellmanndhellmann00000000000000cliff-1.4.5/demoapp/cliffdemo/encoding.py0000644000101700007650000000071112202717230022243 0ustar dhellmanndhellmann00000000000000# -*- encoding: utf-8 -*- import logging from cliff.lister import Lister class Encoding(Lister): """Show some unicode text """ log = logging.getLogger(__name__) def take_action(self, parsed_args): messages = [ u'pi: Ï€', u'GB18030:鼀丅ã€Ù¸à½á §êŒ¢â‚¬', ] return ( ('UTF-8', 'Unicode'), [(repr(t.encode('utf-8')), t) for t in messages], ) cliff-1.4.5/demoapp/cliffdemo/list.py0000644000101700007650000000061211770433433021441 0ustar dhellmanndhellmann00000000000000import logging import os from cliff.lister import Lister class Files(Lister): """Show a list of files in the current directory. The file name and size are printed by default. """ log = logging.getLogger(__name__) def take_action(self, parsed_args): return (('Name', 'Size'), ((n, os.stat(n).st_size) for n in os.listdir('.')) ) cliff-1.4.5/demoapp/cliffdemo/main.py0000644000101700007650000000156011753012445021412 0ustar dhellmanndhellmann00000000000000import logging import sys from cliff.app import App from cliff.commandmanager import CommandManager class DemoApp(App): log = logging.getLogger(__name__) def __init__(self): super(DemoApp, self).__init__( description='cliff demo app', version='0.1', command_manager=CommandManager('cliff.demo'), ) def initialize_app(self, argv): self.log.debug('initialize_app') def prepare_to_run_command(self, cmd): self.log.debug('prepare_to_run_command %s', cmd.__class__.__name__) def clean_up(self, cmd, result, err): self.log.debug('clean_up %s', cmd.__class__.__name__) if err: self.log.debug('got an error: %s', err) def main(argv=sys.argv[1:]): myapp = DemoApp() return myapp.run(argv) if __name__ == '__main__': sys.exit(main(sys.argv[1:])) cliff-1.4.5/demoapp/cliffdemo/show.py0000644000101700007650000000145411770433433021453 0ustar dhellmanndhellmann00000000000000import logging import os from cliff.show import ShowOne class File(ShowOne): "Show details about a file" log = logging.getLogger(__name__) def get_parser(self, prog_name): parser = super(File, self).get_parser(prog_name) parser.add_argument('filename', nargs='?', default='.') return parser def take_action(self, parsed_args): stat_data = os.stat(parsed_args.filename) columns = ('Name', 'Size', 'UID', 'GID', 'Modified Time', ) data = (parsed_args.filename, stat_data.st_size, stat_data.st_uid, stat_data.st_gid, stat_data.st_mtime, ) return (columns, data) cliff-1.4.5/demoapp/cliffdemo/simple.py0000644000101700007650000000104711770434662021767 0ustar dhellmanndhellmann00000000000000import logging from cliff.command import Command class Simple(Command): "A simple command that prints a message." log = logging.getLogger(__name__) def take_action(self, parsed_args): self.log.info('sending greeting') self.log.debug('debugging') self.app.stdout.write('hi!\n') class Error(Command): "Always raises an error" log = logging.getLogger(__name__) def take_action(self, parsed_args): self.log.info('causing error') raise RuntimeError('this is the expected exception') cliff-1.4.5/demoapp/README.rst0000644000101700007650000000170012100332522017633 0ustar dhellmanndhellmann00000000000000================= Running demoapp ================= Setup ----- First, you need to create a virtual environment and activate it. :: $ pip install virtualenv $ virtualenv .venv $ . .venv/bin/activate (.venv)$ Next, install ``cliff`` in the environment. :: (.venv)$ python setup.py install Now, install the demo application into the virtual environment. :: (.venv)$ cd demoapp (.venv)$ python setup.py install Usage ----- With cliff and the demo setup up, you can now play with it. To see a list of commands available, run:: (.venv)$ cliffdemo --help One of the available commands is "simple" and running it :: (.venv)$ cliffdemo simple produces the following :: sending greeting hi! To see help for an individual command, include the command name on the command line:: (.venv)$ cliffdemo files --help Cleaning Up ----------- Finally, when done, deactivate your virtual environment:: (.venv)$ deactivate $ cliff-1.4.5/demoapp/setup.py0000644000101700007650000000341712220115753017675 0ustar dhellmanndhellmann00000000000000#!/usr/bin/env python PROJECT = 'cliffdemo' # Change docs/sphinx/conf.py too! VERSION = '0.1' from setuptools import setup, find_packages try: long_description = open('README.rst', 'rt').read() except IOError: long_description = '' setup( name=PROJECT, version=VERSION, description='Demo app for cliff', long_description=long_description, author='Doug Hellmann', author_email='doug.hellmann@gmail.com', url='https://github.com/dreamhost/cliff', download_url='https://github.com/dreamhost/cliff/tarball/master', classifiers=['Development Status :: 3 - Alpha', 'License :: OSI Approved :: Apache Software License', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.2', 'Intended Audience :: Developers', 'Environment :: Console', ], platforms=['Any'], scripts=[], provides=[], install_requires=['cliff'], namespace_packages=[], packages=find_packages(), include_package_data=True, entry_points={ 'console_scripts': [ 'cliffdemo = cliffdemo.main:main' ], 'cliff.demo': [ 'simple = cliffdemo.simple:Simple', 'two_part = cliffdemo.simple:Simple', 'error = cliffdemo.simple:Error', 'list files = cliffdemo.list:Files', 'files = cliffdemo.list:Files', 'file = cliffdemo.show:File', 'show file = cliffdemo.show:File', 'unicode = cliffdemo.encoding:Encoding', ], }, zip_safe=False, ) cliff-1.4.5/docs/0000755000101700007650000000000012220116306015454 5ustar dhellmanndhellmann00000000000000cliff-1.4.5/docs/build/0000755000101700007650000000000012220116306016553 5ustar dhellmanndhellmann00000000000000cliff-1.4.5/docs/build/html/0000755000101700007650000000000012220116306017517 5ustar dhellmanndhellmann00000000000000cliff-1.4.5/docs/build/html/_sources/0000755000101700007650000000000012220116306021341 5ustar dhellmanndhellmann00000000000000cliff-1.4.5/docs/build/html/_sources/classes.txt0000644000101700007650000000146711751625252023564 0ustar dhellmanndhellmann00000000000000=============== Cliff Classes =============== Application =========== App --- .. autoclass:: cliff.app.App :members: InteractiveApp -------------- .. autoclass:: cliff.interactive.InteractiveApp :members: CommandManager -------------- .. autoclass:: cliff.commandmanager.CommandManager :members: Command ------- .. autoclass:: cliff.command.Command :members: ShowOne ------- .. autoclass:: cliff.show.ShowOne :members: Lister ------ .. autoclass:: cliff.lister.Lister :members: Formatting Output ================= Formatter --------- .. autoclass:: cliff.formatters.base.Formatter :members: ListFormatter ------------- .. autoclass:: cliff.formatters.base.ListFormatter :members: SingleFormatter --------------- .. autoclass:: cliff.formatters.base.SingleFormatter :members: cliff-1.4.5/docs/build/html/_sources/demoapp.txt0000644000101700007650000001565011770436167023561 0ustar dhellmanndhellmann00000000000000======================== 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 and a list of the commands available from the plugins, run:: (.venv)$ cliffdemo -h or:: (.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, use the ``help`` command:: (.venv)$ cliffdemo help files 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:`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:`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``. 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 218, in run_subcommand result = cmd.run(parsed_args) 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') RuntimeError: this is the expected exception Traceback (most recent call last): File "/Users/dhellmann/Envs/cliff/bin/cliffdemo", line 9, in load_entry_point('cliffdemo==0.1', 'console_scripts', 'cliffdemo')() File ".../demoapp/cliffdemo/main.py", line 33, in main return myapp.run(argv) 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) 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') 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 .. _demoapp-show: show.py ------- ``show.py`` includes a single command derived from :class:`cliff.show.ShowOne` which prints the properties of the named file. .. literalinclude:: ../../demoapp/cliffdemo/show.py :linenos: :class:`File` prepares the data, and :class:`ShowOne` manages the output formatter and printing the data to the console. :: (.venv)$ cliffdemo file setup.py +---------------+--------------+ | Field | Value | +---------------+--------------+ | Name | setup.py | | Size | 5825 | | UID | 502 | | GID | 20 | | Modified Time | 1335569964.0 | +---------------+--------------+ 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/ cliff-1.4.5/docs/build/html/_sources/developers.txt0000644000101700007650000000473511753563746024313 0ustar dhellmanndhellmann00000000000000================ For Developers ================ If you would like to contribute to cliff directly, these instructions should help you get started. Patches, bug reports, and feature requests are all welcome through the `GitHub project `_. Contributions in the form of patches or pull requests are easier to integrate and will receive priority attention. .. note:: Before contributing new features to clif core, please consider whether they should be implemented as an extension instead. The architecture is highly pluggable precisely to keep the core small. Building Documentation ====================== The documentation for cliff is written in reStructuredText and converted to HTML using Sphinx. The build itself is driven by make. You will need the following packages in order to build the docs: - Sphinx - docutils Once all of the tools are installed into a virtualenv using pip, run ``make docs`` to generate the HTML version of the documentation:: $ make docs (cd docs && make clean html) sphinx-build -b html -d build/doctrees source build/html Running Sphinx v1.1.3 loading pickled environment... done building [html]: targets for 1 source files that are out of date updating environment: 1 added, 1 changed, 0 removed reading sources... [100%] index looking for now-outdated files... none found pickling environment... done done preparing documents... done writing output... [100%] index writing additional files... genindex search copying static files... done dumping search index... done dumping object inventory... done build succeeded, 2 warnings. Build finished. The HTML pages are in build/html. The output version of the documentation ends up in ``./docs/build/html`` inside your sandbox. Running Tests ============= .. image:: https://secure.travis-ci.org/dhellmann/cliff.png?branch=master The test suite for clif uses tox_, which must be installed separately (``pip install tox``). To run the tests under Python 2.7 and 3.2, run ``tox`` from the top level directory of the git repository. To run tests under a single version of Python, specify the appropriate environment when running tox:: $ tox -e py27 Add new tests by modifying an existing file or creating new script in the ``tests`` directory. .. _tox: http://codespeak.net/tox .. _developer-templates: cliff-1.4.5/docs/build/html/_sources/history.txt0000644000101700007650000000503512041051374023612 0ustar dhellmanndhellmann00000000000000================= Release History ================= 1.3 - Allow user to pass ``argparse_kwargs`` argument to the ``build_option_parser`` method. This argument can contain extra keyword arguments which are passed to the ``ArgumentParser`` constructor. (contributed by Tomaz Muraus) - Updated documentation to include dependency on distribute. 1.2.1 - Fix problem with documentation packaging. - Fix problem with missing ``izip`` import in ``lister.py``. 1.2 - Fix problem with interactive mode ``help`` command. - Disable logging by default but add a ``--log-file`` option to re-enable it at runtime. - Add support for python 2.6. (contributed by Mark McClain for OpenStack Quantum) 1.1.2 - Fix a packaging problem introduced in version 1.1. 1.1 - Move tablib support (JSON, YAML, and HTML formatters) to a separate project to comply with Ubuntu packaging requirements. See https://github.com/dreamhost/cliff-tablib 1.0 - Add trailing newlines after output from tablib-based formatters (JSON, YAML, and HTML). Contributed by Matt Joyce. - 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 - Clean up interactive mode flag settting. - Add support for Python 2.6, contributed by heavenshell. - Fix multi-word commands in interactive mode. 0.6 - Pass the non-global argument list to :func:`initialize_app` to be used in initialization work. 0.5.1 - Remove pinned version requirement for PrettyTable until the OpenStack clients catch up to the API change. 0.5 - Asking for help about a command by prefix lists all matching commands. - Add formatters for HTML, JSON, and YAML. 0.4 - Add shell formatter for single objects. - Add interactive mode. - Expand documentation. 0.3 - Add ShowOne base class for commands that show details about single objects. - Fix a problem with Lister when there is no data to be printed. 0.2 - Incorporate changes from dtroyer to replace use of optparse in App with argparse. - Added "help" subcommand to replace ``--help`` option handling in subcommands. 0.1 - Initial public release. - Included App, CommandManager, Lister, csv and table formatters, a demo application, and basic documentation. cliff-1.4.5/docs/build/html/_sources/index.txt0000644000101700007650000000111011747077561023230 0ustar dhellmanndhellmann00000000000000======================================================= cliff -- Command Line Interface Formulation Framework ======================================================= cliff is a framework for building command line programs. It uses plugins to define sub-commands, output formatters, and other extensions. Contents: .. toctree:: :maxdepth: 2 introduction demoapp list_commands show_commands interactive_mode classes install developers history Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` .. todolist:: cliff-1.4.5/docs/build/html/_sources/install.txt0000644000101700007650000000244612041050260023553 0ustar dhellmanndhellmann00000000000000============== Installation ============== Python Versions =============== cliff is being developed under Python 2.7 and tested with Python 3.2. Dependencies ============ cliff depends on distribute_, the updated replacement for setuptools. If you have an older version of setuptools installed, `you may have trouble installing cliff`_ until you upgrade or set up a virtualenv_ using distribute instead (by using ``--use-distribute``). .. _distribute: http://pypi.python.org/pypi/distribute .. _you may have trouble installing cliff: https://bitbucket.org/tarek/distribute/issue/91/install-glitch-when-using-pip-virtualenv .. _virtualenv: http://pypi.python.org/pypi/virtualenv .. _install-basic: Basic Installation ================== cliff should be installed into the same site-packages area where the application and extensions are installed (either a virtualenv or the global site-packages). You may need administrative privileges to do that. The easiest way to install it is using pip_:: $ pip install cliff or:: $ sudo pip install cliff .. _pip: http://pypi.python.org/pypi/pip Source Code =========== The source is hosted on github: https://github.com/dreamhost/cliff Reporting Bugs ============== Please report bugs through the github project: https://github.com/dreamhost/cliff/issues cliff-1.4.5/docs/build/html/_sources/interactive_mode.txt0000644000101700007650000000533111747077561025453 0ustar dhellmanndhellmann00000000000000================== 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 ): =================================== 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 ): ========================================= 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) cliff-1.4.5/docs/build/html/_sources/introduction.txt0000644000101700007650000000443711770434512024646 0ustar dhellmanndhellmann00000000000000============== 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 four 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:`take_action` 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 cliff-1.4.5/docs/build/html/_sources/list_commands.txt0000644000101700007650000000454112006261746024755 0ustar dhellmanndhellmann00000000000000=============== 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 allow :func:`take_action` to return data to be formatted using a user-selectable formatter. Subclasses should provide a :func:`take_action` 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 ` 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. :: (.venv)$ cliffdemo files -f csv "Name","Size" "build",136 "cliffdemo.log",2690 "Makefile",5569 "source",408 table ----- The ``table`` formatter uses PrettyTable_ to produce output formatted for human consumption. .. _PrettyTable: http://code.google.com/p/prettytable/ :: (.venv)$ cliffdemo files +---------------+------+ | Name | Size | +---------------+------+ | build | 136 | | cliffdemo.log | 2546 | | Makefile | 5569 | | source | 408 | +---------------+------+ Other Formatters ---------------- Formatters using tablib_ to produce JSON, YAML, and HTML are available as part of `cliff-tablib`_. .. _cliff-tablib: https://github.com/dreamhost/cliff-tablib 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. .. _tablib: https://github.com/kennethreitz/tablib cliff-1.4.5/docs/build/html/_sources/show_commands.txt0000644000101700007650000000514612006261746024764 0ustar dhellmanndhellmann00000000000000=============== Show Commands =============== One of the most common patterns with command line programs is the need to print properties of objects. 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 data in their preferred format. ShowOne ======= The :class:`cliff.show.ShowOne` base class API extends :class:`Command` to allow :func:`take_action` to return data to be formatted using a user-selectable formatter. Subclasses should provide a :func:`take_action` implementation that returns a two member tuple 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 ` for details. Show Output Formatters ====================== cliff is delivered with output formatters for show commands. :class:`ShowOne` 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. shell ----- The ``shell`` formatter produces output that can be parsed directly by a typical UNIX shell as variable assignments. This avoids extra parsing overhead in shell scripts. :: (.venv)$ cliffdemo file -f shell setup.py name="setup.py" size="5916" uid="527" gid="501" modified_time="1335655655.0" (.venv)$ eval "$(cliffdemo file -f shell --prefix example_ setup.py)" (.venv)$ echo $example_size 5916 table ----- The ``table`` formatter uses PrettyTable_ to produce output formatted for human consumption. .. _PrettyTable: http://code.google.com/p/prettytable/ :: (.venv)$ cliffdemo file setup.py +---------------+--------------+ | Field | Value | +---------------+--------------+ | Name | setup.py | | Size | 5825 | | UID | 502 | | GID | 20 | | Modified Time | 1335569964.0 | +---------------+--------------+ Other Formatters ---------------- Formatters using tablib_ to produce JSON, YAML, and HTML are available as part of `cliff-tablib`_. .. _cliff-tablib: https://github.com/dreamhost/cliff-tablib 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.ShowFormatter` and registering the plugin in the ``cliff.formatter.show`` namespace. .. _tablib: https://github.com/kennethreitz/tablib cliff-1.4.5/docs/build/html/_static/0000755000101700007650000000000012220116306021145 5ustar dhellmanndhellmann00000000000000cliff-1.4.5/docs/build/html/_static/basic.css0000644000101700007650000002041712041051472022747 0ustar dhellmanndhellmann00000000000000/* * basic.css * ~~~~~~~~~ * * Sphinx stylesheet -- basic theme. * * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ /* -- main layout ----------------------------------------------------------- */ div.clearer { clear: both; } /* -- relbar ---------------------------------------------------------------- */ div.related { width: 100%; font-size: 90%; } div.related h3 { display: none; } div.related ul { margin: 0; padding: 0 0 0 10px; list-style: none; } div.related li { display: inline; } div.related li.right { float: right; margin-right: 5px; } /* -- sidebar --------------------------------------------------------------- */ div.sphinxsidebarwrapper { padding: 10px 5px 0 10px; } div.sphinxsidebar { float: left; width: 230px; margin-left: -100%; font-size: 90%; } div.sphinxsidebar ul { list-style: none; } div.sphinxsidebar ul ul, div.sphinxsidebar ul.want-points { margin-left: 20px; list-style: square; } div.sphinxsidebar ul ul { margin-top: 0; margin-bottom: 0; } div.sphinxsidebar form { margin-top: 10px; } div.sphinxsidebar input { border: 1px solid #98dbcc; font-family: sans-serif; font-size: 1em; } div.sphinxsidebar #searchbox input[type="text"] { width: 170px; } div.sphinxsidebar #searchbox input[type="submit"] { width: 30px; } img { border: 0; } /* -- search page ----------------------------------------------------------- */ ul.search { margin: 10px 0 0 20px; padding: 0; } ul.search li { padding: 5px 0 5px 20px; background-image: url(file.png); background-repeat: no-repeat; background-position: 0 7px; } ul.search li a { font-weight: bold; } ul.search li div.context { color: #888; margin: 2px 0 0 30px; text-align: left; } ul.keywordmatches li.goodmatch a { font-weight: bold; } /* -- index page ------------------------------------------------------------ */ table.contentstable { width: 90%; } table.contentstable p.biglink { line-height: 150%; } a.biglink { font-size: 1.3em; } span.linkdescr { font-style: italic; padding-top: 5px; font-size: 90%; } /* -- general index --------------------------------------------------------- */ table.indextable { width: 100%; } table.indextable td { text-align: left; vertical-align: top; } table.indextable dl, table.indextable dd { margin-top: 0; margin-bottom: 0; } table.indextable tr.pcap { height: 10px; } table.indextable tr.cap { margin-top: 10px; background-color: #f2f2f2; } img.toggler { margin-right: 3px; margin-top: 3px; cursor: pointer; } div.modindex-jumpbox { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; margin: 1em 0 1em 0; padding: 0.4em; } div.genindex-jumpbox { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; margin: 1em 0 1em 0; padding: 0.4em; } /* -- general body styles --------------------------------------------------- */ a.headerlink { visibility: hidden; } h1:hover > a.headerlink, h2:hover > a.headerlink, h3:hover > a.headerlink, h4:hover > a.headerlink, h5:hover > a.headerlink, h6:hover > a.headerlink, dt:hover > a.headerlink { visibility: visible; } div.body p.caption { text-align: inherit; } div.body td { text-align: left; } .field-list ul { padding-left: 1em; } .first { margin-top: 0 !important; } p.rubric { margin-top: 30px; font-weight: bold; } img.align-left, .figure.align-left, object.align-left { clear: left; float: left; margin-right: 1em; } img.align-right, .figure.align-right, object.align-right { clear: right; float: right; margin-left: 1em; } img.align-center, .figure.align-center, object.align-center { display: block; margin-left: auto; margin-right: auto; } .align-left { text-align: left; } .align-center { text-align: center; } .align-right { text-align: right; } /* -- sidebars -------------------------------------------------------------- */ div.sidebar { margin: 0 0 0.5em 1em; border: 1px solid #ddb; padding: 7px 7px 0 7px; background-color: #ffe; width: 40%; float: right; } p.sidebar-title { font-weight: bold; } /* -- topics ---------------------------------------------------------------- */ div.topic { border: 1px solid #ccc; padding: 7px 7px 0 7px; margin: 10px 0 10px 0; } p.topic-title { font-size: 1.1em; font-weight: bold; margin-top: 10px; } /* -- admonitions ----------------------------------------------------------- */ div.admonition { margin-top: 10px; margin-bottom: 10px; padding: 7px; } div.admonition dt { font-weight: bold; } div.admonition dl { margin-bottom: 0; } p.admonition-title { margin: 0px 10px 5px 0px; font-weight: bold; } div.body p.centered { text-align: center; margin-top: 25px; } /* -- tables ---------------------------------------------------------------- */ table.docutils { border: 0; border-collapse: collapse; } table.docutils td, table.docutils th { padding: 1px 8px 1px 5px; border-top: 0; border-left: 0; border-right: 0; border-bottom: 1px solid #aaa; } table.field-list td, table.field-list th { border: 0 !important; } table.footnote td, table.footnote th { border: 0 !important; } th { text-align: left; padding-right: 5px; } table.citation { border-left: solid 1px gray; margin-left: 1px; } table.citation td { border-bottom: none; } /* -- other body styles ----------------------------------------------------- */ ol.arabic { list-style: decimal; } ol.loweralpha { list-style: lower-alpha; } ol.upperalpha { list-style: upper-alpha; } ol.lowerroman { list-style: lower-roman; } ol.upperroman { list-style: upper-roman; } dl { margin-bottom: 15px; } dd p { margin-top: 0px; } dd ul, dd table { margin-bottom: 10px; } dd { margin-top: 3px; margin-bottom: 10px; margin-left: 30px; } dt:target, .highlighted { background-color: #fbe54e; } dl.glossary dt { font-weight: bold; font-size: 1.1em; } .field-list ul { margin: 0; padding-left: 1em; } .field-list p { margin: 0; } .refcount { color: #060; } .optional { font-size: 1.3em; } .versionmodified { font-style: italic; } .system-message { background-color: #fda; padding: 5px; border: 3px solid red; } .footnote:target { background-color: #ffa; } .line-block { display: block; margin-top: 1em; margin-bottom: 1em; } .line-block .line-block { margin-top: 0; margin-bottom: 0; margin-left: 1.5em; } .guilabel, .menuselection { font-family: sans-serif; } .accelerator { text-decoration: underline; } .classifier { font-style: oblique; } abbr, acronym { border-bottom: dotted 1px; cursor: help; } /* -- code displays --------------------------------------------------------- */ pre { overflow: auto; overflow-y: hidden; /* fixes display issues on Chrome browsers */ } td.linenos pre { padding: 5px 0px; border: 0; background-color: transparent; color: #aaa; } table.highlighttable { margin-left: 0.5em; } table.highlighttable td { padding: 0 0.5em 0 0.5em; } tt.descname { background-color: transparent; font-weight: bold; font-size: 1.2em; } tt.descclassname { background-color: transparent; } tt.xref, a tt { background-color: transparent; font-weight: bold; } h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { background-color: transparent; } .viewcode-link { float: right; } .viewcode-back { float: right; font-family: sans-serif; } div.viewcode-block:target { margin: -1px -10px; padding: 0 10px; } /* -- math display ---------------------------------------------------------- */ img.math { vertical-align: middle; } div.body div.math p { text-align: center; } span.eqno { float: right; } /* -- printout stylesheet --------------------------------------------------- */ @media print { div.document, div.documentwrapper, div.bodywrapper { margin: 0 !important; width: 100%; } div.sphinxsidebar, div.related, div.footer, #top-link { display: none; } }cliff-1.4.5/docs/build/html/_static/comment-bright.png0000644000101700007650000000665412017700372024613 0ustar dhellmanndhellmann00000000000000‰PNG  IHDRóÿa OiCCPPhotoshop ICC profilexÚSgTSé=÷ÞôBKˆ€”KoR RB‹€‘&*! Jˆ!¡ÙQÁEEÈ ˆŽŽ€ŒQ, Š Øä!¢Žƒ£ˆŠÊûá{£kÖ¼÷æÍþµ×>ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛbKGDÿÿÿ ½§“ pHYs  šœtIMEÚ 6 B©\<ÞIDAT8Ë…’Kh]e…¿½ÿs1mAÛÄÚ`j‚Ïh[-ˆE(FEŠÁaAœ! bI« àÈ*–BX‘"Ø4)NŠõUR‚Zˆ¹­!’×Mhj“›ssÎùÿíà–¨àãmØ‹Å^‹-\ggßÏ ÷ßì]o|ÑÑÒ¬[3±¶4§Á§6»”û©òèø¯×>zd‘¿ ]½#Œ»î8ÙþüáÇOݺ±t{5·uIÍXN!I=@Vf¾®Ÿ=v×ÀÞþ1ûº}e>;ØÉö×fvìénøvËÍÅxaÉHrÏʪJ’¦Fȹ`œÈðDò¹WZ®]ÀžSíýŸø%S)ÌWAÌœb¹ |0K=âSo7D†~\~qâÍ-ïÀËŸ\ùaóMÅ“Z,S'*æô™‘È} óF`—†ÎNnzæ674¸öËUÈç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛbKGDÿÿÿ ½§“ pHYs  šœtIMEÚ!â›ÈÝ,IDAT8Ëe’_HuÇ?Ïï}ßsŽž3ÍyòË•¶¦‹U2MvQÉÖŠFÔE¬.ŠÑÍÃÅ‚­ÄŠbÑE$DD­‹ËZF5b@QÌ"š:2§›š¦¾ïû{Ÿn.êsõåçû<_ø yî?ô½m÷²ýè·wV™ê@t£R`}Z íÄÐ_£# _=œá_@ÝËý ßw^óRë®·•%6gC-έ(K>ä| $„Éï{¯}ç¬ó³ÏÀ –H3Q5€ ©BàƒÇÄÆáä.@ $p³d!sý#ø~<<+"À¾xÓ ÀM›À0‡ÿêB™\€„Àt‘8K€@zŽB¦@F€˜&S `ËcbãP-`'æÓ€ø™{[”! ‘ eˆDh;¬ÏVŠEX0fKÄ9Ø-0IWfH°·ÀÎ ² 0Qˆ…){`È##x„™FòW<ñ+®ç*x™²<¹$9E[-qWW.(ÎI+6aaš@.Ây™24àóÌ ‘àƒóýxήÎÎ6޶_-ê¿ÿ"bbãþåÏ«p@át~Ñþ,/³€;€mþ¢%îh^  u÷‹f²@µ éÚWópø~<ß5°j>{‘-¨]cöK'XtÀâ÷ò»oÁÔ(€hƒáÏwÿï?ýG %€fI’q^D$.Tʳ?ÇD *°AôÁ,ÀÁÜÁ ü`6„B$ÄÂBB d€r`)¬‚B(†Í°*`/Ô@4ÀQh†“p.ÂU¸=púažÁ(¼ AÈa!ÚˆbŠX#Ž™…ø!ÁH‹$ ɈQ"K‘5H1RŠT UHò=r9‡\Fº‘;È2‚ü†¼G1”²Q=Ô µC¹¨7„F¢ Ðdt1š ›Ðr´=Œ6¡çЫhÚ>CÇ0Àè3Äl0.ÆÃB±8, “c˱"¬ «Æ°V¬»‰õcϱwEÀ 6wB aAHXLXNØH¨ $4Ú 7 „QÂ'"“¨K´&ºùÄb21‡XH,#Ö/{ˆCÄ7$‰C2'¹I±¤TÒÒFÒnR#é,©›4H#“ÉÚdk²9”, +È…ääÃä3ää!ò[ b@q¤øSâ(RÊjJåå4åe˜2AU£šRݨ¡T5ZB­¡¶R¯Q‡¨4uš9̓IK¥­¢•Óhh÷i¯ètºÝ•N—ÐWÒËéGè—èôw †ƒÇˆg(›gw¯˜L¦Ó‹ÇT071ë˜ç™™oUX*¶*|‘Ê •J•&•*/T©ª¦ªÞª UóUËT©^S}®FU3Sã© Ô–«UªPëSSg©;¨‡ªg¨oT?¤~Yý‰YÃLÃOC¤Q ±_ã¼Æ c³x,!k «†u5Ä&±ÍÙ|v*»˜ý»‹=ª©¡9C3J3W³Ró”f?ã˜qøœtN ç(§—ó~ŠÞï)â)¦4L¹1e\kª–—–X«H«Q«Gë½6®í§¦½E»YûAÇJ'\'GgÎçSÙSݧ §M=:õ®.ªk¥¡»Dw¿n§î˜ž¾^€žLo§Þy½çú}/ýTýmú§õG X³ $Û Î<Å5qo</ÇÛñQC]Ã@C¥a•a—á„‘¹Ñ<£ÕFFŒiÆ\ã$ãmÆmÆ£&&!&KMêMîšRM¹¦)¦;L;LÇÍÌÍ¢ÍÖ™5›=1×2ç›ç›×›ß·`ZxZ,¶¨¶¸eI²äZ¦Yî¶¼n…Z9Y¥XUZ]³F­­%Ö»­»§§¹N“N«žÖgðñ¶É¶©·°åØÛ®¶m¶}agbg·Å®Ã“}º}ý= ‡Ù«Z~s´r:V:ޚΜî?}Åô–é/gXÏÏØ3ã¶Ë)ÄiS›ÓGgg¹sƒóˆ‹‰K‚Ë.—>.›ÆÝȽäJtõq]ázÒõ›³›Âí¨Û¯î6îiî‡ÜŸÌ4Ÿ)žY3sÐÃÈCàQåÑ? Ÿ•0k߬~OCOgµç#/c/‘W­×°·¥wª÷aï>ö>rŸã>ã<7Þ2ÞY_Ì7À·È·ËOÃož_…ßC#ÿdÿzÿѧ€%g‰A[ûøz|!¿Ž?:Ûeö²ÙíAŒ ¹AA‚­‚åÁ­!hÈì­!÷ç˜Î‘Îi…P~èÖÐaæa‹Ã~ '…‡…W†?ŽpˆXÑ1—5wÑÜCsßDúD–DÞ›g1O9¯-J5*>ª.j<Ú7º4º?Æ.fYÌÕXXIlK9.*®6nl¾ßüíó‡ââ ã{˜/È]py¡ÎÂô…§©.,:–@LˆN8”ðA*¨Œ%òw%Ž yÂÂg"/Ñ6шØC\*NòH*Mz’쑼5y$Å3¥,幄'©¼L LÝ›:žšv m2=:½1ƒ’‘qBª!M“¶gêgæfvˬe…²þÅn‹·/•Ék³¬Y- ¶B¦èTZ(×*²geWf¿Í‰Ê9–«ž+Íí̳ÊÛ7œïŸÿíÂá’¶¥†KW-X潬j9²‰Š®Û—Ø(Üxå‡oÊ¿™Ü”´©«Ä¹dÏfÒféæÞ-ž[–ª—æ—n ÙÚ´ ßV´íõöEÛ/—Í(Û»ƒ¶C¹£¿<¸¼e§ÉÎÍ;?T¤TôTúT6îÒݵa×ønÑî{¼ö4ìÕÛ[¼÷ý>ɾÛUUMÕfÕeûIû³÷?®‰ªéø–ûm]­NmqíÇÒý#¶×¹ÔÕÒ=TRÖ+ëGǾþïw- 6 UœÆâ#pDyäé÷ ß÷ :ÚvŒ{¬áÓvg/jBšòšF›Sšû[b[ºOÌ>ÑÖêÞzüGÛœ499â?rýéü§CÏdÏ&žþ¢þË®/~øÕë×Îјѡ—ò—“¿m|¥ýêÀë¯ÛÆÂƾÉx31^ôVûíÁwÜwï£ßOä| (ÿhù±õSЧû“““ÿ˜óüc3-ÛbKGDÿÿÿ ½§“ pHYs  šœtIMEÚ 1;ïV·¿§IDAT8Ëu‘ËkÜUÇ?ßsgœ4ÔØøhª‚`µ©ÖG1 RQ‚”îܸp%èBªø”n"‚bРXJ ‹.4V iZð##T;m£µ!4™üæžãbâP­~7÷rîù>ιbwïý†cû†; m;‡oª”ÓAÜàΆ ζZ^«/®þôä£Ãç¸|îs¯ÝÉø{Óý;†¯y¿»Rº¥ð¸Â=È9(rÉt¦Vo¼¾û¡­ûG÷Í1±wíÞÿ#_àÓ©¹›{»¿ìî*•›E&ç å!€€ˆÀƒ(—Lç–VŸßuïÀ«oœéêûÁᲵ‘DŽÀ€ P„‡²G”“4ÿçÊ Ü:&€¯ç~™êî*ݳÖreˆuá: ‚ááS­-,ßUšœ©^Ÿ’ú›E&·™JY[ÃPà!RˆìB ŖޞʖR@_ÎôÈ€dBfó”€NvHfÂ"è2ØTÊî]­ˆR‘’ ³ö j§'BàÖ1‰ddAak…/DIJD… ’D2‘ÌH&L`&L† $Ex,6‹|Ö~_\©¿Pœ‘ $™ýMH`I˜©=Ÿ @¨±Z|õÈÎÁ|ttv´gcåЕ—WTZ'¤õ3rŽÈîje"ܵx¾9ÿö›¯°W> ¹mb©Ñ|by¥ˆ•fFRx{wí%Dúõå¹Z½±€áCíÿÞüô$õwdüÀôðÖ«ÞH¦mW÷nètaµ(ŠM<~;9¿ôáž]C/ñ_¸ãåŸ;÷ÉãÕ«§æã‹Õ#Ÿ}ûÀáÉïoÿ`zS§áÚ·ù_>:;x컓§?Ÿ©yóÝ©ÿ|}æ’~ûwam-/ž®7ž=¾0úìS÷5è»ØíR翚¾P"*Ö¯ IEND®B`‚cliff-1.4.5/docs/build/html/_static/default.css0000644000101700007650000000771012041051472023313 0ustar dhellmanndhellmann00000000000000/* * default.css_t * ~~~~~~~~~~~~~ * * Sphinx stylesheet -- default theme. * * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @import url("basic.css"); /* -- page layout ----------------------------------------------------------- */ body { font-family: sans-serif; font-size: 100%; background-color: #11303d; color: #000; margin: 0; padding: 0; } div.document { background-color: #1c4e63; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 0 0 0 230px; } div.body { background-color: #ffffff; color: #000000; padding: 0 20px 30px 20px; } div.footer { color: #ffffff; width: 100%; padding: 9px 0 9px 0; text-align: center; font-size: 75%; } div.footer a { color: #ffffff; text-decoration: underline; } div.related { background-color: #133f52; line-height: 30px; color: #ffffff; } div.related a { color: #ffffff; } div.sphinxsidebar { } div.sphinxsidebar h3 { font-family: 'Trebuchet MS', sans-serif; color: #ffffff; font-size: 1.4em; font-weight: normal; margin: 0; padding: 0; } div.sphinxsidebar h3 a { color: #ffffff; } div.sphinxsidebar h4 { font-family: 'Trebuchet MS', sans-serif; color: #ffffff; font-size: 1.3em; font-weight: normal; margin: 5px 0 0 0; padding: 0; } div.sphinxsidebar p { color: #ffffff; } div.sphinxsidebar p.topless { margin: 5px 10px 10px 10px; } div.sphinxsidebar ul { margin: 10px; padding: 0; color: #ffffff; } div.sphinxsidebar a { color: #98dbcc; } div.sphinxsidebar input { border: 1px solid #98dbcc; font-family: sans-serif; font-size: 1em; } /* -- hyperlink styles ------------------------------------------------------ */ a { color: #355f7c; text-decoration: none; } a:visited { color: #355f7c; text-decoration: none; } a:hover { text-decoration: underline; } /* -- body styles ----------------------------------------------------------- */ div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: 'Trebuchet MS', sans-serif; background-color: #f2f2f2; font-weight: normal; color: #20435c; border-bottom: 1px solid #ccc; margin: 20px -20px 10px -20px; padding: 3px 0 3px 10px; } div.body h1 { margin-top: 0; font-size: 200%; } div.body h2 { font-size: 160%; } div.body h3 { font-size: 140%; } div.body h4 { font-size: 120%; } div.body h5 { font-size: 110%; } div.body h6 { font-size: 100%; } a.headerlink { color: #c60f0f; font-size: 0.8em; padding: 0 4px 0 4px; text-decoration: none; } a.headerlink:hover { background-color: #c60f0f; color: white; } div.body p, div.body dd, div.body li { text-align: justify; line-height: 130%; } div.admonition p.admonition-title + p { display: inline; } div.admonition p { margin-bottom: 5px; } div.admonition pre { margin-bottom: 5px; } div.admonition ul, div.admonition ol { margin-bottom: 5px; } div.note { background-color: #eee; border: 1px solid #ccc; } div.seealso { background-color: #ffc; border: 1px solid #ff6; } div.topic { background-color: #eee; } div.warning { background-color: #ffe4e4; border: 1px solid #f66; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre { padding: 5px; background-color: #eeffcc; color: #333333; line-height: 120%; border: 1px solid #ac9; border-left: none; border-right: none; } tt { background-color: #ecf0f3; padding: 0 1px 0 1px; font-size: 0.95em; } th { background-color: #ede; } .warning tt { background: #efc2c2; } .note tt { background: #d6d6d6; } .viewcode-back { font-family: sans-serif; } div.viewcode-block:target { background-color: #f4debf; border-top: 1px solid #ac9; border-bottom: 1px solid #ac9; }cliff-1.4.5/docs/build/html/_static/doctools.js0000644000101700007650000001527012017700372023344 0ustar dhellmanndhellmann00000000000000/* * doctools.js * ~~~~~~~~~~~ * * Sphinx JavaScript utilities for all documentation. * * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ /** * select a different prefix for underscore */ $u = _.noConflict(); /** * make the code below compatible with browsers without * an installed firebug like debugger if (!window.console || !console.firebug) { var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; window.console = {}; for (var i = 0; i < names.length; ++i) window.console[names[i]] = function() {}; } */ /** * small helper function to urldecode strings */ jQuery.urldecode = function(x) { return decodeURIComponent(x).replace(/\+/g, ' '); } /** * small helper function to urlencode strings */ jQuery.urlencode = encodeURIComponent; /** * This function returns the parsed url parameters of the * current request. Multiple values per key are supported, * it will always return arrays of strings for the value parts. */ jQuery.getQueryParameters = function(s) { if (typeof s == 'undefined') s = document.location.search; var parts = s.substr(s.indexOf('?') + 1).split('&'); var result = {}; for (var i = 0; i < parts.length; i++) { var tmp = parts[i].split('=', 2); var key = jQuery.urldecode(tmp[0]); var value = jQuery.urldecode(tmp[1]); if (key in result) result[key].push(value); else result[key] = [value]; } return result; }; /** * small function to check if an array contains * a given item. */ jQuery.contains = function(arr, item) { for (var i = 0; i < arr.length; i++) { if (arr[i] == item) return true; } return false; }; /** * highlight a given string on a jquery object by wrapping it in * span elements with the given class name. */ jQuery.fn.highlightText = function(text, className) { function highlight(node) { if (node.nodeType == 3) { var val = node.nodeValue; var pos = val.toLowerCase().indexOf(text); if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { var span = document.createElement("span"); span.className = className; span.appendChild(document.createTextNode(val.substr(pos, text.length))); node.parentNode.insertBefore(span, node.parentNode.insertBefore( document.createTextNode(val.substr(pos + text.length)), node.nextSibling)); node.nodeValue = val.substr(0, pos); } } else if (!jQuery(node).is("button, select, textarea")) { jQuery.each(node.childNodes, function() { highlight(this); }); } } return this.each(function() { highlight(this); }); }; /** * Small JavaScript module for the documentation. */ var Documentation = { init : function() { this.fixFirefoxAnchorBug(); this.highlightSearchWords(); this.initIndexTable(); }, /** * i18n support */ TRANSLATIONS : {}, PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, LOCALE : 'unknown', // gettext and ngettext don't access this so that the functions // can safely bound to a different name (_ = Documentation.gettext) gettext : function(string) { var translated = Documentation.TRANSLATIONS[string]; if (typeof translated == 'undefined') return string; return (typeof translated == 'string') ? translated : translated[0]; }, ngettext : function(singular, plural, n) { var translated = Documentation.TRANSLATIONS[singular]; if (typeof translated == 'undefined') return (n == 1) ? singular : plural; return translated[Documentation.PLURALEXPR(n)]; }, addTranslations : function(catalog) { for (var key in catalog.messages) this.TRANSLATIONS[key] = catalog.messages[key]; this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); this.LOCALE = catalog.locale; }, /** * add context elements like header anchor links */ addContextElements : function() { $('div[id] > :header:first').each(function() { $('\u00B6'). attr('href', '#' + this.id). attr('title', _('Permalink to this headline')). appendTo(this); }); $('dt[id]').each(function() { $('\u00B6'). attr('href', '#' + this.id). attr('title', _('Permalink to this definition')). appendTo(this); }); }, /** * workaround a firefox stupidity */ fixFirefoxAnchorBug : function() { if (document.location.hash && $.browser.mozilla) window.setTimeout(function() { document.location.href += ''; }, 10); }, /** * highlight the search words provided in the url in the text */ highlightSearchWords : function() { var params = $.getQueryParameters(); var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; if (terms.length) { var body = $('div.body'); window.setTimeout(function() { $.each(terms, function() { body.highlightText(this.toLowerCase(), 'highlighted'); }); }, 10); $('') .appendTo($('#searchbox')); } }, /** * init the domain index toggle buttons */ initIndexTable : function() { var togglers = $('img.toggler').click(function() { var src = $(this).attr('src'); var idnum = $(this).attr('id').substr(7); $('tr.cg-' + idnum).toggle(); if (src.substr(-9) == 'minus.png') $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); else $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); }).css('display', ''); if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { togglers.click(); } }, /** * helper function to hide the search marks again */ hideSearchWords : function() { $('#searchbox .highlight-link').fadeOut(300); $('span.highlighted').removeClass('highlighted'); }, /** * make the url absolute */ makeURL : function(relativeURL) { return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; }, /** * get the current relative url */ getCurrentURL : function() { var path = document.location.pathname; var parts = path.split(/\//); $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { if (this == '..') parts.pop(); }); var url = parts.join('/'); return path.substring(url.lastIndexOf('/') + 1, path.length - 1); } }; // quick alias for translations _ = Documentation.gettext; $(document).ready(function() { Documentation.init(); }); cliff-1.4.5/docs/build/html/_static/down-pressed.png0000644000101700007650000000056012017700372024274 0ustar dhellmanndhellmann00000000000000‰PNG  IHDRóÿasRGB®ÎébKGDùC» pHYs × ×B(›xtIMEÚ -vF#ðIDAT8ËÍÒ!OAàïÚJ, ++@ I v¢bÿ@Wñ7F’ HNâ±ú# ‚4¡8Ì6¹4×6Tñ’MvvÞ¼7³»êœûöDs¿‡aóxâ1†U îq‚;<¦ˆÏ E¸Â-f)âºj%ßpˆo4xFà78G…>æ)â-ƒ ž ¡ÂEYm4%7YTk-¾–Q¶a–"NWAo-y†eqÒá¾,)â ÓÒYÓÑú´ptŽÐå½\hóq´Îím˜sÔz¦ìG]ÄNñ‡Òa…‡röçß¶¨s^lã vh\î2Ù%ðâßãŽ0EeRvØIEND®B`‚cliff-1.4.5/docs/build/html/_static/down.png0000644000101700007650000000055312017700372022633 0ustar dhellmanndhellmann00000000000000‰PNG  IHDRóÿasRGB®ÎébKGDùC» pHYs × ×B(›xtIMEÚ"ÅíU{ëIDAT8ËÍÒ¡NCAÐóÚJ, ++@ ™4>‡¨â/ÐUü’¤^,†~T&Ô3M^^^ÛPÅM6ÙÙ¹sïÌî*¥ôí‰RJ¿‡a)e¼GñÃ*ƒœàñ¹¡èW¸Å<"®«Fò ‡øFgÜã78G…>q ƒ†ÁOI¨p‘«‰:s“õAÕjñ5GÙ†yDœ®ƒ^+y†U:ép_%G§@D|ašÕ­O“£s„Æ(ïy¡M,"â¨Íím˜sÔx:÷£.b§@D|`–V˜åÙŸÛ²”²ÜÆìиÜe²KàÅ¿Ç/êG!‚ ™IEND®B`‚cliff-1.4.5/docs/build/html/_static/file.png0000644000101700007650000000061012017700372022575 0ustar dhellmanndhellmann00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ  )¶TIDAT8Ë­‘±JÄ@†¿Ir('[ "&xØÙYZ ‚Xø0‚!i|†_@±Ô÷•t§ÓDÄæÏ] ¹#¹Äxÿjv˜ùç› Y–ÐN‡ažE‘i«(ŠÌÄÉ™yž£µ@D¦£&±ˆ`Û6®ë–P¦Zk’$)5%"ôz½Ê.NñA#Aœba‘`Vsø¾_3ñc°,«™àä2m¼Ýñþjó [kŸìlv¹y|!IÕ´ðþyô;ÀðvÈé "Œß®°—a©?ŸAúðÄ7Œ`ô˜ñÇc^énôk?¸²Bg}»TЙ¹D#ÁÑÞ "R¹D1÷£çyüEŽRê*ŽãÝ6MJ©3þK_U«t8F~ÇIEND®B`‚cliff-1.4.5/docs/build/html/_static/jquery.js0000644000101700007650000021475612017700372023047 0ustar dhellmanndhellmann00000000000000/*! * jQuery JavaScript Library v1.4.2 * http://jquery.com/ * * Copyright 2010, John Resig * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * Includes Sizzle.js * http://sizzlejs.com/ * Copyright 2010, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * * Date: Sat Feb 13 22:33:48 2010 -0500 */ (function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& (d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== "find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
a"; var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, "_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== "="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); (function(){var g=s.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= {},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== "string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== 1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, ""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", ""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, "border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== "string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? "&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== 1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== "json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== "number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
"; a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": "pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); cliff-1.4.5/docs/build/html/_static/minus.png0000644000101700007650000000030712017700372023014 0ustar dhellmanndhellmann00000000000000‰PNG  IHDR &Îàq pHYs  šœtIME× <®8åtEXtCommentöÌ–¿RIDATÓczô(BÅñãÇáÒpö¿ÿ¨èˆip»‘¹P÷îÝÃc· ¸ |¶IEND®B`‚cliff-1.4.5/docs/build/html/_static/pygments.css0000644000101700007650000000753412041051472023541 0ustar dhellmanndhellmann00000000000000.highlight .hll { background-color: #ffffcc } .highlight { background: #eeffcc; } .highlight .c { color: #408090; font-style: italic } /* Comment */ .highlight .err { border: 1px solid #FF0000 } /* Error */ .highlight .k { color: #007020; font-weight: bold } /* Keyword */ .highlight .o { color: #666666 } /* Operator */ .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ .highlight .cp { color: #007020 } /* Comment.Preproc */ .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #A00000 } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #FF0000 } /* Generic.Error */ .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ .highlight .gi { color: #00A000 } /* Generic.Inserted */ .highlight .go { color: #303030 } /* Generic.Output */ .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ .highlight .gt { color: #0040D0 } /* Generic.Traceback */ .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #007020 } /* Keyword.Pseudo */ .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #902000 } /* Keyword.Type */ .highlight .m { color: #208050 } /* Literal.Number */ .highlight .s { color: #4070a0 } /* Literal.String */ .highlight .na { color: #4070a0 } /* Name.Attribute */ .highlight .nb { color: #007020 } /* Name.Builtin */ .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ .highlight .no { color: #60add5 } /* Name.Constant */ .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ .highlight .ne { color: #007020 } /* Name.Exception */ .highlight .nf { color: #06287e } /* Name.Function */ .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #bb60d5 } /* Name.Variable */ .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mf { color: #208050 } /* Literal.Number.Float */ .highlight .mh { color: #208050 } /* Literal.Number.Hex */ .highlight .mi { color: #208050 } /* Literal.Number.Integer */ .highlight .mo { color: #208050 } /* Literal.Number.Oct */ .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ .highlight .sc { color: #4070a0 } /* Literal.String.Char */ .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ .highlight .sx { color: #c65d09 } /* Literal.String.Other */ .highlight .sr { color: #235388 } /* Literal.String.Regex */ .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ .highlight .ss { color: #517918 } /* Literal.String.Symbol */ .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */cliff-1.4.5/docs/build/html/_static/searchtools.js0000644000101700007650000003725312041051472024046 0ustar dhellmanndhellmann00000000000000/* * searchtools.js_t * ~~~~~~~~~~~~~~~~ * * Sphinx JavaScript utilties for the full-text search. * * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ /** * helper function to return a node containing the * search summary for a given text. keywords is a list * of stemmed words, hlwords is the list of normal, unstemmed * words. the first one is used to find the occurance, the * latter for highlighting it. */ jQuery.makeSearchSummary = function(text, keywords, hlwords) { var textLower = text.toLowerCase(); var start = 0; $.each(keywords, function() { var i = textLower.indexOf(this.toLowerCase()); if (i > -1) start = i; }); start = Math.max(start - 120, 0); var excerpt = ((start > 0) ? '...' : '') + $.trim(text.substr(start, 240)) + ((start + 240 - text.length) ? '...' : ''); var rv = $('
').text(excerpt); $.each(hlwords, function() { rv = rv.highlightText(this, 'highlighted'); }); return rv; } /** * Porter Stemmer */ var Stemmer = function() { var step2list = { ational: 'ate', tional: 'tion', enci: 'ence', anci: 'ance', izer: 'ize', bli: 'ble', alli: 'al', entli: 'ent', eli: 'e', ousli: 'ous', ization: 'ize', ation: 'ate', ator: 'ate', alism: 'al', iveness: 'ive', fulness: 'ful', ousness: 'ous', aliti: 'al', iviti: 'ive', biliti: 'ble', logi: 'log' }; var step3list = { icate: 'ic', ative: '', alize: 'al', iciti: 'ic', ical: 'ic', ful: '', ness: '' }; var c = "[^aeiou]"; // consonant var v = "[aeiouy]"; // vowel var C = c + "[^aeiouy]*"; // consonant sequence var V = v + "[aeiou]*"; // vowel sequence var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 var s_v = "^(" + C + ")?" + v; // vowel in stem this.stemWord = function (w) { var stem; var suffix; var firstch; var origword = w; if (w.length < 3) return w; var re; var re2; var re3; var re4; firstch = w.substr(0,1); if (firstch == "y") w = firstch.toUpperCase() + w.substr(1); // Step 1a re = /^(.+?)(ss|i)es$/; re2 = /^(.+?)([^s])s$/; if (re.test(w)) w = w.replace(re,"$1$2"); else if (re2.test(w)) w = w.replace(re2,"$1$2"); // Step 1b re = /^(.+?)eed$/; re2 = /^(.+?)(ed|ing)$/; if (re.test(w)) { var fp = re.exec(w); re = new RegExp(mgr0); if (re.test(fp[1])) { re = /.$/; w = w.replace(re,""); } } else if (re2.test(w)) { var fp = re2.exec(w); stem = fp[1]; re2 = new RegExp(s_v); if (re2.test(stem)) { w = stem; re2 = /(at|bl|iz)$/; re3 = new RegExp("([^aeiouylsz])\\1$"); re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); if (re2.test(w)) w = w + "e"; else if (re3.test(w)) { re = /.$/; w = w.replace(re,""); } else if (re4.test(w)) w = w + "e"; } } // Step 1c re = /^(.+?)y$/; if (re.test(w)) { var fp = re.exec(w); stem = fp[1]; re = new RegExp(s_v); if (re.test(stem)) w = stem + "i"; } // Step 2 re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; if (re.test(w)) { var fp = re.exec(w); stem = fp[1]; suffix = fp[2]; re = new RegExp(mgr0); if (re.test(stem)) w = stem + step2list[suffix]; } // Step 3 re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; if (re.test(w)) { var fp = re.exec(w); stem = fp[1]; suffix = fp[2]; re = new RegExp(mgr0); if (re.test(stem)) w = stem + step3list[suffix]; } // Step 4 re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; re2 = /^(.+?)(s|t)(ion)$/; if (re.test(w)) { var fp = re.exec(w); stem = fp[1]; re = new RegExp(mgr1); if (re.test(stem)) w = stem; } else if (re2.test(w)) { var fp = re2.exec(w); stem = fp[1] + fp[2]; re2 = new RegExp(mgr1); if (re2.test(stem)) w = stem; } // Step 5 re = /^(.+?)e$/; if (re.test(w)) { var fp = re.exec(w); stem = fp[1]; re = new RegExp(mgr1); re2 = new RegExp(meq1); re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) w = stem; } re = /ll$/; re2 = new RegExp(mgr1); if (re.test(w) && re2.test(w)) { re = /.$/; w = w.replace(re,""); } // and turn initial Y back to y if (firstch == "y") w = firstch.toLowerCase() + w.substr(1); return w; } } /** * Search Module */ var Search = { _index : null, _queued_query : null, _pulse_status : -1, init : function() { var params = $.getQueryParameters(); if (params.q) { var query = params.q[0]; $('input[name="q"]')[0].value = query; this.performSearch(query); } }, loadIndex : function(url) { $.ajax({type: "GET", url: url, data: null, success: null, dataType: "script", cache: true}); }, setIndex : function(index) { var q; this._index = index; if ((q = this._queued_query) !== null) { this._queued_query = null; Search.query(q); } }, hasIndex : function() { return this._index !== null; }, deferQuery : function(query) { this._queued_query = query; }, stopPulse : function() { this._pulse_status = 0; }, startPulse : function() { if (this._pulse_status >= 0) return; function pulse() { Search._pulse_status = (Search._pulse_status + 1) % 4; var dotString = ''; for (var i = 0; i < Search._pulse_status; i++) dotString += '.'; Search.dots.text(dotString); if (Search._pulse_status > -1) window.setTimeout(pulse, 500); }; pulse(); }, /** * perform a search for something */ performSearch : function(query) { // create the required interface elements this.out = $('#search-results'); this.title = $('

' + _('Searching') + '

').appendTo(this.out); this.dots = $('').appendTo(this.title); this.status = $('

').appendTo(this.out); this.output = $('