wily\commands\graph.py
-- -- --- --- --- --- --- --- ------- ------- ------- | """
-- -- --- --- --- --- --- --- ------- ------- ------- | Draw graph in HTML for a specific metric.
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | TODO: Add multiple lines for multiple files
-- -- --- --- --- --- --- --- ------- ------- ------- | """
-- -- --- --- --- --- --- --- ------- ------- ------- | import pathlib
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | import plotly.graph_objs as go
-- -- --- --- --- --- --- --- ------- ------- ------- | import plotly.offline
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | from wily import logger, format_datetime
-- -- --- --- --- --- --- --- ------- ------- ------- | from wily.operators import resolve_metric, resolve_metric_as_tuple
-- -- --- --- --- --- --- --- ------- ------- ------- | from wily.state import State
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def metric_parts(metric):
-- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """Convert a metric name into the operator and metric names."""
-- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | operator, met = resolve_metric_as_tuple(metric)
-- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | return operator.name, met.name
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | def graph(config, path, metrics, output=None, x_axis=None, changes=True, text=False):
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | """
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | Graph information about the cache and runtime.
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 |
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | :param config: The configuration.
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | :type config: :class:`wily.config.WilyConfig`
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 |
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | :param path: The path to the files.
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | :type path: ``list``
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 |
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | :param metrics: The Y and Z-axis metrics to report on.
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | :type metrics: ``tuple``
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 |
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | :param output: Save report to specified path instead of opening browser.
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | :type output: ``str``
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | """
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | logger.debug("Running report command")
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 |
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | data = []
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | state = State(config)
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | abs_path = config.path / pathlib.Path(path)
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 |
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | if x_axis is None:
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | x_axis = "history"
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | else:
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | x_operator, x_key = metric_parts(x_axis)
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 |
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | if abs_path.is_dir():
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | paths = [
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | p.relative_to(config.path) for p in pathlib.Path(abs_path).glob("**/*.py")
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | ]
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | else:
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | paths = [path]
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 |
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | operator, key = metric_parts(metrics[0])
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | if len(metrics) == 1: # only y-axis
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | z_axis = None
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | else:
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | z_axis = resolve_metric(metrics[1])
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | z_operator, z_key = metric_parts(metrics[1])
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | for path in paths:
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | x = []
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | y = []
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | z = []
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | labels = []
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | last_y = None
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | for rev in state.index[state.default_archiver].revisions:
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | labels.append(f"{rev.revision.author_name} <br>{rev.revision.message}")
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | try:
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | val = rev.get(config, state.default_archiver, operator, str(path), key)
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | if val != last_y or not changes:
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | y.append(val)
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | if z_axis:
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | z.append(
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | rev.get(
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | config,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | state.default_archiver,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | z_operator,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | str(path),
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | z_key,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | )
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | )
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | if x_axis == "history":
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | x.append(format_datetime(rev.revision.date))
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | else:
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | x.append(
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | rev.get(
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | config,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | state.default_archiver,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | x_operator,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | str(path),
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | x_key,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | )
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | )
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | last_y = val
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | except KeyError:
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | # missing data
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | pass
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 |
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | # Create traces
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | trace = go.Scatter(
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | x=x,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | y=y,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | mode="lines+markers+text" if text else "lines+markers",
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | name=f"{path}",
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | ids=state.index[state.default_archiver].revision_keys,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | text=labels,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | marker=dict(
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | size=0 if z_axis is None else z,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | color=list(range(len(y))),
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | # colorscale='Viridis',
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | ),
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | xcalendar="gregorian",
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | hoveron="points+fills",
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | )
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | data.append(trace)
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | if output:
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | filename = output
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | auto_open = False
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | else:
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | filename = "wily-report.html"
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | auto_open = True
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | y_metric = resolve_metric(metrics[0])
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | title = f"{x_axis.capitalize()} of {y_metric.description} for {path}"
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | plotly.offline.plot(
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | {
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | "data": data,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | "layout": go.Layout(
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | title=title,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | xaxis={"title": x_axis},
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | yaxis={"title": y_metric.description},
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | ),
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | },
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | auto_open=auto_open,
-- 15 006 013 008 015 019 023 0097.70 0338.20 0003.46 | filename=filename,
-- -- 006 013 008 015 019 023 0097.70 0338.20 0003.46 | )