Skip to content

Commit

Permalink
fix(cli): print "no violations" message
Browse files Browse the repository at this point in the history
  • Loading branch information
andreoliwa committed Apr 24, 2021
1 parent b2c1211 commit 2fedd0a
Show file tree
Hide file tree
Showing 10 changed files with 46 additions and 22 deletions.
2 changes: 1 addition & 1 deletion docs/cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ At the end of execution, this command displays:
difference. Return code 0 means nothing would change. Return
code 1 means some files would be modified.
-v, --verbose Verbose logging
-v, --verbose Increase logging verbosity (-v = INFO, -vv = DEBUG)
--help Show this message and exit.
.. _cli_cmd_ls:
Expand Down
13 changes: 11 additions & 2 deletions src/nitpick/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
Also see (1) from https://click.palletsprojects.com/en/5.x/setuptools/#setuptools-integration
"""
import logging
import sys
from pathlib import Path
from typing import Optional

Expand Down Expand Up @@ -65,7 +67,7 @@ def get_nitpick(context: click.Context) -> Nitpick:
help="Don't modify the configuration files, just print the difference."
" Return code 0 means nothing would change. Return code 1 means some files would be modified.",
)
@click.option("--verbose", "-v", is_flag=True, default=False, help="Verbose logging")
@click.option("--verbose", "-v", count=True, default=False, help="Increase logging verbosity (-v = INFO, -vv = DEBUG)")
@click.pass_context
@click.argument("files", nargs=-1)
def run(context, check_only, verbose, files):
Expand All @@ -74,6 +76,13 @@ def run(context, check_only, verbose, files):
You can use partial and multiple file names in the FILES argument.
"""
if verbose:
level = logging.INFO if verbose == 1 else logging.DEBUG

# https://loguru.readthedocs.io/en/stable/resources/recipes.html#changing-the-level-of-an-existing-handler
# https://github.com/Delgan/loguru/issues/138#issuecomment-525594566
logger.remove()
logger.add(sys.stderr, level=logging.getLevelName(level))

logger.enable(PROJECT_NAME)

nit = get_nitpick(context)
Expand All @@ -85,8 +94,8 @@ def run(context, check_only, verbose, files):
click.echo(fuss.pretty)
raise Exit(2) from err

click.secho(Reporter.get_counts())
if Reporter.manual or Reporter.fixed:
click.secho(Reporter.get_counts())
raise Exit(1)


Expand Down
4 changes: 2 additions & 2 deletions src/nitpick/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def enforce_present_absent(self, *partial_names: str) -> Iterator[Fuss]:

for present in (True, False):
key = "present" if present else "absent"
logger.info(f"Enforce {key} files")
logger.debug(f"Enforce {key} files")
absent = not present
file_mapping = self.project.nitpick_files_section.get(key, {})
for filename in filter_names(file_mapping, *partial_names):
Expand Down Expand Up @@ -109,7 +109,7 @@ def enforce_style(self, *partial_names: str, apply=True) -> Iterator[Fuss]:
# 1.
for config_key in filter_names(self.project.style_dict, *partial_names):
config_dict = self.project.style_dict[config_key]
logger.info(f"{config_key}: Finding plugins to enforce style")
logger.debug(f"{config_key}: Finding plugins to enforce style")

# 2.
info = FileInfo.create(self.project, config_key)
Expand Down
2 changes: 1 addition & 1 deletion src/nitpick/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ def merge_styles(self, offline: bool) -> Iterator[Fuss]:
from nitpick.flake8 import NitpickFlake8Extension

