Skip to content

Commit

Permalink
Make output format options mutually exclusive
Browse files Browse the repository at this point in the history
- Add support in MutuallyExclusiveOption for options with an internal
name different from the ones permitted in the command line.
- New hidden option --plain to handle the default output format in
report, aggregate and log commands.
  • Loading branch information
davidag committed May 15, 2019
1 parent dfe9d90 commit 0c7a803
Showing 1 changed file with 66 additions and 35 deletions.
101 changes: 66 additions & 35 deletions watson/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,26 @@ def __init__(self, *args, **kwargs):
super(MutuallyExclusiveOption, self).__init__(*args, **kwargs)

def handle_parse_result(self, ctx, opts, args):
if self.mutually_exclusive.intersection(opts) and self.name in opts:
raise click.UsageError(
'`--{name}` is mutually exclusive with the following options: '
'{options}'.format(name=self.name.replace('_', ''),
options=', '
.join(['`--{}`'.format(_) for _ in
self.mutually_exclusive]))
)

if self.name in opts:
if self.mutually_exclusive.intersection(opts):
self._raise_exclusive_error()
if self.multiple and len(set(opts[self.name])) > 1:
self._raise_exclusive_error()
return super(MutuallyExclusiveOption, self).handle_parse_result(
ctx, opts, args
)

def _raise_exclusive_error(self):
# Use self.opts[-1] instead of self.name to handle options with a
# different internal name.
self.mutually_exclusive.add(self.opts[-1].strip('-'))
raise click.UsageError(
'The following options are mutually exclusive: '
'{options}'.format(options=', '
.join(['`--{}`'.format(_) for _ in
self.mutually_exclusive]))
)


