Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code Flag Options #2259

Merged
merged 16 commits into from Jun 2, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS.md
Expand Up @@ -68,6 +68,7 @@ Multiple contributions by:
- Gustavo Camargo
- hauntsaninja
- [Hadi Alqattan](mailto:alqattanhadizaki@gmail.com)
- [Hassan Abouelela](mailto:hassan@hassanamr.com)
- [Heaford](mailto:dan@heaford.com)
- [Hugo Barrera](mailto::hugo@barrera.io)
- Hugo van Kemenade
Expand Down
2 changes: 2 additions & 0 deletions CHANGES.md
Expand Up @@ -9,6 +9,7 @@
- Respect `.gitignore` files in all levels, not only `root/.gitignore` file (apply
`.gitignore` rules like `git` does) (#2225)
- Restored compatibility with Click 8.0 on Python 3.6 when LANG=C used (#2227)
- Fixed option usage when using the `--code` flag (#2259)
- Add extra uvloop install + import support if in python env (#2258)

### _Blackd_
Expand All @@ -25,6 +26,7 @@
- Fix typos discovered by codespell (#2228)
- Fix Vim plugin installation instructions. (#2235)
- Add new Frequently Asked Questions page (#2247)
- Removed safety checks warning for the `--code` option (#2259)

## 21.5b1

Expand Down
7 changes: 0 additions & 7 deletions docs/usage_and_configuration/the_basics.md
Expand Up @@ -68,13 +68,6 @@ $ black --code "print ( 'hello, world' )"
print("hello, world")
```

```{warning}
--check, --diff, and --safe / --fast have no effect when using -c / --code. Safety
checks normally turned on by default that verify _Black_'s output are disabled as well.
This is a bug which we intend to fix eventually. More details can be found in this [bug
report](https://github.com/psf/black/issues/2104).
```

### Writeback and reporting

By default _Black_ reformats the files given and/or found in place. Sometimes you need
Expand Down
31 changes: 30 additions & 1 deletion src/black/__init__.py
Expand Up @@ -29,6 +29,7 @@
from dataclasses import replace
import click

from black import output
HassanAbouelela marked this conversation as resolved.
Show resolved Hide resolved
from black.const import DEFAULT_LINE_LENGTH, DEFAULT_INCLUDES, DEFAULT_EXCLUDES
from black.const import STDIN_PLACEHOLDER
from black.nodes import STARS, syms, is_simple_decorator_expression
Expand Down Expand Up @@ -385,8 +386,36 @@ def main(
if config and verbose:
out(f"Using configuration from {config}.", bold=False, fg="blue")
if code is not None:
print(format_str(code, mode=mode))
then = datetime.utcnow()

try:
formatted = format_file_contents(code, fast=fast, mode=mode)
except NothingChanged:
formatted = code

stream = io.TextIOWrapper(sys.stdout.buffer)
try:
if write_back is WriteBack.CHECK:
ctx.exit(0 if code == formatted else 1)
elif write_back in (WriteBack.DIFF, WriteBack.COLOR_DIFF):
now = datetime.utcnow()
src_name = f"STDIN\t{then} +0000"
dst_name = f"STDOUT\t{now} +0000"
ichard26 marked this conversation as resolved.
Show resolved Hide resolved

diff_contents = output.diff(code, formatted, src_name, dst_name)
if write_back == WriteBack.COLOR_DIFF:
diff_contents = color_diff(diff_contents)
stream = wrap_stream_for_windows(stream)

stream.write(diff_contents)
else:
stream.write(formatted)
finally:
# Ensure the stream is cleaned up properly
stream.detach()

ctx.exit(0)

report = Report(check=check, diff=diff, quiet=quiet, verbose=verbose)
sources = get_sources(
ctx=ctx,
Expand Down
97 changes: 97 additions & 0 deletions tests/test_black.py
Expand Up @@ -34,6 +34,7 @@
from black import Feature, TargetVersion
from black.cache import get_cache_file
from black.debug import DebugVisitor
from black.output import diff, color_diff
from black.report import Report
import black.files

Expand Down Expand Up @@ -63,6 +64,9 @@
T = TypeVar("T")
R = TypeVar("R")

# Match the time output in a diff, but nothing else
DIFF_TIME = re.compile(r"\t[\d-:+\. ]+")


@contextmanager
def cache_dir(exists: bool = True) -> Iterator[Path]:
Expand Down Expand Up @@ -2069,6 +2073,99 @@ def test_docstring_reformat_for_py27(self) -> None:
actual = result.output
self.assertFormatEqual(actual, expected)

@staticmethod
def compare_results(
result: click.testing.Result, expected_value: str, expected_exit_code: int
) -> None:
"""Helper method to test the value and exit code of a click Result."""
assert (
result.output == expected_value
), "The output did not match the expected value."
assert result.exit_code == expected_exit_code, "The exit code is incorrect."
HassanAbouelela marked this conversation as resolved.
Show resolved Hide resolved

def test_code_option(self) -> None:
"""Test the code option with no changes."""
code = 'print("Hello world")\n'
args = ["--code", code]
result = CliRunner().invoke(black.main, args)

self.compare_results(result, code, 0)

def test_code_option_changed(self) -> None:
"""Test the code option when changes are required."""
code = "print('hello world')"
formatted = black.format_str(code, mode=DEFAULT_MODE)

args = ["--code", code]
result = CliRunner().invoke(black.main, args)

self.compare_results(result, formatted, 0)

def test_code_option_check(self) -> None:
"""Test the code option when check is passed."""
args = ["--check", "--code", 'print("Hello world")\n']
result = CliRunner().invoke(black.main, args)
self.compare_results(result, "", 0)

def test_code_option_check_changed(self) -> None:
"""Test the code option when changes are required, and check is passed."""
args = ["--check", "--code", "print('hello world')"]
result = CliRunner().invoke(black.main, args)
self.compare_results(result, "", 1)

def test_code_option_diff(self) -> None:
"""Test the code option when diff is passed."""
code = "print('hello world')"
formatted = black.format_str(code, mode=DEFAULT_MODE)
result_diff = diff(code, formatted, "STDIN", "STDOUT")

args = ["--diff", "--code", code]
result = CliRunner().invoke(black.main, args)

# Remove time from diff
output = DIFF_TIME.sub("", result.output)

assert output == result_diff, "The output did not match the expected value."
assert result.exit_code == 0, "The exit code is incorrect."

def test_code_option_color_diff(self) -> None:
"""Test the code option when color and diff are passed."""
code = "print('hello world')"
formatted = black.format_str(code, mode=DEFAULT_MODE)

result_diff = diff(code, formatted, "STDIN", "STDOUT")
result_diff = color_diff(result_diff)

args = ["--diff", "--color", "--code", code]
result = CliRunner().invoke(black.main, args)

# Remove time from diff
output = DIFF_TIME.sub("", result.output)

assert output == result_diff, "The output did not match the expected value."
assert result.exit_code == 0, "The exit code is incorrect."

def test_code_option_safe(self) -> None:
"""Test that the code option throws an error when the sanity checks fail."""
# Patch black.assert_equivalent to ensure the sanity checks fail
with patch.object(black, "assert_equivalent", side_effect=AssertionError):
args = ["--safe", "--code", 'print("Hello world")']
result = CliRunner().invoke(black.main, args)

self.compare_results(result, "", 1)

def test_code_option_fast(self) -> None:
"""Test that the code option ignores errors when the sanity checks fail."""
# Patch black.assert_equivalent to ensure the sanity checks fail
with patch.object(black, "assert_equivalent", side_effect=AssertionError):
code = 'print("Hello world")'
formatted = black.format_str(code, mode=DEFAULT_MODE)

args = ["--fast", "--code", code]
result = CliRunner().invoke(black.main, args)

self.compare_results(result, formatted, 0)


with open(black.__file__, "r", encoding="utf-8") as _bf:
black_source_lines = _bf.readlines()
Expand Down