import click
from click.core import ParameterSource
from mypy_extensions import mypyc_attr
+from pathspec import PathSpec
from pathspec.patterns.gitwildmatch import GitWildMatchPatternError
from _black_version import version as __version__
unmask_cell,
)
from black.linegen import LN, LineGenerator, transform_line
-from black.lines import EmptyLineTracker, Line
+from black.lines import EmptyLineTracker, LinesBlock
from black.mode import (
FUTURE_FLAG_TO_FEATURE,
VERSION_TO_FEATURES,
user_level_config = str(find_user_pyproject_toml())
if config == user_level_config:
out(
- "Using configuration from user-level config at "
- f"'{user_level_config}'.",
+ (
+ "Using configuration from user-level config at "
+ f"'{user_level_config}'."
+ ),
fg="blue",
)
elif config_source in (
sources: Set[Path] = set()
root = ctx.obj["root"]
+ using_default_exclude = exclude is None
+ exclude = re_compile_maybe_verbose(DEFAULT_EXCLUDES) if exclude is None else exclude
+ gitignore: Optional[PathSpec] = None
+ root_gitignore = get_gitignore(root)
+
for s in src:
if s == "-" and stdin_filename:
p = Path(stdin_filename)
sources.add(p)
elif p.is_dir():
- if exclude is None:
- exclude = re_compile_maybe_verbose(DEFAULT_EXCLUDES)
- gitignore = get_gitignore(root)
- p_gitignore = get_gitignore(p)
- # No need to use p's gitignore if it is identical to root's gitignore
- # (i.e. root and p point to the same directory).
- if gitignore != p_gitignore:
- gitignore += p_gitignore
- else:
- gitignore = None
+ if using_default_exclude:
+ gitignore = {
+ root: root_gitignore,
+ root / p: get_gitignore(p),
+ }
sources.update(
gen_python_files(
p.iterdir(),
def _format_str_once(src_contents: str, *, mode: Mode) -> str:
src_node = lib2to3_parse(src_contents.lstrip(), mode.target_versions)
- dst_contents = []
+ dst_blocks: List[LinesBlock] = []
if mode.target_versions:
versions = mode.target_versions
else:
normalize_fmt_off(src_node, preview=mode.preview)
lines = LineGenerator(mode=mode)
- elt = EmptyLineTracker(is_pyi=mode.is_pyi)
- empty_line = Line(mode=mode)
- after = 0
+ elt = EmptyLineTracker(mode=mode)
split_line_features = {
feature
for feature in {Feature.TRAILING_COMMA_IN_CALL, Feature.TRAILING_COMMA_IN_DEF}
if supports_feature(versions, feature)
}
+ block: Optional[LinesBlock] = None
for current_line in lines.visit(src_node):
- dst_contents.append(str(empty_line) * after)
- before, after = elt.maybe_empty_lines(current_line)
- dst_contents.append(str(empty_line) * before)
+ block = elt.maybe_empty_lines(current_line)
+ dst_blocks.append(block)
for line in transform_line(
current_line, mode=mode, features=split_line_features
):
- dst_contents.append(str(line))
+ block.content_lines.append(str(line))
+ if dst_blocks:
+ dst_blocks[-1].after = 0
+ dst_contents = []
+ for block in dst_blocks:
+ dst_contents.extend(block.all_lines())
return "".join(dst_contents)