Skip to content

Commit 957729e

Browse files
committed
feat(time): wire up download command
compiler-admin time download --start YYYY-MM-DD --end YYYY-MM-DD --output path/to/file.csv small fix on convert test assertion
1 parent deced79 commit 957729e

File tree

7 files changed

+107
-5
lines changed

7 files changed

+107
-5
lines changed

README.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,30 @@ The `time` command provides an interface for working with time entries from Comp
6262

6363
```bash
6464
$ compiler-admin time -h
65-
usage: compiler-admin time [-h] {convert} ...
65+
usage: compiler-admin time [-h] {convert,download} ...
6666
6767
positional arguments:
68-
{convert} The time command to run.
69-
convert Convert a time report from one format into another.
68+
{convert,download} The time command to run.
69+
convert Convert a time report from one format into another.
70+
download Download a Toggl report in CSV format.
7071
7172
options:
72-
-h, --help show this help message and exit
73+
-h, --help show this help message and exit
74+
```
75+
76+
### Downloading a Toggl report
77+
78+
Use this command to download a time report from Toggl in CSV format:
79+
80+
```bash
81+
$ compiler-admin time download -h
82+
usage: compiler-admin time download [-h] [--start YYYY-MM-DD] [--end YYYY-MM-DD] [--output OUTPUT]
83+
84+
options:
85+
-h, --help show this help message and exit
86+
--start YYYY-MM-DD The start date of the reporting period. Defaults to the beginning of the prior month.
87+
--end YYYY-MM-DD The end date of the reporting period. Defaults to the end of the prior month.
88+
--output OUTPUT The path to the file where converted data should be written. Defaults to stdout.
7389
```
7490

7591
### Converting an hours report

compiler_admin/commands/time/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from argparse import Namespace
22

33
from compiler_admin.commands.time.convert import convert # noqa: F401
4+
from compiler_admin.commands.time.download import download # noqa: F401
45

56

67
def time(args: Namespace, *extra):
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from argparse import Namespace
2+
3+
from compiler_admin import RESULT_SUCCESS
4+
from compiler_admin.services.toggl import INPUT_COLUMNS as TOGGL_COLUMNS, download_time_entries
5+
6+
7+
def download(args: Namespace, *extras):
8+
download_time_entries(args.start, args.end, args.output, TOGGL_COLUMNS)
9+
10+
return RESULT_SUCCESS

compiler_admin/main.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,25 @@ def setup_time_command(cmd_parsers: _SubParsersAction):
7676
)
7777
time_convert.add_argument("--client", default=None, help="The name of the client to use in converted data.")
7878

79+
time_download = add_sub_cmd(time_subcmds, "download", help="Download a Toggl report in CSV format.")
80+
time_download.add_argument(
81+
"--start",
82+
metavar="YYYY-MM-DD",
83+
default=prior_month_start(),
84+
type=lambda s: TZINFO.localize(datetime.strptime(s, "%Y-%m-%d")),
85+
help="The start date of the reporting period. Defaults to the beginning of the prior month.",
86+
)
87+
time_download.add_argument(
88+
"--end",
89+
metavar="YYYY-MM-DD",
90+
default=prior_month_end(),
91+
type=lambda s: TZINFO.localize(datetime.strptime(s, "%Y-%m-%d")),
92+
help="The end date of the reporting period. Defaults to the end of the prior month.",
93+
)
94+
time_download.add_argument(
95+
"--output", default=sys.stdout, help="The path to the file where converted data should be written. Defaults to stdout."
96+
)
97+
7998

8099
def setup_user_command(cmd_parsers: _SubParsersAction):
81100
user_cmd = add_sub_cmd(cmd_parsers, "user", help="Work with users in the Compiler org.")
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from argparse import Namespace
2+
from datetime import datetime
3+
import pytest
4+
5+
from compiler_admin import RESULT_SUCCESS
6+
from compiler_admin.commands.time.download import __name__ as MODULE, download, TOGGL_COLUMNS
7+
8+
9+
@pytest.fixture
10+
def mock_download_time_entries(mocker):
11+
return mocker.patch(f"{MODULE}.download_time_entries")
12+
13+
14+
def test_download_default(mock_download_time_entries):
15+
date = datetime.now()
16+
args = Namespace(start=date, end=date, output="output")
17+
18+
res = download(args)
19+
20+
assert res == RESULT_SUCCESS
21+
mock_download_time_entries.assert_called_once_with(args.start, args.end, args.output, TOGGL_COLUMNS)

tests/commands/user/test_convert.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ def test_convert_partner(mock_google_add_user_to_group, mock_google_move_user_ou
172172
res = convert(args)
173173

174174
assert res == RESULT_SUCCESS
175-
mock_google_add_user_to_group.call_count == 2
175+
assert mock_google_add_user_to_group.call_count == 2
176176
mock_google_move_user_ou.assert_called_once()
177177

178178

tests/test_main.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,41 @@ def test_main_time_convert_default(mock_commands_time):
114114
)
115115

116116

117+
@pytest.mark.usefixtures("mock_local_now")
118+
def test_main_time_download_default(mock_commands_time, mock_start, mock_end):
119+
main(argv=["time", "download"])
120+
121+
mock_commands_time.assert_called_once()
122+
call_args = mock_commands_time.call_args.args
123+
assert (
124+
Namespace(
125+
func=mock_commands_time, command="time", subcommand="download", start=mock_start, end=mock_end, output=sys.stdout
126+
)
127+
in call_args
128+
)
129+
130+
131+
def test_main_time_download_args(mock_commands_time):
132+
main(argv=["time", "download", "--start", "2024-01-01", "--end", "2024-01-31", "--output", "file.csv"])
133+
134+
expected_start = TZINFO.localize(datetime(2024, 1, 1))
135+
expected_end = TZINFO.localize(datetime(2024, 1, 31))
136+
137+
mock_commands_time.assert_called_once()
138+
call_args = mock_commands_time.call_args.args
139+
assert (
140+
Namespace(
141+
func=mock_commands_time,
142+
command="time",
143+
subcommand="download",
144+
start=expected_start,
145+
end=expected_end,
146+
output="file.csv",
147+
)
148+
in call_args
149+
)
150+
151+
117152
def test_main_time_convert_client(mock_commands_time):
118153
main(argv=["time", "convert", "--client", "client123"])
119154

0 commit comments

Comments
 (0)