ronantakizawa/codereview-bench huggingface dataset:
Repository: psf/black
File: tests/test_black.py (Python)

Code before:
        sources.extend(
            black.gen_python_files_in_dir(
                path, re.compile(black.DEFAULT_INCLUDES), empty
            )
        )
        self.assertEqual(sorted(expected), sorted(sources))

    def test_invalid_include_exclude(self) -> None:
        for option in ["--include", "--exclude"]:
            result = CliRunner().invoke(black.main, ["-", option, "**()(!!*)"])
            self.assertEqual(result.exit_code, 2)

    def test_preserves_line_endings(self) -> None:
        with TemporaryDirectory() as workspace:
            test_file = Path(workspace) / "test.py"
            for nl in ["\n", "\r\n"]:
                contents = nl.join(["def f(  ):", "    pass"])
                test_file.write_bytes(contents.encode())
                ff(test_file, write_back=black.WriteBack.YES)
                updated_contents: bytes = test_file.read_bytes()
                self.assertIn(nl.encode(), updated_contents)  # type: ignore
                if nl == "\n":
                    self.assertNotIn(b"\r\n", updated_contents)  # type: ignore


if __name__ == "__main__":
    unittest.main()


Review comment (bug):
mypy complains about this line like so:
```
Cannot infer type argument 1 of "assertIn" of "TestCase"
```
I think it's confused because both arguments are `bytes`. Seems like a bug in mypy to me

Code after:
            Path(path / "b/exclude/a.py"),
            Path(path / "b/exclude/a.pyi"),
            Path(path / "b/.definitely_exclude/a.py"),
            Path(path / "b/.definitely_exclude/a.pyi"),
        ]
        sources.extend(
            black.gen_python_files_in_dir(
                path, re.compile(black.DEFAULT_INCLUDES), empty
            )
        )
        self.assertEqual(sorted(expected), sorted(sources))

    def test_invalid_include_exclude(self) -> None:
        for option in ["--include", "--exclude"]:
            result = CliRunner().invoke(black.main, ["-", option, "**()(!!*)"])
            self.assertEqual(result.exit_code, 2)

    def test_preserves_line_endings(self) -> None:
        with TemporaryDirectory() as workspace:
            test_file = Path(workspace) / "test.py"
            for nl in ["\n", "\r\n"]:
                contents = nl.join(["def f(  ):", "    pass"])
                test_file.write_bytes(contents.encode())
                ff(test_file, write_back=black.WriteBack.YES)
                updated_contents: bytes = test_file.read_bytes()
                self.assertIn(nl.encode(), updated_contents)  # type: ignore
                if nl == "\n":
                    self.assertNotIn(b"\r\n", updated_contents)  # type: ignore


if __name__ == "__main__":
    unittest.main()
Repository: psf/black
File: tests/data/comments7.py (Python)

Code before:


from .config import (
    Any,
    Bool,
    ConfigType,
    ConfigTypeAttributes,
    Int,
    no_comma_here_yet,
    #  and some comments,
    #  resolve_to_config_type,
    #  DEFAULT_TYPE_ATTRIBUTES,
)


result = 1  # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

result = 1  # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

result = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"  # aaa

result = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"  # aaa


def func():
    c = call(
        0.0123, 0.0456, 0.0789, 0.0123, 0.0789, a[-1],  # type: ignore
    )

    # The type: ignore exception only applies to line length, not
    # other types of formatting.
    c = call(
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",  # type: ignore
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
    )


Review comment (refactor):
As an aside, I really don't like the side-effect of #826 that causes this comma to be preserved. It seems like it won't cause much trouble for an already-formatted codebase but I would find it frustrating to clean up in a project that I'm newly formatting.

Code after:


from .config import (
    Any,
    Bool,
    ConfigType,
    ConfigTypeAttributes,
    Int,
    no_comma_here_yet,
    #  and some comments,
    #  resolve_to_config_type,
    #  DEFAULT_TYPE_ATTRIBUTES,
)


result = 1  # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

result = 1  # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

result = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"  # aaa

result = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"  # aaa


def func():
    c = call(0.0123, 0.0456, 0.0789, 0.0123, 0.0789, a[-1],)  # type: ignore

    # The type: ignore exception only applies to line length, not
    # other types of formatting.
    c = call(
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",  # type: ignore
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
    )
