Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate JSON output #194

Open
wants to merge 31 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
b185a34
Add --json option for diff, index, rank and report, allowing to gener…
devdanzin Jul 9, 2023
431e332
Add filename to JSON entries in report().
devdanzin Jul 9, 2023
1481953
Move printing logic of commands to wily.helper.output.print_result().
devdanzin Jul 9, 2023
6d793af
Add tests for JSON output support.
devdanzin Jul 9, 2023
fbc1cd3
Remove blank line.
devdanzin Jul 9, 2023
33dbd3f
black fixes, even though one of them is clearly wrong.
devdanzin Jul 9, 2023
b9f6cbd
Move expected data out of test functions so black doesn't create ugly…
devdanzin Jul 9, 2023
89075f5
Avoid black weirdness.
devdanzin Jul 9, 2023
3e7cef3
Merge master.
devdanzin Jul 11, 2023
c46e1df
Merge branch 'tonybaloney:master' into json_output
devdanzin Jul 12, 2023
d3949b0
Merge branch 'tonybaloney:master' into json_output
devdanzin Jul 12, 2023
1dd904c
Merge master.
devdanzin Jul 17, 2023
828dcba
Merge branch 'tonybaloney:master' into json_output
devdanzin Jul 27, 2023
e4fdec9
Change print_result() into print_json(), restore printing tabulated d…
devdanzin Oct 27, 2023
8f17212
Merge master.
devdanzin Oct 27, 2023
3ef2985
Make as_json in rank() a keyword argument defaulting to False.
devdanzin Oct 27, 2023
be1fb28
Add as_json to command docstrings, fix docstring punctuation.
devdanzin Oct 27, 2023
7ba3429
Raise ruff's allowed number of function arguments.
devdanzin Oct 27, 2023
b95a7e6
Format __main__.py.
devdanzin Oct 27, 2023
0d94aa8
Change ruff option '--format' to '--output-format'.
devdanzin Oct 28, 2023
7c89f4e
Don't use terminal colors for JSON output.
devdanzin Oct 28, 2023
467c87c
Only strip colors in report() if format isn't HTML, so HTML colors work.
devdanzin Oct 28, 2023
5cfcc75
Add unit tests for JSON output in index(), rank() and report().
devdanzin Oct 28, 2023
f57006e
Increase ruff max branches, statements and complexity for report().
devdanzin Oct 28, 2023
a2268c4
Tighten typing info in print_json().
devdanzin Nov 2, 2023
c4cbc86
Rename test_print_result_* to test_print_json_*.
devdanzin Nov 2, 2023
180436b
Make deltas
devdanzin Nov 3, 2023
64b7448
Remove unused branch in report().
devdanzin Nov 3, 2023
7a05c06
Add more typing info to print_json().
devdanzin Nov 3, 2023
af81cfa
Output current and new values as separate columns in diff() when gene…
devdanzin Nov 5, 2023
74d2813
Increase ruff's max values for complexity, branches and statements ag…
devdanzin Nov 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- run: pip install --user ruff
- run: ruff --format=github .
- run: ruff --output-format=github .

pyright:
runs-on: ubuntu-latest
Expand Down
8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,12 @@ target-version = "py37"
known-local-folder = ["wily"]

[tool.ruff.mccabe]
max-complexity = 24
max-complexity = 26

[tool.ruff.per-file-ignores]
"test/*" = ["D"]

[tool.ruff.pylint]
max-args = 10
max-branches = 35
max-statements = 100
max-args = 12
max-branches = 37
max-statements = 105
43 changes: 38 additions & 5 deletions src/wily/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,12 @@ def build(ctx, max_revisions, targets, operators, archiver):
default=True,
help=_("Wrap index text to fit in terminal"),
)
def index(ctx, message, wrap):
@click.option(
"--json/--table",
help=_("Display results as JSON"),
default=False,
)
def index(ctx, message, wrap, json):
"""Show the history archive in the .wily/ folder."""
config = ctx.obj["CONFIG"]

Expand All @@ -169,7 +174,7 @@ def index(ctx, message, wrap):

from wily.commands.index import index

index(config=config, include_message=message, wrap=wrap)
index(config=config, include_message=message, wrap=wrap, as_json=json)


@cli.command(
Expand Down Expand Up @@ -218,8 +223,13 @@ def index(ctx, message, wrap):
default=True,
help=_("Wrap rank text to fit in terminal"),
)
@click.option(
"--json/--table",
help=_("Display results as JSON"),
default=False,
)
@click.pass_context
def rank(ctx, path, metric, revision, limit, desc, threshold, wrap):
def rank(ctx, path, metric, revision, limit, desc, threshold, wrap, json):
"""Rank files, methods and functions in order of any metrics, e.g. complexity."""
config = ctx.obj["CONFIG"]

Expand All @@ -240,6 +250,7 @@ def rank(ctx, path, metric, revision, limit, desc, threshold, wrap):
threshold=threshold,
descending=desc,
wrap=wrap,
as_json=json,
)


