Skip to content

Commit

Permalink
Merge pull request #154 from stopthatcow/feature/89_autocompletion
Browse files Browse the repository at this point in the history
Dynamic Autocompletion
  • Loading branch information
stopthatcow committed Apr 8, 2019
2 parents 9c461c9 + eccb7dc commit 62dc890
Show file tree
Hide file tree
Showing 15 changed files with 211 additions and 88 deletions.
4 changes: 1 addition & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,7 @@ Add the following to your ``~/.zshrc`` file

::

autoload bashcompinit
bashcompinit
eval "$(_ZAZU_COMPLETE=source zazu)"
eval "$(_ZAZU_COMPLETE=source_zsh zazu)"

Handy aliases
-------------
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
'GitPython>=2.1.8', # BSD
'dict-recursive-update>=1.0.1', # MIT
'ruamel.yaml<=0.15', # MIT
'keyring>=11.0', # MIT
'keyring<=8.0', # MIT
'keyrings.alt>=2.3', # MIT
'autopep8>=1.3.4', # MIT
'docformatter>=1.0', # Expat
Expand Down
6 changes: 6 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,9 @@ def test_alt_branch_names(git_repo):
uut = zazu.config.Config('')
assert uut.develop_branch_name() == 'alt_develop'
assert uut.master_branch_name() == 'alt_master'


def test_complete_param(mocker, temp_user_config):
mocker.patch('zazu.config.user_config_filepath', return_value=temp_user_config)
assert zazu.config.complete_param(None, [], '') == ['scmHost.gh.type', 'scmHost.gh.user']
assert zazu.config.complete_param(None, ['--add'], '') == []
21 changes: 21 additions & 0 deletions tests/test_dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,3 +325,24 @@ def test_builds():
result = runner.invoke(zazu.cli.cli, ['dev', 'builds'])
assert result.exception
assert result.exit_code != 0


def test_complete_git_branch(git_repo):
with zazu.util.cd(git_repo.working_tree_dir):
assert zazu.dev.commands.complete_git_branch(None, [], 'mas') == ['master']


def test_complete_issue_and_complete_feature(mocker):
mocked_config = mocker.Mock()
mocked_tracker = mocker.Mock()
mocked_issue = mocker.Mock()
mocked_issue.__str__ = mocker.Mock(return_value='ZZ-1')
mocked_issue.name = 'name'
mocked_tracker.issues = mocker.Mock(return_value=[mocked_issue])
mocked_config.issue_tracker = mocker.Mock(return_value=mocked_tracker)
mocker.patch('zazu.config.Config', return_value=mocked_config)
assert zazu.dev.commands.complete_issue(None, [], 'Z') == [(mocked_issue, 'name')]
assert zazu.dev.commands.complete_issue(None, [], 'Na') == [(mocked_issue, 'name')]
assert zazu.dev.commands.complete_issue(None, [], '') == [(mocked_issue, 'name')]
assert zazu.dev.commands.complete_issue(None, [], 'foo') == []
assert zazu.dev.commands.complete_feature(None, [], 'Z') == [('feature/ZZ-1', 'name')]
20 changes: 20 additions & 0 deletions tests/test_github_issue_tracker.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
import conftest
import copy
import github
import pytest
import zazu.git_helper
Expand Down Expand Up @@ -64,6 +65,19 @@ def test_github_issue_tracker_create_issue(mocker, mocked_github_issue_tracker):
zazu.plugins.github_issue_tracker.GitHubIssueTracker._github_repo.create_issue.call_count == 1


def test_github_issue_tracker_list_issues(mocker, mocked_github_issue_tracker):
mocked_github_issue_tracker._github.get_issues = mocker.Mock(return_value=[mock_issue])
mocked_github_issue_tracker.get_issues = mocker.Mock()
zazu.plugins.github_issue_tracker.GitHubIssueTracker._github_repo.get_issues.call_count == 1


def test_github_issue_tracker_list_issues_error(mocker, mocked_github_issue_tracker):
mocked_github_issue_tracker._github.get_issues = mocker.Mock(side_effect=github.GithubException(404, {}))
with pytest.raises(zazu.issue_tracker.IssueTrackerError) as e:
mocked_github_issue_tracker.issues()
assert '404' in str(e.value)


def test_from_config_no_project(git_repo):
with zazu.util.cd(git_repo.working_tree_dir):
with pytest.raises(zazu.issue_tracker.IssueTrackerError) as e:
Expand Down Expand Up @@ -135,3 +149,9 @@ def test_github_issue_adaptor():
assert uut.browse_url == 'https://github.com/stopthatcow/zazu/issues/1'
assert uut.id == '1'
assert str(uut) == uut.id
mock_issue2 = copy.copy(mock_issue)
mock_issue2.number = 2
uut2 = zazu.plugins.github_issue_tracker.GitHubIssueAdaptor(mock_issue2)
assert uut < uut2
assert uut < 2
assert uut < '2'
15 changes: 15 additions & 0 deletions tests/test_jira_issue_tracker.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
import conftest
import copy
import jira
import jira.client
import pytest
Expand Down Expand Up @@ -121,6 +122,14 @@ def test_jira_assign_issue(mocker, mocked_jira_issue_tracker):
mocked_jira_issue_tracker._jira_handle.assign_issue.assert_called_once_with(mock_issue, 'me')


def test_jira_list_issues(mocker, mocked_jira_issue_tracker):
mocked_jira_issue_tracker._jira_handle.current_user = mocker.Mock(return_value='me')
mocked_jira_issue_tracker._jira_handle.search_issues = mocker.Mock(return_value=[])
mocked_jira_issue_tracker.issues()
mocked_jira_issue_tracker._jira_handle.search_issues.assert_called_once_with(
'assignee=me AND resolution="Unresolved"', fields='key, summary, description')


def test_jira_issue_tracker_no_components(mocker):
uut = zazu.plugins.jira_issue_tracker.JiraIssueTracker.from_config({'url': 'https://jira',
'project': 'ZZ'})
Expand Down Expand Up @@ -167,5 +176,11 @@ def test_jira_issue_adaptor(tracker_mock):
assert uut.type == 'type'
assert uut.browse_url == 'https://jira/browse/ZZ-1'
assert uut.id == 'ZZ-1'
assert uut.parse_key() == ('ZZ', 1)
assert str(uut) == uut.id
assert repr(uut) == uut.id
mock_issue2 = copy.copy(mock_issue)
mock_issue2.key = 'ZZ-2'
uut2 = zazu.plugins.jira_issue_tracker.JiraIssueAdaptor(mock_issue2, tracker_mock)
assert uut < uut2
assert uut < 'ZZ-2'
7 changes: 2 additions & 5 deletions zazu/cli.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
# -*- coding: utf-8 -*-
"""Entry point for zazu."""
import click
import os
import zazu.config
import zazu.dev.commands
import zazu.git_helper
import zazu.repo.commands
import zazu.style
import zazu.upgrade
Expand All @@ -15,10 +13,9 @@

@click.group()
@click.version_option(version=zazu.__version__)
@click.pass_context
def cli(ctx):
def cli():
"""Entry point for zazu cli."""
ctx.obj = zazu.config.Config(zazu.git_helper.get_repo_root(os.getcwd()))
pass


def init():
Expand Down
20 changes: 18 additions & 2 deletions zazu/config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
"""Config classes and methods for zazu."""
import zazu.code_reviewer
import zazu.git_helper
import zazu.issue_tracker
import zazu.scm_host
import zazu.util
Expand Down Expand Up @@ -199,8 +200,10 @@ def write(self):
class Config(object):
"""Hold all zazu configuration info."""

def __init__(self, repo_root):
def __init__(self, repo_root=None):
"""Constructor, doesn't parse configuration or require repo to be valid."""
if repo_root is None:
repo_root = zazu.git_helper.get_repo_root(os.getcwd())
self.repo_root = repo_root
if self.repo_root is not None:
try:
Expand Down Expand Up @@ -339,6 +342,9 @@ def check_repo(self):
raise click.UsageError('The current working directory is not in a git repo')


pass_config = click.make_pass_decorator(Config, ensure=True)


def maybe_write_default_user_config(path):
"""Write a default user config file if it doesn't exist."""
DEFAULT_USER_CONFIG = """# User configuration file for zazu.
Expand All @@ -354,13 +360,23 @@ def maybe_write_default_user_config(path):
f.write(DEFAULT_USER_CONFIG)


def complete_param(ctx, args, incomplete):
"""Completion function that returns parameter names."""
if '--add' in args:
return [] # Don't offer completions when adding new params.
config_file = ConfigFile(user_config_filepath())
config_dict = config_file.dict
flattened = zazu.util.flatten_dict(config_dict)
return sorted([param for param in flattened.keys() if incomplete in param])


@click.command()
@click.pass_context
@click.option('-l', '--list', is_flag=True, help='list config')
@click.option('--show-origin', is_flag=True, help='show origin of each config variable, (implies --list)')
@click.option('--add', is_flag=True, help='add a new variable')
@click.option('--unset', is_flag=True, help='remove a variable')
@click.argument('param_name', required=False, type=str)
@click.argument('param_name', required=False, type=str, autocompletion=complete_param)
@click.argument('param_value', required=False, type=str)
def config(ctx, list, add, unset, show_origin, param_name, param_value):
"""Manage zazu user configuration."""
Expand Down
Loading

0 comments on commit 62dc890

Please sign in to comment.