Skip to content

Commit

Permalink
Make use of rich for the progress bar (#863)
Browse files Browse the repository at this point in the history
The module rich has an excellent and versatile implementation of a
progress bar for Python code. Bandit has an existing custom progress
indicator.

This change makes use of rich for a more visually pleasing progress
bar and more informational by including metrics.

The down side is that this does add another dependency. But I
think it can be useful in the future when implementing multi-process
processing of source code since rich is well adapted for that.

https://github.com/Textualize/rich

Signed-off-by: Eric Brown <browne@vmware.com>
  • Loading branch information
ericwb committed Mar 25, 2022
1 parent 4d4358b commit af9f8dc
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 38 deletions.
3 changes: 0 additions & 3 deletions bandit/core/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
# default plugin name pattern
plugin_name_pattern = "*.py"

# default progress increment
progress_increment = 50

RANKING = ["UNDEFINED", "LOW", "MEDIUM", "HIGH"]
RANKING_VALUES = {"UNDEFINED": 1, "LOW": 3, "MEDIUM": 5, "HIGH": 10}
CRITERIA = [("SEVERITY", "UNDEFINED"), ("CONFIDENCE", "UNDEFINED")]
Expand Down
47 changes: 12 additions & 35 deletions bandit/core/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import tokenize
import traceback

from rich import progress

from bandit.core import constants as b_constants
from bandit.core import extension_loader
from bandit.core import issue
Expand All @@ -25,6 +27,7 @@
LOG = logging.getLogger(__name__)
NOSEC_COMMENT = re.compile(r"#\s*nosec:?\s*(?P<tests>[^#]+)?#?")
NOSEC_COMMENT_TESTS = re.compile(r"(?:(B\d+|[a-z_]+),?)+", re.IGNORECASE)
PROGRESS_THRESHOLD = 50


class BanditManager:
Expand Down Expand Up @@ -69,9 +72,6 @@ def __init__(
self.agg_type = agg_type
self.metrics = metrics.Metrics()
self.b_ts = b_test_set.BanditTestSet(config, profile)

# set the increment of after how many files to show progress
self.progress = b_constants.progress_increment
self.scores = []

def get_skipped(self):
Expand Down Expand Up @@ -263,19 +263,20 @@ def run_tests(self):
:return: -
"""
self._show_progress("%s [" % len(self.files_list))

# if we have problems with a file, we'll remove it from the files_list
# and add it to the skipped list instead
new_files_list = list(self.files_list)
if (
len(self.files_list) > PROGRESS_THRESHOLD
and LOG.getEffectiveLevel() <= logging.INFO
):
files = progress.track(self.files_list)
else:
files = self.files_list

for count, fname in enumerate(self.files_list):
for count, fname in enumerate(files):
LOG.debug("working on file : %s", fname)

if len(self.files_list) > self.progress:
# is it time to update the progress indicator?
if count % self.progress == 0:
self._show_progress("%s.. " % count, flush=True)
try:
if fname == "-":
open_fd = os.fdopen(sys.stdin.fileno(), "rb", 0)
Expand All @@ -291,32 +292,12 @@ def run_tests(self):
self.skipped.append((fname, e.strerror))
new_files_list.remove(fname)

self._show_progress("]\n", flush=True)

# reflect any files which may have been skipped
self.files_list = new_files_list

# do final aggregation of metrics
self.metrics.aggregate()

def _show_progress(self, message, flush=False):
"""Show progress on stderr
Write progress message to stderr, if number of files warrants it and
log level is high enough.
:param message: The message to write to stderr
:param flush: Whether to flush stderr after writing the message
:return:
"""
if (
len(self.files_list) > self.progress
and LOG.getEffectiveLevel() <= logging.INFO
):
sys.stderr.write(message)
if flush:
sys.stderr.flush()

def _parse_file(self, fname, fdata, new_files_list):
try:
# parse the current file
Expand All @@ -340,11 +321,7 @@ def _parse_file(self, fname, fdata, new_files_list):
pass
score = self._execute_ast_visitor(fname, fdata, data, nosec_lines)
self.scores.append(score)
self.metrics.count_issues(
[
score,
]
)
self.metrics.count_issues([score])
except KeyboardInterrupt:
sys.exit(2)
except SyntaxError:
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ GitPython>=1.0.1 # BSD License (3 clause)
PyYAML>=5.3.1 # MIT
stevedore>=1.20.0 # Apache-2.0
colorama>=0.3.9;platform_system=="Windows" # BSD License (3 clause)
rich # MIT

0 comments on commit af9f8dc

Please sign in to comment.