0
# Utilities and Patching
1
2
Utility functions for patching existing Click applications and various helper functions for working with Rich-Click components. These utilities enable integration with existing Click codebases and provide helper functionality for Rich-Click development.
3
4
## Capabilities
5
6
### Patching System
7
8
Functions for monkey-patching existing Click applications to use Rich-Click formatting without code changes.
9
10
```python { .api }
11
def patch(rich_config: Optional[RichHelpConfiguration] = None) -> None:
12
"""
13
Patch Click internals to use rich-click types.
14
15
This function monkey-patches Click's core classes and decorators
16
to use Rich-Click equivalents, enabling rich formatting for
17
existing Click applications without code modifications.
18
19
Parameters:
20
- rich_config (RichHelpConfiguration, optional): Configuration to apply globally
21
22
Effects:
23
- click.command -> rich_command
24
- click.group -> rich_group
25
- click.Command -> _PatchedRichCommand
26
- click.Group -> _PatchedRichGroup
27
- click.CommandCollection -> _PatchedRichCommandCollection
28
- click.MultiCommand -> _PatchedRichMultiCommand (Click < 9.0)
29
"""
30
```
31
32
Usage example:
33
34
```python
35
import click
36
import rich_click
37
38
# Existing Click application
39
@click.command()
40
@click.option('--name', help='Your name')
41
def hello(name):
42
"""Say hello."""
43
click.echo(f'Hello, {name}!')
44
45
# Patch Click to use Rich-Click formatting
46
rich_click.patch()
47
48
# Now the existing Click app will use rich formatting
49
if __name__ == '__main__':
50
hello()
51
```
52
53
### Patched Classes
54
55
Internal classes used by the patching system to provide Rich-Click functionality to existing Click applications.
56
57
```python { .api }
58
class _PatchedRichCommand(RichCommand):
59
"""
60
Patched Rich command class.
61
62
Internal class used when patching Click.Command to provide
63
rich formatting capabilities.
64
"""
65
66
class _PatchedRichGroup(RichGroup, _PatchedRichCommand):
67
"""
68
Patched Rich group class.
69
70
Internal class used when patching Click.Group to provide
71
rich formatting capabilities for command groups.
72
"""
73
74
class _PatchedRichCommandCollection(RichCommandCollection, _PatchedRichCommand):
75
"""
76
Patched Rich command collection class.
77
78
Internal class used when patching Click.CommandCollection.
79
"""
80
81
class _PatchedRichMultiCommand(RichMultiCommand, _PatchedRichCommand):
82
"""
83
Patched Rich multi-command class (deprecated).
84
85
Internal class used when patching Click.MultiCommand in Click < 9.0.
86
"""
87
```
88
89
### Patched Decorators
90
91
Internal decorator functions used by the patching system.
92
93
```python { .api }
94
def rich_command(*args, **kwargs):
95
"""
96
Patched command decorator.
97
98
Internal function that replaces click.command when patching
99
is enabled. Uses _PatchedRichCommand by default.
100
101
Parameters:
102
- *args: Positional arguments for command
103
- **kwargs: Keyword arguments for command
104
105
Returns:
106
Union[Command, Callable]: Command or decorator function
107
"""
108
109
def rich_group(*args, **kwargs):
110
"""
111
Patched group decorator.
112
113
Internal function that replaces click.group when patching
114
is enabled. Uses _PatchedRichGroup by default.
115
116
Parameters:
117
- *args: Positional arguments for group
118
- **kwargs: Keyword arguments for group
119
120
Returns:
121
Union[Group, Callable]: Group or decorator function
122
"""
123
```
124
125
### Utility Functions
126
127
Helper functions for working with Rich-Click components and configuration.
128
129
```python { .api }
130
def truthy(o: Any) -> Optional[bool]:
131
"""
132
Check if string or other object is truthy.
133
134
Converts string representations of boolean values to boolean,
135
handling common string formats used in environment variables
136
and configuration.
137
138
Parameters:
139
- o (Any): Object to check for truthiness
140
141
Returns:
142
Optional[bool]: Boolean value or None if indeterminate
143
144
Examples:
145
- truthy("y") -> True
146
- truthy("yes") -> True
147
- truthy("true") -> True
148
- truthy("1") -> True
149
- truthy("n") -> False
150
- truthy("no") -> False
151
- truthy("false") -> False
152
- truthy("0") -> False
153
- truthy("maybe") -> None
154
- truthy(None) -> None
155
- truthy(42) -> True
156
- truthy(0) -> False
157
"""
158
159
def method_is_from_subclass_of(cls: Type[object], base_cls: Type[object], method_name: str) -> bool:
160
"""
161
Check if a class's method comes from a subclass of some base class.
162
163
Used to determine whether a patched RichCommand's help text methods
164
are compatible with rich-click or might cause issues.
165
166
Parameters:
167
- cls (Type[object]): Class to check
168
- base_cls (Type[object]): Base class to check against
169
- method_name (str): Name of method to check
170
171
Returns:
172
bool: True if method comes from subclass of base_cls
173
"""
174
```
175
176
Usage examples:
177
178
```python
179
import rich_click as click
180
181
# Using truthy for environment variable parsing
182
import os
183
184
debug_mode = click.truthy(os.getenv('DEBUG', 'false'))
185
verbose = click.truthy(os.getenv('VERBOSE'))
186
187
@click.command()
188
def my_command():
189
"""Command that uses environment variables."""
190
if debug_mode:
191
click.echo("Debug mode enabled")
192
if verbose:
193
click.echo("Verbose output enabled")
194
195
# Using method_is_from_subclass_of for compatibility checking
196
from rich_click.utils import method_is_from_subclass_of
197
198
class MyCommand(click.RichCommand):
199
def format_help(self, ctx, formatter):
200
# Custom help formatting
201
return super().format_help(ctx, formatter)
202
203
# Check if format_help method is compatible
204
is_compatible = method_is_from_subclass_of(
205
MyCommand,
206
click.RichCommand,
207
'format_help'
208
)
209
```
210
211
### Type Definitions
212
213
TypedDict definitions for configuration structures used in Rich-Click.
214
215
```python { .api }
216
class CommandGroupDict(TypedDict):
217
"""
218
Specification for command groups.
219
220
Used to define groups of commands for organized help display.
221
222
Attributes:
223
- name (str, optional): Display name for the group
224
- commands (List[str]): List of command names in the group
225
- table_styles (Dict[str, Any], optional): Styling for the group table
226
- panel_styles (Dict[str, Any], optional): Styling for the group panel
227
- deduplicate (bool, optional): Whether to deduplicate commands
228
"""
229
230
class OptionGroupDict(TypedDict):
231
"""
232
Specification for option groups.
233
234
Used to define groups of options for organized help display.
235
236
Attributes:
237
- name (str, optional): Display name for the group
238
- options (List[str], optional): List of option names in the group
239
- table_styles (Dict[str, Any], optional): Styling for the group table
240
- panel_styles (Dict[str, Any], optional): Styling for the group panel
241
- deduplicate (bool, optional): Whether to deduplicate options
242
"""
243
```
244
245
Usage examples for type definitions:
246
247
```python
248
import rich_click as click
249
250
# Define command groups
251
command_groups = [
252
click.CommandGroupDict(
253
name="Database Commands",
254
commands=["init-db", "migrate", "seed"],
255
panel_styles={"border_style": "blue"}
256
),
257
click.CommandGroupDict(
258
name="Server Commands",
259
commands=["run", "debug", "test"],
260
panel_styles={"border_style": "green"}
261
)
262
]
263
264
# Define option groups
265
option_groups = [
266
click.OptionGroupDict(
267
name="Configuration",
268
options=["--config", "--env"],
269
table_styles={"show_lines": True}
270
),
271
click.OptionGroupDict(
272
name="Output Control",
273
options=["--verbose", "--quiet", "--format"],
274
panel_styles={"title_justify": "center"}
275
)
276
]
277
278
# Apply to configuration
279
config = click.RichHelpConfiguration(
280
command_groups={"mycli": command_groups},
281
option_groups={"mycli": option_groups}
282
)
283
284
@click.group()
285
@click.rich_config(config)
286
def mycli():
287
"""My CLI application with grouped commands and options."""
288
pass
289
```
290
291
### Legacy CLI Patching
292
293
Deprecated patch function maintained for backward compatibility.
294
295
```python { .api }
296
def patch(*args, **kwargs):
297
"""
298
Deprecated patch function from rich_click.cli.
299
300
This function has moved to rich_click.patch.patch().
301
Using this import location is deprecated.
302
303
Parameters:
304
- *args: Arguments passed to rich_click.patch.patch()
305
- **kwargs: Keyword arguments passed to rich_click.patch.patch()
306
307
Raises:
308
DeprecationWarning: When used, indicating the new import location
309
"""
310
```
311
312
### Integration Examples
313
314
Examples of integrating Rich-Click utilities with existing applications:
315
316
```python
317
import click
318
import rich_click
319
from rich_click.utils import truthy
320
321
# Configuration from environment
322
def load_config_from_env():
323
"""Load configuration from environment variables."""
324
return {
325
'show_arguments': truthy(os.getenv('RICH_SHOW_ARGS', 'false')),
326
'use_markdown': truthy(os.getenv('RICH_USE_MARKDOWN', 'false')),
327
'style_option': os.getenv('RICH_OPTION_STYLE', 'bold cyan')
328
}
329
330
# Conditional patching
331
def maybe_patch_click():
332
"""Conditionally patch Click based on environment."""
333
if truthy(os.getenv('USE_RICH_CLICK', 'true')):
334
config = rich_click.RichHelpConfiguration(**load_config_from_env())
335
rich_click.patch(rich_config=config)
336
337
# Use in existing Click application
338
maybe_patch_click()
339
340
@click.command()
341
@click.option('--debug', is_flag=True, help='Enable debug mode')
342
def my_app(debug):
343
"""My existing Click application."""
344
if debug:
345
click.echo("Debug mode enabled")
346
```