Repository: psf/black
File: black.py (Python)

Code before:
    TypeVar,
    Union,
    cast,
)
from typing_extensions import Final
from mypy_extensions import mypyc_attr

from appdirs import user_cache_dir
from dataclasses import dataclass, field, replace
import click
import toml
from typed_ast import ast3, ast27
from pathspec import PathSpec

# lib2to3 fork
from blib2to3.pytree import Node, Leaf, type_repr
from blib2to3 import pygram, pytree
from blib2to3.pgen2 import driver, token
from blib2to3.pgen2.grammar import Grammar
from blib2to3.pgen2.parse import ParseError

from _black_version import version as __version__

# This is needed for MyPy static type analysis.
# See https://stackoverflow.com/a/38962160/1354930
if False:
    import colorama  # noqa: F401

DEFAULT_LINE_LENGTH = 88
DEFAULT_EXCLUDES = r"/(\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|\.svn|_build|buck-out|build|dist)/"  # noqa: B950
DEFAULT_INCLUDES = r"\.pyi?$"
CACHE_DIR = Path(user_cache_dir("black", version=__version__))


# types
FileContent = str
Encoding = str
NewLine = str
Depth = int
NodeType = int
LeafID = int
Priority = int
Index = int
LN = Union[Leaf, Node]
SplitFunc = Callable[["Line", Collection["Feature"]], Iterator["Line"]]
Timestamp = float
FileSize = int
CacheInfo = Tuple[Timestamp, FileSize]
Cache = Dict[Path, CacheInfo]
out = partial(click.secho, bold=True, err=True)
err = partial(click.secho, fg="red", err=True)

Review comment (suggestion):
nit: using `TYPE_CHECKING` is a bit more expressive, so you don't need the above comment.
```suggestion
if typing.TYPE_CHECKING:
```

Code after:
    Set,
    Tuple,
    Type,
    TypeVar,
    Union,
    cast,
    TYPE_CHECKING,
)
from typing_extensions import Final
from mypy_extensions import mypyc_attr

from appdirs import user_cache_dir
from dataclasses import dataclass, field, replace
import click
import toml
from typed_ast import ast3, ast27
from pathspec import PathSpec

# lib2to3 fork
from blib2to3.pytree import Node, Leaf, type_repr
from blib2to3 import pygram, pytree
from blib2to3.pgen2 import driver, token
from blib2to3.pgen2.grammar import Grammar
from blib2to3.pgen2.parse import ParseError

from _black_version import version as __version__

if TYPE_CHECKING:
    import colorama  # noqa: F401

DEFAULT_LINE_LENGTH = 88
DEFAULT_EXCLUDES = r"/(\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|\.svn|_build|buck-out|build|dist)/"  # noqa: B950
DEFAULT_INCLUDES = r"\.pyi?$"
CACHE_DIR = Path(user_cache_dir("black", version=__version__))

STRING_PREFIX_CHARS: Final = "furbFURB"  # All possible string prefix characters.


# types
FileContent = str
Encoding = str
NewLine = str
Depth = int
NodeType = int
ParserState = int
LeafID = int
StringID = int
Priority = int
Index = int
LN = Union[Leaf, Node]
Transformer = Callable[["Line", Collection["Feature"]], Iterator["Line"]]
Repository: psf/black
File: src/black/__init__.py (Python)

Code before:
    # Convert tabs to spaces (following the normal Python rules)
    # and split into a list of lines:
    lines = docstring.expandtabs().splitlines()
    # Determine minimum indentation (first line doesn't count):
    indent = sys.maxsize
    for line in lines[1:]:
        stripped = line.lstrip()
        if stripped:
            indent = min(indent, len(line) - len(stripped))
    # Remove indentation (first line is special):
    trimmed = [lines[0].strip()]
    if indent < sys.maxsize:
        last_line_idx = len(lines) - 2
        for i, line in enumerate(lines[1:]):
            stripped_line = line[indent:].rstrip()
            if stripped_line or i == last_line_idx:
                trimmed.append(prefix + stripped_line)
            else:
                trimmed.append("")
    # Return a single string:
    return "\n".join(trimmed)


if __name__ == "__main__":
    patched_main()


