Skip to content

Commit 941ea3d

Browse files
committed
Do not use default group name. An empty name will be empty
1 parent bd48a0e commit 941ea3d

File tree

2 files changed

+35
-38
lines changed

2 files changed

+35
-38
lines changed

click_option_group/_core.py

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -129,18 +129,6 @@ def forbidden_option_attrs(self) -> List[str]:
129129
"""
130130
return []
131131

132-
def get_default_name(self, ctx: click.Context) -> str:
133-
"""Returns default name for the group
134-
135-
:param ctx: Click Context object
136-
:return: group default name
137-
"""
138-
if self.name:
139-
return self.name
140-
141-
option_names = '|'.join(self.get_option_names(ctx))
142-
return f'({option_names})'
143-
144132
def get_help_record(self, ctx: click.Context) -> Optional[Tuple[str, str]]:
145133
"""Returns the help record for the group
146134
@@ -150,14 +138,20 @@ def get_help_record(self, ctx: click.Context) -> Optional[Tuple[str, str]]:
150138
if all(o.hidden for o in self.get_options(ctx).values()):
151139
return None
152140

153-
name = self.get_default_name(ctx)
141+
name = self.name
154142
help_ = self.help if self.help else ''
155143

156144
extra = ', '.join(self.name_extra)
157145
if extra:
158146
extra = f'[{extra}]'
159147

160-
name = f'{name}: {extra}'
148+
if name:
149+
name = f'{name}: {extra}'
150+
elif extra:
151+
name = f'{extra}:'
152+
153+
if not name and not help_:
154+
return None
161155

162156
return name, help_
163157

@@ -251,6 +245,9 @@ def _option_memo(self, func):
251245
option = params[-1]
252246
self._options[func][option.name] = option
253247

248+
def _group_name_str(self) -> str:
249+
return f"'{self.name}'" if self.name else "the"
250+
254251

255252
class RequiredAnyOptionGroup(OptionGroup):
256253
"""Option group with required any options of this group
@@ -272,20 +269,20 @@ def handle_parse_result(self, option: GroupedOption, ctx: click.Context, opts: d
272269

273270
if all(o.hidden for o in self.get_options(ctx).values()):
274271
cls_name = self.__class__.__name__
275-
group_name = self.get_default_name(ctx)
272+
group_name = self._group_name_str()
276273

277274
raise TypeError(
278-
f"Need at least one non-hidden option in group '{group_name}' ('{cls_name}')."
275+
f"Need at least one non-hidden option in {group_name} option group ({cls_name})."
279276
)
280277

281278
option_names = set(self.get_options(ctx))
282279

283280
if not option_names.intersection(opts):
284-
group_name = self.get_default_name(ctx)
281+
group_name = self._group_name_str()
285282
option_info = self.get_error_hint(ctx)
286283

287284
raise click.UsageError(
288-
f"At least one of the following options from '{group_name}' group is required:\n{option_info}",
285+
f"At least one of the following options from {group_name} option group is required:\n{option_info}",
289286
ctx=ctx
290287
)
291288

@@ -308,12 +305,12 @@ def handle_parse_result(self, option: GroupedOption, ctx: click.Context, opts: d
308305
option_names = set(self.get_options(ctx))
309306

310307
if not option_names.issubset(opts):
311-
group_name = self.get_default_name(ctx)
308+
group_name = self._group_name_str()
312309
required_names = option_names.difference(option_names.intersection(opts))
313310
option_info = self.get_error_hint(ctx, required_names)
314311

315312
raise click.UsageError(
316-
f"Missing required options from '{group_name}' group:\n{option_info}",
313+
f"Missing required options from {group_name} option group:\n{option_info}",
317314
ctx=ctx
318315
)
319316

@@ -339,11 +336,11 @@ def handle_parse_result(self, option: GroupedOption, ctx: click.Context, opts: d
339336
given_option_count = len(given_option_names)
340337

341338
if given_option_count > 1:
342-
group_name = self.get_default_name(ctx)
339+
group_name = self._group_name_str()
343340
option_info = self.get_error_hint(ctx, given_option_names)
344341

345342
raise click.UsageError(
346-
f"Mutually exclusive options from '{group_name}' group "
343+
f"Mutually exclusive options from {group_name} option group "
347344
f"cannot be used at the same time:\n{option_info}",
348345
ctx=ctx
349346
)
@@ -367,12 +364,12 @@ def handle_parse_result(self, option: GroupedOption, ctx: click.Context, opts: d
367364
given_option_names = option_names.intersection(opts)
368365

369366
if len(given_option_names) == 0:
370-
group_name = self.get_default_name(ctx)
367+
group_name = self._group_name_str()
371368
option_info = self.get_error_hint(ctx)
372369

373370
raise click.UsageError(
374371
"Missing one of the required mutually exclusive options from "
375-
f"'{group_name}' option group:\n{option_info}",
372+
f"{group_name} option group:\n{option_info}",
376373
ctx=ctx
377374
)
378375

@@ -396,11 +393,11 @@ def handle_parse_result(self, option: GroupedOption, ctx: click.Context, opts: d
396393
option_names = set(self.get_options(ctx))
397394

398395
if not option_names.isdisjoint(opts) and option_names.intersection(opts) != option_names:
399-
group_name = self.get_default_name(ctx)
396+
group_name = self._group_name_str()
400397
option_info = self.get_error_hint(ctx)
401398

402399
raise click.UsageError(
403-
"All options should be specified or none should be specified from the group "
404-
f"'{group_name}'. Missing required options:\n{option_info}",
400+
f"All options from {group_name} option group should be specified or none should be specified. "
401+
f"Missing required options:\n{option_info}",
405402
ctx=ctx
406403
)

tests/test_click_option_group.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,25 +47,24 @@ def cli(hello, foo1, bar1, lol, foo2, bar2, goodbye):
4747
assert 'foo1,bar1,foo2,bar2' in result.output
4848

4949

50-
def test_default_group_name(runner):
50+
def test_noname_group(runner):
5151
@click.command()
5252
@optgroup()
5353
@optgroup.option('--foo')
54-
def cli(foo, bar):
54+
def cli(foo):
5555
pass
5656

5757
result = runner.invoke(cli, ['--help'])
58-
assert '(foo):' in result.output
58+
assert 'Options:\n --foo' in result.output
5959

6060
@click.command()
61-
@optgroup()
61+
@optgroup(help='Group description')
6262
@optgroup.option('--foo')
63-
@optgroup.option('--bar')
64-
def cli(foo, bar):
63+
def cli(foo):
6564
pass
6665

6766
result = runner.invoke(cli, ['--help'])
68-
assert '(foo|bar):' in result.output
67+
assert 'Group description' in result.output
6968

7069

7170
def test_mix_decl_first_api():
@@ -303,7 +302,8 @@ def cli(foo, bar):
303302
result = runner.invoke(cli, ['--foo', 'foo'])
304303
assert result.exception
305304
assert result.exit_code == 2
306-
assert 'All options should be specified or none should be specified' in result.output
305+
assert 'All options from' in result.output
306+
assert 'should be specified or none should be specified' in result.output
307307
assert '--foo' in result.output
308308
assert '--bar' in result.output
309309

@@ -565,7 +565,7 @@ def command(foo2, bar2):
565565

566566

567567
def test_group_context_second_api(runner):
568-
group = OptionGroup()
568+
group = OptionGroup('My Group')
569569

570570
@click.command()
571571
@group.option('--foo1')
@@ -581,13 +581,13 @@ def cli2(foo2, bar2):
581581

582582
result = runner.invoke(cli1, ['--help'])
583583
assert not result.exception
584-
assert '(foo1|bar1):' in result.output
584+
assert 'My Group:' in result.output
585585
assert '--foo1' in result.output
586586
assert '--bar1' in result.output
587587

588588
result = runner.invoke(cli2, ['--help'])
589589
assert not result.exception
590-
assert '(foo2|bar2):' in result.output
590+
assert 'My Group:' in result.output
591591
assert '--foo2' in result.output
592592
assert '--bar2' in result.output
593593

0 commit comments

Comments
 (0)