-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
decorators.py
125 lines (99 loc) 路 4.45 KB
/
decorators.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# Copyright Kevin Deldycke <kevin@deldycke.com> and contributors.
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
"""Decorators for group, commands and options."""
from functools import wraps
import cloup
from .colorize import ColorOption, HelpOption
from .commands import ExtraCommand, ExtraGroup, TimerOption
from .config import ConfigOption, ShowParamsOption
from .logging import VerbosityOption
from .tabulate import TableFormatOption
from .version import VersionOption
def allow_missing_parenthesis(dec_factory):
"""Allow to use decorators with or without parenthesis.
As proposed in
`Cloup issue #127 <https://github.com/janluke/cloup/issues/127#issuecomment-1264704896>`_.
"""
@wraps(dec_factory)
def new_factory(*args, **kwargs):
if args and callable(args[0]):
return dec_factory(*args[1:], **kwargs)(args[0])
return dec_factory(*args, **kwargs)
return new_factory
def decorator_factory(dec, **new_defaults):
"""Clone decorator with a set of new defaults.
Used to create our own collection of decorators for our custom options, based on
Cloup's.
"""
@allow_missing_parenthesis
def decorator(*args, **kwargs):
"""Returns a new decorator instanciated with custom defaults.
These defaults values are merged with the user's own arguments.
A special case is made for the ``params`` argument, to allow it to be callable.
This limits the issue of the mutable options being shared between commands.
This decorator can be used with or without arguments.
"""
# Use a copy of the defaults to avoid modifying the original dict.
new_kwargs = new_defaults.copy()
new_kwargs.update(kwargs)
# If the params argument is a callable, we need to call it to get the actual
# list of options.
params_func = new_kwargs.get("params")
if callable(params_func):
new_kwargs["params"] = params_func()
# Return the original decorator with the new defaults.
return dec(*args, **new_kwargs)
return decorator
def default_extra_params():
"""Default additional options added to ``extra_command`` and ``extra_group``:
#. ``--time`` / ``--no-time``
#. ``--color``, ``--ansi`` / ``--no-color``, ``--no-ansi``
#. ``-C``, ``--config CONFIG_PATH``
#. ``--show-params``
#. ``-v``, ``--verbosity LEVEL``
#. ``--version``
#. ``-h``, ``--help``
Order is important to let options at the top have influence on those below.
"""
return [
TimerOption(),
ColorOption(),
# XXX Should we move config to the top as it might influence other options?
ConfigOption(),
ShowParamsOption(),
VerbosityOption(),
VersionOption(print_env_info=True),
HelpOption(),
]
# Redefine cloup decorators to allow them to be used with or without parenthesis.
command = decorator_factory(dec=cloup.command)
group = decorator_factory(dec=cloup.group)
# Extra command and group decorators with default options.
extra_command = decorator_factory(
dec=cloup.command, cls=ExtraCommand, params=default_extra_params
)
extra_group = decorator_factory(
dec=cloup.group, cls=ExtraGroup, params=default_extra_params
)
# Option decorators.
color_option = decorator_factory(dec=cloup.option, cls=ColorOption)
config_option = decorator_factory(dec=cloup.option, cls=ConfigOption)
help_option = decorator_factory(dec=cloup.option, cls=HelpOption)
show_params_option = decorator_factory(dec=cloup.option, cls=ShowParamsOption)
table_format_option = decorator_factory(dec=cloup.option, cls=TableFormatOption)
timer_option = decorator_factory(dec=cloup.option, cls=TimerOption)
verbosity_option = decorator_factory(dec=cloup.option, cls=VerbosityOption)
version_option = decorator_factory(dec=cloup.option, cls=VersionOption)