Improve performance by skipping unnecessary normalisation (#3751)
This speeds up black by about 40% when the cache is full
This commit is contained in:
parent
f3b50e4669
commit
2593af2c5d
@ -55,6 +55,7 @@
|
|||||||
|
|
||||||
<!-- Changes that improve Black's performance. -->
|
<!-- Changes that improve Black's performance. -->
|
||||||
|
|
||||||
|
- Speed up _Black_ significantly when the cache is full (#3751)
|
||||||
- Avoid importing `IPython` in a case where we wouldn't need it (#3748)
|
- Avoid importing `IPython` in a case where we wouldn't need it (#3748)
|
||||||
|
|
||||||
### Output
|
### Output
|
||||||
|
@ -276,15 +276,24 @@ def normalize_path_maybe_ignore(
|
|||||||
return root_relative_path
|
return root_relative_path
|
||||||
|
|
||||||
|
|
||||||
def path_is_ignored(
|
def _path_is_ignored(
|
||||||
path: Path, gitignore_dict: Dict[Path, PathSpec], report: Report
|
root_relative_path: str,
|
||||||
|
root: Path,
|
||||||
|
gitignore_dict: Dict[Path, PathSpec],
|
||||||
|
report: Report,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
|
path = root / root_relative_path
|
||||||
|
# Note that this logic is sensitive to the ordering of gitignore_dict. Callers must
|
||||||
|
# ensure that gitignore_dict is ordered from least specific to most specific.
|
||||||
for gitignore_path, pattern in gitignore_dict.items():
|
for gitignore_path, pattern in gitignore_dict.items():
|
||||||
relative_path = normalize_path_maybe_ignore(path, gitignore_path, report)
|
try:
|
||||||
if relative_path is None:
|
relative_path = path.relative_to(gitignore_path).as_posix()
|
||||||
|
except ValueError:
|
||||||
break
|
break
|
||||||
if pattern.match_file(relative_path):
|
if pattern.match_file(relative_path):
|
||||||
report.path_ignored(path, "matches a .gitignore file content")
|
report.path_ignored(
|
||||||
|
path.relative_to(root), "matches a .gitignore file content"
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -326,7 +335,9 @@ def gen_python_files(
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# First ignore files matching .gitignore, if passed
|
# First ignore files matching .gitignore, if passed
|
||||||
if gitignore_dict and path_is_ignored(child, gitignore_dict, report):
|
if gitignore_dict and _path_is_ignored(
|
||||||
|
normalized_path, root, gitignore_dict, report
|
||||||
|
):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Then ignore with `--exclude` `--extend-exclude` and `--force-exclude` options.
|
# Then ignore with `--exclude` `--extend-exclude` and `--force-exclude` options.
|
||||||
|
@ -508,6 +508,8 @@ def _mocked_calls() -> bool:
|
|||||||
"pathlib.Path.cwd", return_value=working_directory
|
"pathlib.Path.cwd", return_value=working_directory
|
||||||
), patch("pathlib.Path.is_dir", side_effect=mock_n_calls([True])):
|
), patch("pathlib.Path.is_dir", side_effect=mock_n_calls([True])):
|
||||||
ctx = FakeContext()
|
ctx = FakeContext()
|
||||||
|
# Note that the root folder (project_root) isn't the folder
|
||||||
|
# named "root" (aka working_directory)
|
||||||
ctx.obj["root"] = project_root
|
ctx.obj["root"] = project_root
|
||||||
report = MagicMock(verbose=True)
|
report = MagicMock(verbose=True)
|
||||||
black.get_sources(
|
black.get_sources(
|
||||||
@ -527,7 +529,7 @@ def _mocked_calls() -> bool:
|
|||||||
for _, mock_args, _ in report.path_ignored.mock_calls
|
for _, mock_args, _ in report.path_ignored.mock_calls
|
||||||
), "A symbolic link was reported."
|
), "A symbolic link was reported."
|
||||||
report.path_ignored.assert_called_once_with(
|
report.path_ignored.assert_called_once_with(
|
||||||
Path("child", "b.py"), "matches a .gitignore file content"
|
Path("root", "child", "b.py"), "matches a .gitignore file content"
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_report_verbose(self) -> None:
|
def test_report_verbose(self) -> None:
|
||||||
|
Loading…
Reference in New Issue
Block a user