Skip to content

Commit 2623269

Browse files
authored
Ignore pyproject.toml missing tool.black section (#4204)
Fixes #2863 This is pretty desirable in a monorepo situation where you have configuration in the root since it will mean you don't have to reconfigure every project. The good news for backward compatibility is that `find_project_root` continues to stop at any git or hg root, so in all cases repo root coincides with a pyproject.toml missing tool.black, we'll continue to have the project root as before and end up using default config (i.e. we're unlikely to randomly start using the user config). The other thing we need to be a little careful about is that changing find_project_root logic affects what `exclude` is relative to. Since we only change in cases where there is no config, this only applies where users were using `exclude` via command line arg (and had pyproject.toml missing tool.black in a dir that was not repo root). Finally, for the few who could be affected, the fix is to put an empty `[tool.black]` in pyproject.toml
1 parent 24c9c01 commit 2623269

File tree

4 files changed

+37
-10
lines changed

4 files changed

+37
-10
lines changed

Diff for: CHANGES.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@
1616

1717
### Configuration
1818

19-
<!-- Changes to how Black can be configured -->
19+
- _Black_ now ignores `pyproject.toml` that is missing a `tool.black` section when
20+
discovering project root and configuration. Since _Black_ continues to use version
21+
control as an indicator of project root, this is expected to primarily change behavior
22+
for users in a monorepo setup (desirably). If you wish to preserve previous behavior,
23+
simply add an empty `[tool.black]` to the previously discovered `pyproject.toml`
24+
(#4204)
2025

2126
### Packaging
2227

Diff for: docs/usage_and_configuration/the_basics.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -456,10 +456,11 @@ of tools like [Poetry](https://python-poetry.org/),
456456

457457
### Where _Black_ looks for the file
458458

459-
By default _Black_ looks for `pyproject.toml` starting from the common base directory of
460-
all files and directories passed on the command line. If it's not there, it looks in
461-
parent directories. It stops looking when it finds the file, or a `.git` directory, or a
462-
`.hg` directory, or the root of the file system, whichever comes first.
459+
By default _Black_ looks for `pyproject.toml` containing a `[tool.black]` section
460+
starting from the common base directory of all files and directories passed on the
461+
command line. If it's not there, it looks in parent directories. It stops looking when
462+
it finds the file, or a `.git` directory, or a `.hg` directory, or the root of the file
463+
system, whichever comes first.
463464

464465
If you're formatting standard input, _Black_ will look for configuration starting from
465466
the current working directory.

Diff for: src/black/files.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@
4242
import colorama # noqa: F401
4343

4444

45+
@lru_cache
46+
def _load_toml(path: Union[Path, str]) -> Dict[str, Any]:
47+
with open(path, "rb") as f:
48+
return tomllib.load(f)
49+
50+
4551
@lru_cache
4652
def find_project_root(
4753
srcs: Sequence[str], stdin_filename: Optional[str] = None
@@ -84,7 +90,9 @@ def find_project_root(
8490
return directory, ".hg directory"
8591

8692
if (directory / "pyproject.toml").is_file():
87-
return directory, "pyproject.toml"
93+
pyproject_toml = _load_toml(directory / "pyproject.toml")
94+
if "black" in pyproject_toml.get("tool", {}):
95+
return directory, "pyproject.toml"
8896

8997
return directory, "file system root"
9098

@@ -117,8 +125,7 @@ def parse_pyproject_toml(path_config: str) -> Dict[str, Any]:
117125
118126
If parsing fails, will raise a tomllib.TOMLDecodeError.
119127
"""
120-
with open(path_config, "rb") as f:
121-
pyproject_toml = tomllib.load(f)
128+
pyproject_toml = _load_toml(path_config)
122129
config: Dict[str, Any] = pyproject_toml.get("tool", {}).get("black", {})
123130
config = {k.replace("--", "").replace("-", "_"): v for k, v in config.items()}
124131

Diff for: tests/test_black.py

+16-2
Original file line numberDiff line numberDiff line change
@@ -1668,9 +1668,9 @@ def test_find_project_root(self) -> None:
16681668
src_dir.mkdir()
16691669

16701670
root_pyproject = root / "pyproject.toml"
1671-
root_pyproject.touch()
1671+
root_pyproject.write_text("[tool.black]", encoding="utf-8")
16721672
src_pyproject = src_dir / "pyproject.toml"
1673-
src_pyproject.touch()
1673+
src_pyproject.write_text("[tool.black]", encoding="utf-8")
16741674
src_python = src_dir / "foo.py"
16751675
src_python.touch()
16761676

@@ -1693,6 +1693,20 @@ def test_find_project_root(self) -> None:
16931693
(src_dir.resolve(), "pyproject.toml"),
16941694
)
16951695

1696+
src_sub = src_dir / "sub"
1697+
src_sub.mkdir()
1698+
1699+
src_sub_pyproject = src_sub / "pyproject.toml"
1700+
src_sub_pyproject.touch() # empty
1701+
1702+
src_sub_python = src_sub / "bar.py"
1703+
1704+
# we skip src_sub_pyproject since it is missing the [tool.black] section
1705+
self.assertEqual(
1706+
black.find_project_root((src_sub_python,)),
1707+
(src_dir.resolve(), "pyproject.toml"),
1708+
)
1709+
16961710
@patch(
16971711
"black.files.find_user_pyproject_toml",
16981712
)

0 commit comments

Comments
 (0)