Skip to content

Commit

Permalink
feat(cli): display violation count
Browse files Browse the repository at this point in the history
  • Loading branch information
andreoliwa committed Feb 6, 2021
1 parent e642069 commit fbd45f5
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 29 deletions.
6 changes: 2 additions & 4 deletions .editorconfig
Expand Up @@ -14,14 +14,12 @@ trim_trailing_whitespace=true

# Matches multiple files with brace expansion notation
# Set default charset
[*.{js,py}]
[*.{js,json,py}]
charset=utf-8
indent_size=2

[*.{yml,yaml}]
indent_size=2

[Makefile]
indent_style=tab

[*.rst]
indent_size=unset
14 changes: 5 additions & 9 deletions Makefile
Expand Up @@ -13,7 +13,7 @@ help:
@echo 'Run 'make -B' or 'make --always-make' to force a rebuild of all targets'
.PHONY: help

quick: pytest pre-commit # Run pytest and pre-commit fast, without tox
quick: pytest nitpick pre-commit pylint # Run pytest and pre-commit fast, without tox
.PHONY: quick

full-build: .remove-old-cache .cache/make/long-pre-commit .cache/make/long-poetry .cache/make/lint .cache/make/test .cache/make/doc # Build the project fully, like in CI
Expand All @@ -39,7 +39,7 @@ install: install-pre-commit install-poetry # Install pre-commit hooks and Poetry

# Poetry install is needed to create the Nitpick plugin entries on setuptools, used by pluggy
install-poetry .cache/make/long-poetry src/nitpick.egg-info/entry_points.txt: pyproject.toml # Install Poetry dependencies
poetry install
poetry install -E test -E lint
touch .cache/make/long-poetry
.PHONY: install-poetry

Expand Down Expand Up @@ -72,16 +72,12 @@ pre-commit: # Run pre-commit for all files
.PHONY: pre-commit

pylint: # Run pylint for all files
pre-commit run --all-files pylint
poetry run pylint src/
.PHONY: pylint

nitpick: # Run the nitpick pre-commit hook to check local style changes
pre-commit run --all-files nitpick-local
.PHONY: nitpick

flake8: # Run flake8 to check local style changes
nitpick: # Run Nitpick locally on itself (with flake8)
poetry run flake8 --select=NIP
.PHONY: flake8
.PHONY: nitpick

TOX_PYTHON_ENVS = $(shell tox -l | egrep '^py' | xargs echo | tr ' ' ',')

Expand Down
4 changes: 2 additions & 2 deletions docs/nitpick_section.rst
Expand Up @@ -14,8 +14,8 @@ Show an upgrade message to the developer if Nitpick's version is below ``minimum

.. code-block:: toml
[nitpick]
minimum_version = "0.10.0"
[nitpick]
minimum_version = "0.10.0"
[nitpick.files]
---------------
Expand Down
6 changes: 3 additions & 3 deletions docs/troubleshooting.rst
Expand Up @@ -12,13 +12,13 @@ On macOS, flake8_ might raise this error when calling ``requests.get(url)``:

.. code-block:: shell
objc[93329]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[93329]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
objc[93329]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[93329]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
To solve this issue, add this environment variable to ``.bashrc`` (or the initialization file for your favorite shell):

.. code-block:: shell
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
Thanks to `this StackOverflow answer <https://stackoverflow.com/questions/50168647/multiprocessing-causes-python-to-crash-and-gives-an-error-may-have-been-in-progr/52230415#52230415>`_.
2 changes: 2 additions & 0 deletions package.json
Expand Up @@ -51,6 +51,8 @@
2,
"always",
[
"cli",
"flake8",
"style",
"pre-commit",
"pyproject.toml",
Expand Down
4 changes: 2 additions & 2 deletions setup.cfg
Expand Up @@ -86,8 +86,8 @@ description = Run tests with pytest and coverage
deps = pytest-cov
extras = test
depends =
{py39,py38,py37,py36}: clean
report: py39,py38,py37,py36
{py39,py38,py37,py36}: clean
report: py39,py38,py37,py36
setenv =
PY_IGNORE_IMPORTMISMATCH = 1
commands =
Expand Down
12 changes: 7 additions & 5 deletions src/nitpick/cli.py
Expand Up @@ -6,9 +6,9 @@
problems: the code will get executed twice:
- When you run `python -mnitpick` python will execute ``__main__.py`` as a script.
That means there won't be any ``nitpick.__main__`` in ``sys.modules``.
That means there won't be any ``nitpick.__main__`` in ``sys.modules``.
- When you import __main__ it will get executed again (as a module) because
there's no ``nitpick.__main__`` in ``sys.modules``.
there's no ``nitpick.__main__`` in ``sys.modules``.
Also see (1) from http://click.pocoo.org/5/setuptools/#setuptools-integration
"""
Expand Down Expand Up @@ -89,11 +89,13 @@ def nitpick_cli(project_root: Path = None, offline=False, check=False, verbose=F
except ValueError:
pass

valid = True
violations = 0
for err in nit.run():
valid = False
violations += 1
click.echo(f"{path}{err.pretty}")

click.secho("All done! ✨ 🍰 ✨", fg="bright_white")
if not valid:
if violations:
plural = "s" if violations > 1 else ""
click.secho(f"{violations} violation{plural}.")
raise Exit(1)
11 changes: 9 additions & 2 deletions tests/helpers.py
Expand Up @@ -237,15 +237,22 @@ def assert_fusses_are_exactly(self, *args: Fuss) -> "ProjectMock":
compare(expected=set(args), actual=self._actual_fusses)
return self

def assert_cli_output(self, str_or_lines: StrOrList = None) -> "ProjectMock":
def assert_cli_output(self, str_or_lines: StrOrList = None, violations=0) -> "ProjectMock":
"""Assert the expected CLI output."""
result = CliRunner().invoke(nitpick_cli, ["--project", str(self.root_dir)])
actual: List[str] = result.output.splitlines()

if isinstance(str_or_lines, str):
expected_lines = dedent(str_or_lines).strip().splitlines()
else:
expected_lines = list(always_iterable(str_or_lines))
expected_lines.append("All done! ✨ 🍰 ✨")
if violations:
plural = "s" if violations > 1 else ""
expected_lines.append(f"{violations} violation{plural}.")
elif str_or_lines:
del actual[-1]

compare(actual=result.output.splitlines(), expected=expected_lines)
compare(actual=actual, expected=expected_lines)
compare(actual=result.exit_code, expected=(1 if str_or_lines else 0))
return self
2 changes: 1 addition & 1 deletion tests/test_config.py
Expand Up @@ -67,7 +67,7 @@ def test_at_least_one_python_file(python_file, error, request):
)
if error:
project.assert_single_error(
"NIP102 No Python file was found on the root dir and subdir of {!r}".format(str(project.root_dir))
f"NIP102 No Python file was found on the root dir and subdir of {str(project.root_dir)!r}"
)
else:
project.assert_no_errors()
Expand Down
6 changes: 5 additions & 1 deletion tests/test_pyproject_toml.py
Expand Up @@ -15,4 +15,8 @@ def test_suggest_initial_contents(request):
[nitpick.files.present]
"pyproject.toml" = "Do something"
"""
).simulate_run().assert_errors_contain(f"NIP103 File {PYPROJECT_TOML} should exist: Do something")
).simulate_run().assert_errors_contain(
f"NIP103 File {PYPROJECT_TOML} should exist: Do something"
).assert_cli_output(
f"{PYPROJECT_TOML}:1: NIP103 should exist: Do something", violations=1
)

0 comments on commit fbd45f5

Please sign in to comment.