summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Ronacher <armin.ronacher@active-4.com>2015-09-15 16:46:29 -0700
committerArmin Ronacher <armin.ronacher@active-4.com>2015-09-15 16:46:29 -0700
commit5620b05385c3bdaeac0f0347fd2373ae1479624c (patch)
tree7ae58099e571fe21cddfc0a8eaecd3aeea214074
parentc4c9eb23243174cd1ffc9fd0162caf31e93b49ee (diff)
downloadclick-5620b05385c3bdaeac0f0347fd2373ae1479624c.tar.gz
We're not rejecting multi commands below chained multi commands. This fixes #415
-rw-r--r--CHANGES3
-rw-r--r--click/core.py22
-rw-r--r--docs/commands.rst3
3 files changed, 27 insertions, 1 deletions
diff --git a/CHANGES b/CHANGES
index e49a437..51fffc1 100644
--- a/CHANGES
+++ b/CHANGES
@@ -10,6 +10,9 @@ Version 6.0
- Optimized the progressbar rendering to not render when it did not
actually change.
+- Actively reject multi commands within chained multi commands. This
+ cannot be supported with the current setup of how the invocation for
+ subcommands works.
Version 5.1
-----------
diff --git a/click/core.py b/click/core.py
index b3b51c4..e4aaca9 100644
--- a/click/core.py
+++ b/click/core.py
@@ -37,6 +37,25 @@ def _bashcomplete(cmd, prog_name, complete_var=None):
sys.exit(1)
+def _check_multicommand(base_command, cmd_name, cmd, register=False):
+ if not base_command.chain or not isinstance(cmd, MultiCommand):
+ return
+ if register:
+ hint = 'It is not possible to add multi commands as children to ' \
+ 'another multi command that is in chain mode'
+ else:
+ hint = 'Found a multi command as subcommand to a multi command ' \
+ 'that is in chain mode. This is not supported'
+ raise RuntimeError('%s. Command "%s" is set to chain and "%s" was '
+ 'added as subcommand but it in itself is a '
+ 'multi command. ("%s" is a %s within a chained '
+ '%s named "%s")' % (
+ hint, base_command.name, cmd_name,
+ cmd_name, cmd.__class__.__name__,
+ base_command.__class__.__name__,
+ base_command.name))
+
+
def batch(iterable, batch_size):
return list(zip(*repeat(iter(iterable), batch_size)))
@@ -1111,6 +1130,7 @@ class Group(MultiCommand):
name = name or cmd.name
if name is None:
raise TypeError('Command has no name.')
+ _check_multicommand(self, name, cmd, register=True)
self.commands[name] = cmd
def command(self, *args, **kwargs):
@@ -1163,6 +1183,8 @@ class CommandCollection(MultiCommand):
def get_command(self, ctx, cmd_name):
for source in self.sources:
rv = source.get_command(ctx, cmd_name)
+ if self.chain:
+ _check_multicommand(self, cmd_name, rv)
if rv is not None:
return rv
diff --git a/docs/commands.rst b/docs/commands.rst
index 642f873..157d004 100644
--- a/docs/commands.rst
+++ b/docs/commands.rst
@@ -310,7 +310,8 @@ Now you can invoke it like this:
invoke(cli, prog_name='setup.py', args=['sdist', 'bdist_wheel'])
When using multi command chaining you can only have one command (the last)
-use ``nargs=-1`` on an argument. Other than that there are no
+use ``nargs=-1`` on an argument. It is also not possible to nest multi
+commands below chained multicommands. Other than that there are no
restrictions on how they work. They can accept options and arguments as
normal.