yellow team mailing list archive
-
yellow team
-
Mailing list archive
-
Message #00638
[Merge] lp:~frankban/lpsetup/steps into lp:lpsetup
Francesco Banconi has proposed merging lp:~frankban/lpsetup/steps into lp:lpsetup.
Requested reviews:
Launchpad Yellow Squad (yellow)
For more details, see:
https://code.launchpad.net/~frankban/lpsetup/steps/+merge/98815
== Changes ==
lpsetup sub commands are able to execute only a subset of their internal functions. Now these functions composing a sub command are called "steps". Gary suggested that the previous name ("actions") could generate confusion since Python argparse has his own concept of actions.
== Tests ==
$ bin/test
Running zope.testrunner.layer.UnitTests tests:
Set up zope.testrunner.layer.UnitTests in 0.000 seconds.
Ran 36 tests with 0 failures and 0 errors in 0.024 seconds.
Tearing down left over layers:
Tear down zope.testrunner.layer.UnitTests in 0.000 seconds.
--
https://code.launchpad.net/~frankban/lpsetup/steps/+merge/98815
Your team Launchpad Yellow Squad is requested to review the proposed merge of lp:~frankban/lpsetup/steps into lp:lpsetup.
=== modified file 'lpsetup/__init__.py'
--- lpsetup/__init__.py 2012-03-16 11:03:51 +0000
+++ lpsetup/__init__.py 2012-03-22 11:09:20 +0000
@@ -9,7 +9,7 @@
'get_version',
]
-VERSION = (0, 1, 1)
+VERSION = (0, 1, 2)
def get_version():
=== modified file 'lpsetup/argparser.py'
--- lpsetup/argparser.py 2012-03-12 14:13:55 +0000
+++ lpsetup/argparser.py 2012-03-22 11:09:20 +0000
@@ -6,7 +6,7 @@
__metaclass__ = type
__all__ = [
- 'ActionsBasedSubCommand',
+ 'StepsBasedSubCommand',
'ArgumentParser',
'BaseSubCommand',
]
@@ -311,25 +311,25 @@
pass
-class ActionsBasedSubCommand(BaseSubCommand):
- """A sub command that uses "actions" to handle its execution.
+class StepsBasedSubCommand(BaseSubCommand):
+ """A sub command that uses "steps" to handle its execution.
- Actions are callables stored in the `actions` attribute, together
+ Steps are callables stored in the `steps` attribute, together
with the arguments they expect. Those arguments are strings
representing attributes of the argparse namespace::
>>> trace = []
- >>> def action1(foo):
- ... trace.append('action1 received ' + foo)
-
- >>> def action2(foo, bar):
- ... trace.append('action2 received {0} and {1}'.format(foo, bar))
-
- >>> class SubCommand(ActionsBasedSubCommand):
- ... actions = (
- ... (action1, 'foo'),
- ... (action2, 'foo', 'bar'),
+ >>> def step1(foo):
+ ... trace.append('step1 received ' + foo)
+
+ >>> def step2(foo, bar):
+ ... trace.append('step2 received {0} and {1}'.format(foo, bar))
+
+ >>> class SubCommand(StepsBasedSubCommand):
+ ... steps = (
+ ... (step1, 'foo'),
+ ... (step2, 'foo', 'bar'),
... )
...
... def add_arguments(self, parser):
@@ -337,7 +337,7 @@
... parser.add_argument('--foo')
... parser.add_argument('--bar')
- This class implements an handler method that executes actions in the
+ This class implements an handler method that executes steps in the
order they are provided::
>>> parser = ArgumentParser()
@@ -345,43 +345,42 @@
>>> namespace = parser.parse_args('sub --foo eggs --bar spam'.split())
>>> namespace.main(namespace)
>>> trace
- ['action1 received eggs', 'action2 received eggs and spam']
+ ['step1 received eggs', 'step2 received eggs and spam']
- A special argument `-a` or `--actions` is automatically added to the
- parser. It can be used to execute only one or a subset of actions::
+ A special argument `-s` or `--steps` is automatically added to the
+ parser. It can be used to execute only one or a subset of steps::
>>> trace = []
- >>> namespace = parser.parse_args('sub --foo eggs -a action1'.split())
+ >>> namespace = parser.parse_args('sub --foo eggs -s step1'.split())
>>> namespace.main(namespace)
>>> trace
- ['action1 received eggs']
+ ['step1 received eggs']
- A special argument `--skip-actions` is automatically added to the
- parser. It can be used to skip one or more actions::
+ A special argument `--skip-steps` is automatically added to the
+ parser. It can be used to skip one or more steps::
>>> trace = []
>>> namespace = parser.parse_args(
- ... 'sub --foo eggs --skip-actions action1'.split())
+ ... 'sub --foo eggs --skip-steps step1'.split())
>>> namespace.main(namespace)
>>> trace
- ['action2 received eggs and None']
+ ['step2 received eggs and None']
- The actions execution is stopped if an action raises
- `subprocess.CalledProcessError`.
+ The steps execution is stopped if a step raises `CalledProcessError`.
In that case, the error is returned by the handler.
>>> trace = []
- >>> def erroneous_action(foo):
+ >>> def erroneous_step(foo):
... raise subprocess.CalledProcessError(1, 'command')
>>> class SubCommandWithErrors(SubCommand):
- ... actions = (
- ... (action1, 'foo'),
- ... (erroneous_action, 'foo'),
- ... (action2, 'foo', 'bar'),
+ ... steps = (
+ ... (step1, 'foo'),
+ ... (erroneous_step, 'foo'),
+ ... (step2, 'foo', 'bar'),
... )
>>> parser = ArgumentParser()
@@ -391,66 +390,66 @@
>>> str(error)
"Command 'command' returned non-zero exit status 1"
- The action `action2` is not executed::
+ The step `step2` is not executed::
>>> trace
- ['action1 received eggs']
+ ['step1 received eggs']
"""
- actions = ()
+ steps = ()
def __init__(self, *args, **kwargs):
- super(ActionsBasedSubCommand, self).__init__(*args, **kwargs)
- self._action_names = []
- self._actions = {}
- for action_args in self.actions:
- action, args = action_args[0], action_args[1:]
- action_name = self._get_action_name(action)
- self._action_names.append(action_name)
- self._actions[action_name] = (action, args)
-
- def _get_action_name(self, action):
- """Return the string representation of an action callable.
-
- The name is retrieved using attributes lookup for `action_name`
+ super(StepsBasedSubCommand, self).__init__(*args, **kwargs)
+ self._step_names = []
+ self._steps = {}
+ for step_args in self.steps:
+ step, args = step_args[0], step_args[1:]
+ step_name = self._get_step_name(step)
+ self._step_names.append(step_name)
+ self._steps[step_name] = (step, args)
+
+ def _get_step_name(self, step):
+ """Return the string representation of a step callable.
+
+ The name is retrieved using attributes lookup for `step_name`
and then `__name__`::
- >>> def action1():
- ... pass
- >>> action1.action_name = 'myaction'
-
- >>> def action2():
- ... pass
-
- >>> sub_command = ActionsBasedSubCommand('foo')
- >>> sub_command._get_action_name(action1)
- 'myaction'
- >>> sub_command._get_action_name(action2)
- 'action2'
+ >>> def step1():
+ ... pass
+ >>> step1.step_name = 'mystep'
+
+ >>> def step2():
+ ... pass
+
+ >>> sub_command = StepsBasedSubCommand('foo')
+ >>> sub_command._get_step_name(step1)
+ 'mystep'
+ >>> sub_command._get_step_name(step2)
+ 'step2'
"""
try:
- return action.action_name
+ return step.step_name
except AttributeError:
- return action.__name__
+ return step.__name__
def add_arguments(self, parser):
- super(ActionsBasedSubCommand, self).add_arguments(parser)
+ super(StepsBasedSubCommand, self).add_arguments(parser)
parser.add_argument(
- '-a', '--actions', nargs='+', choices=self._action_names,
+ '-s', '--steps', nargs='+', choices=self._step_names,
help='Call one or more internal functions.')
parser.add_argument(
- '--skip-actions', nargs='+', choices=self._action_names,
+ '--skip-steps', nargs='+', choices=self._step_names,
help='Skip one or more internal functions.')
def handle(self, namespace):
- skip_actions = namespace.skip_actions or []
- action_names = filter(
- lambda action_name: action_name not in skip_actions,
- namespace.actions or self._action_names)
- for action_name in action_names:
- action, arg_names = self._actions[action_name]
+ skip_steps = namespace.skip_steps or []
+ step_names = filter(
+ lambda step_name: step_name not in skip_steps,
+ namespace.steps or self._step_names)
+ for step_name in step_names:
+ step, arg_names = self._steps[step_name]
args = [getattr(namespace, i) for i in arg_names]
try:
- action(*args)
+ step(*args)
except subprocess.CalledProcessError as err:
return err
=== modified file 'lpsetup/subcommands/install.py'
--- lpsetup/subcommands/install.py 2012-03-16 17:40:22 +0000
+++ lpsetup/subcommands/install.py 2012-03-22 11:09:20 +0000
@@ -211,10 +211,10 @@
file_append(HOSTS_FILE, line)
-class SubCommand(argparser.ActionsBasedSubCommand):
+class SubCommand(argparser.StepsBasedSubCommand):
"""Install the Launchpad environment."""
- actions = (
+ steps = (
(initialize,
'user', 'full_name', 'email', 'lpuser',
'private_key', 'public_key', 'valid_ssh_keys', 'ssh_key_path',
@@ -283,7 +283,7 @@
'given user (see -u argument). '
'[DEFAULT={0}]'.format(CHECKOUT_DIR))
parser.add_argument(
- '-s', '--ssh-key-name', default=SSH_KEY_NAME,
+ '-S', '--ssh-key-name', default=SSH_KEY_NAME,
help='{0} [DEFAULT={1}]'.format(
self.ssh_key_name_help, SSH_KEY_NAME))
parser.add_argument(
=== modified file 'lpsetup/subcommands/lxcinstall.py'
--- lpsetup/subcommands/lxcinstall.py 2012-03-16 17:40:22 +0000
+++ lpsetup/subcommands/lxcinstall.py 2012-03-22 11:09:20 +0000
@@ -150,7 +150,7 @@
class SubCommand(install.SubCommand):
"""Install the Launchpad environment inside an LXC."""
- actions = (
+ steps = (
(install.initialize,
'user', 'full_name', 'email', 'lpuser', 'private_key',
'public_key', 'valid_ssh_keys', 'dependencies_dir', 'directory'),
=== modified file 'lpsetup/subcommands/update.py'
--- lpsetup/subcommands/update.py 2012-03-16 17:40:22 +0000
+++ lpsetup/subcommands/update.py 2012-03-22 11:09:20 +0000
@@ -56,10 +56,10 @@
call(cmd, '--parent', dependencies_dir, '--target', branch)
-class SubCommand(argparser.ActionsBasedSubCommand):
+class SubCommand(argparser.StepsBasedSubCommand):
"""Update the Launchpad environment to latest version."""
- actions = (
+ steps = (
(update_launchpad,
'user', 'valid_ssh_keys', 'dependencies_dir', 'directory', 'apt'),
(link_sourcecode_in_branches,
=== modified file 'lpsetup/tests/examples.py'
--- lpsetup/tests/examples.py 2012-03-15 17:13:37 +0000
+++ lpsetup/tests/examples.py 2012-03-22 11:09:20 +0000
@@ -6,11 +6,11 @@
__metaclass__ = type
__all__ = [
- 'action1',
- 'action2',
- 'ActionsBasedSubCommand',
- 'ActionsBasedSubCommandWithErrors',
- 'bad_action',
+ 'step1',
+ 'step2',
+ 'StepsBasedSubCommand',
+ 'StepsBasedSubCommandWithErrors',
+ 'bad_step',
'SubCommand',
]
@@ -19,16 +19,16 @@
from lpsetup import argparser
-def action1(foo):
- print 'action1 received ' + foo
-
-
-def action2(foo, bar):
- print 'action2 received {0} and {1}'.format(foo, bar)
-action2.action_name = 'myaction'
-
-
-def bad_action(foo):
+def step1(foo):
+ print 'step1 received ' + foo
+
+
+def step2(foo, bar):
+ print 'step2 received {0} and {1}'.format(foo, bar)
+step2.step_name = 'mystep'
+
+
+def bad_step(foo):
raise subprocess.CalledProcessError(1, 'command')
@@ -45,25 +45,25 @@
return namespace
-class ActionsBasedSubCommand(argparser.ActionsBasedSubCommand):
- """An example action based sub command."""
+class StepsBasedSubCommand(argparser.StepsBasedSubCommand):
+ """An example steps based sub command."""
- actions = (
- (action1, 'foo'),
- (action2, 'foo', 'bar'),
+ steps = (
+ (step1, 'foo'),
+ (step2, 'foo', 'bar'),
)
def add_arguments(self, parser):
- super(ActionsBasedSubCommand, self).add_arguments(parser)
+ super(StepsBasedSubCommand, self).add_arguments(parser)
parser.add_argument('--foo')
parser.add_argument('--bar')
-class ActionsBasedSubCommandWithErrors(ActionsBasedSubCommand):
- """An example action based sub command (containing a failing action)."""
+class StepsBasedSubCommandWithErrors(StepsBasedSubCommand):
+ """An example steps based sub command (containing a failing step)."""
- actions = (
- (action1, 'foo'),
- (bad_action, 'foo'),
- (action2, 'foo', 'bar'),
+ steps = (
+ (step1, 'foo'),
+ (bad_step, 'foo'),
+ (step2, 'foo', 'bar'),
)
=== modified file 'lpsetup/tests/test_argparser.py'
--- lpsetup/tests/test_argparser.py 2012-03-15 17:13:37 +0000
+++ lpsetup/tests/test_argparser.py 2012-03-22 11:09:20 +0000
@@ -143,48 +143,48 @@
self.assertIn(self.sub_command.help, help)
-class ActionsBasedSubCommandTest(SubCommandTestMixin, unittest.TestCase):
-
- sub_command_class = examples.ActionsBasedSubCommand
-
- def test_actions(self):
- # Ensure actions are executed in the order they are provided.
+class StepsBasedSubCommandTest(SubCommandTestMixin, unittest.TestCase):
+
+ sub_command_class = examples.StepsBasedSubCommand
+
+ def test_steps(self):
+ # Ensure steps are executed in the order they are provided.
with capture_output() as output:
self.parse_and_call_main('--foo eggs --bar spam')
self.check_output(
- ['action1 received eggs', 'action2 received eggs and spam'],
+ ['step1 received eggs', 'step2 received eggs and spam'],
output)
- def test_action_flag(self):
- # A special argument `-a` or `--actions` is automatically added to the
- # parser. It can be used to execute only one or a subset of actions.
- with capture_output() as output:
- self.parse_and_call_main('--foo eggs -a action1')
- self.check_output(['action1 received eggs'], output)
-
- def test_skip_action(self):
- # A special argument `--skip-actions` is automatically added to the
- # parser. It can be used to skip one or more actions.
- with capture_output() as output:
- self.parse_and_call_main('--foo eggs --skip-actions action1')
- self.check_output(['action2 received eggs and None'], output)
-
- def test_action_name(self):
- # Ensure the string representation of an action i correctly retrieved.
- method = self.sub_command._get_action_name
- self.assertEqual('action1', method(examples.action1))
- self.assertEqual('myaction', method(examples.action2))
-
-
-class ActionsBasedSubCommandWithErrorsTest(
+ def test_step_flag(self):
+ # A special argument `-s` or `--steps` is automatically added to the
+ # parser. It can be used to execute only one or a subset of steps.
+ with capture_output() as output:
+ self.parse_and_call_main('--foo eggs -s step1')
+ self.check_output(['step1 received eggs'], output)
+
+ def test_skip_steps(self):
+ # A special argument `--skip-steps` is automatically added to the
+ # parser. It can be used to skip one or more steps.
+ with capture_output() as output:
+ self.parse_and_call_main('--foo eggs --skip-steps step1')
+ self.check_output(['step2 received eggs and None'], output)
+
+ def test_step_name(self):
+ # Ensure the string representation of a step is correctly retrieved.
+ method = self.sub_command._get_step_name
+ self.assertEqual('step1', method(examples.step1))
+ self.assertEqual('mystep', method(examples.step2))
+
+
+class StepsBasedSubCommandWithErrorsTest(
SubCommandTestMixin, unittest.TestCase):
- sub_command_class = examples.ActionsBasedSubCommandWithErrors
+ sub_command_class = examples.StepsBasedSubCommandWithErrors
- def test_failing_action(self):
- # Ensure the actions execution is stopped if an action raises
+ def test_failing_step(self):
+ # Ensure the steps execution is stopped if a step raises
# `subprocess.CalledProcessError`.
with capture_output() as output:
error = self.parse_and_call_main('--foo eggs')
self.assertEqual(1, error.returncode)
- self.check_output(['action1 received eggs'], output)
+ self.check_output(['step1 received eggs'], output)