-- -- --- --- --- --- --- --- ------- ------- ------- |
"""Main command line."""
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
import traceback
-- -- --- --- --- --- --- --- ------- ------- ------- |
from pathlib import Path
-- -- --- --- --- --- --- --- ------- ------- ------- |
from sys import exit
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
import click
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily import WILY_LOG_NAME, __version__, logger
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.archivers import resolve_archiver
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.cache import exists, get_default_metrics
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.config import load as load_config
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.defaults import DEFAULT_CONFIG_PATH, DEFAULT_GRID_STYLE
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.helper import get_style
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.helper.custom_enums import ReportFormat
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.lang import _
-- -- --- --- --- --- --- --- ------- ------- ------- |
from wily.operators import resolve_operators
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
version_text = _("Version: ") + __version__ + "\n\n"
-- -- --- --- --- --- --- --- ------- ------- ------- |
help_header = version_text + _(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"""\U0001F98A Inspect and search through the complexity of your source code.
-- -- --- --- --- --- --- --- ------- ------- ------- |
To get started, run setup:
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
$ wily setup
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
To reindex any changes in your source code:
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
$ wily build <src>
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
Then explore basic metrics with:
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
$ wily report <file>
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
You can also graph specific metrics in a browser with:
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
$ wily graph <file> <metric>
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
"""
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.group(help=help_header)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.version_option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
__version__,
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-V",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--version",
-- -- --- --- --- --- --- --- ------- ------- ------- |
message="\U0001F98A %(prog)s, {version} %(version)s".format(version=_("version")),
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Show the version and exit."),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.help_option(help=_("Show this message and exit."))
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--debug/--no-debug",
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=False,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Print debug information, used for development"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--config",
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=DEFAULT_CONFIG_PATH,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Path to configuration file, defaults to wily.cfg"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-p",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--path",
-- -- --- --- --- --- --- --- ------- ------- ------- |
type=click.Path(resolve_path=True),
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=".",
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Root path to the project folder to scan"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-c",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--cache",
-- -- --- --- --- --- --- --- ------- ------- ------- |
type=click.Path(resolve_path=True),
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Override the default cache path (defaults to $HOME/.wily/HASH)"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.pass_context
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
def cli(ctx, debug, config, path, cache):
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
"""CLI entry point."""
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
ctx.ensure_object(dict)
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
ctx.obj["DEBUG"] = debug
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
if debug:
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
logger.setLevel("DEBUG")
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
else:
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
logger.setLevel("INFO")
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
ctx.obj["CONFIG"] = load_config(config)
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
if path:
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
logger.debug(f"Fixing path to {path}")
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
ctx.obj["CONFIG"].path = path
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
if cache:
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
logger.debug(f"Fixing cache to {cache}")
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
ctx.obj["CONFIG"].cache_path = cache
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
logger.debug(f"Loaded configuration from {config}")
-- 04 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
logger.debug(f"Capturing logs to {WILY_LOG_NAME}")
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
@cli.command(help=_("""Build the wily cache."""))
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-n",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--max-revisions",
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=None,
-- -- --- --- --- --- --- --- ------- ------- ------- |
type=click.INT,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("The maximum number of historical commits to archive"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.argument("targets", type=click.Path(resolve_path=True), nargs=-1, required=False)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-o",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--operators",
-- -- --- --- --- --- --- --- ------- ------- ------- |
type=click.STRING,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("List of operators, separated by commas"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-a",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--archiver",
-- -- --- --- --- --- --- --- ------- ------- ------- |
type=click.STRING,
-- -- --- --- --- --- --- --- ------- ------- ------- |
default="git",
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Archiver to use, defaults to git if git repo, else filesystem"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.pass_context
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
def build(ctx, max_revisions, targets, operators, archiver):
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
"""Build the wily cache."""
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
config = ctx.obj["CONFIG"]
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
from wily.commands.build import build
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
if max_revisions:
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
logger.debug(f"Fixing revisions to {max_revisions}")
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
config.max_revisions = max_revisions
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
if operators:
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
logger.debug(f"Fixing operators to {operators}")
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
config.operators = operators.strip().split(",")
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
if archiver:
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
logger.debug(f"Fixing archiver to {archiver}")
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
config.archiver = archiver
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
if targets:
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
logger.debug(f"Fixing targets to {targets}")
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
config.targets = targets
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
build(
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
config=config,
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
archiver=resolve_archiver(config.archiver),
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
operators=resolve_operators(config.operators),
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
)
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
logger.info(
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
_(
-- 05 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
"Completed building wily history, run `wily report <file>` or `wily index` to see more."
-- -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
)
-- -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
@cli.command(help=_("""Show the history archive in the .wily/ folder."""))
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.pass_context
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-m", "--message/--no-message", default=False, help=_("Include revision message")
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-w",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--wrap/--no-wrap",
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=True,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Wrap index text to fit in terminal"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
def index(ctx, message, wrap):
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
"""Show the history archive in the .wily/ folder."""
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
config = ctx.obj["CONFIG"]
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
if not exists(config):
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
handle_no_cache(ctx)
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
from wily.commands.index import index
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
index(config=config, include_message=message, wrap=wrap)
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
@cli.command(
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"""
-- -- --- --- --- --- --- --- ------- ------- ------- |
Rank files, methods and functions in order of any metrics, e.g. complexity.
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
Some common examples:
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
Rank all .py files within src/ for the maintainability.mi metric
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
$ wily rank src/ maintainability.mi
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
Rank all .py files in the index for the default metrics across all archivers
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
$ wily rank
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
Rank all .py files in the index for the default metrics across all archivers
-- -- --- --- --- --- --- --- ------- ------- ------- |
and return a non-zero exit code if the total is below the given threshold
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
$ wily rank --threshold=80
-- -- --- --- --- --- --- --- ------- ------- ------- |
"""
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.argument("path", type=click.Path(resolve_path=False), required=False)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.argument("metric", required=False, default="maintainability.mi")
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-r", "--revision", help=_("Compare against specific revision"), type=click.STRING
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-l", "--limit", help=_("Limit the number of results shown"), type=click.INT
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--desc/--asc",
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Order to show results (ascending or descending)"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=False,
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--threshold",
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Return a non-zero exit code under the specified threshold"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
type=click.INT,
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-w",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--wrap/--no-wrap",
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=True,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Wrap rank text to fit in terminal"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.pass_context
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
def rank(ctx, path, metric, revision, limit, desc, threshold, wrap):
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
"""Rank files, methods and functions in order of any metrics, e.g. complexity."""
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
config = ctx.obj["CONFIG"]
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
if not exists(config):
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
handle_no_cache(ctx)
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
from wily.commands.rank import rank
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
logger.debug(f"Running rank on {path} for metric {metric} and revision {revision}")
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
rank(
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
config=config,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
path=path,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
metric=metric,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
revision_index=revision,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
limit=limit,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
threshold=threshold,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
descending=desc,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
wrap=wrap,
-- -- 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
@cli.command(help=_("""Show metrics for a given file."""))
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.argument("file", type=click.Path(resolve_path=False))
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.argument("metrics", nargs=-1, required=False)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option("-n", "--number", help="Number of items to show", type=click.INT)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-m", "--message/--no-message", default=False, help=_("Include revision message")
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-f",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--format",
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=ReportFormat.CONSOLE.name,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Specify report format (console or html)"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
type=click.Choice(ReportFormat.get_all()),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--console-format",
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=DEFAULT_GRID_STYLE,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"Style for the console grid, see Tabulate Documentation for a list of styles."
-- -- --- --- --- --- --- --- ------- ------- ------- |
),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-o",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--output",
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Output report to specified HTML path, e.g. reports/out.html"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-c",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--changes/--all",
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=False,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Only show revisions that have changes"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-w",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--wrap/--no-wrap",
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=True,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Wrap report text to fit in terminal"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.pass_context
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
def report(
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
ctx, file, metrics, number, message, format, console_format, output, changes, wrap
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
):
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
"""Show metrics for a given file."""
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
config = ctx.obj["CONFIG"]
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
if not exists(config):
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
handle_no_cache(ctx)
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
if not metrics:
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
metrics = get_default_metrics(config)
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
logger.info(f"Using default metrics {metrics}")
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
new_output = Path().cwd()
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
if output:
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
new_output = new_output / Path(output)
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
else:
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
new_output = new_output / "wily_report" / "index.html"
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
style = get_style(console_format)
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
from wily.commands.report import report
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
logger.debug(f"Running report on {file} for metric {metrics}")
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
logger.debug(f"Output format is {format}")
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
report(
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
config=config,
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
path=file,
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
metrics=metrics,
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
n=number,
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
output=new_output,
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
include_message=message,
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
format=ReportFormat[format],
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
console_format=style,
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
changes_only=changes,
-- 04 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
wrap=wrap,
-- -- 002 007 005 008 009 013 0041.21 0047.10 0001.14 |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
@cli.command(help=_("""Show the differences in metrics for each file."""))
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.argument("files", type=click.Path(resolve_path=False), nargs=-1, required=True)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-m",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--metrics",
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=None,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("comma-separated list of metrics, see list-metrics for choices"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-a/-c",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--all/--changes-only",
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=False,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Show all files, instead of changes only"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--detail/--no-detail",
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=True,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Show function/class level metrics where available"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-r", "--revision", help=_("Compare against specific revision"), type=click.STRING
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-w",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--wrap/--no-wrap",
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=True,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Wrap diff text to fit in terminal"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.pass_context
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
def diff(ctx, files, metrics, all, detail, revision, wrap):
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
"""Show the differences in metrics for each file."""
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
config = ctx.obj["CONFIG"]
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
if not exists(config):
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
handle_no_cache(ctx)
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
if not metrics:
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
metrics = get_default_metrics(config)
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
logger.info(f"Using default metrics {metrics}")
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
else:
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
metrics = metrics.split(",")
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
logger.info(f"Using specified metrics {metrics}")
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
from wily.commands.diff import diff
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
logger.debug(f"Running diff on {files} for metric {metrics}")
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
diff(
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
config=config,
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
files=files,
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
metrics=metrics,
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
changes_only=not all,
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
detail=detail,
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
revision=revision,
-- 03 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
wrap=wrap,
-- -- 001 003 003 003 004 006 0012.00 0006.00 0000.50 |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
@cli.command(
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"""
-- -- --- --- --- --- --- --- ------- ------- ------- |
Graph a specific metric for a given file, if a path is given, all files within path will be graphed.
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
Some common examples:
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
Graph all .py files within src/ for the raw.loc metric
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
$ wily graph src/ raw.loc
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
Graph test.py against raw.loc and cyclomatic.complexity metrics
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
$ wily graph src/test.py raw.loc cyclomatic.complexity
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
Graph test.py against raw.loc and raw.sloc on the x-axis
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
$ wily graph src/test.py raw.loc --x-axis raw.sloc
-- -- --- --- --- --- --- --- ------- ------- ------- |
"""
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.argument("path", type=click.Path(resolve_path=False))
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.argument("metrics", nargs=-1, required=True)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-o",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--output",
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Output report to specified HTML path, e.g. reports/out.html"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option("-x", "--x-axis", help=_("Metric to use on x-axis, defaults to history."))
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-a/-c", "--changes/--all", default=True, help=_("All commits or changes only")
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-s/-i",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--aggregate/--individual",
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=False,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Aggregate if path is directory"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.pass_context
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
def graph(ctx, path, metrics, output, x_axis, changes, aggregate):
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
"""Output report to specified HTML path, e.g. reports/out.html."""
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
config = ctx.obj["CONFIG"]
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
if not exists(config):
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
handle_no_cache(ctx)
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
from wily.commands.graph import graph
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
logger.debug(f"Running report on {path} for metrics {metrics}")
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
graph(
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
config=config,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
path=path,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
metrics=metrics,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
output=output,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
x_axis=x_axis,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
changes=changes,
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
aggregate=aggregate,
-- -- 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
@cli.command(help=_("""Clear the .wily/ folder."""))
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option("-y/-p", "--yes/--prompt", default=False, help=_("Skip prompt"))
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.pass_context
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
def clean(ctx, yes):
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
"""Clear the .wily/ folder."""
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
config = ctx.obj["CONFIG"]
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
if not exists(config):
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
logger.info(_("Wily cache does not exist, nothing to remove."))
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
exit(0)
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
if not yes:
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
p = input(_("Are you sure you want to delete wily cache? [y/N]"))
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
if p.lower() != "y":
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
exit(0)
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
from wily.cache import clean
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
-- 04 002 004 003 004 006 007 0018.09 0018.09 0001.00 |
clean(config)
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
@cli.command("list-metrics", help=_("""List the available metrics."""))
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.option(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"-w",
-- -- --- --- --- --- --- --- ------- ------- ------- |
"--wrap/--no-wrap",
-- -- --- --- --- --- --- --- ------- ------- ------- |
default=True,
-- -- --- --- --- --- --- --- ------- ------- ------- |
help=_("Wrap metrics text to fit in terminal"),
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.pass_context
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
def list_metrics(ctx, wrap):
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
"""List the available metrics."""
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
config = ctx.obj["CONFIG"]
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
if not exists(config):
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
handle_no_cache(ctx)
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
from wily.commands.list_metrics import list_metrics
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
-- 02 001 001 001 001 002 002 0002.00 0001.00 0000.50 |
list_metrics(wrap)
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
@cli.command("setup", help=_("""Run a guided setup to build the wily cache."""))
-- -- --- --- --- --- --- --- ------- ------- ------- |
@click.pass_context
-- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
def setup(ctx):
-- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
"""Run a guided setup to build the wily cache."""
-- 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
handle_no_cache(ctx)
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
def handle_no_cache(context):
-- 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
"""Handle lack-of-cache error, prompt user for index process."""
-- 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
logger.error(
-- 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
_("Could not locate wily cache, the cache is required to provide insights.")
-- 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
)
-- 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
p = input(_("Do you want to run setup and index your project now? [y/N]"))
-- 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
if p.lower() != "y":
-- 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
exit(1)
-- 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
else:
-- 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
revisions = input(_("How many previous git revisions do you want to index? : "))
-- 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
revisions = int(revisions)
-- 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
path = input(_("Path to your source files; comma-separated for multiple: "))
-- 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
paths = path.split(",")
-- 02 001 002 001 002 003 003 0004.75 0002.38 0000.50 |
context.invoke(build, max_revisions=revisions, targets=paths, operators=None)
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
if __name__ == "__main__": # pragma: no cover
-- -- --- --- --- --- --- --- ------- ------- ------- |
try:
-- -- --- --- --- --- --- --- ------- ------- ------- |
cli() # type: ignore
-- -- --- --- --- --- --- --- ------- ------- ------- |
except Exception as runtime:
-- -- --- --- --- --- --- --- ------- ------- ------- |
logger.error(f"Oh no, Wily crashed! See {WILY_LOG_NAME} for information.")
-- -- --- --- --- --- --- --- ------- ------- ------- |
logger.info(
-- -- --- --- --- --- --- --- ------- ------- ------- |
"If you think this crash was unexpected, please raise an issue at https://github.com/tonybaloney/wily/issues and copy the log file into the issue report along with some information on what you were doing."
-- -- --- --- --- --- --- --- ------- ------- ------- |
)
-- -- --- --- --- --- --- --- ------- ------- ------- |
logger.debug(traceback.format_exc())