=== added directory 'lava'
=== added file 'lava/__init__.py'
@@ -0,0 +1,3 @@
+__import__('pkg_resources').declare_namespace(__name__)
+# DO NOT ADD ANYTHING TO THIS FILE!
+# IT MUST STAY AS IS (empty apart from the two lines above)
=== added directory 'lava/tool'
=== added file 'lava/tool/__init__.py'
@@ -0,0 +1,27 @@
+# Copyright (C) 2010, 2011 Linaro Limited
+#
+# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
+# Author: Michael Hudson-Doyle <michael.hudson@linaro.org>
+#
+# This file is part of lava-tool.
+#
+# lava-tool is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# as published by the Free Software Foundation
+#
+# lava-tool 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 Lesser General Public License
+# along with lava-tool. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+lava.tool
+=========
+
+Generic code for command line utilities for LAVA
+"""
+
+__version__ = (0, 4, 0, "dev", 0)
=== added file 'lava/tool/command.py'
@@ -0,0 +1,157 @@
+# Copyright (C) 2010, 2011 Linaro Limited
+#
+# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
+#
+# This file is part of lava-tool.
+#
+# lava-tool is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# as published by the Free Software Foundation
+#
+# lava-tool 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 Lesser General Public License
+# along with lava-tool. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Interface for all lava-tool commands
+"""
+
+import inspect
+
+
+class Command(object):
+ """
+ Base class for all command line tool sub-commands.
+ """
+
+ def __init__(self, parser, args):
+ """
+ Prepare instance for executing commands.
+
+ This method is called immediately after all arguments are parsed and
+ results are available. This gives subclasses a chance to configure
+ themselves. The provided parser is an instance of
+ argparse.ArgumentParser but it may not be the top-level parser (it will
+ be a parser specific for this command)
+
+ The default implementation stores both arguments as instance
+ attributes.
+ """
+ self.parser = parser
+ self.args = args
+
+ def invoke(self):
+ """
+ Invoke command action.
+ """
+ raise NotImplementedError()
+
+ def reparse_arguments(self, parser, raw_args):
+ """
+ Re-parse raw arguments into normal arguments
+
+ Parser is the same as in register_arguments (a sub-parser) The true,
+ topmost parser is in self.parser.
+
+ This method is only needed for specific commands that need to peek at
+ the arguments before being able to truly redefine the parser and
+ re-parse the raw arguments again.
+ """
+ raise NotImplementedError()
+
+ @classmethod
+ def get_name(cls):
+ """
+ Return the name of this command.
+
+ The default implementation strips any leading underscores and replaces
+ all other underscores with dashes.
+ """
+ return cls.__name__.lstrip("_").replace("_", "-")
+
+ @classmethod
+ def get_help(cls):
+ """
+ Return the help message of this command
+ """
+ doc = inspect.getdoc(cls)
+ if doc is not None and "" in doc:
+ doc = doc[:doc.index("")].rstrip()
+ return doc
+
+ @classmethod
+ def get_epilog(cls):
+ """
+ Return the epilog of the help message
+ """
+ doc = inspect.getdoc(cls)
+ if doc is not None and "" in doc:
+ doc = doc[doc.index("") + 1:].lstrip()
+ else:
+ doc = None
+ return doc
+
+ @classmethod
+ def register_arguments(cls, parser):
+ """
+ Register arguments if required.
+
+ Subclasses can override this to add any arguments that will be
+ exposed to the command line interface.
+ """
+ pass
+
+
+class SubCommand(Command):
+ """
+ Base class for all command sub-command hubs.
+
+ This class is needed when one wants to get a custom level of command
+ options that can be freely extended, just like the top-level lava-tool
+ command.
+
+ For example, a SubCommand 'actions' will load additional commands from a
+ the 'lava.actions' namespace. For the end user it will be available as::
+
+ $ lava-tool foo actions xxx
+
+ Where xxx is one of the Commands that is declared to live in the namespace
+ provided by 'foo actions'.
+ """
+
+ namespace = None
+
+ @classmethod
+ def get_namespace(cls):
+ """
+ Return the pkg-resources entry point namespace name from which
+ sub-commands will be loaded.
+ """
+ return cls.namespace
+
+ @classmethod
+ def register_subcommands(cls, parser):
+ """
+ Register sub commands.
+
+ This method is called around the same time as register_arguments()
+ would be called for the plain command classes. It loads commands from
+ the entry point namespace returned by get_namespace() and registeres
+ them with a BaseDispatcher class. The parsers used by that dispatcher
+ are linked to the calling dispatcher parser so the new commands enrich
+ the top-level parser tree.
+
+ In addition, the provided parser stores a dispatcher instance in its
+ defaults. This is useful when one wants to access it later. To a final
+ command instance it shall be available as self.args.dispatcher.
+ """
+ from lava.tool.dispatcher import BaseDispatcher
+ dispatcher = BaseDispatcher(parser, name=cls.get_name())
+ namespace = cls.get_namespace()
+ if namespace is not None:
+ dispatcher.import_commands(namespace)
+ parser.set_defaults(dispatcher=dispatcher)
=== added directory 'lava/tool/commands'
=== added file 'lava/tool/commands/__init__.py'
@@ -0,0 +1,83 @@
+# Copyright (C) 2010 Linaro Limited
+#
+# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
+#
+# This file is part of lava-tool.
+#
+# lava-tool is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# as published by the Free Software Foundation
+#
+# lava-tool 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 Lesser General Public License
+# along with lava-tool. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Package with command line commands
+"""
+
+import argparse
+import re
+
+
+class ExperimentalNoticeAction(argparse.Action):
+ """
+ Argparse action that implements the --experimental-notice
+ """
+
+ message = """
+ Some lc-tool sub-commands are marked as EXPERIMENTAL. Those commands are
+ not guaranteed to work identically, or have identical interface between
+ subsequent lc-tool releases.
+
+ We do that to make it possible to provide good user interface and
+ server-side API when working on new features. Once a feature is stabilized
+ the UI will be frozen and all subsequent changes will retain backwards
+ compatibility.
+ """
+ message = message.lstrip()
+ message = re.sub(re.compile("[ \t]+", re.M), " ", message)
+ message = re.sub(re.compile("^ ", re.M), "", message)
+
+ def __init__(self,
+ option_strings, dest, default=None, required=False,
+ help=None):
+ super(ExperimentalNoticeAction, self).__init__(
+ option_strings=option_strings, dest=dest, default=default, nargs=0,
+ help=help)
+
+ def __call__(self, parser, namespace, values, option_string=None):
+ parser.exit(message=self.message)
+
+
+class ExperimentalCommandMixIn(object):
+ """
+ Experimental command.
+
+ Prints a warning message on each call to invoke()
+ """
+
+ def invoke(self):
+ self.print_experimental_notice()
+ return super(ExperimentalCommandMixIn, self).invoke()
+
+ @classmethod
+ def register_arguments(cls, parser):
+ retval = super(ExperimentalCommandMixIn,
+ cls).register_arguments(parser)
+ parser.register("action", "experimental_notice",
+ ExperimentalNoticeAction)
+ group = parser.add_argument_group("experimental commands")
+ group.add_argument("--experimental-notice",
+ action="experimental_notice",
+ default=argparse.SUPPRESS,
+ help="Explain the nature of experimental commands")
+ return retval
+
+ def print_experimental_notice(self):
+ print ("EXPERIMENTAL - SUBJECT TO CHANGE"
+ " (See --experimental-notice for more info)")
=== added file 'lava/tool/commands/help.py'
@@ -0,0 +1,35 @@
+# Copyright (C) 2010 Linaro Limited
+#
+# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
+#
+# This file is part of lava-tool.
+#
+# lava-tool is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# as published by the Free Software Foundation
+#
+# lava-tool 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 Lesser General Public License
+# along with lava-tool. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+lava.tool.commands.help
+=======================
+
+Implementation of `lava help`
+"""
+
+from lava.tool.command import Command
+
+
+class help(Command):
+ """
+ Show a summary of all available commands
+ """
+
+ def invoke(self):
+ self.parser.print_help()
=== added file 'lava/tool/dispatcher.py'
@@ -0,0 +1,128 @@
+# Copyright (C) 2010, 2011, 2012 Linaro Limited
+#
+# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
+#
+# This file is part of lava-tool.
+#
+# lava-tool is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# as published by the Free Software Foundation
+#
+# lava-tool 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 Lesser General Public License
+# along with lava-tool. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Module with LavaDispatcher - the command dispatcher
+"""
+
+import argparse
+import logging
+import pkg_resources
+import sys
+
+from lava.tool.errors import CommandError
+
+
+class Dispatcher(object):
+ """
+ Class implementing command line interface for launch control
+ """
+
+ description = None
+ epilog = None
+
+ def __init__(self, parser=None, name=None):
+ self.parser = parser or self.construct_parser()
+ self.subparsers = self.parser.add_subparsers(
+ title="Sub-command to invoke")
+ self.name = name
+
+ def __repr__(self):
+ return "%r(name=%r)" % (self.__class__.__name__, self.name)
+
+ @classmethod
+ def construct_parser(cls):
+ """
+ Construct a parser for this dispatcher.
+
+ This is only used if the parser is not provided by the parent
+ dispatcher instance.
+ """
+ parser_args = dict(add_help=True)
+ if cls.description is not None:
+ parser_args['description'] = cls.description
+ if cls.epilog is not None:
+ parser_args['epilog'] = cls.epilog
+ return argparse.ArgumentParser(**parser_args)
+
+ def import_commands(self, entrypoint_name):
+ """
+ Import commands from given entry point namespace
+ """
+ logging.debug("Loading commands in entry point %r", entrypoint_name)
+ for entrypoint in pkg_resources.iter_entry_points(entrypoint_name):
+ self.add_command_cls(entrypoint.load())
+
+ def add_command_cls(self, command_cls):
+ """
+ Add a new command class to this dispatcher.
+
+ The command must be a subclass of Command or SubCommand.
+ """
+ logging.debug("Loading command class %r", command_cls)
+ # Create a sub-parser where the command/sub-command can register
+ # things.
+ sub_parser = self.subparsers.add_parser(
+ command_cls.get_name(),
+ help=command_cls.get_help(),
+ epilog=command_cls.get_epilog())
+ from lava.tool.command import SubCommand
+ if issubclass(command_cls, SubCommand):
+ # Handle SubCommand somewhat different. Instead of calling
+ # register_arguments we call register_subcommands
+ command_cls.register_subcommands(sub_parser)
+ else:
+ # Handle plain commands easily by recording their commands in the
+ # dedicated sub-parser we've crated for them.
+ command_cls.register_arguments(sub_parser)
+ # In addition, since we don't want to require all sub-classes of
+ # Command to super-call register_arguments (everyone would forget
+ # this anyway) we manually register the command class for that
+ # sub-parser so that dispatch() can look it up later.
+ sub_parser.set_defaults(
+ command_cls=command_cls,
+ parser=sub_parser)
+
+ def dispatch(self, raw_args=None):
+ """
+ Dispatch a command with the specified arguments.
+
+ If arguments are left out they are looked up in sys.argv automatically
+ """
+ # First parse whatever input arguments we've got
+ args = self.parser.parse_args(raw_args)
+ # Then look up the command class and construct it with the parser it
+ # belongs to and the parsed arguments.
+ command = args.command_cls(args.parser, args)
+ try:
+ # Give the command a chance to re-parse command line arguments
+ command.reparse_arguments(args.parser, raw_args)
+ except NotImplementedError:
+ pass
+ try:
+ return command.invoke()
+ except CommandError as ex:
+ print >> sys.stderr, "ERROR: %s" % (ex,)
+ return 1
+
+ @classmethod
+ def run(cls):
+ """
+ Dispatch commandsd and exit
+ """
+ raise SystemExit(cls().dispatch())
=== added file 'lava/tool/errors.py'
@@ -0,0 +1,31 @@
+# Copyright (C) 2010, 2011, 2012 Linaro Limited
+#
+# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
+#
+# This file is part of lava-tool.
+#
+# lava-tool is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# as published by the Free Software Foundation
+#
+# lava-tool 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 Lesser General Public License
+# along with lava-tool. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+lava.tool.errors
+================
+
+Error classes for LAVA Tool.
+"""
+
+class CommandError(Exception):
+ """
+ Raise this from a Command's invoke() method to display an error nicely.
+
+ lava-tool will exit with a status of 1 if this is raised.
+ """
=== added file 'lava/tool/main.py'
@@ -0,0 +1,41 @@
+# Copyright (C) 2010, 2011 Linaro Limited
+#
+# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
+#
+# This file is part of lava-tool.
+#
+# lava-tool is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# as published by the Free Software Foundation
+#
+# lava-tool 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 Lesser General Public License
+# along with lava-tool. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+lava.tool.main
+==============
+
+Implementation of the `lava` shell command.
+"""
+
+from lava.tool.dispatcher import Dispatcher
+
+
+class LavaDispatcher(Dispatcher):
+ """
+ Dispatcher implementing the `lava` shell command
+
+ This dispatcher imports plugins from `lava.commands` pkg_resources
+ namespace. Additional plugins can be registered as either
+ :class:`lava.command.Command` or :class:`lava.command.SubCommand`
+ sub-classes.
+ """
+
+ def __init__(self):
+ super(LavaDispatcher, self).__init__()
+ self.import_commands('lava.commands')
=== modified file 'lava_tool/__init__.py'
@@ -18,7 +18,7 @@
# along with lava-tool. If not, see <http://www.gnu.org/licenses/>.
"""
-Lava Tool package
+Deprecated lava_tool package
"""
-__version__ = (0, 4, 0, "dev", 0)
+from lava.tool import __version__
=== modified file 'lava_tool/commands/__init__.py'
@@ -20,64 +20,5 @@
Package with command line commands
"""
-import argparse
-import re
-
-
-class ExperimentalNoticeAction(argparse.Action):
- """
- Argparse action that implements the --experimental-notice
- """
-
- message = """
- Some lc-tool sub-commands are marked as EXPERIMENTAL. Those commands are
- not guaranteed to work identically, or have identical interface between
- subsequent lc-tool releases.
-
- We do that to make it possible to provide good user interface and
- server-side API when working on new features. Once a feature is stabilized
- the UI will be frozen and all subsequent changes will retain backwards
- compatibility.
- """
- message = message.lstrip()
- message = re.sub(re.compile("[ \t]+", re.M), " ", message)
- message = re.sub(re.compile("^ ", re.M), "", message)
-
- def __init__(self,
- option_strings, dest, default=None, required=False,
- help=None):
- super(ExperimentalNoticeAction, self).__init__(
- option_strings=option_strings, dest=dest, default=default, nargs=0,
- help=help)
-
- def __call__(self, parser, namespace, values, option_string=None):
- parser.exit(message=self.message)
-
-
-class ExperimentalCommandMixIn(object):
- """
- Experimental command.
-
- Prints a warning message on each call to invoke()
- """
-
- def invoke(self):
- self.print_experimental_notice()
- return super(ExperimentalCommandMixIn, self).invoke()
-
- @classmethod
- def register_arguments(cls, parser):
- retval = super(ExperimentalCommandMixIn,
- cls).register_arguments(parser)
- parser.register("action", "experimental_notice",
- ExperimentalNoticeAction)
- group = parser.add_argument_group("experimental commands")
- group.add_argument("--experimental-notice",
- action="experimental_notice",
- default=argparse.SUPPRESS,
- help="Explain the nature of experimental commands")
- return retval
-
- def print_experimental_notice(self):
- print ("EXPERIMENTAL - SUBJECT TO CHANGE"
- " (See --experimental-notice for more info)")
+
+from lava.tool.commands import ExperimentalNoticeAction, ExperimentalCommandMixIn
=== removed file 'lava_tool/commands/misc.py'
@@ -1,31 +0,0 @@
-# Copyright (C) 2010 Linaro Limited
-#
-# Author: Zygmunt Krynicki <zygmunt.krynicki@linaro.org>
-#
-# This file is part of lava-tool.
-#
-# lava-tool is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3
-# as published by the Free Software Foundation
-#
-# lava-tool 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 Lesser General Public License
-# along with lava-tool. If not, see <http://www.gnu.org/licenses/>.
-
-"""
-Module with miscellaneous commands (such as help and version)
-"""
-
-from lava_tool.interface import Command
-
-
-class help(Command):
- """
- Show a summary of all available commands
- """
- def invoke(self):
- self.parser.print_help()
=== modified file 'lava_tool/dispatcher.py'
@@ -20,10 +20,12 @@
Module with LavaDispatcher - the command dispatcher
"""
-from lava_tool.interface import LavaCommandError, BaseDispatcher
-
-
-class LavaDispatcher(BaseDispatcher):
+from lava.tool.dispatcher import Dispatcher
+from lava.tool.main import LavaDispatcher as LavaNonLegacyDispatcher
+from lava_tool.interface import LavaCommandError
+
+
+class LavaDispatcher(Dispatcher):
"""
Class implementing command line interface for launch control
"""
@@ -39,26 +41,9 @@
self.import_commands("%s.commands" % prefix)
-class LavaNonLegacyDispatcher(BaseDispatcher):
- """
- A dispatcher that wants to load only top-level commands,
- not everything-and-the-kitchen-sink into one flat namespace
-
- Available as `lava` command from shell
- """
-
- def __init__(self):
- super(LavaNonLegacyDispatcher, self).__init__()
- self.import_commands('lava.commands')
-
-
def run_with_dispatcher_class(cls):
- raise SystemExit(cls().dispatch())
+ raise cls.run()
def main():
- run_with_dispatcher_class(LavaDispatcher)
-
-
-def main_nonlegacy():
- run_with_dispatcher_class(LavaNonLegacyDispatcher)
+ LavaDispatcher.run()
=== modified file 'lava_tool/interface.py'
@@ -20,239 +20,5 @@
Interface for all lava-tool commands
"""
-import argparse
-import inspect
-import logging
-import pkg_resources
-import sys
-
-
-class LavaCommandError(Exception):
- """
- Raise this from a Command's invoke() method to display an error nicely.
-
- lava-tool will exit with a status of 1 if this is raised.
- """
-
-
-class Command(object):
- """
- Base class for all command line tool sub-commands.
- """
-
- def __init__(self, parser, args):
- """
- Prepare instance for executing commands.
-
- This method is called immediately after all arguments are parsed and
- results are available. This gives subclasses a chance to configure
- themselves. The provided parser is an instance of
- argparse.ArgumentParser but it may not be the top-level parser (it will
- be a parser specific for this command)
-
- The default implementation stores both arguments as instance attributes.
- """
- self.parser = parser
- self.args = args
-
- def invoke(self):
- """
- Invoke command action.
- """
- raise NotImplementedError()
-
- def reparse_arguments(self, parser, raw_args):
- """
- Re-parse raw arguments into normal arguments
-
- Parser is the same as in register_arguments (a sub-parser) The true,
- topmost parser is in self.parser.
-
- This method is only needed for specific commands that need to peek at
- the arguments before being able to truly redefine the parser and
- re-parse the raw arguments again.
- """
- raise NotImplementedError()
-
- @classmethod
- def get_name(cls):
- """
- Return the name of this command.
-
- The default implementation strips any leading underscores and replaces
- all other underscores with dashes.
- """
- return cls.__name__.lstrip("_").replace("_", "-")
-
- @classmethod
- def get_help(cls):
- """
- Return the help message of this command
- """
- doc = inspect.getdoc(cls)
- if doc is not None and "" in doc:
- doc = doc[:doc.index("")].rstrip()
- return doc
-
- @classmethod
- def get_epilog(cls):
- """
- Return the epilog of the help message
- """
- doc = inspect.getdoc(cls)
- if doc is not None and "" in doc:
- doc = doc[doc.index("") + 1:].lstrip()
- else:
- doc = None
- return doc
-
- @classmethod
- def register_arguments(cls, parser):
- """
- Register arguments if required.
-
- Subclasses can override this to add any arguments that will be
- exposed to the command line interface.
- """
- pass
-
-
-class SubCommand(Command):
- """
- Base class for all command sub-command hubs.
-
- This class is needed when one wants to get a custom level of command
- options that can be freely extended, just like the top-level lava-tool
- command.
-
- For example, a SubCommand 'actions' will load additional commands from a
- the 'lava.actions' namespace. For the end user it will be available as::
-
- $ lava-tool foo actions xxx
-
- Where xxx is one of the Commands that is declared to live in the namespace
- provided by 'foo actions'.
- """
-
- namespace = None
-
- @classmethod
- def get_namespace(cls):
- """
- Return the pkg-resources entry point namespace name from which
- sub-commands will be loaded.
- """
- return cls.namespace
-
- @classmethod
- def register_subcommands(cls, parser):
- """
- Register sub commands.
-
- This method is called around the same time as register_arguments()
- would be called for the plain command classes. It loads commands from
- the entry point namespace returned by get_namespace() and registeres
- them with a BaseDispatcher class. The parsers used by that dispatcher
- are linked to the calling dispatcher parser so the new commands enrich
- the top-level parser tree.
-
- In addition, the provided parser stores a dispatcher instance in its
- defaults. This is useful when one wants to access it later. To a final
- command instance it shall be available as self.args.dispatcher.
- """
- dispatcher = BaseDispatcher(parser, name=cls.get_name())
- namespace = cls.get_namespace()
- if namespace is not None:
- dispatcher.import_commands(namespace)
- parser.set_defaults(dispatcher=dispatcher)
-
-
-class BaseDispatcher(object):
- """
- Class implementing command line interface for launch control
- """
-
- description = None
- epilog = None
-
- def __init__(self, parser=None, name=None):
- self.parser = parser or self.construct_parser()
- self.subparsers = self.parser.add_subparsers(
- title="Sub-command to invoke")
- self.name = name
-
- def __repr__(self):
- return "%r(name=%r)" % (self.__class__.__name__, self.name)
-
- @classmethod
- def construct_parser(cls):
- """
- Construct a parser for this dispatcher.
-
- This is only used if the parser is not provided by the parent
- dispatcher instance.
- """
- parser_args = dict(add_help=True)
- if cls.description is not None:
- parser_args['description'] = cls.description
- if cls.epilog is not None:
- parser_args['epilog'] = cls.epilog
- return argparse.ArgumentParser(**parser_args)
-
- def import_commands(self, entrypoint_name):
- """
- Import commands from given entry point namespace
- """
- logging.debug("Loading commands in entry point %r", entrypoint_name)
- for entrypoint in pkg_resources.iter_entry_points(entrypoint_name):
- self.add_command_cls(entrypoint.load())
-
- def add_command_cls(self, command_cls):
- """
- Add a new command class to this dispatcher.
-
- The command must be a subclass of Command or SubCommand.
- """
- logging.debug("Loading command class %r", command_cls)
- # Create a sub-parser where the command/sub-command can register things.
- sub_parser = self.subparsers.add_parser(
- command_cls.get_name(),
- help=command_cls.get_help(),
- epilog=command_cls.get_epilog())
- if issubclass(command_cls, SubCommand):
- # Handle SubCommand somewhat different. Instead of calling
- # register_arguments we call register_subcommands
- command_cls.register_subcommands(sub_parser)
- else:
- # Handle plain commands easily by recording their commands in the
- # dedicated sub-parser we've crated for them.
- command_cls.register_arguments(sub_parser)
- # In addition, since we don't want to require all sub-classes of
- # Command to super-call register_arguments (everyone would forget
- # this anyway) we manually register the command class for that
- # sub-parser so that dispatch() can look it up later.
- sub_parser.set_defaults(
- command_cls=command_cls,
- parser=sub_parser)
-
- def dispatch(self, raw_args=None):
- """
- Dispatch a command with the specified arguments.
-
- If arguments are left out they are looked up in sys.argv automatically
- """
- # First parse whatever input arguments we've got
- args = self.parser.parse_args(raw_args)
- # Then look up the command class and construct it with the parser it
- # belongs to and the parsed arguments.
- command = args.command_cls(args.parser, args)
- try:
- # Give the command a chance to re-parse command line arguments
- command.reparse_arguments(args.parser, raw_args)
- except NotImplementedError:
- pass
- try:
- return command.invoke()
- except LavaCommandError as ex:
- print >> sys.stderr, "ERROR: %s" % (ex,)
- return 1
+from lava.tool.errors import CommandError as LavaCommandError
+from lava.tool.command import Command, SubCommand
=== modified file 'setup.py'
@@ -23,9 +23,10 @@
setup(
name='lava-tool',
- version=":versiontools:lava_tool:__version__",
+ version=":versiontools:lava.tool:__version__",
author="Zygmunt Krynicki",
author_email="zygmunt.krynicki@linaro.org",
+ namespace_packages=['lava'],
packages=find_packages(),
description="Command line utility for Linaro validation services",
url='https://launchpad.net/lava-tool',
@@ -34,11 +35,11 @@
entry_points="""
[console_scripts]
lava-tool = lava_tool.dispatcher:main
- lava = lava_tool.dispatcher:main_nonlegacy
+ lava = lava.tool.main:LavaDispatcher.run
[lava.commands]
- help = lava_tool.commands.misc:help
+ help = lava.tool.commands.help:help
[lava_tool.commands]
- help = lava_tool.commands.misc:help
+ help = lava.tool.commands.help:help
auth-add = lava_tool.commands.auth:auth_add
""",
classifiers=[