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

Add --note flag to associate messages with frames #383

Open
wants to merge 68 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
5919ae2
Refactor 'watson.frames':
SpotlightKid Apr 13, 2016
92b8733
Fix flake8 complaint by refactoring boolean expr
SpotlightKid Apr 13, 2016
a1a905a
Optimize index access to Frames and add tests for 'get_by_index'
SpotlightKid Apr 14, 2016
2ab1991
Update merge command to work with new frame format
SpotlightKid May 26, 2016
8ed29c8
Remove uneccessary assignment since both names already refer to the s…
SpotlightKid May 26, 2016
553e34a
Assigning a Frames instance to watson.frames should work with new Fra…
SpotlightKid May 26, 2016
714b581
Make sure passing a sequence of frames works with tuple and list items
SpotlightKid May 26, 2016
73c2593
Add more tests for setting watson.frames
SpotlightKid May 26, 2016
c956089
(Re-)add support for looking up frames by ID prefix
SpotlightKid Jun 9, 2016
8d2206f
When looking up a frame by ID prefix, iterate over keys in reverse or…
SpotlightKid Jun 11, 2016
c7c3c84
Add script to convert between old and new frame format (for development)
SpotlightKid Jun 11, 2016
909e091
Add log message to frames and allow setting it with stop or edit command
SpotlightKid May 26, 2016
0fff33d
Add tests for log messages
SpotlightKid May 26, 2016
5a9578d
Add options for stop command to bash completion config
SpotlightKid Jun 9, 2016
9b84581
Update documentation for stop command
SpotlightKid Jun 12, 2016
c369bb7
Enhanced stop command help
SpotlightKid Jun 15, 2016
67db7ee
Updated user guide
SpotlightKid Jun 15, 2016
c5b11b5
Revert "Add script to convert between old and new frame format (for d…
jnsebgosselin Sep 5, 2018
124dc00
Revert "When looking up a frame by ID prefix, iterate over keys in re…
jnsebgosselin Sep 5, 2018
51c49c9
Revert "(Re-)add support for looking up frames by ID prefix"
jnsebgosselin Sep 5, 2018
075580e
Revert "Add more tests for setting watson.frames"
jnsebgosselin Sep 5, 2018
39f966e
Revert "Make sure passing a sequence of frames works with tuple and l…
jnsebgosselin Sep 5, 2018
0b3673a
Revert "Assigning a Frames instance to watson.frames should work with…
jnsebgosselin Sep 5, 2018
aa075b3
Revert "Remove uneccessary assignment since both names already refer …
jnsebgosselin Sep 5, 2018
8f98674
Merge branch 'feature/refactor-frames' into feature/log-message
jnsebgosselin Sep 5, 2018
a09ada7
Revert "Optimize index access to Frames and add tests for 'get_by_ind…
jnsebgosselin Sep 5, 2018
6463412
Revert "Fix flake8 complaint by refactoring boolean expr"
jnsebgosselin Sep 5, 2018
4628f94
Revert "Refactor 'watson.frames'"
jnsebgosselin Sep 5, 2018
639553d
Add back a missing ) deleted by mistake
jnsebgosselin Sep 5, 2018
fd1869b
Merge remote-tracking branch 'refs/remotes/TailorDev/master' into add…
jnsebgosselin Sep 5, 2018
80234bd
Merge remote-tracking branch 'refs/remotes/TailorDev/master' into add…
jnsebgosselin Jan 4, 2019
8b4bc2e
Merge remote-tracking branch 'refs/remotes/TailorDev/master' into add…
jnsebgosselin Jan 4, 2019
3eab100
Merge remote-tracking branch 'refs/remotes/TailorDev/master' into add…
jnsebgosselin Feb 9, 2019
693d9d5
Fix test_frames_with_message
jnsebgosselin Feb 9, 2019
dc9d299
Fix test test_frames_without_message
jnsebgosselin Feb 9, 2019
5993b2f
Fix test_stop_started_project_without_message
jnsebgosselin Feb 9, 2019
a76cbd3
Fix test_stop_started_project_with_message
jnsebgosselin Feb 9, 2019
ed469a8
Remove blank spaces
jnsebgosselin Feb 9, 2019
61427d6
Fix test_save_empty_current
jnsebgosselin Feb 9, 2019
d5f9da2
merge log message branch and master
prat0088 Nov 16, 2019
8ad05ad
fix: flake8 error
prat0088 Nov 16, 2019
bb17bbf
add venv to .gitignore
prat0088 Nov 16, 2019
4e051d1
fix: message wasn't saving; move some logic from cli to watson
prat0088 Nov 16, 2019
7038bb6
write message to csv, json
prat0088 Nov 16, 2019
ecd4d30
update stop message test
prat0088 Nov 17, 2019
6ec9298
merge upstream master
prat0088 Dec 10, 2019
588c50c
properly handle messages in edit; pass message to start
prat0088 Dec 10, 2019
b288f58
restructure log print loop
prat0088 Dec 11, 2019
b25bdca
refactor
prat0088 Dec 12, 2019
19f36fc
include messages when building reports
prat0088 Dec 12, 2019
68d2918
clean up flake8 errors
prat0088 Dec 12, 2019
aeb56cc
add tests for report log messages
prat0088 Dec 12, 2019
3a08968
wip: report/aggregate messages
prat0088 Dec 12, 2019
d80f4db
change -m/--message to -n/--note
prat0088 Jan 13, 2020
c8e5edd
fix: aggregate/report -n params not detected as flags on Windows
prat0088 Jan 13, 2020
3745115
Merge branch 'master' into note-flag
joelostblom Jun 18, 2020
1ca1c1a
Remove comment
joelostblom Jun 18, 2020
e054ebc
Print note and warning message when overwriting
joelostblom Jun 18, 2020
8735168
Change note flag to plural for log only
joelostblom Jun 18, 2020
4e0e4b6
Always pass id to new_frame
joelostblom Jun 18, 2020
e3c7f9b
Align rows of multiline notes
joelostblom Jun 18, 2020
90a2417
Join unnecesarily split rows
joelostblom Jun 18, 2020
b4bebae
Realign to fix flake8 test
joelostblom Jun 18, 2020
0df7fbb
Remove extra venv from gitignore and add newline to completion file
joelostblom Jun 18, 2020
e8a4e14
Use old format syntax instead of f-strings
joelostblom Jun 18, 2020
29ca769
Pluralize consistently
joelostblom Jun 22, 2020
72d1bfb
Do not print empty notes after edits and in the log
joelostblom Jun 22, 2020
0ea8473
Remove seemingly redundant note assignment
joelostblom Jun 22, 2020
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
8 changes: 7 additions & 1 deletion docs/user-guide/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -689,17 +689,23 @@ If '--at' option is given, the provided stopping time is used. The
specified time must be after the begin of the to be ended frame and must
not be in the future.