Review comment (suggestion):
That's a bit hacky; maybe we should turn the Transformer type into a pair instead to store this extra information.

Code after:
            stop_after = leaf.opening_bracket
        else:
            last = leaf
    else:
        raise LookupError("Last two leaves were also skipped")


def run_transformer(
    line: Line,
    transform: Transformer,
    mode: Mode,
    features: Collection[Feature],
    *,
    line_str: str = "",
) -> List[Line]:
    if not line_str:
        line_str = line_to_string(line)
    result: List[Line] = []
    for transformed_line in transform(line, features):
        if str(transformed_line).strip("\n") == line_str:
            raise CannotTransform("Line transformer returned an unchanged result")

        result.extend(transform_line(transformed_line, mode=mode, features=features))

    if not (
        transform.__name__ == "rhs"
        and line.bracket_tracker.invisible
        and not any(bracket.value for bracket in line.bracket_tracker.invisible)
        and not line.contains_multiline_strings()
        and not result[0].contains_uncollapsable_type_comments()
        and not result[0].contains_unsplittable_type_ignore()
        and not is_line_short_enough(result[0], line_length=mode.line_length)
    ):
        return result

    line_copy = line.clone()
    append_leaves(line_copy, line, line.leaves)
    features_fop = set(features) | {Feature.FORCE_OPTIONAL_PARENTHESES}
    second_opinion = run_transformer(
        line_copy, transform, mode, features_fop, line_str=line_str
    )
    if all(
        is_line_short_enough(ln, line_length=mode.line_length) for ln in second_opinion
    ):
        result = second_opinion
    return result


def get_cache_file(mode: Mode) -> Path:
    return CACHE_DIR / f"cache.{mode.get_cache_key()}.pickle"
Repository: psf/black
File: src/black/__init__.py (Python)

Code before:
@click.option(
    "--exclude",
    type=str,
    default=DEFAULT_EXCLUDES,
    help=(
        "A regular expression that matches files and directories that should be"
        " excluded on recursive searches.  An empty value means no paths are excluded."
        " Use forward slashes for directories on all platforms (Windows, too). "
        " Exclusions are calculated first, inclusions later."
    ),
    show_default=True,
)
@click.option(
    "--force-exclude",
    type=str,
    help=(
        "Like --exclude, but files and directories matching this regex will be "
        "excluded even when they are passed explicitly as arguments."
    ),
)
@click.option(
    "--stdin-filename",
    type=str,
    help=(
        "The name of the file when passing it through stdin. Useful to make "
        "sure black will respect --force-exclude option on some "
        "editors that rely on using stdin."
    ),
)
@click.option(
    "-q",
    "--quiet",
    is_flag=True,
    help=(
        "Don't emit non-error messages to stderr. Errors are still emitted; silence"
        " those with 2>/dev/null."
    ),
)
@click.option(
    "-v",
    "--verbose",
    is_flag=True,
    help=(
        "Also emit messages to stderr about files that were not changed or were ignored"
        " due to --exclude=."
    ),
)
@click.version_option(version=__version__)
@click.argument(
    "src",
    nargs=-1,

Review comment (suggestion):
```suggestion
        "sure Black will respect --force-exclude option on some "
```

Code after:
@click.option(
    "--exclude",
    type=str,
    default=DEFAULT_EXCLUDES,
    help=(
        "A regular expression that matches files and directories that should be"
        " excluded on recursive searches.  An empty value means no paths are excluded."
        " Use forward slashes for directories on all platforms (Windows, too). "
        " Exclusions are calculated first, inclusions later."
    ),
    show_default=True,
)
@click.option(
    "--force-exclude",
    type=str,
    help=(
        "Like --exclude, but files and directories matching this regex will be "
        "excluded even when they are passed explicitly as arguments."
    ),
)
@click.option(
    "--stdin-filename",
    type=str,
    help=(
        "The name of the file when passing it through stdin. Useful to make "
        "sure Black will respect --force-exclude option on some "
        "editors that rely on using stdin."
    ),
)
@click.option(
    "-q",
    "--quiet",
    is_flag=True,
    help=(
        "Don't emit non-error messages to stderr. Errors are still emitted; silence"
        " those with 2>/dev/null."
    ),
)
@click.option(
    "-v",
    "--verbose",
    is_flag=True,
    help=(
        "Also emit messages to stderr about files that were not changed or were ignored"
        " due to --exclude=."
    ),
)
@click.version_option(version=__version__)
@click.argument(
    "src",
    nargs=-1,
Repository: psf/black
File: src/black/__init__.py (Python)

Code before:
    )

    if len(sources) == 1:
        reformat_one(
            src=sources.pop(),
            fast=fast,
            write_back=write_back,
            mode=mode,
            report=report,
        )
    else:
        reformat_many(
            sources=sources, fast=fast, write_back=write_back, mode=mode, report=report
        )

    if verbose or not quiet:
        out("Oh no! 💥 💔 💥" if report.return_code else "All done! ✨ 🍰 ✨")
        click.secho(str(report), err=True)
    ctx.exit(report.return_code)


def test_regex(
    ctx: click.Context,
    regex_name: str,
    regex: Optional[str],
) -> Optional[Pattern]:
    try:
        return re_compile_maybe_verbose(regex) if regex else None
    except re.error:
        err(f"Invalid regular expression for {regex_name} given: {regex!r}")
        ctx.exit(2)


def get_sources(
    *,
    ctx: click.Context,
    src: Tuple[str, ...],
    quiet: bool,
    verbose: bool,
    include: str,
    exclude: str,
    extend_exclude: Optional[str],
    force_exclude: Optional[str],
    report: "Report",
    stdin_filename: Optional[str],
) -> Set[Path]:
    """Compute the set of files to be formatted."""

    include_regex = test_regex(ctx, "include", include)
    exclude_regex = test_regex(ctx, "exclude", exclude)
    extend_exclude_regex = test_regex(ctx, "extend_exclude", extend_exclude)

Review comment (suggestion):
I don't know the `mypy` incantation to say this returns an optional if `regex` was an optional. Suggestions welcome 👍 

Code after:
    )

    if len(sources) == 1:
        reformat_one(
            src=sources.pop(),
            fast=fast,
            write_back=write_back,
            mode=mode,
            report=report,
        )
    else:
        reformat_many(
            sources=sources, fast=fast, write_back=write_back, mode=mode, report=report
        )

    if verbose or not quiet:
        out("Oh no! 💥 💔 💥" if report.return_code else "All done! ✨ 🍰 ✨")
        click.secho(str(report), err=True)
    ctx.exit(report.return_code)


