launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #12194
[Merge] lp:~allenap/maas/deintroducing-commandant into lp:maas
Gavin Panella has proposed merging lp:~allenap/maas/deintroducing-commandant into lp:maas.
Requested reviews:
MAAS Maintainers (maas-maintainers)
For more details, see:
https://code.launchpad.net/~allenap/maas/deintroducing-commandant/+merge/125145
--
https://code.launchpad.net/~allenap/maas/deintroducing-commandant/+merge/125145
Your team MAAS Maintainers is requested to review the proposed merge of lp:~allenap/maas/deintroducing-commandant into lp:maas.
=== removed directory 'src/maascli/lib'
=== removed file 'src/maascli/lib/Makefile'
--- src/maascli/lib/Makefile 2012-09-12 15:26:07 +0000
+++ src/maascli/lib/Makefile 1970-01-01 00:00:00 +0000
@@ -1,8 +0,0 @@
-commandant:
- bzr export $@ --revision 45 lp:commandant/commandant
- $(RM) -rv $@/test*
-
-clean:
- $(RM) -r commandant
-
-.PHONY: clean
=== removed directory 'src/maascli/lib/commandant'
=== removed file 'src/maascli/lib/commandant/__init__.py'
--- src/maascli/lib/commandant/__init__.py 2012-09-12 15:26:07 +0000
+++ src/maascli/lib/commandant/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,16 +0,0 @@
-"""Commandant is a framework for building command-oriented tools.
-
-A command-oriented command-line program takes a command name as its first
-argument, which it finds and runs, passing along any subsequent
-arguments. Bazaar is command-oriented, for instance. Commandant is inspired
-by Bazaar's user interface and uses bzrlib in its internal implementation.
-
-Commandant is a command discovery and execution tool. Executables, such as
-shell scripts, can be used as commands. Commands can also be implemented in
-Python. These commands, along with help topics, are bundled together in a
-directory. Commandant, when pointed at the directory containing the commands,
-provides a Bazaar-like user interface to discover and run them.
-"""
-
-__version__ = "0.4.0"
-__version_info__ = (0, 4, 0)
=== removed file 'src/maascli/lib/commandant/builtins.py'
--- src/maascli/lib/commandant/builtins.py 2012-09-17 03:16:23 +0000
+++ src/maascli/lib/commandant/builtins.py 1970-01-01 00:00:00 +0000
@@ -1,169 +0,0 @@
-# Commandant is a framework for building command-oriented tools.
-# Copyright (C) 2009-2010 Jamshed Kakar.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-"""Builtin commands."""
-
-from cStringIO import StringIO
-import os
-from platform import platform
-
-import bzrlib
-from bzrlib.commands import Command
-from bzrlib.option import Option
-import commandant
-from commandant.formatting import print_columns
-from commandant.help_topics import (
- CommandHelpTopic,
- HelpTopic,
- )
-
-
-class cmd_version(Command):
- """Show version of commandant."""
-
- takes_options = [Option("short", help="Print just the version number.")]
-
- def run(self, short=None):
- """Print the version."""
- if short:
- print >>self.outf, "%s" % (self.controller.program_version,)
- else:
- print >>self.outf, "%s %s" % (self.controller.program_name,
- self.controller.program_version)
- python_path = os.path.dirname(os.__file__)
- bzrlib_path = bzrlib.__path__[0]
- commandant_path = os.path.abspath(commandant.__path__[0])
- print >>self.outf, " Platform:", platform(aliased=1)
- print >>self.outf, " Python standard library:", python_path
- print >>self.outf, " bzrlib:", bzrlib_path
- print >>self.outf, " commandant:", commandant_path
-
-
-class cmd_help(Command):
- """Show help about a command or topic."""
-
- aliases = ["?", "--help", "-?", "-h"]
- takes_args = ["topic?"]
- _see_also = ["topics"]
-
- def run(self, topic=None):
- """
- Show help for the C{bzrlib.commands.Command} or L{HelpTopic} matching
- C{name}.
-
- @param topic: Optionally, the name of the topic to show. Default is
- C{basic}.
- """
- if topic is None:
- topic = "basic"
- text = None
- command = self.controller.get_command(topic)
- help_topic = self.controller.get_help_topic(topic)
- if help_topic:
- text = help_topic.get_text().strip()
- elif command:
- help_topic = CommandHelpTopic(command)
- help_topic.controller = self.controller
- text = help_topic.get_text()
- if text:
- print >>self.outf, text
- elif not (command or help_topic):
- print >>self.outf, "%s is an unknown command or topic." % (topic,)
-
-
-class topic_basic(HelpTopic):
- """Show basic help about this program."""
-
- def get_summary(self):
- """Get a short topic summary for use in a topic listing."""
- return "Basic commands."
-
- def get_text(self):
- """Get topic content."""
- return """\
-%(program-name)s -- %(program-summary)s
-%(program-url)s
-
-Basic commands:
- %(program-name)s help commands List all commands
- %(program-name)s help topics List all help topics
-""" % {"program-name": self.controller.program_name,
- "program-summary": self.controller.program_summary,
- "program-url": self.controller.program_url}
-
-
-class topic_commands(HelpTopic):
- """List available commands with a short summary describing each one."""
-
- def get_summary(self):
- """Get a short topic summary for use in a topic listing."""
- return "Basic help for all commands."
-
- def get_text(self):
- """Get topic content."""
- stream = StringIO()
- result = []
- for name in self.controller.get_command_names():
- command = self.controller.get_command(name)
- help_topic = self.controller.get_help_topic(name)
- if not help_topic and command:
- help_topic = CommandHelpTopic(command)
- if self.controller is not None:
- help_topic.controller = self.controller
- summary = ""
- if help_topic:
- summary = help_topic.get_summary()
- if self.include_command(command):
- result.append((name, summary))
- result.sort(key=lambda item: item[0])
- print_columns(stream, result)
- return stream.getvalue()
-
- def include_command(self, command):
- """Return C{True} if C{command} is visible."""
- return not command.hidden
-
-
-class topic_hidden_commands(topic_commands):
- """List hidden commands with a short summary describing each one."""
-
- def get_summary(self):
- """Get a short topic summary for use in a topic listing."""
- return "Basic help for hidden commands."
-
- def include_command(self, command):
- """Return C{True} if C{command} is hidden."""
- return command.hidden
-
-
-class topic_topics(HelpTopic):
- """List available help topics with a short summary describing each one."""
-
- def get_summary(self):
- """Get a short topic summary for use in a topic listing."""
- return "Topics list."
-
- def get_text(self):
- """Get topic content."""
- stream = StringIO()
- command_names = self.controller.get_command_names()
- help_topic_names = self.controller.get_help_topic_names()
- result = [(name, self.controller.get_help_topic(name).get_summary())
- for name in help_topic_names if name not in command_names]
- result.sort(key=lambda item: item[0])
- print_columns(stream, result)
- return stream.getvalue()
=== removed file 'src/maascli/lib/commandant/commands.py'
--- src/maascli/lib/commandant/commands.py 2012-09-17 03:16:23 +0000
+++ src/maascli/lib/commandant/commands.py 1970-01-01 00:00:00 +0000
@@ -1,120 +0,0 @@
-# Commandant is a framework for building command-oriented tools.
-# Copyright (C) 2009-2010 Jamshed Kakar.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-"""Infrastructure extends C{bzrlib.commands.Command} to support executables."""
-
-import os
-import sys
-
-from bzrlib.commands import Command
-from twisted.internet.defer import Deferred
-
-
-class ExecutableCommand(Command):
- """Specialized command runs an executable program."""
-
- path = None
-
- def run_argv_aliases(self, argv, alias_argv=None):
- """
- Disable proper handling of argv and aliases so that arguments can be
- passed directly to the executable.
- """
- self.run(argv)
-
- def run(self, argv):
- """
- Run the executable, passing whatever arguments were passed to the
- command.
- """
- if argv:
- os.system("%s %s" % (self.path, " ".join(argv)))
- else:
- os.system(self.path)
-
-
-class TwistedCommand(Command):
- """A command that runs with a Twisted reactor."""
-
- _return_value = None
- _failure_value = None
-
- def get_reactor(self):
- """Get the Twisted reactor to use when running this command."""
- from twisted.internet import reactor
- return reactor
-
- def run_argv_aliases(self, argv, alias_argv=None):
- """Start a reactor for the command to run in."""
- self._start_reactor(argv, alias_argv)
- if self._failure_value is not None:
- type, value, traceback = self._failure_value
- raise type, value, traceback
- return self._return_value
-
- def _start_reactor(self, argv, alias_argv):
- """Start a reactor and queue a call to run the command."""
- reactor = self.get_reactor()
- reactor.callLater(0, self._run_command, argv, alias_argv)
- reactor.run()
- return self._return_value
-
- def _run_command(self, argv, alias_argv):
- """Run the command and stop the reactor when it completes."""
- subclass = super(TwistedCommand, self)
- try:
- result = subclass.run_argv_aliases(argv, alias_argv)
- except:
- self._failure_value = sys.exc_info()
- return self._stop_reactor(self._failure_value)
- else:
- return self._stop_reactor(result)
-
- def _capture_return_value(self, result):
- """Store the return value after running the command."""
- self._return_value = result
-
- def _capture_failure_value(self, failure):
- """Store the failure value after running the command."""
- self._failure_value = (failure.type, failure.value, failure.tb)
-
- def _stop_reactor(self, result):
- """Stop the reactor."""
- reactor = self.get_reactor()
- if isinstance(result, Deferred):
- result.addErrback(self._capture_failure_value)
- result.addCallback(self._capture_return_value)
- # Use callLater to stop the reactor so that application code can
- # add callbacks to the Deferred after its been returned by the run
- # method.
- result.addCallback(
- lambda ignored: reactor.callLater(0, reactor.stop))
- else:
- self._capture_return_value(result)
- reactor.callLater(0, reactor.stop)
-
- def run(self):
- """Actually run the command.
-
- This method is invoked inside a running Twisted reactor, with the
- options and arguments bound to keyword parameters.
-
- Return a C{Deferred} or None if the command was successful. It's okay
- for this method to allow an exception to raise up.
- """
- raise NotImplementedError("Command '%r' needs to be implemented."
- % self.name())
=== removed file 'src/maascli/lib/commandant/controller.py'
--- src/maascli/lib/commandant/controller.py 2012-09-17 03:16:23 +0000
+++ src/maascli/lib/commandant/controller.py 1970-01-01 00:00:00 +0000
@@ -1,267 +0,0 @@
-# Commandant is a framework for building command-oriented tools.
-# Copyright (C) 2009-2010 Jamshed Kakar.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-"""Infrastructure to run C{bzrlib.commands.Command}s and L{HelpTopic}s."""
-
-import os
-import shutil
-import stat
-import sys
-import tempfile
-
-from bzrlib.commands import (
- Command,
- run_bzr,
- )
-import bzrlib.ui
-from commandant import __version__
-from commandant.commands import ExecutableCommand
-from commandant.help_topics import FileHelpTopic
-
-
-DEFAULT_PROGRAM_NAME = "commandant"
-DEFAULT_PROGRAM_VERSION = __version__
-DEFAULT_PROGRAM_SUMMARY = "A framework for building command-oriented tools."
-DEFAULT_PROGRAM_URL = "http://launchpad.net/commandant"
-
-
-class CommandRegistry(object):
-
- def __init__(self):
- self._commands = {}
-
- def install_bzrlib_hooks(self):
- """
- Register this controller with C{Command.hooks} so that the controller
- can take advantage of Bazaar's command infrastructure. C{bzrlib.ui}
- is initialized for use in a terminal during this process.
-
- L{_list_commands} and L{_get_command} are registered as callbacks for
- the C{list_commands} and C{get_commands} hooks, respectively.
- """
- Command.hooks.install_named_hook(
- "list_commands", self._list_commands, "commandant commands")
- Command.hooks.install_named_hook(
- "get_command", self._get_command, "commandant commands")
- bzrlib.ui.ui_factory = bzrlib.ui.make_ui_for_terminal(
- sys.stdin, sys.stdout, sys.stderr)
-
- def _list_commands(self, names):
- """
- Hook to find C{bzrlib.commands.Command} names is called by C{bzrlib}.
-
- @param names: A set of C{bzrlib.commands.Command} names to update with
- names from this controller.
- """
- names.update(self._commands.iterkeys())
- return names
-
- def _get_command(self, command, name):
- """
- Hook to get the C{bzrlib.commands.Command} for C{name} is called by
- C{bzrlib}.
-
- @param command: A C{bzrlib.commands.Command}, or C{None}, to be
- returned if a command matching C{name} can't be found.
- @param name: The name of the C{bzrlib.commands.Command} to retrieve.
- @return: The C{bzrlib.commands.Command} from the index or C{command}
- if one isn't available for C{name}.
- """
- try:
- local_command = self._commands[name]()
- except KeyError:
- return command
- local_command.controller = self
- return local_command
-
- def register_command(self, name, command_class):
- """Register a C{bzrlib.commands.Command} with this controller.
-
- @param name: The name to register the command with.
- @param command_class: A type object, typically a subclass of
- C{bzrlib.commands.Command} to use when the command is invoked.
- """
- self._commands[name] = command_class
-
-
-class HelpTopicRegistry(object):
-
- def __init__(self):
- self._help_topics = {}
-
- def register_help_topic(self, name, help_topic_class):
- """Register a C{bzrlib.commands.Command} to this controller.
-
- @param name: The name to register the command with.
- @param command_class: A type object, typically a subclass of
- C{bzrlib.commands.Command} to use when the command is invoked.
- """
- self._help_topics[name] = help_topic_class
-
- def get_help_topic_names(self):
- """Get a C{set} of help topic names."""
- return set(self._help_topics.iterkeys())
-
- def get_help_topic(self, name):
- """
- Get the help topic matching C{name} or C{None} if a match isn't found.
- """
- try:
- help_topic = self._help_topics[name]()
- except KeyError:
- return None
- help_topic.controller = self
- return help_topic
-
-
-class CommandDiscoveryMixin(object):
-
- def load_path(self, path):
- """Load C{bzrlib.commands.Command}s and L{HelpTopic}s from C{path}.
-
- Python files foundin C{path} are loaded and
- C{bzrlib.commands.Command}s and L{HelpTopic}s within are loaded.
- L{ExecutableCommand}s are created for executable programs in C{path}
- and L{FileHelpTopic}s are created for text file help topics.
- """
- package_path = tempfile.mkdtemp()
- try:
- for filename in os.listdir(path):
- file_path = os.path.join(path, filename)
- if filename.endswith("~") or not os.path.exists(file_path):
- continue
- file_mode = os.stat(file_path)[0]
- if not os.path.isfile(file_path):
- continue
- if file_mode | stat.S_IEXEC == file_mode:
- sanitized_name = filename.replace("_", "-")
- executable = type(
- "Executable", (ExecutableCommand,),
- {"path": file_path})
- self.register_command(sanitized_name, executable)
- elif filename.endswith(".py"):
- command_module = import_module(filename, file_path,
- package_path)
- self.load_module(command_module)
- elif filename.endswith(".txt"):
- sanitized_name = filename.replace("_", "-")[:-4]
- topic = type(
- "Topic", (FileHelpTopic,),
- {"path": file_path})
- self.register_help_topic(sanitized_name, topic)
- finally:
- shutil.rmtree(package_path)
-
- def load_module(self, module):
- """Load C{bzrlib.commands.Command}s and L{HelpTopic}s from C{module}.
-
- Objects found in the module with names that start with C{cmd_} are
- treated as C{bzrlib.commands.Command}s and objects with names that
- start with C{topic_} are treated as L{HelpTopic}s.
- """
- for name in module.__dict__:
- if name.startswith("cmd_"):
- sanitized_name = name[4:].replace("_", "-")
- self.register_command(sanitized_name, module.__dict__[name])
- elif name.startswith("topic_"):
- sanitized_name = name[6:].replace("_", "-")
- self.register_help_topic(sanitized_name, module.__dict__[name])
-
- def get_command_names(self):
- """
- Get the C{set} of C{bzrlib.commands.Command} names registered with
- this controller.
-
- This method is equivalent to C{bzrlib.commands.all_command_names} when
- the controller is installed with C{bzrlib}.
- """
- return set(self._commands.iterkeys())
-
- def get_command(self, name):
- """Get the C{bzrlib.commands.Command} registered for C{name}.
-
- @return: The C{bzrlib.commands.Command} from the index or C{None} if
- one isn't available for C{name}.
- """
- return self._get_command(None, name)
-
-
-class CommandExecutionMixin(object):
-
- def run(self, argv):
- """Run the C{bzrlib.commands.Command} specified in C{argv}.
-
- @raise BzrCommandError: Raised if a matching command can't be found.
- """
- run_bzr(argv)
-
-
-class CommandController(CommandRegistry, HelpTopicRegistry,
- CommandDiscoveryMixin, CommandExecutionMixin):
- """C{bzrlib.commands.Command} discovery and execution controller.
-
- A L{CommandController} is a container for named C{bzrlib.commands.Command}s
- and L{HelpTopic}s types. The L{load_module} and L{load_path} methods load
- C{bzrlib.commands.Command} and L{HelpTopic} types from modules and from
- the file system. The L{register_command} and L{register_help_topic}
- methods register C{bzrlib.commands.Command}s and L{HelpTopic}s types with
- the controller.
-
- A controller is an execution engine for commands. The L{run} method
- accepts command line arguments, finds a matching command, and runs it.
- """
-
- def __init__(self, program_name=None, program_version=None,
- program_summary=None, program_url=None):
- CommandRegistry.__init__(self)
- HelpTopicRegistry.__init__(self)
- self.program_name = program_name or DEFAULT_PROGRAM_NAME
- self.program_version = program_version or DEFAULT_PROGRAM_VERSION
- self.program_summary = program_summary or DEFAULT_PROGRAM_SUMMARY
- self.program_url = program_url or DEFAULT_PROGRAM_URL
-
-
-def import_module(filename, file_path, package_path):
- """Import a module and make it a child of C{commandant_command}.
-
- The module source in C{filename} at C{file_path} is copied to a temporary
- directory, a Python package called C{commandant_command}.
-
- @param filename: The name of the module file.
- @param file_path: The path to the module file.
- @param package_path: The path for the new C{commandant_command} package.
- @return: The new module.
- """
- module_path = os.path.join(package_path, "commandant_command")
- if not os.path.exists(module_path):
- os.mkdir(module_path)
-
- init_path = os.path.join(module_path, "__init__.py")
- open(init_path, "w").close()
-
- source_code = open(file_path, "r").read()
- module_file_path = os.path.join(module_path, filename)
- module_file = open(module_file_path, "w")
- module_file.write(source_code)
- module_file.close()
-
- name = filename[:-3]
- sys.path.append(package_path)
- try:
- return __import__("commandant_command.%s" % (name,), fromlist=[name])
- finally:
- sys.path.pop()
=== removed file 'src/maascli/lib/commandant/entry_point.py'
--- src/maascli/lib/commandant/entry_point.py 2012-09-17 03:16:23 +0000
+++ src/maascli/lib/commandant/entry_point.py 1970-01-01 00:00:00 +0000
@@ -1,48 +0,0 @@
-# Commandant is a framework for building command-oriented tools.
-# Copyright (C) 2009-2010 Jamshed Kakar.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-"""Bootstrap code starts and runs Commandant."""
-
-from commandant import builtins
-from commandant.controller import CommandController
-from commandant.errors import UsageError
-
-
-def main(argv):
- """Run the command named in C{argv}.
-
- If a command name isn't provided the C{help} command is shown.
-
- @raises UsageError: Raised if too few arguments are provided.
- @param argv: A list command-line arguments. The first argument should be
- the path to C{bzrlib.commands.Command}s and L{HelpTopic}s to load and
- the second argument should be the name of the command to run. Any
- further arguments are passed to the command.
- """
- if len(argv) < 2 or (len(argv) > 1 and argv[1].startswith("-")):
- raise UsageError(
- "You must provide a path to the commands you want to run.")
- elif len(argv) < 3:
- argv.append("help")
-
- # Load commands topic from the user-supplied path after loading builtins,
- # in case any of the user's commands or topics replace builtin ones.
- controller = CommandController()
- controller.load_module(builtins)
- controller.load_path(argv[1])
- controller.install_bzrlib_hooks()
- controller.run(argv[2:])
=== removed file 'src/maascli/lib/commandant/errors.py'
--- src/maascli/lib/commandant/errors.py 2012-09-12 15:26:07 +0000
+++ src/maascli/lib/commandant/errors.py 1970-01-01 00:00:00 +0000
@@ -1,28 +0,0 @@
-# Commandant is a framework for building command-oriented tools.
-# Copyright (C) 2009-2010 Jamshed Kakar.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-"""Exception classes."""
-
-
-class CommandantError(StandardError):
- """Base class for Commandant exceptions."""
- pass
-
-
-class UsageError(CommandantError):
- """Raised when too few command-line arguments are provided."""
- pass
=== removed file 'src/maascli/lib/commandant/formatting.py'
--- src/maascli/lib/commandant/formatting.py 2012-09-12 15:26:07 +0000
+++ src/maascli/lib/commandant/formatting.py 1970-01-01 00:00:00 +0000
@@ -1,59 +0,0 @@
-# Commandant is a framework for building command-oriented tools.
-# Copyright (C) 2009-2010 Jamshed Kakar.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-"""Infrastructure for pretty-printing formatted output."""
-
-
-def print_columns(outf, rows, shrink_index=None, max_width=78, padding=2):
- """Calculate optimal column widths and print C{rows} to C{outf}.
-
- @param outf: The stream to write to.
- @param rows: A list of rows to print. Each row is a tuple of columns.
- All rows must contain the same number of columns.
- @param shrink_index: The index of the column to shrink, if the columns
- provided exceed C{max_width}. Shrinking is disabled by default.
- @param max_width: The maximum number of characters per line. Defaults to
- 78, though it isn't enforced unless C{shrink_index} is specified.
- @param padding: The number of blank characters to output between columns.
- Defaults to 2.
- """
- if not rows:
- return
-
- widths = []
- for row in rows:
- if not widths:
- widths = [len(column) for i, column in enumerate(row)]
- else:
- widths = [
- max(widths[i], len(column)) for i, column in enumerate(row)]
-
- if shrink_index is not None:
- fixed_width = sum(width + padding for i, width in enumerate(widths)
- if i != shrink_index)
- if fixed_width + widths[shrink_index] > max_width:
- widths[shrink_index] = max_width - fixed_width
-
- padding_space = "".ljust(padding)
- for row in rows:
- output = []
- for i, column in enumerate(row):
- text = column[:widths[i]].ljust(widths[i])
- if (i + 1 == len(row)):
- text = text.strip()
- output.append(text)
- print >>outf, padding_space.join(output)
=== removed file 'src/maascli/lib/commandant/help_topics.py'
--- src/maascli/lib/commandant/help_topics.py 2012-09-12 15:26:07 +0000
+++ src/maascli/lib/commandant/help_topics.py 1970-01-01 00:00:00 +0000
@@ -1,131 +0,0 @@
-# Commandant is a framework for building command-oriented tools.
-# Copyright (C) 2009-2010 Jamshed Kakar.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-"""Infrastructure for building L{HelpTopic} components."""
-
-from inspect import getdoc
-
-
-class HelpTopic(object):
- """A help topic."""
-
- controller = None
-
- def get_summary(self):
- """Get a short topic summary for use in a topic listing."""
- raise NotImplementedError("Must be implemented by sub-class.")
-
- def get_text(self):
- """Get topic content."""
- raise NotImplementedError("Must be implemented by sub-class.")
-
-
-class DocstringHelpTopic(object):
- """A help topic that loads content from its docstring."""
-
- def __init__(self):
- super(DocstringHelpTopic, self).__init__()
- self._summary = None
- self._text = None
-
- def _get_docstring(self):
- """Get the docstring for this help topic."""
- return getdoc(self)
-
- def _load_help_text(self):
- """Load summary and text content."""
- docstring = self._get_docstring()
- if not docstring:
- return "", ""
- else:
- return self._load_docstring(docstring)
-
- def _load_docstring(self, docstring):
- """Load summary and text content from a docstring."""
- lines = [line for line in docstring.splitlines()]
- return lines[0], "\n".join(lines[1:]).strip()
-
- def get_summary(self):
- """Get a short topic summary for use in a topic listing."""
- if self._summary is None:
- (self._summary, self._text) = self._load_help_text()
- return self._summary
-
- def get_text(self):
- """Get topic content."""
- if self._text is None:
- (self._summary, self._text) = self._load_help_text()
- return self._text
-
-
-class FileHelpTopic(HelpTopic):
- """A help topic that loads content from a file."""
-
- path = None
-
- def __init__(self):
- super(FileHelpTopic, self).__init__()
- self._summary = None
- self._text = None
-
- def _load(self):
- """Load and cache summary and text content."""
- file = open(self.path, "r")
- self._summary = file.readline().strip()
- self._text = file.read().strip()
- # FIXME Test this.
- file.close()
-
- def get_summary(self):
- """Get a short topic summary for use in a topic listing."""
- if self._summary is None:
- self._load()
- return self._summary
-
- def get_text(self):
- """Get topic content."""
- if self._text is None:
- self._load()
- return self._text
-
-
-class CommandHelpTopic(DocstringHelpTopic):
- """
- A help topic that loads content from a C{bzrlib.commands.Command}
- docstring.
- """
-
- def __init__(self, command):
- super(CommandHelpTopic, self).__init__()
- self.command = command
-
- def _get_docstring(self):
- """Get the docstring for the command."""
- return getdoc(self.command)
-
- def _load_docstring(self, docstring):
- """Load summary and text content from a docstring."""
- lines = [line for line in docstring.splitlines()]
- summary = lines[0]
- try:
- text = self.command.get_help_text().strip()
- text = text.replace("bzr", self.controller.program_name)
- except NotImplementedError:
- pass
- else:
- return summary, text
- return summary, ""
=== modified file 'src/provisioningserver/utils.py'
--- src/provisioningserver/utils.py 2012-09-17 10:55:11 +0000
+++ src/provisioningserver/utils.py 2012-09-19 09:44:41 +0000
@@ -326,14 +326,7 @@
class ActionScript:
- """A command-line script that follows a command+verb pattern.
-
- It is probably worth replacing this with Commandant_ or something similar
- - just bzrlib.commands for example - in the future, so we don't have to
- maintain this.
-
- .. _Commandant: https://launchpad.net/commandant
- """
+ """A command-line script that follows a command+verb pattern."""
def __init__(self, description):
super(ActionScript, self).__init__()