wily\commands\rank.py
-- -- --- --- --- --- --- --- ------- ------- ------- | """
-- -- --- --- --- --- --- --- ------- ------- ------- | 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: Refactor individual file work into a separate function
-- -- --- --- --- --- --- --- ------- ------- ------- | TODO: Layer on Click invocation in operators section, __main__.py file
-- -- --- --- --- --- --- --- ------- ------- ------- | TODO: Is the a better way to retrieve the revision number than via index?
-- -- --- --- --- --- --- --- ------- ------- ------- | """
-- -- --- --- --- --- --- --- ------- ------- ------- | import tabulate
-- -- --- --- --- --- --- --- ------- ------- ------- | import operator as op
-- -- --- --- --- --- --- --- ------- ------- ------- | from pathlib import Path
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | from wily import logger, format_date, format_revision, MAX_MESSAGE_WIDTH
-- -- --- --- --- --- --- --- ------- ------- ------- | from wily.config import DEFAULT_GRID_STYLE
-- -- --- --- --- --- --- --- ------- ------- ------- | from wily.operators import resolve_metric, MetricType
-- -- --- --- --- --- --- --- ------- ------- ------- | from wily.state import State
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def aggregate_metric(metric_table: list):
-- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
-- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Aggregate/total wily metrics in a tabular format.
-- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
-- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Data is assumed to be in the tabular format of the rank function within the rank.py
-- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | command.
-- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
-- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | :param metric_table: table with list of wily metrics across multiple files.
-- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | :type metric_table: ''list''
-- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
-- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | :return: Sorted table of all files in path, sorted in order of metric.
-- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
-- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | # value in first draft is assumed to be the fifth item in the list.
-- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | return ["Total", "---", "---", "---", sum(float(rev[4]) for rev in metric_table)]
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | def rank(config, path, metric, revision_index):
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | """
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | Rank command ordering files, methods or functions using metrics.
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 |
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | :param config: The configuration
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | :type config: :class:'wily.config.WilyConfig'
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 |
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | :param path: The path to the file
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | :type path ''str''
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 |
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | :param metric: Name of the metric to report on
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | :type metric: ''str''
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 |
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | :param revision_index: Version of git repository to revert to.
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | :type revision_index: ''int''
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 |
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | :return: Sorted table of all files in path, sorted in order of metric.
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | """
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | logger.debug("Running rank command")
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | logger.info(f"-----------Rank for {metric}------------")
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 |
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | data = []
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 |
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | operator, key = metric.split(".")
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | metric = resolve_metric(metric)
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | metric_meta = {
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | "key": key,
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | "operator": operator,
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | "title": metric.description,
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | "type": metric.type,
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | "wily_metric_type": metric.measure.name, # AimHigh, AimLow, Informational
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | }
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 |
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | # Assumption is there is only one metric (e.g., therefore list of metrics commented out)
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | pth = Path(path)
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | if not str(pth).endswith(".py"):
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | items = pth.glob("**/*.py")
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | else:
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | items = [pth]
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | for item in items:
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | state = State(config)
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | for archiver in state.archivers:
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | # Last revision in the list is the first item (ordered Newest to Oldest => 0 to -1 index.
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | rev = state.index[archiver].revisions[revision_index]
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | try:
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | logger.debug(
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | f"Fetching metric {metric_meta['key']} for {metric_meta['operator']} in {str(item)}"
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | )
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | val = rev.get(
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | config,
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | archiver,
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | metric_meta["operator"],
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | str(item),
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | metric_meta["key"],
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | )
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | value = str(val)
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | except KeyError as e:
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | value = f"Not found {e}"
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | # Assumption is there is only one metric (e.g., value versus val* as in report.py command
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | data.append(
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | (
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | item,
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | format_revision(rev.revision.key),
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | rev.revision.author_name,
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | format_date(rev.revision.date),
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | value,
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | )
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | )
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | # before moving towards the print tabular data - the values are sorted according to the metric type
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | # The "value" is assumed to be the fourth item in an individual data row. An alternative that may
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | # be more readable is the op.attrgetter.
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | if metric_meta["wily_metric_type"] == "AimHigh":
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | # AimHigh is sorted lowest to highest
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | data.sort(key=op.itemgetter(4))
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | elif metric_meta["wily_metric_type"] == "AimLow":
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | # AimLow is sorted highest to lowest
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | data.sort(key=op.itemgetter(4), reverse=True)
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | # Tack on the total row at the end
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | data.append(aggregate_metric(data))
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 |
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | headers = ("File", "Revision", "Author", "Date", metric_meta["title"])
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | print(
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | tabulate.tabulate(
-- 07 002 005 003 005 007 008 0022.46 0022.46 0001.00 | headers=headers, tabular_data=data, tablefmt=DEFAULT_GRID_STYLE
-- -- 002 005 003 005 007 008 0022.46 0022.46 0001.00 | )
-- -- --- --- --- --- --- --- ------- ------- ------- | )