def test_regex(
    ctx: click.Context,
    regex_name: str,
    regex: Optional[str],
) -> Optional[Pattern]:
    try:
        return re_compile_maybe_verbose(regex) if regex is not None else None
    except re.error:
        err(f"Invalid regular expression for {regex_name} given: {regex!r}")
        ctx.exit(2)


def get_sources(
    *,
    ctx: click.Context,
    src: Tuple[str, ...],
    quiet: bool,
    verbose: bool,
    include: str,
    exclude: str,
    extend_exclude: Optional[str],
    force_exclude: Optional[str],
    report: "Report",
    stdin_filename: Optional[str],
) -> Set[Path]:
    """Compute the set of files to be formatted."""

    include_regex = test_regex(ctx, "include", include)
    exclude_regex = test_regex(ctx, "exclude", exclude)
    assert exclude_regex is not None
Repository: psf/black
File: tests/data/comments7.py (Python)

Code before:
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
    MyLovelyCompanyTeamProjectComponent as component,  # DRY
)


result = 1  # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

result = 1  # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

result = (  # aaa
    "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
)

result = (  # aaa
    "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
)


def func():
    c = call(
        0.0123,
        0.0456,
        0.0789,
        0.0123,
        0.0789,
        a[-1],  #  type: ignore
    )
    c = call(0.0123, 0.0456, 0.0789, 0.0123, 0.0789, a[-1])  # type: ignore
    c = call(
        0.0123,
        0.0456,
        0.0789,
        0.0123,
        0.0456,
        0.0789,
        0.0123,
        0.0456,
        0.0789,
        a[-1],  # type: ignore
    )

    #  The type: ignore exception only applies to line length, not
    # other types of formatting.
    c = call(
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",  # type: ignore
        "aaaaaaaa",

Review comment (suggestion):
Looks like it turns "#<nbsp>type" into "# <nbsp>type". Let's just leave it as is instead of inserting an additional space.

Code after:
    MyLovelyCompanyTeamProjectComponent,  # NOT DRY
)
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
    MyLovelyCompanyTeamProjectComponent as component,  # DRY
)


