Skip to content

Commit 33a6894

Browse files
Address review feedback: flatten due params, fix fixture aliasing
- Replace Due model input param with flat fields (due_string, due_date, due_datetime, due_lang, due_timezone) matching add_task pattern - Use distinct id/item_id values in test fixtures to properly exercise the item_id -> task_id alias Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 85267e1 commit 33a6894

4 files changed

Lines changed: 90 additions & 24 deletions

File tree

tests/data/test_defaults.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ class PaginatedItems(TypedDict):
270270

271271
DEFAULT_REMINDER_RESPONSE: dict[str, Any] = {
272272
"id": "6X7rM8997g3RQmvh",
273-
"item_id": "6X7rM8997g3RQmvh",
273+
"item_id": "6Jf8VQXxpwv56VQ7",
274274
"notify_uid": "34567",
275275
"type": "relative",
276276
"is_deleted": False,
@@ -299,7 +299,7 @@ class PaginatedItems(TypedDict):
299299

300300
DEFAULT_LOCATION_REMINDER_RESPONSE: dict[str, Any] = {
301301
"id": "6X7rM8997g3RQmvh",
302-
"item_id": "6X7rM8997g3RQmvh",
302+
"item_id": "6Jf8VQXxpwv56VQ7",
303303
"project_id": "6Jf8VQXxpwv56VQ7",
304304
"notify_uid": "34567",
305305
"name": "Office",

tests/test_api_reminders.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66

77
from tests.data.test_defaults import (
88
DEFAULT_API_URL,
9-
DEFAULT_DUE_RESPONSE,
109
PaginatedResults,
1110
)
1211
from tests.utils.test_utils import api_headers, enumerate_async, mock_route
13-
from todoist_api_python.models import Due, Reminder
12+
from todoist_api_python.models import Reminder
1413

1514
if TYPE_CHECKING:
1615
import respx
@@ -101,7 +100,6 @@ async def test_add_reminder(
101100
default_reminder: Reminder,
102101
) -> None:
103102
task_id = "6X7rM8997g3RQmvh"
104-
due = Due.from_dict(DEFAULT_DUE_RESPONSE)
105103

106104
mock_route(
107105
respx_mock,
@@ -111,7 +109,7 @@ async def test_add_reminder(
111109
request_json={
112110
"task_id": task_id,
113111
"reminder_type": "absolute",
114-
"due": due.to_dict(),
112+
"due": {"string": "tomorrow at 12", "lang": "en"},
115113
"service": "push",
116114
},
117115
response_json=default_reminder_response,
@@ -121,7 +119,8 @@ async def test_add_reminder(
121119
new_reminder = todoist_api.add_reminder(
122120
task_id=task_id,
123121
reminder_type="absolute",
124-
due=due,
122+
due_string="tomorrow at 12",
123+
due_lang="en",
125124
service="push",
126125
)
127126

@@ -131,7 +130,8 @@ async def test_add_reminder(
131130
new_reminder = await todoist_api_async.add_reminder(
132131
task_id=task_id,
133132
reminder_type="absolute",
134-
due=due,
133+
due_string="tomorrow at 12",
134+
due_lang="en",
135135
service="push",
136136
)
137137

todoist_api_python/api.py

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
Attachment,
4848
Collaborator,
4949
Comment,
50-
Due,
5150
Label,
5251
LocationReminder,
5352
Project,
@@ -1572,30 +1571,47 @@ def add_reminder(
15721571
*,
15731572
reminder_type: Literal["relative", "absolute"] = "relative",
15741573
minute_offset: int | None = None,
1575-
due: Due | None = None,
1574+
due_string: str | None = None,
1575+
due_date: date | None = None,
1576+
due_datetime: datetime | None = None,
1577+
due_lang: LanguageCode | None = None,
1578+
due_timezone: str | None = None,
15761579
service: Literal["email", "push"] | None = None,
15771580
) -> Reminder:
15781581
"""
15791582
Create a new reminder.
15801583
15811584
For relative reminders, provide `minute_offset`.
1582-
For absolute reminders, provide `due`.
1585+
For absolute reminders, provide due date fields.
15831586
15841587
:param task_id: The ID of the task to add the reminder to.
15851588
:param reminder_type: The type of reminder ("relative" or "absolute").
15861589
:param minute_offset: Minutes before the due date/time to trigger (relative).
1587-
:param due: The absolute due date/time for the reminder (absolute).
1590+
:param due_string: The due date in natural language format (absolute).
1591+
:param due_date: The due date as a date object (absolute).
1592+
:param due_datetime: The due date and time as a datetime object (absolute).
1593+
:param due_lang: Language for parsing the due date.
1594+
:param due_timezone: Timezone for the due date.
15881595
:param service: The notification service ("email" or "push").
15891596
:return: The newly created reminder.
15901597
:raises httpx.HTTPStatusError: If the API request fails.
15911598
"""
15921599
endpoint = get_api_url(REMINDERS_PATH)
15931600

1601+
due = kwargs_without_none(
1602+
string=due_string,
1603+
date=format_date(due_date)
1604+
if due_date is not None
1605+
else (format_datetime(due_datetime) if due_datetime is not None else None),
1606+
lang=due_lang,
1607+
timezone=due_timezone,
1608+
)
1609+
15941610
data = kwargs_without_none(
15951611
task_id=task_id,
15961612
reminder_type=reminder_type,
15971613
minute_offset=minute_offset,
1598-
due=due.to_dict() if due is not None else None,
1614+
due=due or None,
15991615
service=service,
16001616
)
16011617

@@ -1614,7 +1630,11 @@ def update_reminder(
16141630
reminder_id: str,
16151631
*,
16161632
minute_offset: int | None = None,
1617-
due: Due | None = None,
1633+
due_string: str | None = None,
1634+
due_date: date | None = None,
1635+
due_datetime: datetime | None = None,
1636+
due_lang: LanguageCode | None = None,
1637+
due_timezone: str | None = None,
16181638
service: Literal["email", "push"] | None = None,
16191639
) -> Reminder:
16201640
"""
@@ -1624,16 +1644,29 @@ def update_reminder(
16241644
16251645
:param reminder_id: The ID of the reminder to update.
16261646
:param minute_offset: Minutes before the due date/time to trigger.
1627-
:param due: The absolute due date/time for the reminder.
1647+
:param due_string: The due date in natural language format.
1648+
:param due_date: The due date as a date object.
1649+
:param due_datetime: The due date and time as a datetime object.
1650+
:param due_lang: Language for parsing the due date.
1651+
:param due_timezone: Timezone for the due date.
16281652
:param service: The notification service ("email" or "push").
16291653
:return: The updated reminder.
16301654
:raises httpx.HTTPStatusError: If the API request fails.
16311655
"""
16321656
endpoint = get_api_url(f"{REMINDERS_PATH}/{reminder_id}")
16331657

1658+
due = kwargs_without_none(
1659+
string=due_string,
1660+
date=format_date(due_date)
1661+
if due_date is not None
1662+
else (format_datetime(due_datetime) if due_datetime is not None else None),
1663+
lang=due_lang,
1664+
timezone=due_timezone,
1665+
)
1666+
16341667
data = kwargs_without_none(
16351668
minute_offset=minute_offset,
1636-
due=due.to_dict() if due is not None else None,
1669+
due=due or None,
16371670
service=service,
16381671
)
16391672

todoist_api_python/api_async.py

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
Attachment,
4848
Collaborator,
4949
Comment,
50-
Due,
5150
Label,
5251
LocationReminder,
5352
Project,
@@ -1592,30 +1591,47 @@ async def add_reminder(
15921591
*,
15931592
reminder_type: Literal["relative", "absolute"] = "relative",
15941593
minute_offset: int | None = None,
1595-
due: Due | None = None,
1594+
due_string: str | None = None,
1595+
due_date: date | None = None,
1596+
due_datetime: datetime | None = None,
1597+
due_lang: LanguageCode | None = None,
1598+
due_timezone: str | None = None,
15961599
service: Literal["email", "push"] | None = None,
15971600
) -> Reminder:
15981601
"""
15991602
Create a new reminder.
16001603
16011604
For relative reminders, provide `minute_offset`.
1602-
For absolute reminders, provide `due`.
1605+
For absolute reminders, provide due date fields.
16031606
16041607
:param task_id: The ID of the task to add the reminder to.
16051608
:param reminder_type: The type of reminder ("relative" or "absolute").
16061609
:param minute_offset: Minutes before the due date/time to trigger (relative).
1607-
:param due: The absolute due date/time for the reminder (absolute).
1610+
:param due_string: The due date in natural language format (absolute).
1611+
:param due_date: The due date as a date object (absolute).
1612+
:param due_datetime: The due date and time as a datetime object (absolute).
1613+
:param due_lang: Language for parsing the due date.
1614+
:param due_timezone: Timezone for the due date.
16081615
:param service: The notification service ("email" or "push").
16091616
:return: The newly created reminder.
16101617
:raises httpx.HTTPStatusError: If the API request fails.
16111618
"""
16121619
endpoint = get_api_url(REMINDERS_PATH)
16131620

1621+
due = kwargs_without_none(
1622+
string=due_string,
1623+
date=format_date(due_date)
1624+
if due_date is not None
1625+
else (format_datetime(due_datetime) if due_datetime is not None else None),
1626+
lang=due_lang,
1627+
timezone=due_timezone,
1628+
)
1629+
16141630
data = kwargs_without_none(
16151631
task_id=task_id,
16161632
reminder_type=reminder_type,
16171633
minute_offset=minute_offset,
1618-
due=due.to_dict() if due is not None else None,
1634+
due=due or None,
16191635
service=service,
16201636
)
16211637

@@ -1634,7 +1650,11 @@ async def update_reminder(
16341650
reminder_id: str,
16351651
*,
16361652
minute_offset: int | None = None,
1637-
due: Due | None = None,
1653+
due_string: str | None = None,
1654+
due_date: date | None = None,
1655+
due_datetime: datetime | None = None,
1656+
due_lang: LanguageCode | None = None,
1657+
due_timezone: str | None = None,
16381658
service: Literal["email", "push"] | None = None,
16391659
) -> Reminder:
16401660
"""
@@ -1644,16 +1664,29 @@ async def update_reminder(
16441664
16451665
:param reminder_id: The ID of the reminder to update.
16461666
:param minute_offset: Minutes before the due date/time to trigger.
1647-
:param due: The absolute due date/time for the reminder.
1667+
:param due_string: The due date in natural language format.
1668+
:param due_date: The due date as a date object.
1669+
:param due_datetime: The due date and time as a datetime object.
1670+
:param due_lang: Language for parsing the due date.
1671+
:param due_timezone: Timezone for the due date.
16481672
:param service: The notification service ("email" or "push").
16491673
:return: The updated reminder.
16501674
:raises httpx.HTTPStatusError: If the API request fails.
16511675
"""
16521676
endpoint = get_api_url(f"{REMINDERS_PATH}/{reminder_id}")
16531677

1678+
due = kwargs_without_none(
1679+
string=due_string,
1680+
date=format_date(due_date)
1681+
if due_date is not None
1682+
else (format_datetime(due_datetime) if due_datetime is not None else None),
1683+
lang=due_lang,
1684+
timezone=due_timezone,
1685+
)
1686+
16541687
data = kwargs_without_none(
16551688
minute_offset=minute_offset,
1656-
due=due.to_dict() if due is not None else None,
1689+
due=due or None,
16571690
service=service,
16581691
)
16591692

0 commit comments

Comments
 (0)