Repository: psf/black

Issue:
Running from the command-line still has issues with Click
I've just run into the same problem with PyCharm and Click that was reported in issue #277:

```
RuntimeError: Click will abort further execution because Python 3 was configured to use ASCII as encoding for the environment.
```
I think there is still a problem and I believe the problem may be that the generated command line script _only_ calls the `main()` function from `black.py` (see the entry point on line 60 in `setup.py`: `black=black:main`). 

So, after running `pip install black`, the generated command-line script looks like this:

```
#!/usr/local/opt/python/bin/python3.6

# -*- coding: utf-8 -*-
import re
import sys

from black import main

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(main())
```

If you try to use this script to invoke black (e.g. as the command for an "external tool" in PyCharm), the `patch_click()` function won't be called and you'll get the original error reported in #277. 

To verify, I edited this script by hand, like so:

```
#!/usr/local/opt/python/bin/python3.6

# -*- coding: utf-8 -*-
import re
import sys

from black import main, patch_click

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    patch_click()
    sys.exit(main())
```
This appears to work, but is probably is not the best way to permanently fix the issue. 

One possible fix (although I don't claim that this is the best approach, especially since I'm not sure how it might interact with `blackd`), would be to create a new `main` that can be used as the entry point for the cli script. Maybe something like this at the end of `black.py`:

```
def patched_main():
    patch_click()
    main()

if __name__ == "__main__":
    patched_main()
````
along with this change in `setup.py`:
```
entry_points={"console_scripts": ["black=black:patched_main", "blackd=blackd:main [d]"]},
```
Anyway, as I said, I don't know if this is a good solution. I mostly wanted to post it as a means of clarifying what I think the problem is. 

Thank you for your time and for creating this awesome tool!



Discussion:
@wooters, your conclusion is absolutely right. We should be patching Click in entry_points, too. Please create a PR with your `patched_main()` function and I'll accept it. Don't forget to add yourself to `Authors` in the README.
Will do. Thanks.
This was fixed a good while back.
This issue seems to be back with the recent v8.0.0 release of the click library, [automatically pulled with the current constraint](https://github.com/psf/black/blob/21.5b1/Pipfile#L27). Here is a reproducer and possible fix with a constraint on `click` version
```bash
docker run -it --rm ubuntu:18.04 bash -c "set -x; apt update && apt install -y python3-pip && pip3 install --upgrade black && black --version; LANG=C.UTF-8 black --version; pip3 install --upgrade 'click<8.0.0' && black --version"
```
Ubuntu 18.04 repos ship `Python 3.6.9` if that matters.
Luckily this only affects Python 3.6 users so an increasingly marginal subset. We will fix our workaround to work with Click 8.0. In the meantime your workaround to pin to Click<8.0 works. You can also upgrade to Python 3.7+.

Resolving patch:
diff --git a/src/black/__init__.py b/src/black/__init__.py
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -1029,7 +1029,7 @@ def nullcontext() -> Iterator[None]:
 
 
 def patch_click() -> None:
-    """Make Click not crash.
+    """Make Click not crash on Python 3.6 with LANG=C.
 
     On certain misconfigured environments, Python 3 selects the ASCII encoding as the
     default which restricts paths that it can access during the lifetime of the
@@ -1047,7 +1047,9 @@ def patch_click() -> None:
 
     for module in (core, _unicodefun):
         if hasattr(module, "_verify_python3_env"):
-            module._verify_python3_env = lambda: None
+            module._verify_python3_env = lambda: None  # type: ignore
+        if hasattr(module, "_verify_python_env"):
+            module._verify_python_env = lambda: None  # type: ignore
 
 
 def patched_main() -> None:


Test patch: