diff --git a/CHANGES.md b/CHANGES.md index 4fd030d..a3ffba6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,7 +16,12 @@ ### Configuration - +- _Black_ now ignores `pyproject.toml` that is missing a `tool.black` section when + discovering project root and configuration. Since _Black_ continues to use version + control as an indicator of project root, this is expected to primarily change behavior + for users in a monorepo setup (desirably). If you wish to preserve previous behavior, + simply add an empty `[tool.black]` to the previously discovered `pyproject.toml` + (#4204) ### Packaging diff --git a/docs/usage_and_configuration/the_basics.md b/docs/usage_and_configuration/the_basics.md index dc9d9a6..61c5245 100644 --- a/docs/usage_and_configuration/the_basics.md +++ b/docs/usage_and_configuration/the_basics.md @@ -456,10 +456,11 @@ of tools like [Poetry](https://python-poetry.org/), ### Where _Black_ looks for the file -By default _Black_ looks for `pyproject.toml` starting from the common base directory of -all files and directories passed on the command line. If it's not there, it looks in -parent directories. It stops looking when it finds the file, or a `.git` directory, or a -`.hg` directory, or the root of the file system, whichever comes first. +By default _Black_ looks for `pyproject.toml` containing a `[tool.black]` section +starting from the common base directory of all files and directories passed on the +command line. If it's not there, it looks in parent directories. It stops looking when +it finds the file, or a `.git` directory, or a `.hg` directory, or the root of the file +system, whichever comes first. If you're formatting standard input, _Black_ will look for configuration starting from the current working directory. diff --git a/src/black/files.py b/src/black/files.py index 1eb8745..960f13e 100644 --- a/src/black/files.py +++ b/src/black/files.py @@ -42,6 +42,12 @@ import colorama # noqa: F401 +@lru_cache +def _load_toml(path: Union[Path, str]) -> Dict[str, Any]: + with open(path, "rb") as f: + return tomllib.load(f) + + @lru_cache def find_project_root( srcs: Sequence[str], stdin_filename: Optional[str] = None @@ -84,7 +90,9 @@ def find_project_root( return directory, ".hg directory" if (directory / "pyproject.toml").is_file(): - return directory, "pyproject.toml" + pyproject_toml = _load_toml(directory / "pyproject.toml") + if "black" in pyproject_toml.get("tool", {}): + return directory, "pyproject.toml" return directory, "file system root" @@ -117,8 +125,7 @@ def parse_pyproject_toml(path_config: str) -> Dict[str, Any]: If parsing fails, will raise a tomllib.TOMLDecodeError. """ - with open(path_config, "rb") as f: - pyproject_toml = tomllib.load(f) + pyproject_toml = _load_toml(path_config) config: Dict[str, Any] = pyproject_toml.get("tool", {}).get("black", {}) config = {k.replace("--", "").replace("-", "_"): v for k, v in config.items()} diff --git a/tests/test_black.py b/tests/test_black.py index 123ea0b..f876d36 100644 --- a/tests/test_black.py +++ b/tests/test_black.py @@ -1668,9 +1668,9 @@ def test_find_project_root(self) -> None: src_dir.mkdir() root_pyproject = root / "pyproject.toml" - root_pyproject.touch() + root_pyproject.write_text("[tool.black]", encoding="utf-8") src_pyproject = src_dir / "pyproject.toml" - src_pyproject.touch() + src_pyproject.write_text("[tool.black]", encoding="utf-8") src_python = src_dir / "foo.py" src_python.touch() @@ -1693,6 +1693,20 @@ def test_find_project_root(self) -> None: (src_dir.resolve(), "pyproject.toml"), ) + src_sub = src_dir / "sub" + src_sub.mkdir() + + src_sub_pyproject = src_sub / "pyproject.toml" + src_sub_pyproject.touch() # empty + + src_sub_python = src_sub / "bar.py" + + # we skip src_sub_pyproject since it is missing the [tool.black] section + self.assertEqual( + black.find_project_root((src_sub_python,)), + (src_dir.resolve(), "pyproject.toml"), + ) + @patch( "black.files.find_user_pyproject_toml", )