Skip to content

Commit

Permalink
Merge 9facc8e into ad496e5
Browse files Browse the repository at this point in the history
  • Loading branch information
Rizhiy committed Feb 1, 2023
2 parents ad496e5 + 9facc8e commit d50f92e
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 46 deletions.
39 changes: 25 additions & 14 deletions src/yamlfix/entrypoints/__init__.py
Expand Up @@ -6,38 +6,49 @@

import logging
import sys
from enum import Enum

# Ansi color codes
RED = 31
YELLOW = 33
CYAN = 36
GREEN = 32

class ANSIFGColorCode(Enum):
"""ANSI escape codes for colored output."""

BLACK = 30
RED = 31
GREEN = 32
YELLOW = 33
BLUE = 34
MAGENTA = 35
CYAN = 36
WHITE = 37
RESET = 0


class ConsoleColorFormatter(logging.Formatter):
"""Custom formatter that prints log levels to the console as colored plus signs."""

# ANSI escape codes for colored output
colors = {
logging.DEBUG: GREEN,
logging.INFO: CYAN,
logging.WARNING: YELLOW,
logging.ERROR: RED,
logging.DEBUG: ANSIFGColorCode.GREEN,
15: ANSIFGColorCode.BLUE,
logging.INFO: ANSIFGColorCode.CYAN,
logging.WARNING: ANSIFGColorCode.YELLOW,
logging.ERROR: ANSIFGColorCode.RED,
}

def format(self, record: logging.LogRecord) -> str:
"""Format log records as a colored plus sign followed by the log message."""
color = self.colors.get(record.levelno, 0)
self._style._fmt = f"[\033[{color}m+\033[0m] %(message)s" # noqa: W0212
color = self.colors.get(record.levelno, ANSIFGColorCode.RESET)
self._style._fmt = f"[\033[{color.value}m+\033[0m] %(message)s" # noqa: W0212
return super().format(record)


def load_logger(verbose: bool = False) -> None:
def load_logger(verbose: int = 0) -> None:
"""Configure the Logging logger.
Args:
verbose: Set the logging level to Debug.
verbose: Decrease logging threshold by 10 for each level.
"""
log_level = logging.DEBUG if verbose else logging.INFO
log_level = logging.INFO - verbose * 5
logging.basicConfig(stream=sys.stderr, level=log_level)
for handler in logging.getLogger().handlers:
handler.setFormatter(ConsoleColorFormatter())
14 changes: 2 additions & 12 deletions src/yamlfix/entrypoints/cli.py
Expand Up @@ -17,19 +17,14 @@
log = logging.getLogger(__name__)


def _format_file_list(files: List[TextIOWrapper]) -> str:
file_names = [file.name for file in files]
return "\n - ".join([""] + file_names)


def _find_all_yaml_files(dir_: Path) -> List[Path]:
files = [dir_.rglob(f"*.{ext}") for ext in ["yml", "yaml"]]
return [file for list_ in files for file in list_]


