-- -- --- --- --- --- --- --- ------- ------- ------- |
"""
-- -- --- --- --- --- --- --- ------- ------- ------- |
Diff command.
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
Compares metrics between uncommitted files and indexed files.
-- -- --- --- --- --- --- --- ------- ------- ------- |
"""
-- -- --- --- --- --- --- --- ------- ------- ------- |
import multiprocessing
-- -- --- --- --- --- --- --- ------- ------- ------- |
import tabulate
-- -- --- --- --- --- --- --- ------- ------- ------- |
from pathlib import Path
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily import logger
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.config import DEFAULT_GRID_STYLE, DEFAULT_PATH
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.operators import (
-- -- --- --- --- --- --- --- ------- ------- ------- |
resolve_metric,
-- -- --- --- --- --- --- --- ------- ------- ------- |
resolve_operator,
-- -- --- --- --- --- --- --- ------- ------- ------- |
get_metric,
-- -- --- --- --- --- --- --- ------- ------- ------- |
GOOD_COLORS,
-- -- --- --- --- --- --- --- ------- ------- ------- |
BAD_COLORS,
-- -- --- --- --- --- --- --- ------- ------- ------- |
OperatorLevel,
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.commands.build import run_operator
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.state import State
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
def diff(config, files, metrics, changes_only=True, detail=True):
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
"""
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
Show the differences in metrics for each of the files.
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
:param config: The wily configuration
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
:type config: :namedtuple:`wily.config.WilyConfig`
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
:param files: The files to compare.
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
:type files: ``list`` of ``str``
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
:param metrics: The metrics to measure.
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
:type metrics: ``list`` of ``str``
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
:param changes_only: Only include changes files in output.
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
:type changes_only: ``bool``
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
:param detail: Show details (function-level)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
:type detail: ``bool``
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
"""
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
config.targets = files
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
files = list(files)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
state = State(config)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
# Resolve target paths when the cli has specified --path
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
if config.path != DEFAULT_PATH:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
targets = [str(Path(config.path) / Path(file)) for file in files]
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
else:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
targets = files
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
last_revision = state.index[state.default_archiver].last_revision
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
# Convert the list of metrics to a list of metric instances
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
operators = {resolve_operator(metric.split(".")[0]) for metric in metrics}
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
metrics = [(metric.split(".")[0], resolve_metric(metric)) for metric in metrics]
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
results = []
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
# Build a set of operators
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
with multiprocessing.Pool(processes=len(operators)) as pool:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
operator_exec_out = pool.starmap(
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
run_operator,
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
[(operator, None, config, targets) for operator in operators],
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
data = {}
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
for operator_name, result in operator_exec_out:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
data[operator_name] = result
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
# Write a summary table
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
extra = []
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
for operator, metric in metrics:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
if detail and resolve_operator(operator).level == OperatorLevel.Object:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
for file in files:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
try:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
extra.extend(
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
[
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
f"{file}:{k}"
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
for k in data[operator][file]["detailed"].keys()
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
if k != metric.name
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
and isinstance(data[operator][file]["detailed"][k], dict)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
]
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
except KeyError:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
logger.debug(f"File {file} not in cache")
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
logger.debug("Cache follows -- ")
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
logger.debug(data[operator])
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
files.extend(extra)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
logger.debug(files)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
for file in files:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
metrics_data = []
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
has_changes = False
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
for operator, metric in metrics:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
try:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
current = last_revision.get(
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
config, state.default_archiver, operator, file, metric.name
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
except KeyError:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
current = "-"
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
try:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
new = get_metric(data, operator, file, metric.name)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
except KeyError:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
new = "-"
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
if new != current:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
has_changes = True
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
if metric.type in (int, float) and new != "-" and current != "-":
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
if current > new:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
metrics_data.append(
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
"{0:n} -> \u001b[{2}m{1:n}\u001b[0m".format(
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
current, new, BAD_COLORS[metric.measure]
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
elif current < new:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
metrics_data.append(
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
"{0:n} -> \u001b[{2}m{1:n}\u001b[0m".format(
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
current, new, GOOD_COLORS[metric.measure]
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
else:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
metrics_data.append("{0:n} -> {1:n}".format(current, new))
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
else:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
if current == "-" and new == "-":
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
metrics_data.append("-")
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
else:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
metrics_data.append("{0} -> {1}".format(current, new))
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
if has_changes or not changes_only:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
results.append((file, *metrics_data))
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
else:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
logger.debug(metrics_data)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
descriptions = [metric.description for operator, metric in metrics]
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
headers = ("File", *descriptions)
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
if len(results) > 0:
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
print(
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
# But it still makes more sense to show the newest at the top, so reverse again
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
tabulate.tabulate(
-- 31 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
headers=headers, tabular_data=results, tablefmt=DEFAULT_GRID_STYLE
-- -- 009 027 019 038 036 057 0294.69 1866.34 0006.33 |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
)