result = 1  # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

result = 1  # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

result = (  # aaa
    "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
)

result = (  # aaa
    "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
)


def func():
    c = call(
        0.0123,
        0.0456,
        0.0789,
        0.0123,
        0.0789,
        a[-1],  # type: ignore
    )
    c = call(0.0123, 0.0456, 0.0789, 0.0123, 0.0789, a[-1])  # type: ignore
    c = call(
        0.0123,
        0.0456,
        0.0789,
        0.0123,
        0.0456,
        0.0789,
        0.0123,
        0.0456,
        0.0789,
        a[-1],  # type: ignore
    )

    # The type: ignore exception only applies to line length, not
    # other types of formatting.
    c = call(
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
        "aaaaaaaa",
Repository: psf/black
File: tests/data/comments7.py (Python)

Code before:
from .config import (
    Any,
    Bool,
    ConfigType,
    ConfigTypeAttributes,
    Int,
    Path,
    #  String,
    #  resolve_to_config_type,
    #  DEFAULT_TYPE_ATTRIBUTES,
)


from .config import (
    Any,
    Bool,
    ConfigType,
    ConfigTypeAttributes,
    Int,
    no_comma_here_yet
    #  and some comments,
    #  resolve_to_config_type,
    #  DEFAULT_TYPE_ATTRIBUTES,
)
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
    MyLovelyCompanyTeamProjectComponent  # NOT DRY
)
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
    MyLovelyCompanyTeamProjectComponent as component  # DRY
)


result = 1  # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


Review comment (suggestion):
It's going to be hard for readers of this file to recognize what's going on here, because nbsps look the same as spaces pretty much all the time, at least in environments I'm familiar with.

What about undoing the changes to this file and instead adding a new test like `nbsp.py` just for testing comments with nbsps in them? You'll have to add a new test function in test_black.py, but that's pretty easy.

Code after:
from .config import (
    Any,
    Bool,
    ConfigType,
    ConfigTypeAttributes,
    Int,
    Path,
    #  String,
    #  resolve_to_config_type,
    #  DEFAULT_TYPE_ATTRIBUTES,
)


from .config import (
    Any,
    Bool,
    ConfigType,
    ConfigTypeAttributes,
    Int,
    no_comma_here_yet
    #  and some comments,
    #  resolve_to_config_type,
    #  DEFAULT_TYPE_ATTRIBUTES,
)
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
    MyLovelyCompanyTeamProjectComponent  # NOT DRY
)
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
    MyLovelyCompanyTeamProjectComponent as component  # DRY
)


result = 1  # look ma, no comment migration xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Repository: psf/black
File: src/black/report.py (Python)

Code before:
"""
Summarize Black runs to users.
"""
from dataclasses import dataclass
from enum import Enum
from pathlib import Path
import typing

from click import style

from black.output import out, err


class Changed(Enum):
    NO = 0
    CACHED = 1
    YES = 2


@dataclass
class Report:
    """Provides a reformatting counter. Can be rendered with `str(report)`."""

    check: bool = False
    diff: bool = False
    quiet: bool = False
    verbose: bool = False
    change_count: int = 0
    same_count: int = 0
    failure_count: int = 0

    def done(self, src: typing.Union[Path, str], changed: Changed) -> None:

Review comment (suggestion):
Prefer `from typing import Union` (but with my suggested change above you should be able to undo all changes to this file)

Code after:
"""
Summarize Black runs to users.
"""
from dataclasses import dataclass
from enum import Enum
from pathlib import Path

from click import style

from black.output import out, err


class Changed(Enum):
    NO = 0
    CACHED = 1
    YES = 2


@dataclass
class Report:
    """Provides a reformatting counter. Can be rendered with `str(report)`."""

    check: bool = False
    diff: bool = False
    quiet: bool = False
    verbose: bool = False
    change_count: int = 0
    same_count: int = 0
    failure_count: int = 0

    def done(self, src: Path, changed: Changed) -> None:
        """Increment the counter for successful reformatting. Write out a message."""