minimum_version = search_dict(NITPICK_MINIMUM_VERSION_JMEX, self.style_dict, None)
logger.info(f"Minimum version: {minimum_version}")
logger.debug(f"Minimum version: {minimum_version}")
if minimum_version and version_to_tuple(NitpickFlake8Extension.version) < version_to_tuple(minimum_version):
yield Reporter().make_fuss(
ProjectViolations.MINIMUM_VERSION,
Expand Down
8 changes: 4 additions & 4 deletions src/nitpick/style/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,16 @@ def get_default_style_url():
def find_initial_styles(self, configured_styles: StrOrIterable) -> Iterator[Fuss]:
"""Find the initial style(s) and include them."""
if configured_styles:
chosen_styles = configured_styles
log_message = f"Styles configured in {PYPROJECT_TOML}"
chosen_styles: StrOrIterable = list(configured_styles)
log_message = f"Using styles configured in {PYPROJECT_TOML}"
else:
paths = climb_directory_tree(self.project.root, [NITPICK_STYLE_TOML])
if paths:
chosen_styles = str(sorted(paths)[0])
log_message = "Found style climbing the directory tree"
log_message = "Using local style found climbing the directory tree"
else:
chosen_styles = self.get_default_style_url()
log_message = "Loading default Nitpick style"
log_message = "Using default remote Nitpick style"
logger.info(f"{log_message}: {chosen_styles}")

yield from self.include_multiple_styles(chosen_styles)
Expand Down
4 changes: 3 additions & 1 deletion src/nitpick/style/fetchers/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ def _do_fetch(self, url) -> str:
except requests.ConnectionError as err:
logger.exception(f"Request failed with {err}")
click.secho(
"Your network is unreachable. Fix your connection or use"
f"The URL {url} could not be downloaded. Either your network is unreachable or the URL is broken."
f" Check the URL, fix your connection, or use "
f" {OptionEnum.OFFLINE.as_flake8_flag()} / {OptionEnum.OFFLINE.as_envvar()}=1",
fg="red",
err=True,
Expand All @@ -44,6 +45,7 @@ def _do_fetch(self, url) -> str:
return contents

def _download(self, url) -> str:
logger.info(f"Downloading style from {url}")
response = self._session.get(url)
response.raise_for_status()
return response.text
2 changes: 1 addition & 1 deletion src/nitpick/violations.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,5 +144,5 @@ def get_counts(cls) -> str:
if cls.manual:
parts.append(f"❌ {cls.manual} to change manually")
if not parts:
return "🎖 No violations found."
return "No violations found. ✨ 🍰 ✨"
return f"Violations: {', '.join(parts)}."
26 changes: 18 additions & 8 deletions tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,34 +315,39 @@ def assert_violations(self, *expected_violations: Fuss, disclaimer="") -> "Proje
compare(expected=manual, actual=Reporter.manual)
return self

def _simulate_cli(self, command: str, str_or_lines: StrOrList = None, *args: str, exit_code: int = None):
def _simulate_cli(self, command: str, expected_str_or_lines: StrOrList = None, *args: str, exit_code: int = None):
result = CliRunner().invoke(nitpick_cli, ["--project", str(self.root_dir), command, *args])
actual: List[str] = result.output.splitlines()

if isinstance(str_or_lines, str):
expected = dedent(str_or_lines).strip().splitlines()
if isinstance(expected_str_or_lines, str):
expected = dedent(expected_str_or_lines).strip().splitlines()
else:
expected = list(always_iterable(str_or_lines))
expected = list(always_iterable(expected_str_or_lines))

compare(actual=result.exit_code, expected=exit_code or 0)

return result, actual, expected

def cli_run(
self, str_or_lines: StrOrList = None, apply=False, violations=0, exception_class=None, exit_code: int = None
self,
expected_str_or_lines: StrOrList = None,
apply=False,
violations=0,
exception_class=None,
exit_code: int = None,
) -> "ProjectMock":
"""Assert the expected CLI output for the chosen command."""
cli_args = [] if apply else ["--check"]
if exit_code is None:
exit_code = 1 if str_or_lines else 0
result, actual, expected = self._simulate_cli("run", str_or_lines, *cli_args, exit_code=exit_code)
exit_code = 1 if expected_str_or_lines else 0
result, actual, expected = self._simulate_cli("run", expected_str_or_lines, *cli_args, exit_code=exit_code)
if exception_class:
assert isinstance(result.exception, exception_class)
return self

if violations:
expected.append(f"Violations: ❌ {violations} to change manually.")
elif str_or_lines:
elif expected_str_or_lines:
# If the number of violations was not passed but a list of errors was,
# remove the violation count from the actual results.
# This is useful when checking only if the error is contained in a list of errors,
Expand All @@ -351,6 +356,11 @@ def cli_run(
if actual[-1].startswith("Violations"):
del actual[-1]

if not violations and not expected_str_or_lines:
# Remove the "no violations" message
if actual[-1].startswith("No violations"):
del actual[-1]

compare(actual=actual, expected=expected)
return self

Expand Down
5 changes: 4 additions & 1 deletion tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,7 @@ def test_offline_recommend_using_flag(tmp_path, capsys):
ProjectMock(tmp_path).flake8()
out, err = capsys.readouterr()
assert out == ""
assert err == "Your network is unreachable. Fix your connection or use --nitpick-offline / NITPICK_OFFLINE=1\n"
assert (
"could not be downloaded. Either your network is unreachable or the URL is broken."
" Check the URL, fix your connection, or use --nitpick-offline / NITPICK_OFFLINE=1" in err
)
2 changes: 1 addition & 1 deletion tests/test_violations.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def test_reporter():
reporter.reset()
assert reporter.manual == 0
assert reporter.fixed == 0
assert reporter.get_counts() == "🎖 No violations found."
assert reporter.get_counts() == "No violations found. ✨ 🍰 ✨"

reporter.increment()
assert reporter.manual == 1
Expand Down

0 comments on commit 2fedd0a

Please sign in to comment.