Expand Down Expand Up @@ -281,9 +292,24 @@ def rank(ctx, path, metric, revision, limit, desc, threshold, wrap):
default=True,
help=_("Wrap report text to fit in terminal"),
)
@click.option(
"--json/--table",
help=_("Display results as JSON"),
default=False,
)
@click.pass_context
def report(
ctx, file, metrics, number, message, format, console_format, output, changes, wrap
ctx,
file,
metrics,
number,
message,
format,
console_format,
output,
changes,
wrap,
json,
):
"""Show metrics for a given file."""
config = ctx.obj["CONFIG"]
Expand Down Expand Up @@ -319,6 +345,7 @@ def report(
console_format=style,
changes_only=changes,
wrap=wrap,
as_json=json,
)


Expand Down Expand Up @@ -350,8 +377,13 @@ def report(
default=True,
help=_("Wrap diff text to fit in terminal"),
)
@click.option(
"--json/--table",
help=_("Display results as JSON"),
default=False,
)
@click.pass_context
def diff(ctx, files, metrics, all, detail, revision, wrap):
def diff(ctx, files, metrics, all, detail, revision, wrap, json):
"""Show the differences in metrics for each file."""
config = ctx.obj["CONFIG"]

Expand All @@ -376,6 +408,7 @@ def diff(ctx, files, metrics, all, detail, revision, wrap):
detail=detail,
revision=revision,
wrap=wrap,
as_json=json,
)


