Skip to content

Commit 8496217

Browse files
authored
Fix: simplify date parsing in download (#41)
2 parents 54b042d + 90483f2 commit 8496217

File tree

3 files changed

+62
-60
lines changed

3 files changed

+62
-60
lines changed

compiler_admin/api/toggl.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def detailed_time_entries(self, start_date: datetime, end_date: datetime, **kwar
5555
Args:
5656
start_date (datetime): The beginning of the reporting period.
5757
58-
end_date (str): The end of the reporting period.
58+
end_date (datetime): The end of the reporting period.
5959
6060
Extra `kwargs` are passed through as a POST json body.
6161

compiler_admin/commands/time/download.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from datetime import datetime, timedelta
2-
import os
32
from typing import List
43

54
import click
@@ -8,7 +7,7 @@
87
from compiler_admin.services.toggl import TOGGL_COLUMNS, download_time_entries
98

109

11-
TZINFO = timezone(os.environ.get("TZ_NAME", "America/Los_Angeles"))
10+
TZINFO = timezone("America/Los_Angeles")
1211

1312

1413
def local_now():
@@ -17,7 +16,7 @@ def local_now():
1716

1817
def prior_month_end():
1918
now = local_now()
20-
first = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
19+
first = now.replace(day=1)
2120
return first - timedelta(days=1)
2221

2322

@@ -30,15 +29,15 @@ def prior_month_start():
3029
@click.option(
3130
"--start",
3231
metavar="YYYY-MM-DD",
33-
default=prior_month_start(),
34-
callback=lambda ctx, param, val: datetime.strptime(val, "%Y-%m-%d %H:%M:%S%z"),
32+
default=prior_month_start().strftime("%Y-%m-%d"),
33+
callback=lambda ctx, param, val: datetime.strptime(val, "%Y-%m-%d").replace(tzinfo=TZINFO),
3534
help="The start date of the reporting period. Defaults to the beginning of the prior month.",
3635
)
3736
@click.option(
3837
"--end",
3938
metavar="YYYY-MM-DD",
40-
default=prior_month_end(),
41-
callback=lambda ctx, param, val: datetime.strptime(val, "%Y-%m-%d %H:%M:%S%z"),
39+
default=prior_month_end().strftime("%Y-%m-%d"),
40+
callback=lambda ctx, param, val: datetime.strptime(val, "%Y-%m-%d").replace(tzinfo=TZINFO),
4241
help="The end date of the reporting period. Defaults to the end of the prior month.",
4342
)
4443
@click.option(
@@ -123,3 +122,6 @@ def download(
123122
click.echo(f" {k}: {v}")
124123

125124
download_time_entries(**params)
125+
126+
click.echo()
127+
click.echo(f"Download complete: ./{output}")

tests/commands/time/test_download.py

Lines changed: 52 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
from compiler_admin import RESULT_SUCCESS
55
from compiler_admin.commands.time.download import (
66
__name__ as MODULE,
7-
download,
87
TOGGL_COLUMNS,
98
TZINFO,
9+
download,
1010
prior_month_end,
1111
prior_month_start,
1212
)
@@ -19,40 +19,35 @@ def mock_local_now(mocker):
1919
return dt
2020

2121

22-
@pytest.fixture
23-
def mock_start(mock_local_now):
24-
return datetime(2024, 8, 1, tzinfo=TZINFO)
25-
26-
27-
@pytest.fixture
28-
def mock_end(mock_local_now):
29-
return datetime(2024, 8, 31, tzinfo=TZINFO)
30-
31-
3222
@pytest.fixture
3323
def mock_download_time_entries(mocker):
3424
return mocker.patch(f"{MODULE}.download_time_entries")
3525

3626

37-
def test_prior_month_start(mock_start):
27+
def test_prior_month_start(mock_local_now):
3828
start = prior_month_start()
3929

40-
assert start == mock_start
30+
assert start.year == 2024
31+
assert start.month == 8
32+
assert start.day == 1
33+
assert start.tzinfo == TZINFO
4134

4235

43-
def test_prior_month_end(mock_end):
36+
def test_prior_month_end(mock_local_now):
4437
end = prior_month_end()
4538

46-
assert end == mock_end
39+
assert end.year == 2024
40+
assert end.month == 8
41+
assert end.day == 31
42+
assert end.tzinfo == TZINFO
4743

4844

49-
def test_download(cli_runner, mock_download_time_entries):
50-
date = datetime.now(tz=TZINFO).replace(hour=0, minute=0, second=0, microsecond=0)
45+
def test_download(cli_runner, mock_local_now, mock_download_time_entries):
5146
args = [
5247
"--start",
53-
date.strftime("%Y-%m-%d %H:%M:%S%z"),
48+
mock_local_now.strftime("%Y-%m-%d"),
5449
"--end",
55-
date.strftime("%Y-%m-%d %H:%M:%S%z"),
50+
mock_local_now.strftime("%Y-%m-%d"),
5651
"--output",
5752
"output",
5853
"-c",
@@ -77,8 +72,8 @@ def test_download(cli_runner, mock_download_time_entries):
7772

7873
assert result.exit_code == RESULT_SUCCESS
7974
mock_download_time_entries.assert_called_once_with(
80-
start_date=date,
81-
end_date=date,
75+
start_date=mock_local_now,
76+
end_date=mock_local_now,
8277
output_path="output",
8378
billable=True,
8479
output_cols=TOGGL_COLUMNS,
@@ -89,43 +84,48 @@ def test_download(cli_runner, mock_download_time_entries):
8984
)
9085

9186

92-
def test_download_client_envvar(cli_runner, monkeypatch, mock_download_time_entries):
93-
monkeypatch.setenv("TOGGL_CLIENT_ID", 1234)
94-
95-
date = datetime.now(tz=TZINFO).replace(hour=0, minute=0, second=0, microsecond=0)
96-
args = [
97-
"--start",
98-
date.strftime("%Y-%m-%d %H:%M:%S%z"),
99-
"--end",
100-
date.strftime("%Y-%m-%d %H:%M:%S%z"),
101-
"--output",
102-
"output",
103-
]
87+
def test_download_default(cli_runner, mock_download_time_entries):
88+
expected_start, expected_end = prior_month_start(), prior_month_end()
10489

105-
result = cli_runner.invoke(download, args)
90+
result = cli_runner.invoke(download, [])
10691

10792
assert result.exit_code == RESULT_SUCCESS
108-
mock_download_time_entries.assert_called_once_with(
109-
start_date=date, end_date=date, output_path="output", output_cols=TOGGL_COLUMNS, billable=True, client_ids=(1234,)
93+
mock_download_time_entries.assert_called_once()
94+
call = mock_download_time_entries.mock_calls[0]
95+
96+
actual_start = call.kwargs["start_date"]
97+
assert actual_start.year == expected_start.year
98+
assert actual_start.month == expected_start.month
99+
assert actual_start.day == expected_start.day
100+
101+
actual_end = call.kwargs["end_date"]
102+
assert actual_end.year == expected_end.year
103+
assert actual_end.month == expected_end.month
104+
assert actual_end.day == expected_end.day
105+
106+
assert (
107+
call.kwargs["output_path"]
108+
== f"Toggl_time_entries_{expected_start.strftime('%Y-%m-%d')}_{expected_end.strftime('%Y-%m-%d')}.csv"
110109
)
110+
assert call.kwargs["output_cols"] == TOGGL_COLUMNS
111+
assert call.kwargs["billable"] is True
111112

112113

113-
def test_download_all(cli_runner, monkeypatch, mock_download_time_entries):
114-
monkeypatch.delenv("TOGGL_CLIENT_ID", raising=False)
115-
date = datetime.now(tz=TZINFO).replace(hour=0, minute=0, second=0, microsecond=0)
116-
args = [
117-
"--start",
118-
date.strftime("%Y-%m-%d %H:%M:%S%z"),
119-
"--end",
120-
date.strftime("%Y-%m-%d %H:%M:%S%z"),
121-
"--output",
122-
"output",
123-
"--all",
124-
]
114+
def test_download_client_envvar(cli_runner, monkeypatch, mock_download_time_entries):
115+
monkeypatch.setenv("TOGGL_CLIENT_ID", 1234)
125116

126-
result = cli_runner.invoke(download, args)
117+
result = cli_runner.invoke(download, [])
127118

128119
assert result.exit_code == RESULT_SUCCESS
129-
mock_download_time_entries.assert_called_once_with(
130-
start_date=date, end_date=date, output_path="output", output_cols=TOGGL_COLUMNS
131-
)
120+
mock_download_time_entries.assert_called_once()
121+
call = mock_download_time_entries.mock_calls[0]
122+
assert call.kwargs["client_ids"] == (1234,)
123+
124+
125+
def test_download_all(cli_runner, mock_download_time_entries):
126+
result = cli_runner.invoke(download, ["--all"])
127+
128+
assert result.exit_code == RESULT_SUCCESS
129+
mock_download_time_entries.assert_called_once()
130+
call = mock_download_time_entries.mock_calls[0]
131+
assert "billable" not in call.kwargs

0 commit comments

Comments
 (0)