Skip to content

Commit

Permalink
Ignore pyproject.toml missing tool.black section (#4204)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
hauntsaninja committed Feb 2, 2024
1 parent 24c9c01 commit 2623269
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 10 deletions.
7 changes: 6 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@

### Configuration

<!-- Changes to how Black can be configured -->
- _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

Expand Down
9 changes: 5 additions & 4 deletions docs/usage_and_configuration/the_basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
13 changes: 10 additions & 3 deletions src/black/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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"

Expand Down Expand Up @@ -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()}

Expand Down
18 changes: 16 additions & 2 deletions tests/test_black.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand All @@ -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",
)
Expand Down

0 comments on commit 2623269

Please sign in to comment.