class WatsonCliError(click.ClickException):
def format_message(self):
Expand Down Expand Up @@ -439,15 +446,23 @@ def status(watson, project, tags, elapsed):
help="Reports activity only for frames containing the given "
"tag. You can add several tags by using this option multiple "
"times")
@click.option('-j', '--json', 'format_json', is_flag=True,
help="Format the report in JSON instead of plain text")
@click.option('-s', '--csv', 'format_csv', is_flag=True,
help="Format the report in JSON instead of plain text")
@click.option('-j', '--json', 'output_format', cls=MutuallyExclusiveOption,
flag_value='json', mutually_exclusive=['csv'],
multiple=True,
help="Format output in JSON instead of plain text")
@click.option('-s', '--csv', 'output_format', cls=MutuallyExclusiveOption,
flag_value='csv', mutually_exclusive=['json'],
multiple=True,
help="Format output in JSON instead of plain text")
@click.option('--plain', 'output_format', cls=MutuallyExclusiveOption,
flag_value='plain', mutually_exclusive=['json', 'csv'],
multiple=True, default=True, hidden=True,
help="Format output in plain text (default)")
@click.option('-g/-G', '--pager/--no-pager', 'pager', default=None,
help="(Don't) view output through a pager.")
@click.pass_obj
def report(watson, current, from_, to, projects, tags, year, month,
week, day, luna, all, format_json, format_csv, pager,
week, day, luna, all, output_format, pager,
aggregated=False):
"""
Display a report of the time spent on each project.
Expand Down Expand Up @@ -558,13 +573,13 @@ def report(watson, current, from_, to, projects, tags, year, month,
except watson.WatsonError as e:
raise click.ClickException(e)

if format_json and not aggregated:
if 'json' in output_format and not aggregated:
click.echo(json.dumps(report, indent=4, sort_keys=True))
return
elif format_csv and not aggregated:
elif 'csv' in output_format and not aggregated:
click.echo(build_csv(flatten_report(report)))
return
elif (format_json or format_csv) and aggregated:
elif 'plain' not in output_format and aggregated:
return report

lines = []
Expand Down Expand Up @@ -676,16 +691,24 @@ def _final_print(lines):
help="Reports activity only for frames containing the given "
"tag. You can add several tags by using this option multiple "
"times")
@click.option('-j', '--json', 'format_json', is_flag=True,
help="Format the report in JSON instead of plain text")
@click.option('-s', '--csv', 'format_csv', is_flag=True,
help="Format the report in JSON instead of plain text")
@click.option('-j', '--json', 'output_format', cls=MutuallyExclusiveOption,
flag_value='json', mutually_exclusive=['csv'],
multiple=True,
help="Format output in JSON instead of plain text")
@click.option('-s', '--csv', 'output_format', cls=MutuallyExclusiveOption,
flag_value='csv', mutually_exclusive=['json'],
multiple=True,
help="Format output in JSON instead of plain text")
@click.option('--plain', 'output_format', cls=MutuallyExclusiveOption,
flag_value='plain', mutually_exclusive=['json', 'csv'],
multiple=True, default=True, hidden=True,
help="Format output in plain text (default)")
@click.option('-g/-G', '--pager/--no-pager', 'pager', default=None,
help="(Don't) view output through a pager.")
@click.pass_obj
@click.pass_context
def aggregate(ctx, watson, current, from_, to, projects, tags,
format_json, format_csv, pager):
def aggregate(ctx, watson, current, from_, to, projects, tags, output_format,
pager):
"""
Display a report of the time spent on each project aggregated by day.
Expand Down Expand Up @@ -746,12 +769,12 @@ def aggregate(ctx, watson, current, from_, to, projects, tags,
from_offset = from_ + offset
output = ctx.invoke(report, current=current, from_=from_offset,
to=from_offset, projects=projects, tags=tags,
format_json=format_json, format_csv=format_csv,
output_format=output_format,
pager=pager, aggregated=True)

if format_json:
if 'json' in output_format:
lines.append(output)
elif format_csv:
elif 'csv' in output_format:
lines.extend(flatten_report(output))
else:
# if there is no activity for the day, append a newline
Expand All @@ -761,9 +784,9 @@ def aggregate(ctx, watson, current, from_, to, projects, tags,

lines.append(u'\n'.join(output))

if format_json:
if 'json' in output_format:
click.echo(json.dumps(lines, indent=4, sort_keys=True))
elif format_csv:
elif 'csv' in output_format:
click.echo(build_csv(lines))
elif pager or (pager is None and
watson.config.getboolean('options', 'pager', True)):
Expand Down Expand Up @@ -813,15 +836,23 @@ def aggregate(ctx, watson, current, from_, to, projects, tags,
help="Logs activity only for frames containing the given "
"tag. You can add several tags by using this option multiple "
"times")
@click.option('-j', '--json', 'format_json', is_flag=True,
help="Format the log in JSON instead of plain text")
@click.option('-s', '--csv', 'format_csv', is_flag=True,
help="Format the log in JSON instead of plain text")
@click.option('-j', '--json', 'output_format', cls=MutuallyExclusiveOption,
flag_value='json', mutually_exclusive=['csv'],
multiple=True,
help="Format output in JSON instead of plain text")
@click.option('-s', '--csv', 'output_format', cls=MutuallyExclusiveOption,
flag_value='csv', mutually_exclusive=['json'],
multiple=True,
help="Format output in JSON instead of plain text")
@click.option('--plain', 'output_format', cls=MutuallyExclusiveOption,
flag_value='plain', mutually_exclusive=['json', 'csv'],
multiple=True, default=True, hidden=True,
help="Format output in plain text (default)")
@click.option('-g/-G', '--pager/--no-pager', 'pager', default=None,
help="(Don't) view output through a pager.")
@click.pass_obj
def log(watson, current, from_, to, projects, tags, year, month, week, day,
luna, all, format_json, format_csv, pager):
luna, all, output_format, pager):
"""
Display each recorded session during the given timespan.
Expand Down Expand Up @@ -891,11 +922,11 @@ def log(watson, current, from_, to, projects, tags, year, month, week, day,
projects=projects or None, tags=tags or None, span=span
)

if format_json:
if 'json' in output_format:
click.echo(frames_to_json(filtered_frames))
return

if format_csv:
if 'csv' in output_format:
click.echo(frames_to_csv(filtered_frames))
return

Expand Down

0 comments on commit 0c7a803

Please sign in to comment.