summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAngus L'Herrou <piraka@brandeis.edu>2021-05-14 10:19:23 -0400
committerDavid Lord <davidism@gmail.com>2022-02-19 10:14:39 -0800
commit74e7f7079cb31578fa2578f219d93a33cfeb46f8 (patch)
tree7a22e7d0c9c06392cc955a32f077e4b04bd29dcf /src
parent77961478cdaf9cf55c8b15fd1db0681ff75ffcfb (diff)
downloadclick-74e7f7079cb31578fa2578f219d93a33cfeb46f8.tar.gz
command and group decorator parentheses are optional
Diffstat (limited to 'src')
-rw-r--r--src/click/core.py32
-rw-r--r--src/click/decorators.py58
2 files changed, 85 insertions, 5 deletions
diff --git a/src/click/core.py b/src/click/core.py
index 95d852b..3d11ab5 100644
--- a/src/click/core.py
+++ b/src/click/core.py
@@ -1797,7 +1797,7 @@ class Group(MultiCommand):
def command(
self, *args: t.Any, **kwargs: t.Any
- ) -> t.Callable[[t.Callable[..., t.Any]], Command]:
+ ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], Command], Command]:
"""A shortcut decorator for declaring and attaching a command to
the group. This takes the same arguments as :func:`command` and
immediately registers the created command with this group by
@@ -1806,6 +1806,9 @@ class Group(MultiCommand):
To customize the command class used, set the
:attr:`command_class` attribute.
+ .. versionchanged:: 8.1
+ This decorator can be applied without parentheses.
+
.. versionchanged:: 8.0
Added the :attr:`command_class` attribute.
"""
@@ -1814,16 +1817,25 @@ class Group(MultiCommand):
if self.command_class is not None and "cls" not in kwargs:
kwargs["cls"] = self.command_class
+ func: t.Optional[t.Callable] = None
+
+ if args and callable(args[0]):
+ func = args[0]
+ args = args[1:]
+
def decorator(f: t.Callable[..., t.Any]) -> Command:
- cmd = command(*args, **kwargs)(f)
+ cmd: Command = command(*args, **kwargs)(f)
self.add_command(cmd)
return cmd
+ if func is not None:
+ return decorator(func)
+
return decorator
def group(
self, *args: t.Any, **kwargs: t.Any
- ) -> t.Callable[[t.Callable[..., t.Any]], "Group"]:
+ ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], "Group"], "Group"]:
"""A shortcut decorator for declaring and attaching a group to
the group. This takes the same arguments as :func:`group` and
immediately registers the created group with this group by
@@ -1832,11 +1844,20 @@ class Group(MultiCommand):
To customize the group class used, set the :attr:`group_class`
attribute.
+ .. versionchanged:: 8.1
+ This decorator can be applied without parentheses.
+
.. versionchanged:: 8.0
Added the :attr:`group_class` attribute.
"""
from .decorators import group
+ func: t.Optional[t.Callable] = None
+
+ if args and callable(args[0]):
+ func = args[0]
+ args = args[1:]
+
if self.group_class is not None and "cls" not in kwargs:
if self.group_class is type:
kwargs["cls"] = type(self)
@@ -1844,10 +1865,13 @@ class Group(MultiCommand):
kwargs["cls"] = self.group_class
def decorator(f: t.Callable[..., t.Any]) -> "Group":
- cmd = group(*args, **kwargs)(f)
+ cmd: Group = group(*args, **kwargs)(f)
self.add_command(cmd)
return cmd
+ if func is not None:
+ return decorator(func)
+
return decorator
def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]:
diff --git a/src/click/decorators.py b/src/click/decorators.py
index 7930a16..a8c6d2d 100644
--- a/src/click/decorators.py
+++ b/src/click/decorators.py
@@ -153,11 +153,29 @@ def _make_command(
)
+@t.overload
def command(
name: t.Optional[str] = None,
cls: t.Optional[t.Type[Command]] = None,
**attrs: t.Any,
) -> t.Callable[[F], Command]:
+ ...
+
+
+@t.overload
+def command(
+ name: t.Callable,
+ cls: t.Optional[t.Type[Command]] = None,
+ **attrs: t.Any,
+) -> Command:
+ ...
+
+
+def command(
+ name: t.Union[str, t.Callable, None] = None,
+ cls: t.Optional[t.Type[Command]] = None,
+ **attrs: t.Any,
+) -> t.Union[Command, t.Callable[[F], Command]]:
r"""Creates a new :class:`Command` and uses the decorated function as
callback. This will also automatically attach all decorated
:func:`option`\s and :func:`argument`\s as parameters to the command.
@@ -176,24 +194,62 @@ def command(
name with underscores replaced by dashes.
:param cls: the command class to instantiate. This defaults to
:class:`Command`.
+
+ .. versionchanged:: 8.1
+ This decorator can be applied without parentheses.
"""
if cls is None:
cls = Command
+ func: t.Optional[t.Callable] = None
+
+ if callable(name):
+ func = name
+ name = None
+
def decorator(f: t.Callable[..., t.Any]) -> Command:
cmd = _make_command(f, name, attrs, cls) # type: ignore
cmd.__doc__ = f.__doc__
return cmd
+ if func is not None:
+ return decorator(func)
+
return decorator
-def group(name: t.Optional[str] = None, **attrs: t.Any) -> t.Callable[[F], Group]:
+@t.overload
+def group(
+ name: t.Optional[str] = None,
+ **attrs: t.Any,
+) -> t.Callable[[F], Group]:
+ ...
+
+
+@t.overload
+def group(
+ name: t.Callable,
+ **attrs: t.Any,
+) -> Group:
+ ...
+
+
+def group(
+ name: t.Union[str, t.Callable, None] = None, **attrs: t.Any
+) -> t.Union[Group, t.Callable[[F], Group]]:
"""Creates a new :class:`Group` with a function as callback. This
works otherwise the same as :func:`command` just that the `cls`
parameter is set to :class:`Group`.
+
+ .. versionchanged:: 8.1
+ This decorator can be applied without parentheses.
"""
attrs.setdefault("cls", Group)
+
+ if callable(name):
+ grp: t.Callable[[F], Group] = t.cast(Group, command(**attrs))
+ return grp(name)
+
return t.cast(Group, command(name, **attrs))