Skip to content

Commit f8d9710

Browse files
Tom Moyerprat0088joelostblomtommoyer
committed
This commit ports jazzband#405 to df4b720
This is a large commit that adds the following: 1. Syntax: `watson stop --notes "some additional information"`. 2. Print only non-empty notes in log. 3. Always pass id to `new_frame` so that the length of array with/without notes doesn't cause ambiguity. 4. Print a warning message and the existing note if overwriting a note. 5. Print notes in report. 6. Print notes in `watson log` 7. Fixed tests 8. Add notes with the add command 9. Tweaked Makefile to work with newer Ubuntu versions (python vs python3) Primary work here was done by the following people: Co-authored-by: Tristan Pratt <[email protected]> Co-authored-by: Joel Ostblom <[email protected]> Co-authored-by: Tom Moyer <[email protected]>
1 parent d9de4fc commit f8d9710

File tree

9 files changed

+311
-63
lines changed

9 files changed

+311
-63
lines changed

Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Watson
22

3-
PYTHON ?= python
3+
PYTHON ?= python3
44
PIP ?= pip
55

66
VENV = virtualenv
@@ -55,3 +55,8 @@ docs: install-dev
5555
completion-scripts:
5656
scripts/create-completion-script.sh bash
5757
scripts/create-completion-script.sh zsh
58+
59+
.PHONY: wheel
60+
wheel:
61+
$(PYTHON) setup.py bdist_wheel
62+

docs/user-guide/commands.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -710,17 +710,23 @@ If `--at` option is given, the provided stopping time is used. The
710710
specified time must be after the beginning of the to-be-ended frame and must
711711
not be in the future.
712712

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

716+
Example:
715717

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

719724
### Options
720725

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

726732
## `sync`

tests/test_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ def test_frames_to_csv(watson):
300300
result = frames_to_csv(watson.frames)
301301

302302
read_csv = list(csv.reader(StringIO(result)))
303-
header = ['id', 'start', 'stop', 'project', 'tags']
303+
header = ['id', 'start', 'stop', 'project', 'tags', 'note']
304304
assert len(read_csv) == 2
305305
assert read_csv[0] == header
306306
assert read_csv[1][3] == 'foo'
@@ -319,7 +319,7 @@ def test_frames_to_json(watson):
319319

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

322-
keys = {'id', 'start', 'stop', 'project', 'tags'}
322+
keys = {'id', 'start', 'stop', 'project', 'tags', 'note'}
323323
assert len(result) == 1
324324
assert set(result[0].keys()) == keys
325325
assert result[0]['project'] == 'foo'

tests/test_watson.py

Lines changed: 108 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,54 @@ def test_frames_without_tags(mocker, watson):
159159
assert watson.frames[0].tags == []
160160

161161

162+
def test_frames_with_note(mocker, watson):
163+
"""Test loading frames with notes."""
164+
content = json.dumps([
165+
[3601, 3610, 'foo', 'abcdefg', ['A', 'B', 'C'], 3650,
166+
"My hovercraft is full of eels"]
167+
])
168+
169+
mocker.patch('builtins.open', mocker.mock_open(read_data=content))
170+
assert len(watson.frames) == 1
171+
frame = watson.frames['abcdefg']
172+
assert frame.id == 'abcdefg'
173+
assert frame.project == 'foo'
174+
assert frame.start == arrow.get(3601)
175+
assert frame.stop == arrow.get(3610)
176+
assert frame.tags == ['A', 'B', 'C']
177+
assert frame.note == "My hovercraft is full of eels"
178+
179+
180+
def test_frames_without_note(mocker, watson):
181+
"""Test loading frames without notes."""
182+
content = json.dumps([
183+
[3601, 3610, 'foo', 'abcdefg'],
184+
[3611, 3620, 'foo', 'hijklmn', ['A', 'B', 'C']],
185+
[3621, 3630, 'foo', 'opqrstu', ['A', 'B', 'C'], 3630]
186+
])
187+
188+
mocker.patch('builtins.open', mocker.mock_open(read_data=content))
189+
assert len(watson.frames) == 3
190+
frame = watson.frames['abcdefg']
191+
assert frame.id == 'abcdefg'
192+
assert frame.project == 'foo'
193+
assert frame.start == arrow.get(3601)
194+
assert frame.stop == arrow.get(3610)
195+
assert frame.tags == []
196+
assert frame.note is None
197+
198+
frame = watson.frames['hijklmn']
199+
assert frame.id == 'hijklmn'
200+
assert frame.tags == ['A', 'B', 'C']
201+
assert frame.note is None
202+
203+
frame = watson.frames['opqrstu']
204+
assert frame.id == 'opqrstu'
205+
assert frame.tags == ['A', 'B', 'C']
206+
assert frame.updated_at == arrow.get(3630)
207+
assert frame.note is None
208+
209+
162210
def test_frames_with_empty_file(mocker, watson):
163211
mocker.patch('builtins.open', mocker.mock_open(read_data=""))
164212
mocker.patch('os.path.getsize', return_value=0)
@@ -331,6 +379,32 @@ def test_stop_started_project_without_tags(watson):
331379
assert watson.frames[0].tags == []
332380

