From 2dfa69bb7fc1d310902ae565271d595d307f166b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Tue, 19 Jun 2018 22:40:26 -0700 Subject: [PATCH] Stop Click from crashing Black on invalid environments Fixes #277 --- README.md | 4 ++++ black.py | 23 +++++++++++++++++++++++ tests/test_black.py | 22 ++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/README.md b/README.md index 39510390acf..c93c3003ff0 100644 --- a/README.md +++ b/README.md @@ -833,6 +833,10 @@ More details can be found in [CONTRIBUTING](CONTRIBUTING.md). * they now work when an indentation block starts with empty lines or misaligned comments (#334) +* made Click not fail on invalid environments; note that Click is right but the + likelihood we'll need to access non-ASCII file paths when dealing with Python source + code is low (#277) + * fixed improper formatting of f-strings with quotes inside interpolated expressions (#322) diff --git a/black.py b/black.py index 7e39c92009d..b9eca0adbaf 100644 --- a/black.py +++ b/black.py @@ -3482,5 +3482,28 @@ def write_cache( pass +def patch_click() -> None: + """Make Click not crash. + + 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 + application. Click refuses to work in this scenario by raising a RuntimeError. + + In case of Black the likelihood that non-ASCII characters are going to be used in + file paths is minimal since it's Python source code. Moreover, this crash was + spurious on Python 3.7 thanks to PEP 538 and PEP 540. + """ + try: + from click import core + from click import _unicodefun # type: ignore + except ModuleNotFoundError: + return + + for module in (core, _unicodefun): + if hasattr(module, "_verify_python3_env"): + module._verify_python3_env = lambda: None + + if __name__ == "__main__": + patch_click() main() diff --git a/tests/test_black.py b/tests/test_black.py index 6638dc4f119..191f4b8cd40 100644 --- a/tests/test_black.py +++ b/tests/test_black.py @@ -1213,6 +1213,28 @@ def test_symlink_out_of_root_directory(self) -> None: child.is_symlink.assert_called() self.assertEqual(child.is_symlink.call_count, 2) + def test_shhh_click(self) -> None: + try: + from click import _unicodefun # type: ignore + except ModuleNotFoundError: + self.skipTest("Incompatible Click version") + if not hasattr(_unicodefun, "_verify_python3_env"): + self.skipTest("Incompatible Click version") + # First, let's see if Click is crashing with a preferred ASCII charset. + with patch("locale.getpreferredencoding") as gpe: + gpe.return_value = "ASCII" + with self.assertRaises(RuntimeError): + _unicodefun._verify_python3_env() + # Now, let's silence Click... + black.patch_click() + # ...and confirm it's silent. + with patch("locale.getpreferredencoding") as gpe: + gpe.return_value = "ASCII" + try: + _unicodefun._verify_python3_env() + except RuntimeError as re: + self.fail(f"`patch_click()` failed, exception still raised: {re}") + if __name__ == "__main__": unittest.main(module="test_black")