pallets / pallets/click

Unexposed option name is `None` when the parameter name is not a python identifier

Open
#2,768 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

parsing
Dominant language
Python
Stars
17.7k
Forks
2.3k
Avg merge
1d 30m
Merged PRs (30d)
18

Description

I would like to have dots in option names. As click requires option names to be valid python identifiers, I would like to use unexposed options to make dots in option names possible, and a custom callback to store the option name somewhere:

import click


def option_callback(ctx, param, value):
    ctx.ensure_object(dict)
    ctx.obj.setdefault("params", {})[param.name] = value

    return value


@click.command()
@click.option("--foo.foo", expose_value=False, callback=option_callback)
@click.option("--bar-bar", expose_value=False, callback=option_callback)
@click.pass_obj
def cli(obj):
    click.echo(obj["params"])


if __name__ == "__main__":  # pragma: no cover
    cli()

In that situation, in the callback context, option.name is None if the original option name is not a valid identifier:

$ python example.py --foo.foo baz --bar-bar baz
{None: 'baz', 'bar_bar': 'baz'}

I suppose this is due to those lines:
https://github.com/pallets/click/blob/99015e1456b6952054fda8312b40ea646737168d/src/click/core.py#L2594-L2595

Ideally I would love a simple way to use non identifier option names, like proposed in https://github.com/pallets/click/discussions/2433.
In the meantime I would suggest to allow Option.name to have its original value instead of None for unexposed option. I would volunteer for a PR if this is accepted.

What do you think?

  • Python version: 3.12
  • Click version: 8.1.7

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/click/core.py around the linked lines 2594-2595 and trace how an unexposed option gets its name. Reproduce the example with dotted and hyphenated options, then add regression coverage showing the callback receives the intended original name and run the relevant Click tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.