Example:
You can optionally pass a log message to be saved with the frame via
the ``-n/--note`` option.

Example:

$ watson stop --at 13:37
Stopping project apollo11, started an hour ago and stopped 30 minutes ago. (id: e9ccd52) # noqa: E501
$ watson stop -n "Done some thinking"
Stopping project apollo11, started a minute ago. (id: e7ccd52)
Log message: Done some thinking

### Options

Flag | Help
-----|-----
`--at TIME` | Stop frame at this time. Must be in (YYYY-MM-DDT)?HH:MM(:SS)? format.
`-n, --note TEXT` | Save given log message with the project frame.
`--help` | Show this message and exit.

## `sync`
Expand Down
4 changes: 2 additions & 2 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ def test_frames_to_csv(watson):
result = frames_to_csv(watson.frames)

read_csv = list(csv.reader(StringIO(result)))
header = ['id', 'start', 'stop', 'project', 'tags']
header = ['id', 'start', 'stop', 'project', 'tags', 'note']
assert len(read_csv) == 2
assert read_csv[0] == header
assert read_csv[1][3] == 'foo'
Expand All @@ -330,7 +330,7 @@ def test_frames_to_json(watson):

result = json.loads(frames_to_json(watson.frames))

keys = {'id', 'start', 'stop', 'project', 'tags'}
keys = {'id', 'start', 'stop', 'project', 'tags', 'note'}
assert len(result) == 1
assert set(result[0].keys()) == keys
assert result[0]['project'] == 'foo'
Expand Down
111 changes: 108 additions & 3 deletions tests/test_watson.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,54 @@ def test_frames_without_tags(mocker, watson):
assert watson.frames[0].tags == []


def test_frames_with_note(mocker, watson):
"""Test loading frames with notes."""
content = json.dumps([
[3601, 3610, 'foo', 'abcdefg', ['A', 'B', 'C'], 3650,
"My hovercraft is full of eels"]
])

mocker.patch('%s.open' % builtins, mocker.mock_open(read_data=content))
assert len(watson.frames) == 1
frame = watson.frames['abcdefg']
assert frame.id == 'abcdefg'
assert frame.project == 'foo'
assert frame.start == arrow.get(3601)
assert frame.stop == arrow.get(3610)
assert frame.tags == ['A', 'B', 'C']
assert frame.note == "My hovercraft is full of eels"


def test_frames_without_note(mocker, watson):
"""Test loading frames without notes."""
content = json.dumps([
[3601, 3610, 'foo', 'abcdefg'],
[3611, 3620, 'foo', 'hijklmn', ['A', 'B', 'C']],
[3621, 3630, 'foo', 'opqrstu', ['A', 'B', 'C'], 3630]
])

mocker.patch('%s.open' % builtins, mocker.mock_open(read_data=content))
assert len(watson.frames) == 3
frame = watson.frames['abcdefg']
assert frame.id == 'abcdefg'
assert frame.project == 'foo'
assert frame.start == arrow.get(3601)
assert frame.stop == arrow.get(3610)
assert frame.tags == []
assert frame.note is None