@click.command()
@click.version_option(version="", message=version.version_info())
@click.option("--verbose", is_flag=True, help="Enable verbose logging.")
@click.option("--verbose", "-v", help="Enable verbose logging.", count=True)
@click.option(
"--check",
is_flag=True,
Expand Down Expand Up @@ -81,11 +76,7 @@ def cli(
sys.exit(0)

load_logger(verbose)
log.info(
"%s files:%s",
"Checking" if check else "Fixing",
_format_file_list(files_to_fix),
)
log.info("YamlFix: %s files", "Checking" if check else "Fixing")

config = YamlfixConfig()
configure_yamlfix(
Expand All @@ -98,7 +89,6 @@ def cli(

if fixed_code is not None:
print(fixed_code, end="")
log.info("Done.")

if changed and check:
sys.exit(1)
Expand Down
27 changes: 18 additions & 9 deletions src/yamlfix/services.py
Expand Up @@ -36,9 +36,7 @@ def fix_files(


def fix_files( # pylint: disable=too-many-branches
files: Files,
dry_run: Optional[bool] = None,
config: Optional[YamlfixConfig] = None,
files: Files, dry_run: Optional[bool] = None, config: Optional[YamlfixConfig] = None
) -> Union[Optional[str], Tuple[Optional[str], bool]]: # noqa: TAE002
"""Fix the yaml source code of a list of files.
Expand Down Expand Up @@ -69,6 +67,8 @@ def fix_files( # pylint: disable=too-many-branches
UserWarning,
)

total_fixed = 0

for file_ in files:
if isinstance(file_, str):
with open(file_, "r", encoding="utf-8") as file_descriptor:
Expand All @@ -83,15 +83,21 @@ def fix_files( # pylint: disable=too-many-branches

if fixed_source != source:
changed = True
if dry_run:
log.info("Would fix %s", file_name)
else:
log.info("Fixed %s", file_name)
total_fixed += 1
else:
log.log(15, "%s is already well formatted", file_name)

if file_name == "<stdin>":
if dry_run is None:
return fixed_source
return (fixed_source, changed)
return fixed_source, changed

if fixed_source != source:
if dry_run:
log.debug("Need to fix file %s.", file_name)
continue
if isinstance(file_, str):
with open(file_, "w", encoding="utf-8") as file_descriptor:
Expand All @@ -100,14 +106,17 @@ def fix_files( # pylint: disable=too-many-branches
file_.seek(0)
file_.write(fixed_source)
file_.truncate()
log.debug("Fixed file %s.", file_name)
else:
log.debug("Left file %s unmodified.", file_name)
log.info(
"Checked %d files: %d fixed, %d left unchanged",
len(files),
total_fixed,
len(files) - total_fixed,
)

if dry_run is None:
return None

return (None, changed)
return None, changed


def fix_code(source_code: str, config: Optional[YamlfixConfig] = None) -> str:
Expand Down
36 changes: 25 additions & 11 deletions tests/e2e/test_cli.py
Expand Up @@ -3,6 +3,7 @@
import logging
import os
import re
from itertools import product
from pathlib import Path
from textwrap import dedent

Expand All @@ -26,8 +27,7 @@ def test_version(runner: CliRunner) -> None:

assert result.exit_code == 0
assert re.search(
rf" *yamlfix: {__version__}\n *Python: .*\n *Platform: .*",
result.stdout,
rf" *yamlfix: {__version__}\n *Python: .*\n *Platform: .*", result.stdout
)


Expand Down Expand Up @@ -87,22 +87,36 @@ def test_corrects_code_from_stdin(runner: CliRunner) -> None:


@pytest.mark.secondary()
@pytest.mark.parametrize("verbose", [True, False])
def test_verbose_option(runner: CliRunner, verbose: bool) -> None:
@pytest.mark.parametrize(
("verbose", "requires_fixing"), product([0, 1, 2], [True, False])
)
def test_verbose_option(runner: CliRunner, verbose: int, requires_fixing: bool) -> None:
"""Prints debug level logs only when called with --verbose"""
# Clear logging handlers for logs to work with CliRunner
# For more info see https://github.com/pallets/click/issues/1053)
logging.getLogger().handlers = []
source = "program: yamlfix"
args = ["-", "--verbose"] if verbose else ["-"]
source = "program: yamlfix" if requires_fixing else "---\nprogram: yamlfix\n"
args = ["-"]
if verbose >= 1:
args.append("--verbose")
if verbose >= 2:
args.append("-v")

result = runner.invoke(cli, args, input=source)

debug_log_format = "[\033[32m+\033[0m]"
if verbose:
assert debug_log_format in result.stderr
else:
unchanged_log_format = "[\033[34m+\033[0m]"
info_log_format = "[\033[36m+\033[0m]"
# Check that changes are printed at info level
assert (f"{info_log_format} Fixed <stdin>" in result.stderr) == requires_fixing
if verbose == 0:
assert debug_log_format not in result.stderr
assert unchanged_log_format not in result.stderr
if verbose >= 1:
# If no changes are required, unchanged log should not be printed
assert (unchanged_log_format in result.stderr) != requires_fixing
if verbose >= 2:
assert debug_log_format in result.stderr


def test_ignores_correct_files(
Expand All @@ -120,8 +134,8 @@ def test_ignores_correct_files(
assert test_file.read_text() == "---\na: 1\n"
assert (
"yamlfix.services",
logging.DEBUG,
f"Left file {test_file} unmodified.",
15,
f"{test_file} is already well formatted",
) in caplog.record_tuples


Expand Down

0 comments on commit d50f92e

Please sign in to comment.