Change from argparse to pocoo click

This commit is contained in:
Sijmen 2018-07-21 14:36:02 +02:00
parent 37346015a0
commit 70f00be2c8
7 changed files with 83 additions and 124 deletions

View file

@ -130,13 +130,13 @@ def __print_blockers(token: str, project_id: int, story_id: int) -> None:
print(f' [{resolved}] {desc}')
def _stories_info(args: argparse.Namespace) -> None:
def _stories_info(story: str) -> None:
try:
token = Config['user']['api_token']
except KeyError:
sys.exit(1)
story_id = base32_crockford.decode(args.story)
story_id = base32_crockford.decode(story)
story = api.stories.get(token, story_id)
project_id = story['project_id']

5
commands/cli.py Normal file
View file

@ -0,0 +1,5 @@
import click
@click.group()
def cli():
pass

View file

@ -1,16 +1,19 @@
import argparse
import getpass
import click
import api.me
from config import Config
from .cli import cli
def login(arguments: argparse.Namespace) -> None:
username = input('E-mail: ')
password = getpass.getpass()
@cli.command('login')
@click.option('--email', prompt=True)
@click.option('--password', prompt=True, hide_input=True)
def login(email: str, password: str) -> None:
user = api.me.get(email, password)
me = api.me.get(username, password)
print()
print(f"Logged in successfully as {user['name']} (@{user['username']}).")
Config['user']['api_token'] = me['api_token']
Config['user']['initials'] = me['initials']
Config['user']['api_token'] = user['api_token']
Config['user']['initials'] = user['initials']
Config.write()

View file

@ -1,17 +1,25 @@
import argparse
import sys
from typing import Dict
import base32_crockford
import click
import tabulate
import api.projects
from config import Config
from util import require_login
from .cli import cli
@cli.group('projects', invoke_without_command=True)
@click.pass_context
@require_login
def list_projects(arguments: argparse.Namespace) -> None:
def projects(context: click.Context) -> None:
if context.invoked_subcommand is not None:
# click calls this function when a subcommand is
# invoked as well. In this case, do nothing.
return
projects = api.projects.get(Config['user']['api_token'])
projects.sort(key=lambda project: project['name'])
@ -28,24 +36,36 @@ def list_projects(arguments: argparse.Namespace) -> None:
print(tabulate.tabulate(table, headers=('Code', 'Name', 'Alias')))
def alias(arguments: argparse.Namespace) -> None:
project_id = base32_crockford.decode(arguments.code)
Config['project_aliases'][arguments.alias] = str(project_id)
@projects.group('alias')
def alias() -> None:
pass
@alias.command('add')
@click.argument('code')
@click.argument('name')
def alias_add(code: str, name: str) -> None:
project_id = base32_crockford.decode(code)
Config['project_aliases'][name] = str(project_id)
Config.write()
def rmalias(arguments: argparse.Namespace) -> None:
del Config['project_aliases'][arguments.alias]
@alias.command('rm')
@click.argument('name')
def alias_rm(name: str) -> None:
del Config['project_aliases'][name]
Config.write()
def info(arguments: argparse.Namespace) -> None:
@projects.command('info')
@click.argument('name')
def info(name: str) -> None:
try:
token = Config['user']['api_token']
project_id = int(Config['project_aliases'][arguments.alias])
project_id = int(Config['project_aliases'][name])
except KeyError:
print(f'unknown alias {arguments.alias}')
print(f'unknown alias {name}')
sys.exit(1)
projects = api.projects.get_project(token, project_id).items()
print(tabulate.tabulate(projects))
project_info = api.projects.get_project(token, project_id)
print(tabulate.tabulate(project_info.items()))

View file