frame = watson.frames['hijklmn']
assert frame.id == 'hijklmn'
assert frame.tags == ['A', 'B', 'C']
assert frame.note is None

frame = watson.frames['opqrstu']
assert frame.id == 'opqrstu'
assert frame.tags == ['A', 'B', 'C']
assert frame.updated_at == arrow.get(3630)
assert frame.note is None


def test_frames_with_empty_file(mocker, watson):
mocker.patch('%s.open' % builtins, mocker.mock_open(read_data=""))
mocker.patch('os.path.getsize', return_value=0)
Expand Down Expand Up @@ -322,6 +370,32 @@ def test_stop_started_project_without_tags(watson):
assert watson.frames[0].tags == []


def test_stop_started_project_without_note(watson):
"""Test stopping watson without adding a note."""
watson.start('foo')
watson.stop()

assert watson.current == {}
assert watson.is_started is False
assert len(watson.frames) == 1
frame = watson.frames[0]
assert frame.project == 'foo'
assert frame.note is None


def test_stop_started_project_with_note(watson):
"""Test stopping watson when adding a note."""
watson.start('foo')
watson.stop(None, "My hovercraft is full of eels")

assert watson.current == {}
assert watson.is_started is False
assert len(watson.frames) == 1
frame = watson.frames[0]
assert frame.project == 'foo'
assert frame.note == "My hovercraft is full of eels"


def test_stop_no_project(watson):
with pytest.raises(WatsonError):
watson.stop()
Expand Down Expand Up @@ -410,7 +484,8 @@ def test_save_empty_current(config_dir, mocker, json_mock):

assert json_mock.call_count == 1
result = json_mock.call_args[0][0]
assert result == {'project': 'foo', 'start': 4000, 'tags': []}
assert result == {'project': 'foo', 'start': 4000,
'tags': [], 'note': None}

watson.current = {}
watson.save()
Expand Down Expand Up @@ -770,9 +845,12 @@ def test_report(watson):
assert 'time' in report['projects'][0]['tags'][0]
assert report['projects'][0]['tags'][1]['name'] == 'B'
assert 'time' in report['projects'][0]['tags'][1]
assert len(report['projects'][0]['notes']) == 0
assert len(report['projects'][0]['tags'][0]['notes']) == 0
assert len(report['projects'][0]['tags'][1]['notes']) == 0

watson.start('bar', tags=['C'])
watson.stop()
watson.stop(note='bar note')

report = watson.report(arrow.now(), arrow.now())
assert len(report['projects']) == 2
Expand All @@ -781,6 +859,13 @@ def test_report(watson):
assert len(report['projects'][0]['tags']) == 1
assert report['projects'][0]['tags'][0]['name'] == 'C'

assert len(report['projects'][1]['notes']) == 0
assert len(report['projects'][1]['tags'][0]['notes']) == 0
assert len(report['projects'][1]['tags'][1]['notes']) == 0
assert len(report['projects'][0]['notes']) == 0
assert len(report['projects'][0]['tags'][0]['notes']) == 1
assert report['projects'][0]['tags'][0]['notes'][0] == 'bar note'

report = watson.report(
arrow.now(), arrow.now(), projects=['foo'], tags=['B']
)
Expand All @@ -790,16 +875,36 @@ def test_report(watson):
assert report['projects'][0]['tags'][0]['name'] == 'B'

watson.start('baz', tags=['D'])
watson.stop()
watson.stop(note='baz note')

watson.start('foo')
watson.stop(note='foo no tags')

watson.start('foo', tags=['A'])
watson.stop(note='foo one tag A')

report = watson.report(arrow.now(), arrow.now(), projects=["foo"])

assert len(report['projects']) == 1
assert len(report['projects'][0]['notes']) == 1
# A project-level note because this frame has no tags
assert report['projects'][0]['notes'][0] == 'foo no tags'
assert len(report['projects'][0]['tags']) == 2
assert report['projects'][0]['tags'][0]['name'] == 'A'
assert report['projects'][0]['tags'][1]['name'] == 'B'
assert len(report['projects'][0]['tags'][0]['notes']) == 1
assert len(report['projects'][0]['tags'][1]['notes']) == 0
# A tag-level note because this frame has tags
assert report['projects'][0]['tags'][0]['notes'][0] == 'foo one tag A'

report = watson.report(arrow.now(), arrow.now(), ignore_projects=["bar"])
assert len(report['projects']) == 2

report = watson.report(arrow.now(), arrow.now(), tags=["A"])
assert len(report['projects']) == 1
assert len(report['projects'][0]['notes']) == 0
assert len(report['projects'][0]['tags'][0]['notes']) == 1
assert report['projects'][0]['tags'][0]['notes'][0] == 'foo one tag A'

report = watson.report(arrow.now(), arrow.now(), ignore_tags=["D"])
assert len(report['projects']) == 2
Expand Down
Loading