Skip to content

Commit

Permalink
Merge pull request #1349 from sztamas/issue/1177/colored-output-in-ch…
Browse files Browse the repository at this point in the history
…eck-mode

Adds color to ERROR and SUCCESS in check mode.
  • Loading branch information
timothycrosley committed Jul 28, 2020
2 parents 05baa33 + dc44cc8 commit 2115ed8
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 4 deletions.
11 changes: 11 additions & 0 deletions docs/configuration/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,17 @@ See isort's determined config, as well as sources of config options.

- --show-config

## Color Terminal Output

Tells isort to use color in terminal output.

**Type:** Bool
**Default:** `False`
**Python & Config File Name:** color_output
**CLI Flags:**

- --color

## Deprecated Flags

==SUPPRESS==
Expand Down
7 changes: 4 additions & 3 deletions isort/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
)
from .format import (
ask_whether_to_apply_changes_to_file,
create_terminal_printer,
format_natural,
remove_whitespace,
show_unified_diff,
Expand Down Expand Up @@ -216,13 +217,13 @@ def check_stream(
file_path=file_path,
disregard_skip=disregard_skip,
)

printer = create_terminal_printer(color=config.color_output)
if not changed:
if config.verbose:
print(f"SUCCESS: {file_path or ''} Everything Looks Good!")
printer.success(f"{file_path or ''} Everything Looks Good!")
return True
else:
print(f"ERROR: {file_path or ''} Imports are incorrectly sorted and/or formatted.")
printer.error(f"{file_path or ''} Imports are incorrectly sorted and/or formatted.")
if show_diff:
output_stream = StringIO()
input_stream.seek(0)
Expand Down
49 changes: 49 additions & 0 deletions isort/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
from pathlib import Path
from typing import Optional, TextIO

try:
import colorama
except ImportError:
colorama_unavailable = True
else:
colorama_unavailable = False
colorama.init()


def format_simplified(import_line: str) -> str:
import_line = import_line.strip()
Expand Down Expand Up @@ -70,3 +78,44 @@ def ask_whether_to_apply_changes_to_file(file_path: str) -> bool:
def remove_whitespace(content: str, line_separator: str = "\n") -> str:
content = content.replace(line_separator, "").replace(" ", "").replace("\x0c", "")
return content


class BasicPrinter:
ERROR = "ERROR"
SUCCESS = "SUCCESS"

def success(self, message: str) -> None:
print(f"{self.SUCCESS}: {message}")

def error(self, message: str) -> None:
print(
f"{self.ERROR}: {message}",
# TODO this should print to stderr, but don't want to make it backward incompatible now
# file=sys.stderr
)


class ColoramaPrinter(BasicPrinter):
def __init__(self):
self.ERROR = self.style_text("ERROR", colorama.Fore.RED)
self.SUCCESS = self.style_text("SUCCESS", colorama.Fore.GREEN)

@staticmethod
def style_text(text: str, style: str) -> str:
return style + text + colorama.Style.RESET_ALL


def create_terminal_printer(color: bool):
if color and colorama_unavailable:
no_colorama_message = (
"\n"
"Sorry, but to use --color (color_output) the colorama python package is required.\n\n"
"Reference: https://pypi.org/project/colorama/\n\n"
"You can either install it separately on your system or as the colors extra "
"for isort. Ex: \n\n"
"$ pip install isort[colors]\n"
)
print(no_colorama_message, file=sys.stderr)
sys.exit(1)

return ColoramaPrinter() if color else BasicPrinter()
6 changes: 6 additions & 0 deletions isort/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,12 @@ def _build_arg_parser() -> argparse.ArgumentParser:
" aliases to signify intent and change behaviour."
),
)
parser.add_argument(
"--color",
dest="color_output",
action="store_true",
help="Tells isort to use color in terminal output.",
)
parser.add_argument(
"--float-to-top",
dest="float_to_top",
Expand Down
1 change: 1 addition & 0 deletions isort/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ class _Config:
filter_files: bool = False
formatter: str = ""
formatting_function: Optional[Callable[[str, str, object], str]] = None
color_output: bool = False

def __post_init__(self):
py_version = self.py_version
Expand Down
1 change: 1 addition & 0 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@ pipreqs = {version = "*", optional = true}
requirementslib = {version = "*", optional = true}
tomlkit = {version = ">=0.5.3", optional = true}
pip-api = {version = "*", optional = true}
colorama = {version = "^0.4.3", optional = true}

[tool.poetry.extras]
pipfile_deprecated_finder = ["pipreqs", "tomlkit", "requirementslib", "pip-shims<=0.3.4"]
requirements_deprecated_finder = ["pipreqs", "pip-api"]
colors = ["colorama"]

[tool.poetry.dev-dependencies]
vulture = "^1.0"
Expand Down
39 changes: 39 additions & 0 deletions tests/test_format.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from unittest.mock import MagicMock, patch

import colorama
import pytest
from hypothesis_auto import auto_pytest_magic

Expand All @@ -16,3 +17,41 @@ def test_ask_whether_to_apply_changes_to_file():
with patch("isort.format.input", MagicMock(return_value="q")):
with pytest.raises(SystemExit):
assert isort.format.ask_whether_to_apply_changes_to_file("")


def test_basic_printer(capsys):
printer = isort.format.create_terminal_printer(color=False)
printer.success("All good!")
out, _ = capsys.readouterr()
assert out == "SUCCESS: All good!\n"
printer.error("Some error")
out, _ = capsys.readouterr()
assert out == "ERROR: Some error\n"


def test_colored_printer_success(capsys):
printer = isort.format.create_terminal_printer(color=True)
printer.success("All good!")
out, _ = capsys.readouterr()
assert "SUCCESS" in out
assert "All good!" in out
assert colorama.Fore.GREEN in out


def test_colored_printer_error(capsys):
printer = isort.format.create_terminal_printer(color=True)
printer.error("Some error")
out, _ = capsys.readouterr()
assert "ERROR" in out
assert "Some error" in out
assert colorama.Fore.RED in out


@patch("isort.format.colorama_unavailable", True)
def test_colorama_not_available_handled_gracefully(capsys):
with pytest.raises(SystemExit) as system_exit:
_ = isort.format.create_terminal_printer(color=True)
assert system_exit.value.code > 0
_, err = capsys.readouterr()
assert "colorama" in err
assert "colors extra" in err
3 changes: 2 additions & 1 deletion tests/test_isort.py
Original file line number Diff line number Diff line change
Expand Up @@ -2683,7 +2683,8 @@ def test_strict_whitespace_by_default(capsys) -> None:
test_input = "import os\nfrom django.conf import settings\n"
assert not api.check_code_string(test_input)
out, _ = capsys.readouterr()
assert out == "ERROR: Imports are incorrectly sorted and/or formatted.\n"
assert "ERROR" in out
assert out.endswith("Imports are incorrectly sorted and/or formatted.\n")


def test_strict_whitespace_no_closing_newline_issue_676(capsys) -> None:
Expand Down

0 comments on commit 2115ed8

Please sign in to comment.