Expand Down
41 changes: 24 additions & 17 deletions src/wily/commands/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from wily.config import DEFAULT_PATH
from wily.config.types import WilyConfig
from wily.helper import get_maxcolwidth, get_style
from wily.helper.output import print_json
from wily.operators import (
BAD_COLORS,
GOOD_COLORS,
Expand All @@ -37,17 +38,20 @@ def diff(
detail: bool = True,
revision: Optional[str] = None,
wrap: bool = False,
as_json: bool = False,
) -> None:
"""
Show the differences in metrics for each of the files.

:param config: The wily configuration
:param config: The wily configuration.
:param files: The files to compare.
:param metrics: The metrics to measure.
:param changes_only: Only include changes files in output.
:param detail: Show details (function-level)
:param revision: Compare with specific revision
:param wrap: Wrap output
:param detail: Show details (function-level).
:param revision: Compare with specific revision.
:param wrap: Wrap output.
:param as_json: Output results as JSON.

"""
config.targets = files
files = list(files)
Expand Down Expand Up @@ -142,11 +146,11 @@ def diff(
if new != current:
has_changes = True
if metric.metric_type in (int, float) and new != "-" and current != "-":
if current > new: # type: ignore
if current > new and not as_json: # type: ignore
metrics_data.append(
f"{current:n} -> \u001b[{BAD_COLORS[metric.measure]}m{new:n}\u001b[0m"
)
elif current < new: # type: ignore
elif current < new and not as_json: # type: ignore
metrics_data.append(
f"{current:n} -> \u001b[{GOOD_COLORS[metric.measure]}m{new:n}\u001b[0m"
)
Expand All @@ -165,15 +169,18 @@ def diff(
descriptions = [metric.description for _, metric in resolved_metrics]
headers = ("File", *descriptions)
if len(results) > 0:
maxcolwidth = get_maxcolwidth(headers, wrap)
style = get_style()
print(
# But it still makes more sense to show the newest at the top, so reverse again
tabulate.tabulate(
headers=headers,
tabular_data=results,
tablefmt=style,
maxcolwidths=maxcolwidth,
maxheadercolwidths=maxcolwidth,
if as_json:
print_json(results, headers)
else:
maxcolwidth = get_maxcolwidth(headers, wrap)
style = get_style()
print(
# But it still makes more sense to show the newest at the top, so reverse again
tabulate.tabulate(
headers=headers,
tabular_data=results,
tablefmt=style,
maxcolwidths=maxcolwidth,
maxheadercolwidths=maxcolwidth,
)
)
)
36 changes: 22 additions & 14 deletions src/wily/commands/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,23 @@
from wily import MAX_MESSAGE_WIDTH, format_date, format_revision, logger
from wily.config.types import WilyConfig
from wily.helper import get_maxcolwidth, get_style
from wily.helper.output import print_json
from wily.state import State


def index(
config: WilyConfig, include_message: bool = False, wrap: bool = False
config: WilyConfig,
include_message: bool = False,
wrap: bool = False,
as_json: bool = False,
) -> None:
"""
Show information about the cache and runtime.

:param config: The wily configuration
:param include_message: Include revision messages
:param wrap: Wrap long lines
:param config: The wily configuration.
:param include_message: Include revision messages.
:param wrap: Wrap long lines.
:param as_json: Output results as JSON.
"""
state = State(config=config)
logger.debug("Running show command")
Expand Down Expand Up @@ -58,14 +63,17 @@ def index(
headers = ("Revision", "Author", "Message", "Date")
else:
headers = ("Revision", "Author", "Date")
maxcolwidth = get_maxcolwidth(headers, wrap)
style = get_style()
print(
tabulate.tabulate(
headers=headers,
tabular_data=data,
tablefmt=style,
maxcolwidths=maxcolwidth,
maxheadercolwidths=maxcolwidth,
if as_json:
print_json(data, headers)
else:
maxcolwidth = get_maxcolwidth(headers, wrap)
style = get_style()
print(
tabulate.tabulate(
headers=headers,
tabular_data=data,
tablefmt=style,
maxcolwidths=maxcolwidth,
maxheadercolwidths=maxcolwidth,
)
)
)
31 changes: 19 additions & 12 deletions src/wily/commands/rank.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from wily.archivers import resolve_archiver
from wily.config import DEFAULT_PATH, WilyConfig
from wily.helper import get_maxcolwidth, get_style
from wily.helper.output import print_json
from wily.operators import resolve_metric_as_tuple
from wily.state import State

Expand All @@ -33,6 +34,7 @@ def rank(
threshold: int,
descending: bool,
wrap: bool,
as_json: bool = False,
) -> None:
"""
Rank command ordering files, methods or functions using metrics.
Expand All @@ -43,8 +45,9 @@ def rank(
:param revision_index: Version of git repository to revert to.
:param limit: Limit the number of items in the table.
:param threshold: For total values beneath the threshold return a non-zero exit code.
:param descending: Rank in descending order
:param wrap: Wrap output
:param descending: Rank in descending order.
:param wrap: Wrap output.
:param as_json: Output results as JSON.

:return: Sorted table of all files in path, sorted in order of metric.
"""
Expand Down Expand Up @@ -131,17 +134,21 @@ def rank(
data.append(("Total", total))

headers = ("File", resolved_metric.description)
maxcolwidth = get_maxcolwidth(headers, wrap)
style = get_style()
print(
tabulate.tabulate(
headers=headers,
tabular_data=data,
tablefmt=style,
maxcolwidths=maxcolwidth,
maxheadercolwidths=maxcolwidth,

if as_json:
print_json(data, headers)
else:
maxcolwidth = get_maxcolwidth(headers, wrap)
style = get_style()
print(
tabulate.tabulate(
headers=headers,
tabular_data=data,
tablefmt=style,
maxcolwidths=maxcolwidth,
maxheadercolwidths=maxcolwidth,
)
)
)

if threshold and total < threshold:
logger.error(
Expand Down
47 changes: 28 additions & 19 deletions src/wily/commands/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from wily.config.types import WilyConfig
from wily.helper import get_maxcolwidth
from wily.helper.custom_enums import ReportFormat
from wily.helper.output import print_json
from wily.lang import _
from wily.operators import MetricType, resolve_metric_as_tuple
from wily.state import State
Expand All @@ -35,20 +36,22 @@ def report(
format: ReportFormat = ReportFormat.CONSOLE,
changes_only: bool = False,
wrap: bool = False,
as_json: bool = False,
) -> None:
"""
Show metrics for a given file.

:param config: The configuration
:param path: The path to the file
:param metrics: List of metrics to report on
:param n: Number of items to list
:param output: Output path
:param include_message: Include revision messages
:param format: Output format
:param console_format: Grid format style for tabulate
:param changes_only: Only report revisions where delta != 0
:param wrap: Wrap output
:param config: The configuration.
:param path: The path to the file.
:param metrics: List of metrics to report on.
:param n: Number of items to list.
:param output: Output path.
:param include_message: Include revision messages.
:param format: Output format.
:param console_format: Grid format style for tabulate.
:param changes_only: Only report revisions where delta != 0.
:param wrap: Wrap output.
:param as_json: Output results as JSON.
"""
metrics = sorted(metrics)
logger.debug("Running report command")
Expand Down Expand Up @@ -114,6 +117,9 @@ def report(

if delta == 0:
delta_col = delta
elif as_json and not format == ReportFormat.HTML:
# Only strip colors if format isn't HTML, so HTML colors work
delta_col = f"{delta:n}"
elif delta < 0:
delta_col = (
f"\u001b[{meta['decrease_color']}m{delta:n}\u001b[0m"
Expand Down Expand Up @@ -201,13 +207,16 @@ def report(

logger.info("wily report was saved to %s", report_path)
else:
maxcolwidth = get_maxcolwidth(headers, wrap)
print(
tabulate.tabulate(
headers=headers,
tabular_data=data[::-1],
tablefmt=console_format,
maxcolwidths=maxcolwidth,
maxheadercolwidths=maxcolwidth,
if as_json:
print_json(data[::-1], headers, path)
else:
maxcolwidth = get_maxcolwidth(headers, wrap)
print(
tabulate.tabulate(
headers=headers,
tabular_data=data[::-1],
tablefmt=console_format,
maxcolwidths=maxcolwidth,
maxheadercolwidths=maxcolwidth,
)
)
)
Loading