Repository: psf/black

Issue:
Misdetection of project root when `--stdin-filename` targets a filepath outside the current working directory
**To Reproduce**

```console
~/programming/oss/black on HEAD (b776bf9) [$?] via Python v3.8.5 (venv) 
❯ echo "print('Hello, world!')" > ../outside.py

~/programming/oss/black on HEAD (b776bf9) [$?] via Python v3.8.5 (venv) 
❯ cat ../outside.py | black --stdin-filename "../outside.py" -

No Python files are present to be formatted. Nothing to do 😴

~/programming/oss/black on HEAD (b776bf9) [$?] via Python v3.8.5 (venv) took 711ms 
❯ black ../outside.py 
reformatted ../outside.py

All done! ✨ 🍰 ✨
1 file reformatted.
```

**Expected behavior**

That `cat ../outside.py | black --stdin-filename "../outside.py" -` would also reformat `../outside.py`.

**Environment**


- Black's version: <!-- e.g. [main] --> b776bf92adb7f47cd92f550e33c2db445d226f78
- OS and Python version: <!-- e.g. [Linux/Python 3.7.4rc1] --> CPython 3.8.5 on Ubuntu 20.04.04 LTS

**Additional context**

I said I would look into this issue in https://github.com/microsoft/vscode-black-formatter/issues/52 where it was originally discovered but I never did. I'd appreciate it if someone else could look into this for me :)


Discussion:

Resolving patch:
diff --git a/src/black/__init__.py b/src/black/__init__.py
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -469,7 +469,9 @@ def main(  # noqa: C901
         out(main.get_usage(ctx) + "\n\nOne of 'SRC' or 'code' is required.")
         ctx.exit(1)
 
-    root, method = find_project_root(src) if code is None else (None, None)
+    root, method = (
+        find_project_root(src, stdin_filename) if code is None else (None, None)
+    )
     ctx.obj["root"] = root
 
     if verbose:
@@ -480,7 +482,9 @@ def main(  # noqa: C901
             )
 
             normalized = [
-                (normalize_path_maybe_ignore(Path(source), root), source)
+                (source, source)
+                if source == "-"
+                else (normalize_path_maybe_ignore(Path(source), root), source)
                 for source in src
             ]
             srcs_string = ", ".join(
diff --git a/src/black/files.py b/src/black/files.py
--- a/src/black/files.py
+++ b/src/black/files.py
@@ -39,7 +39,9 @@
 
 
 @lru_cache()
-def find_project_root(srcs: Sequence[str]) -> Tuple[Path, str]:
+def find_project_root(
+    srcs: Sequence[str], stdin_filename: Optional[str] = None
+) -> Tuple[Path, str]:
     """Return a directory containing .git, .hg, or pyproject.toml.
 
     That directory will be a common parent of all files and directories
@@ -52,6 +54,8 @@ def find_project_root(srcs: Sequence[str]) -> Tuple[Path, str]:
     the second element as a string describing the method by which the
     project root was discovered.
     """
+    if stdin_filename is not None:
+        srcs = tuple(stdin_filename if s == "-" else s for s in srcs)
     if not srcs:
         srcs = [str(Path.cwd().resolve())]
 


Test patch:
diff --git a/tests/test_black.py b/tests/test_black.py
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -1396,6 +1396,12 @@ def test_find_project_root(self) -> None:
                 (src_dir.resolve(), "pyproject.toml"),
             )
 
+            with change_directory(test_dir):
+                self.assertEqual(
+                    black.find_project_root(("-",), stdin_filename="../src/a.py"),
+                    (src_dir.resolve(), "pyproject.toml"),
+                )
+
     @patch(
         "black.files.find_user_pyproject_toml",
     )