-- -- --- --- --- --- --- --- ------- ------- ------- |
"""
-- -- --- --- --- --- --- --- ------- ------- ------- |
Rank command.
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
The report command gives a table of files sorted according their ranking scheme
-- -- --- --- --- --- --- --- ------- ------- ------- |
of a specified metric.
-- -- --- --- --- --- --- --- ------- ------- ------- |
Will compare the values between files and return a sorted table.
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
TODO: Layer on Click invocation in operators section, __main__.py file
-- -- --- --- --- --- --- --- ------- ------- ------- |
"""
-- -- --- --- --- --- --- --- ------- ------- ------- |
import operator as op
-- -- --- --- --- --- --- --- ------- ------- ------- |
import os
-- -- --- --- --- --- --- --- ------- ------- ------- |
from pathlib import Path
-- -- --- --- --- --- --- --- ------- ------- ------- |
from sys import exit
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
import radon.cli.harvest
-- -- --- --- --- --- --- --- ------- ------- ------- |
import tabulate
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily import format_date, format_revision, logger
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.archivers import resolve_archiver
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.config import DEFAULT_PATH, WilyConfig
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.helper import get_maxcolwidth, get_style
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.operators import resolve_metric_as_tuple
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.state import State
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
def rank(
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
config: WilyConfig,
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
path: str,
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
metric: str,
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
revision_index: str,
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
limit: int,
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
threshold: int,
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
descending: bool,
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
wrap: bool,
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
) -> None:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
"""
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
Rank command ordering files, methods or functions using metrics.
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
:param config: The configuration.
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
:param path: The path to the file.
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
:param metric: Name of the metric to report on.
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
:param revision_index: Version of git repository to revert to.
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
:param limit: Limit the number of items in the table.
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
:param threshold: For total values beneath the threshold return a non-zero exit code.
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
:param descending: Rank in descending order
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
:param wrap: Wrap output
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
:return: Sorted table of all files in path, sorted in order of metric.
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
"""
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
logger.debug("Running rank command")
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
data = []
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
operator, resolved_metric = resolve_metric_as_tuple(metric)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
operator = operator.name
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
state = State(config)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
if not revision_index:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
target_revision = state.index[state.default_archiver].last_revision
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
else:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
rev = (
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
resolve_archiver(state.default_archiver)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
.archiver_cls(config)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
.find(revision_index)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
logger.debug(f"Resolved {revision_index} to {rev.key} ({rev.message})")
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
try:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
target_revision = state.index[state.default_archiver][rev.key]
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
except KeyError:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
logger.error(
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
f"Revision {revision_index} is not in the cache, make sure you have run wily build."
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
exit(1)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
logger.info(
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
f"-----------Rank for {resolved_metric.description} for {format_revision(target_revision.revision.key)} by {target_revision.revision.author_name} on {format_date(target_revision.revision.date)}.------------"
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
if path is None:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
files = target_revision.get_paths(config, state.default_archiver, operator)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
logger.debug(f"Analysing {files}")
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
else:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
# Resolve target paths when the cli has specified --path
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
if config.path != DEFAULT_PATH:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
targets = [str(Path(config.path) / Path(path))]
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
else:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
targets = [path]
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
# Expand directories to paths
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
files = [
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
os.path.relpath(fn, config.path)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
for fn in radon.cli.harvest.iter_filenames(targets)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
]
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
logger.debug(f"Targeting - {files}")
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
for item in files:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
for archiver in state.archivers:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
try:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
logger.debug(
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
f"Fetching metric {resolved_metric.name} for {operator} in {str(item)}"
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
val = target_revision.get(
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
config, archiver, operator, str(item), resolved_metric.name
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
value = val
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
data.append((item, value))
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
except KeyError:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
logger.debug(f"Could not find file {item} in index")
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
# Sort by ideal value
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
data = sorted(data, key=op.itemgetter(1), reverse=descending)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
if limit:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
data = data[:limit]
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
if not data:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
return
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
# Tack on the total row at the end
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
total = resolved_metric.aggregate(rev[1] for rev in data)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
data.append(["Total", total])
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
headers = ("File", resolved_metric.description)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
maxcolwidth = get_maxcolwidth(headers, wrap)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
style = get_style()
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
print(
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
tabulate.tabulate(
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
headers=headers,
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
tabular_data=data,
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
tablefmt=style,
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
maxcolwidths=maxcolwidth,
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
maxheadercolwidths=maxcolwidth,
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
if threshold and total < threshold:
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
logger.error(
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
f"Total value below the specified threshold: {total} < {threshold}"
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
)
-- 14 006 010 007 012 016 019 0076.00 0273.60 0003.60 |
exit(1)