333381

382+
def test_stop_started_project_without_note(watson):
383+
"""Test stopping watson without adding a note."""
384+
watson.start('foo')
385+
watson.stop()
386+
387+
assert watson.current == {}
388+
assert watson.is_started is False
389+
assert len(watson.frames) == 1
390+
frame = watson.frames[0]
391+
assert frame.project == 'foo'
392+
assert frame.note is None
393+
394+
395+
def test_stop_started_project_with_note(watson):
396+
"""Test stopping watson when adding a note."""
397+
watson.start('foo')
398+
watson.stop(None, "My hovercraft is full of eels")
399+
400+
assert watson.current == {}
401+
assert watson.is_started is False
402+
assert len(watson.frames) == 1
403+
frame = watson.frames[0]
404+
assert frame.project == 'foo'
405+
assert frame.note == "My hovercraft is full of eels"
406+
407+
334408
def test_stop_no_project(watson):
335409
with pytest.raises(WatsonError):
336410
watson.stop()
@@ -419,7 +493,8 @@ def test_save_empty_current(config_dir, mocker, json_mock):
419493

420494
assert json_mock.call_count == 1
421495
result = json_mock.call_args[0][0]
422-
assert result == {'project': 'foo', 'start': 4000, 'tags': []}
496+
assert result == {'project': 'foo', 'start': 4000,
497+
'tags': [], 'note': None}
423498

424499
watson.current = {}
425500
watson.save()
@@ -779,9 +854,12 @@ def test_report(watson):
779854
assert 'time' in report['projects'][0]['tags'][0]
780855
assert report['projects'][0]['tags'][1]['name'] == 'B'
781856
assert 'time' in report['projects'][0]['tags'][1]
857+
assert len(report['projects'][0]['notes']) == 0
858+
assert len(report['projects'][0]['tags'][0]['notes']) == 0
859+
assert len(report['projects'][0]['tags'][1]['notes']) == 0
782860

783861
watson.start('bar', tags=['C'])
784-
watson.stop()
862+
watson.stop(note='bar note')
785863

786864
report = watson.report(arrow.now(), arrow.now())
787865
assert len(report['projects']) == 2
@@ -790,6 +868,13 @@ def test_report(watson):
790868
assert len(report['projects'][0]['tags']) == 1
791869
assert report['projects'][0]['tags'][0]['name'] == 'C'
792870

871+
assert len(report['projects'][1]['notes']) == 0
872+
assert len(report['projects'][1]['tags'][0]['notes']) == 0
873+
assert len(report['projects'][1]['tags'][1]['notes']) == 0
874+
assert len(report['projects'][0]['notes']) == 0
875+
assert len(report['projects'][0]['tags'][0]['notes']) == 1
876+
assert report['projects'][0]['tags'][0]['notes'][0] == 'bar note'
877+
793878
report = watson.report(
794879
arrow.now(), arrow.now(), projects=['foo'], tags=['B']
795880
)
@@ -799,16 +884,36 @@ def test_report(watson):
799884
assert report['projects'][0]['tags'][0]['name'] == 'B'
800885

801886
watson.start('baz', tags=['D'])
802-
watson.stop()
887+
watson.stop(note='baz note')
888+
889+
watson.start('foo')
890+
watson.stop(note='foo no tags')
891+
892+
watson.start('foo', tags=['A'])
893+
watson.stop(note='foo one tag A')
803894

804895
report = watson.report(arrow.now(), arrow.now(), projects=["foo"])
896+
805897
assert len(report['projects']) == 1
898+
assert len(report['projects'][0]['notes']) == 1
899+
# A project-level note because this frame has no tags
900+
assert report['projects'][0]['notes'][0] == 'foo no tags'
901+
assert len(report['projects'][0]['tags']) == 2
902+
assert report['projects'][0]['tags'][0]['name'] == 'A'
903+
assert report['projects'][0]['tags'][1]['name'] == 'B'
904+
assert len(report['projects'][0]['tags'][0]['notes']) == 1
905+
assert len(report['projects'][0]['tags'][1]['notes']) == 0
906+
# A tag-level note because this frame has tags
907+
assert report['projects'][0]['tags'][0]['notes'][0] == 'foo one tag A'
806908

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

810912
report = watson.report(arrow.now(), arrow.now(), tags=["A"])
811913
assert len(report['projects']) == 1
914+
assert len(report['projects'][0]['notes']) == 0
915+
assert len(report['projects'][0]['tags'][0]['notes']) == 1
916+
assert report['projects'][0]['tags'][0]['notes'][0] == 'foo one tag A'
812917

813918
report = watson.report(arrow.now(), arrow.now(), ignore_tags=["D"])
814919
assert len(report['projects']) == 2

0 commit comments

Comments
 (0)