Skip to content

Commit

Permalink
Merge pull request #221 from trailofbits/plurals
Browse files Browse the repository at this point in the history
Handle plurals correctly in output
  • Loading branch information
di committed Jan 14, 2022
2 parents ebe7381 + cd5a7d2 commit 2a1e89e
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 7 deletions.
30 changes: 23 additions & 7 deletions pip_audit/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,7 @@ def _fatal(msg: str) -> NoReturn:
sys.exit(1)


def audit() -> None:
"""
The primary entrypoint for `pip-audit`.
"""
def _parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
prog="pip-audit",
description="audit the Python environment for dependencies with known vulnerabilities",
Expand Down Expand Up @@ -241,8 +238,20 @@ def audit() -> None:
action="store_true",
help="automatically upgrade dependencies with known vulnerabilities",
)
return parser


def _parse_args(parser: argparse.ArgumentParser) -> argparse.Namespace:
return parser.parse_args()


def audit() -> None:
"""
The primary entrypoint for `pip-audit`.
"""
parser = _parser()
args = _parse_args(parser)

args = parser.parse_args()
if args.verbose:
logging.root.setLevel("DEBUG")

Expand Down Expand Up @@ -307,10 +316,17 @@ def audit() -> None:
# TODO(ww): Refine this: we should always output if our output format is an SBOM
# or other manifest format (like the default JSON format).
if vuln_count > 0:
summary_msg = f"Found {vuln_count} known vulnerabilities in {pkg_count} packages"
summary_msg = (
f"Found {vuln_count} known "
f"{'vulnerability' if vuln_count == 1 else 'vulnerabilities'} "
f"in {pkg_count} {'package' if pkg_count == 1 else 'packages'}"
)
if args.fix:
summary_msg += (
f" and fixed {fixed_vuln_count} vulnerabilities in {fixed_pkg_count} packages"
f" and fixed {fixed_vuln_count} "
f"{'vulnerability' if fixed_vuln_count == 1 else 'vulnerabilities'} "
f"in {fixed_pkg_count} "
f"{'package' if fixed_pkg_count == 1 else 'packages'}"
)
print(summary_msg, file=sys.stderr)
print(formatter.format(result))
Expand Down
50 changes: 50 additions & 0 deletions test/test_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import pretend # type: ignore
import pytest

import pip_audit._cli


@pytest.mark.parametrize(
"args, vuln_count, pkg_count, expected",
[
([], 1, 1, "Found 1 known vulnerability in 1 package"),
([], 2, 1, "Found 2 known vulnerabilities in 1 package"),
([], 2, 2, "Found 2 known vulnerabilities in 2 packages"),
(["--fix"], 1, 1, "fixed 1 vulnerability in 1 package"),
(["--fix"], 2, 1, "fixed 2 vulnerabilities in 1 package"),
(["--fix"], 2, 2, "fixed 2 vulnerabilities in 2 packages"),
],
)
def test_plurals(capsys, monkeypatch, args, vuln_count, pkg_count, expected):
dummysource = pretend.stub(fix=lambda a: None)
monkeypatch.setattr(pip_audit._cli, "PipSource", lambda *a, **kw: dummysource)

parser = pip_audit._cli._parser()
monkeypatch.setattr(pip_audit._cli, "_parse_args", lambda x: parser.parse_args(args))

result = [
(
pretend.stub(
is_skipped=lambda: False,
name="something" + str(i),
canonical_name="something" + str(i),
version=1,
),
[pretend.stub(fix_versions=[2], id="foo")] * (vuln_count // pkg_count),
)
for i in range(pkg_count)
]

auditor = pretend.stub(audit=lambda a: result)
monkeypatch.setattr(pip_audit._cli, "Auditor", lambda *a, **kw: auditor)

resolve_fix_versions = [pretend.stub(is_skipped=lambda: False, dep=spec) for spec, _ in result]
monkeypatch.setattr(pip_audit._cli, "resolve_fix_versions", lambda *a: resolve_fix_versions)

try:
pip_audit._cli.audit()
except SystemExit:
pass

captured = capsys.readouterr()
assert expected in captured.err

0 comments on commit 2a1e89e

Please sign in to comment.