@ -1,7 +1,8 @@
import argparse
import click
from collections import defaultdict
from datetime import datetime, timedelta
from typing import Any, DefaultDict, Dict, List, Sequence, Tuple
from typing import Any, DefaultDict, Dict, List, Sequence, Tuple, Optional
import base32_crockford
import tabulate
@ -13,6 +14,7 @@ from util import require_login
from . import COLOR_HEADER, _format_state, _get_persons
from ._stories_info import _stories_info
from .cli import cli
STATES = 'unstarted', 'planned', 'started', 'finished', 'delivered', 'accepted'
@ -126,34 +128,50 @@ def __print_burndown(token: str, iteration: Dict[str, Any], persons: Persons,
print()
def _stories_current(arguments: argparse.Namespace) -> None:
def _stories_current(project: str, scope: str, show_accepted: bool) -> None:
try:
project_id = int(Config['project_aliases'][arguments.project])
project_id = int(Config['project_aliases'][project])
except KeyError:
project_id = base32_crockford.decode(arguments.project)
project_id = base32_crockford.decode(project)
token = Config['user']['api_token']
iterations = api.projects.get_iterations(
token, project_id, scope=arguments.scope)
token, project_id, scope=scope)
if not iterations:
print('No current iteration.')
return
iteration = iterations[0]
persons = _get_persons(token, project_id=project_id)
totals: DefaultDict[int, Dict[str, int]] = \
defaultdict(lambda: dict((state, 0) for state in STATES))
iteration = iterations[0]
__print_stories(iteration['stories'], persons, totals)
__print_totals(totals, persons)
__print_burndown(token, iteration, persons, arguments.hide_accepted)
__print_burndown(token, iteration, persons, not show_accepted)
def _set_story_state(story: str, state: str) -> None:
token = Config['user']['api_token']
story_id = base32_crockford.decode(story)
api.stories.put_story(token, story_id, current_state=state)
@cli.command('stories')
@click.argument('project')
@click.argument('story', required=False)
@click.option('--scope', default='current')
@click.option('--show-accepted/--hide-accepted', default=True)
@click.option('--set-state', type=click.Choice([
'started', 'finished', 'delivered', 'rejected', 'accepted']))
@require_login
def stories(arguments: argparse.Namespace) -> None:
if arguments.story:
_stories_info(arguments)
def stories(project: str, story: Optional[str], scope: str,
show_accepted: bool, set_state: str) -> None:
if story is not None:
if set_state is not None:
_set_story_state(story, set_state)
else:
_stories_info(story)
else:
_stories_current(arguments)
_stories_current(project, scope, show_accepted)

View file

@ -1,96 +1,8 @@
#!/usr/bin/env python3
import argparse
import commands.login as cmd_login
import commands.projects as cmd_projects
import commands.stories as cmd_stories
import api.stories
from commands.cli import cli
from config import Config
from base32_crockford import decode as b32_decode
def start_story(args) -> None:
story_set_state(args.story, 'finished')
def finish_story(args) -> None:
story_set_state(args.story, 'finished')
def deliver_story(args) -> None:
story_set_state(args.story, 'delivered')
def accept_story(args) -> None:
story_set_state(args.story, 'accepted')
def story_set_state(args, state: str) -> None:
token = Config['user']['api_token']
story_id = b32_decode(args.story)
api.stories.put_story(token, story_id, current_state=state)
def parse_arguments() -> None:
parser = argparse.ArgumentParser()
parser.set_defaults(func=lambda _: parser.print_help())
commands = parser.add_subparsers(title='commands')
login_parser = commands.add_parser('login')
login_parser.set_defaults(func=cmd_login.login)
projects_parser = commands.add_parser('projects')
projects_parser.set_defaults(func=cmd_projects.list_projects)
projects_commands = projects_parser.add_subparsers(title='commands')
projects_list_parser = projects_commands.add_parser('list')
projects_list_parser.set_defaults(func=cmd_projects.list_projects)
projects_alias_parser = projects_commands.add_parser('alias')
projects_alias_parser.add_argument('code', type=str)
projects_alias_parser.add_argument('alias', type=str)
projects_alias_parser.set_defaults(func=cmd_projects.alias)
projects_rmalias_parser = projects_commands.add_parser('rmalias')
projects_rmalias_parser.add_argument('alias', type=str)
projects_rmalias_parser.set_defaults(func=cmd_projects.rmalias)
projects_info_parser = projects_commands.add_parser('info')
projects_info_parser.add_argument('alias', type=str)
projects_info_parser.set_defaults(func=cmd_projects.info)
stories_parser = commands.add_parser('stories', description='story stuff')
stories_parser.set_defaults(func=cmd_stories.stories)
stories_parser.add_argument('project', type=str)
stories_parser.add_argument('story', type=str, nargs='?', default=None)
stories_parser.add_argument('--scope', type=str, default='current')
stories_parser.add_argument('--hide-accepted', nargs='?', type=bool,
const=True, default=False)
story_start_parser = commands.add_parser('start')
story_start_parser.set_defaults(
func=lambda args: story_set_state(args, 'started'))
story_start_parser.add_argument('story', type=str)
story_finish_parser = commands.add_parser('finish')
story_finish_parser.set_defaults(
func=lambda args: story_set_state(args, 'finished'))
story_finish_parser.add_argument('story', type=str)
story_deliver_parser = commands.add_parser('deliver')
story_deliver_parser.set_defaults(
func=lambda args: story_set_state(args, 'delivered'))
story_deliver_parser.add_argument('story', type=str)
story_accept_parser = commands.add_parser('accept')
story_accept_parser.set_defaults(
func=lambda args: story_set_state(args, 'accepted'))
story_accept_parser.add_argument('story', type=str)
args = parser.parse_args()
args.func(args)
if __name__ == '__main__':
Config.read()
parse_arguments()
cli()

View file

@ -35,3 +35,4 @@ urllib3==1.22
urwid==2.0.1
wcwidth==0.1.7
wrapt==1.10.11
click=6.7