Repository: pallets/click

Issue:
version_option doesn't automatically detect version anymore with click 8.0.0
Hello, I just came across what seems to be a regression with click 8.0.0

# Bug

For a given click command `click-issue-test` installed with setuptools configured with the `click.version_option()` decorator, running `click-issue-test --version` fails with the following error:

```
Traceback (most recent call last):
  File "/Users/florian.veaux/go/src/github.com/DataDog/integrations-core/click-issue-test/click-issue-test/lib/python3.9/site-packages/click/decorators.py", line 384, in callback
    version = metadata.version(package_name)  # type: ignore
  File "/Users/florian.veaux/.pyenv/versions/3.9.0/Python.framework/Versions/3.9/lib/python3.9/importlib/metadata.py", line 551, in version
    return distribution(distribution_name).version
  File "/Users/florian.veaux/.pyenv/versions/3.9.0/Python.framework/Versions/3.9/lib/python3.9/importlib/metadata.py", line 524, in distribution
    return Distribution.from_name(distribution_name)
  File "/Users/florian.veaux/.pyenv/versions/3.9.0/Python.framework/Versions/3.9/lib/python3.9/importlib/metadata.py", line 187, in from_name
    raise PackageNotFoundError(name)
importlib.metadata.PackageNotFoundError: cli

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/florian.veaux/go/src/github.com/DataDog/integrations-core/click-issue-test/click-issue-test/bin/click-issue-test", line 33, in <module>
    sys.exit(load_entry_point('click-issue-test', 'console_scripts', 'click-issue-test')())
  File "/Users/florian.veaux/go/src/github.com/DataDog/integrations-core/click-issue-test/click-issue-test/lib/python3.9/site-packages/click/core.py", line 1134, in __call__
    return self.main(*args, **kwargs)
  File "/Users/florian.veaux/go/src/github.com/DataDog/integrations-core/click-issue-test/click-issue-test/lib/python3.9/site-packages/click/core.py", line 1058, in main
    with self.make_context(prog_name, args, **extra) as ctx:
  File "/Users/florian.veaux/go/src/github.com/DataDog/integrations-core/click-issue-test/click-issue-test/lib/python3.9/site-packages/click/core.py", line 927, in make_context
    self.parse_args(ctx, args)
  File "/Users/florian.veaux/go/src/github.com/DataDog/integrations-core/click-issue-test/click-issue-test/lib/python3.9/site-packages/click/core.py", line 1376, in parse_args
    value, args = param.handle_parse_result(ctx, opts, args)
  File "/Users/florian.veaux/go/src/github.com/DataDog/integrations-core/click-issue-test/click-issue-test/lib/python3.9/site-packages/click/core.py", line 2352, in handle_parse_result
    value = self.process_value(ctx, value)
  File "/Users/florian.veaux/go/src/github.com/DataDog/integrations-core/click-issue-test/click-issue-test/lib/python3.9/site-packages/click/core.py", line 2314, in process_value
    value = self.callback(ctx, self, value)
  File "/Users/florian.veaux/go/src/github.com/DataDog/integrations-core/click-issue-test/click-issue-test/lib/python3.9/site-packages/click/decorators.py", line 386, in callback
    raise RuntimeError(
RuntimeError: 'cli' is not installed. Try passing 'package_name' instead.
```

# Replication steps

*cli.py*:
```
import click

@click.command()
@click.version_option()
def cli():
    print("Hello")

if __name__ == '__main__':
    cli()
```

*setup.py*
```
from setuptools import setup

setup(
    name='click-issue-test',
    version='1.2.3',
    py_modules=['cli'],
    install_requires=[
        'Click',
    ],
    entry_points='''
        [console_scripts]
        click-issue-test=cli:cli
    ''',
)
```

Then run:
```
$ pip install -e .
$ click-issue-test --version
```

The last command was working with click 7.1.2 and was printing `click-issue-test, version 1.2.3`. 

Environment:

- Python version: 3.9
- Click version: 8.0.0



Discussion:
I think it is related, mypy gives me the errors after 8.0.0 update:

```
error: Module has no attribute "version_option"  [attr-defined]
    @click.version_option()
error: Untyped decorator makes function "main" untyped  [misc]
    @click.version_option()
```

Hey, FYI: I reported a similar issue here (on python 3.8): https://github.com/jazzband/pip-tools/issues/1398
This was intentional, but I forgot to add a detailed entry about it to the changelog. See https://github.com/pallets/click/pull/1582#issuecomment-649085376:

> It looks like the values returned by `importlib.metadata.entry_points()` aren't linked to the distributions that own them, so there's not really a nice way to use the previous implementation.

We switched from the (slow, not guaranteed to exist) `pkg_resources` to the built-in `importlib.metadata`. However, while it allows introspecting the entry points by name, they don't have a reference to the distribution that created them, so there's no way to get the version from that.

The `version_option` docs describe the new behavior:

> If `package_name` is not provided, Click will try to detect it by inspecting the stack frames. This will be used to detect the version, so it must match the name of the installed package.

If your entry point name matches your package/module name, everything is detected correctly. This is generally a good idea, but it does fail in some cases, such as when `piptools` is the Python package name, but `pip-tools` is the installed package/distribution name. To fix that, you need to pass `version_option(package_name='pip-tools')`, or `package_name='click-issue-test'` in this issue's example. (Or rename the test file to `click_issue_test.py`.)

If someone figures out a way to get the distribution version from the entry point name with `importlib.metadata`, I'd welcome a PR to improve our detection, but from my experiments with it I was not able to find how to do it. For now, I'll update the changelog.

Resolving patch:
diff --git a/src/click/decorators.py b/src/click/decorators.py
--- a/src/click/decorators.py
+++ b/src/click/decorators.py
@@ -330,7 +330,10 @@ def version_option(
         value for messages.
 
     .. versionchanged:: 8.0
-        Use :mod:`importlib.metadata` instead of ``pkg_resources``.
+        Use :mod:`importlib.metadata` instead of ``pkg_resources``. The
+        version is detected based on the package name, not the entry
+        point name. The Python package name must match the installed
+        package name, or be passed with ``package_name=``.
     """
     if message is None:
         message = _("%(prog)s, version %(version)s")


Test patch: