Repository: psf/black

Issue:
Black --check returns 1 when invalid config file is specified
**Describe the bug**

`--check` returns `1` when invalid `--config` is specified, not some higher error code as implied. This can make debugging issues tricky for CI integrations relying on return codes. I wouldn't go so far as to call it a bug, but it was a bit unexpected to me.

(It also happens without `--check`.)

**To Reproduce**

```console
$ printf "def a():\n    pass\n" | black - --check; echo "return: $?"
def a():
    pass
All done! ✨ 🍰 ✨
1 file left unchanged.
return: 0
$ printf "def a():\n    pass\n" | black - --check --config "foo"; echo "return: $?"
Error: Could not open file foo: Error reading configuration file: [Errno 2] No such file or directory: 'foo'
return: 1
```

**Expected behavior**

`--check` says:

> Don't write the files back, just return the status.  Return code 0 means nothing would change.  Return code 1 means some files would be reformatted.  Return code 123 means there was an internal error.

So I would expect this case to return an error code other than `1`.

**Environment (please complete the following information):**

- Version: `19.10b0`, `master` (both tested)
- OS and Python version: macOS 10.15.3 with Python 3.7.7; and Ubuntu 18.04.4 with Python 3.6.9

**Does this bug also happen on master?**

Yes (tested via cloning and `pipenv shell`)

**Additional context**

This can be very awkward to debug in a CI environment if you rely on return codes only.


Discussion:
tobywf: Please let me know if there's anything you need from me to get this merged (did I forget a label or an assignee?). Would be nice to get it in before the refactor happens :)

Patch:
diff --git a/black.py b/black.py
index d9348a3..26a2915 100644
--- a/black.py
+++ b/black.py
@@ -394,7 +394,7 @@ def target_version_option_callback(
 @click.option(
     "--config",
     type=click.Path(
-        exists=False, file_okay=True, dir_okay=False, readable=True, allow_dash=False
+        exists=True, file_okay=True, dir_okay=False, readable=True, allow_dash=False
     ),
     is_eager=True,
     callback=read_pyproject_toml,


Test patch:
diff --git a/tests/test_black.py b/tests/test_black.py
index acbaade..7a4a3bb 100644
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -1645,6 +1645,16 @@ def test_blackd_main(self) -> None:
                 raise result.exception
             self.assertEqual(result.exit_code, 0)
 
+    def test_invalid_config_return_code(self) -> None:
+        tmp_file = Path(black.dump_to_file())
+        try:
+            tmp_config = Path(black.dump_to_file())
+            tmp_config.unlink()
+            args = ["--config", str(tmp_config), str(tmp_file)]
+            self.invokeBlack(args, exit_code=2, ignore_config=False)
+        finally:
+            tmp_file.unlink()
+
 
 class BlackDTestCase(AioHTTPTestCase):
     async def get_application(self) -> web.Application: