Skip to content

Commit

Permalink
merge upstream master
Browse files Browse the repository at this point in the history
  • Loading branch information
prat0088 committed Dec 10, 2019
2 parents ecd4d30 + 9b3b40d commit 6ec9298
Show file tree
Hide file tree
Showing 18 changed files with 869 additions and 567 deletions.
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,8 @@ mostlyclean: clean distclean
docs: install-dev
$(PYTHON) scripts/gen-cli-docs.py
mkdocs build

.PHONY: completion-scripts
completion-scripts:
scripts/create-completion-script.sh bash
scripts/create-completion-script.sh zsh
2 changes: 2 additions & 0 deletions docs/contributing/release-new-version.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Edit the following files to describe changes and bump the version number:
* `watson/version.py`: update the version number
* `CHANGELOG.md`: add release notes (see previous releases examples)
* `docs/about/release-notes.md`: copy/paste release notes here
* `watson.completion` and `watson.zsh-completion`: generate up-to-date
completion script by running `make completion-scripts`

Then commit your work, tag the release and push everything to GitHub:

Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ $ python setup.py install

#### Bash


If you use a Bash-compatible shell, you can install the `watson.completion` file from the source distribution as `/etc/bash.completion.d/watson` - or wherever your distribution keeps the Bash completion configuration files. After you restart your shell, you can then just type `watson` on your command line and then hit `TAB` to see all available commands. Depending on your input, it completes `watson` commands, command options, projects, tags and frame IDs.

#### ZSH
Expand Down
3 changes: 3 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[pytest]
markers =
datafiles: pytest-datafiles plugin marker. This avoids warning message.
44 changes: 44 additions & 0 deletions scripts/create-completion-script.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash

set -euo pipefail

function print_help() {

cat <<EOF
Usage: $0 shell-type
This script generates the auto completion receipt required by Bash or Zsh.
Since the generated receipt is only a wrapper around the click framework, this
results in correct tab completion, regardless of the currently used version
watson.
The argument shell-type must be either "bash" or "zsh".
EOF
}

# Parse command line parameters
if [[ $# -ne 1 ]]
then
echo "Please provide exactly one input argument." >&2
exit 1
fi

case $1 in
-h|--help)
print_help
exit 0
;;
bash)
src_command="source"
target_file="watson.completion"
;;
zsh)
src_command="source_zsh"
target_file="watson.zsh-completion"
;;
*)
echo "Unknown argument '$1'. Please consult help text." >&2
exit 1
esac

_WATSON_COMPLETE=$src_command watson > "$target_file" || true
10 changes: 10 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Utility functions for the unit tests."""

import os
import datetime

try:
Expand All @@ -12,6 +13,15 @@
except ImportError:
from io import StringIO

import py


TEST_FIXTURE_DIR = py.path.local(
os.path.dirname(
os.path.realpath(__file__)
)
) / 'resources'


def mock_datetime(dt, dt_module):

Expand Down
12 changes: 12 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Provide fixtures for pytest-based unit tests."""

from click.testing import CliRunner
import pytest

from watson import Watson
Expand All @@ -13,3 +14,14 @@ def config_dir(tmpdir):
@pytest.fixture
def watson(config_dir):
return Watson(config_dir=config_dir)


@pytest.fixture
def runner():
return CliRunner()


@pytest.fixture
def watson_df(datafiles):
"""Creates a Watson object with datafiles in config directory."""
return Watson(config_dir=str(datafiles))
102 changes: 102 additions & 0 deletions tests/resources/autocompletion/frames
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
[
[
1539683175,
1539685649,
"project1",
"41dcffb7bd74442794b9385c3e8891fc",
[
"tag1"
],
1539685649
],
[
1546588591,
1546589427,
"project2",
"e8b53f1dda684672806e0f347d2b11fc",
[
"tag2"
],
1546589427
],
[
1550065199,
1550068200,
"project1",
"ef9933131f254b6fa94dda2a85107195",
[
"tag1"
],
1550069493
],
[
1550150400,
1550152117,
"project3-A",
"f4f78aa79744440b9cbd28edef1ba0b0",
[
"tag2"
],
1550152117
],
[
1550829600,
1550831642,
"project3-A",
"10c6ff8612c84b239b5141cd04f10415",
[
"tag2"
],
1550831642
],
[
1551954000,
1551956768,
"project1",
"e113e26dbf8d4db3ba6361a73709ffd6",
[
"tag2"
],
1551956768
],
[
1552489966,
1552492200,
"project2",
"d5185c8e811a40efbad43d2ff775f5e8",
[
"tag2"
],
1552549848
],
[
1553507114,
1553509735,
"project3-B",
"379f567a9d584498aa8729a170b8b8ad",
[
"tag2"
],
1553509735
],
[
1555050600,
1555052400,
"project4",
"f4f7429d70454175bb87ce2254bbd925",
[
"tag3"
],
1555063210
],
[
1556615369,
1556616625,
"project3-B",
"af9fe637030a465ba279abc3c1441b66",
[
"tag3"
],
1556616626
]
]
148 changes: 148 additions & 0 deletions tests/test_autocompletion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
"""Unit tests for the 'autocompletion' module."""

import json
from argparse import Namespace

import pytest

from watson.autocompletion import (
get_frames,
get_project_or_task_completion,
get_projects,
get_rename_name,
get_rename_types,
get_tags,
)

from . import TEST_FIXTURE_DIR


AUTOCOMPLETION_FRAMES_PATH = TEST_FIXTURE_DIR / "autocompletion"
with open(str(AUTOCOMPLETION_FRAMES_PATH / "frames")) as fh:
N_FRAMES = len(json.load(fh))
N_PROJECTS = 5
N_TASKS = 3
N_VARIATIONS_OF_PROJECT3 = 2
N_FRAME_IDS_FOR_PREFIX = 2

ClickContext = Namespace


@pytest.mark.datafiles(AUTOCOMPLETION_FRAMES_PATH)
@pytest.mark.parametrize(
"func_to_test, rename_type, args",
[
(get_frames, None, []),
(get_project_or_task_completion, None, ["project1", "+tag1"]),
(get_project_or_task_completion, None, []),
(get_projects, None, []),
(get_rename_name, "project", []),
(get_rename_name, "tag", []),
(get_rename_types, None, []),
(get_tags, None, []),
],
)
def test_if_returned_values_are_distinct(
watson_df, func_to_test, rename_type, args
):
ctx = ClickContext(obj=watson_df, params={"rename_type": rename_type})
prefix = ""
ret_list = list(func_to_test(ctx, args, prefix))
assert sorted(ret_list) == sorted(set(ret_list))


@pytest.mark.datafiles(AUTOCOMPLETION_FRAMES_PATH)
@pytest.mark.parametrize(
"func_to_test, n_expected_returns, rename_type, args",
[
(get_frames, N_FRAMES, None, []),
(get_project_or_task_completion, N_TASKS, None, ["project1", "+"]),
(get_project_or_task_completion, N_PROJECTS, None, []),
(get_projects, N_PROJECTS, None, []),
(get_rename_name, N_PROJECTS, "project", []),
(get_rename_name, N_TASKS, "tag", []),
(get_rename_types, 2, None, []),
(get_tags, N_TASKS, None, []),
],
)
def test_if_empty_prefix_returns_everything(
watson_df, func_to_test, n_expected_returns, rename_type, args
):
prefix = ""
ctx = ClickContext(obj=watson_df, params={"rename_type": rename_type})
completed_vals = set(func_to_test(ctx, args, prefix))
assert len(completed_vals) == n_expected_returns


@pytest.mark.datafiles(AUTOCOMPLETION_FRAMES_PATH)
@pytest.mark.parametrize(
"func_to_test, rename_type, args",
[
(get_frames, None, []),
(get_project_or_task_completion, None, ["project1", "+"]),
(get_project_or_task_completion, None, ["project1", "+tag1", "+"]),
(get_project_or_task_completion, None, []),
(get_projects, None, []),
(get_rename_name, "project", []),
(get_rename_name, "tag", []),
(get_rename_types, None, []),
(get_tags, None, []),
],
)
def test_completion_of_nonexisting_prefix(
watson_df, func_to_test, rename_type, args
):
ctx = ClickContext(obj=watson_df, params={"rename_type": rename_type})
prefix = "NOT-EXISTING-PREFIX"
ret_list = list(func_to_test(ctx, args, prefix))
assert not ret_list


@pytest.mark.datafiles(AUTOCOMPLETION_FRAMES_PATH)
@pytest.mark.parametrize(
"func_to_test, prefix, n_expected_vals, rename_type, args",
[
(get_frames, "f4f7", N_FRAME_IDS_FOR_PREFIX, None, []),
(
get_project_or_task_completion,
"+tag",
N_TASKS,
None,
["project1", "+tag3"],
),
(get_project_or_task_completion, "+tag", N_TASKS, None, ["project1"]),
(
get_project_or_task_completion,
"project3",
N_VARIATIONS_OF_PROJECT3,
None,
[],
),
(get_projects, "project3", N_VARIATIONS_OF_PROJECT3, None, []),
(get_rename_name, "project3", N_VARIATIONS_OF_PROJECT3, "project", []),
(get_rename_name, "tag", N_TASKS, "tag", []),
(get_rename_types, "ta", 1, None, []),
(get_tags, "tag", N_TASKS, None, []),
],
)
def test_completion_of_existing_prefix(
watson_df, func_to_test, prefix, n_expected_vals, rename_type, args
):
ctx = ClickContext(obj=watson_df, params={"rename_type": rename_type})
ret_set = set(func_to_test(ctx, args, prefix))
assert len(ret_set) == n_expected_vals
assert all(cur_elem.startswith(prefix) for cur_elem in ret_set)


@pytest.mark.datafiles(AUTOCOMPLETION_FRAMES_PATH)
@pytest.mark.parametrize(
"func_to_test, prefix, expected_vals",
[
(get_rename_types, "", ["project", "tag"]),
(get_rename_types, "t", ["tag"]),
(get_rename_types, "p", ["project"]),
],
)
def test_for_known_completion_values(func_to_test, prefix, expected_vals):
ret_list = list(func_to_test(None, [], prefix))
assert ret_list == expected_vals
Loading

0 comments on commit 6ec9298

Please sign in to comment.