rtmilk 3.0.0__tar.gz → 3.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. {rtmilk-3.0.0 → rtmilk-3.0.2}/.github/workflows/ci.yml +3 -5
  2. {rtmilk-3.0.0 → rtmilk-3.0.2}/PKG-INFO +2 -3
  3. {rtmilk-3.0.0 → rtmilk-3.0.2}/pyproject.toml +2 -2
  4. {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/_sansio.py +6 -2
  5. {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/_utils.py +2 -2
  6. {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/client.py +9 -2
  7. {rtmilk-3.0.0 → rtmilk-3.0.2}/tests/test_client.py +13 -1
  8. {rtmilk-3.0.0 → rtmilk-3.0.2}/.gitignore +0 -0
  9. {rtmilk-3.0.0 → rtmilk-3.0.2}/LICENSE +0 -0
  10. {rtmilk-3.0.0 → rtmilk-3.0.2}/README.md +0 -0
  11. {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/__init__.py +0 -0
  12. {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/_properties.py +0 -0
  13. {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/_secrets.py +0 -0
  14. {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/api_async.py +0 -0
  15. {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/api_base.py +0 -0
  16. {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/api_sync.py +0 -0
  17. {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/authorization.py +0 -0
  18. {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/filter.py +0 -0
  19. {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/mirror.py +0 -0
  20. {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/models.py +0 -0
  21. {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/py.typed +0 -0
  22. {rtmilk-3.0.0 → rtmilk-3.0.2}/tests/conftest.py +0 -0
  23. {rtmilk-3.0.0 → rtmilk-3.0.2}/tests/generate_credentials.py +0 -0
  24. {rtmilk-3.0.0 → rtmilk-3.0.2}/tests/test_api_wrapper.py +0 -0
  25. {rtmilk-3.0.0 → rtmilk-3.0.2}/tests/test_filter.py +0 -0
  26. {rtmilk-3.0.0 → rtmilk-3.0.2}/tests/test_mirror.py +0 -0
@@ -19,12 +19,10 @@ jobs:
19
19
 
20
20
  steps:
21
21
  - uses: actions/checkout@v4
22
- - name: Set up Python ${{ matrix.python-version }}
23
- uses: actions/setup-python@v5
24
- with:
25
- python-version: ${{ matrix.python-version }}
26
22
  - name: Install uv
27
- uses: yezz123/setup-uv@v4
23
+ uses: astral-sh/setup-uv@v3
24
+ - name: Set up Python ${{ matrix.python-version }}
25
+ run: uv python install ${{ matrix.python-version }}
28
26
  - name: Dependencies
29
27
  run: |
30
28
  uv sync --no-cache
@@ -1,10 +1,9 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rtmilk
3
- Version: 3.0.0
3
+ Version: 3.0.2
4
4
  Summary: Remember The Milk API wrapper
5
5
  Project-URL: Homepage, https://github.com/rkhwaja/rtmilk
6
6
  Maintainer-email: Rehan Khwaja <rehan@khwaja.name>
7
- License-File: LICENSE
8
7
  Keywords: Milk,Remember,RememberTheMilk
9
8
  Classifier: Development Status :: 5 - Production/Stable
10
9
  Classifier: Intended Audience :: Developers
@@ -17,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.13
17
16
  Requires-Python: >=3.9
18
17
  Requires-Dist: aiohttp>=3.9
19
18
  Requires-Dist: listdiff>=1.0.2
20
- Requires-Dist: pydantic>=2.4.2
19
+ Requires-Dist: pydantic>=2.8
21
20
  Requires-Dist: requests>=2.23.0
22
21
  Requires-Dist: urllib3>=1.26; python_version >= '3.10'
23
22
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "rtmilk"
3
- version = "3.0.0"
3
+ version = "3.0.2"
4
4
  description = "Remember The Milk API wrapper"
5
5
  maintainers = [
6
6
  { name = "Rehan Khwaja", email = "rehan@khwaja.name" }
@@ -21,7 +21,7 @@ requires-python = ">=3.9"
21
21
  dependencies = [
22
22
  "requests>=2.23.0",
23
23
  "urllib3>=1.26; python_version>='3.10'",
24
- "pydantic>=2.4.2",
24
+ "pydantic>=2.8",
25
25
  "aiohttp>=3.9",
26
26
  "listdiff>=1.0.2",
27
27
  ]
@@ -303,7 +303,9 @@ class TasksSetDueDate(AuthorizedCall):
303
303
  if 'has_due_time' in kwargs:
304
304
  kwargs['has_due_time'] = '1' if kwargs['has_due_time'] else '0'
305
305
  if 'due' in kwargs:
306
- if isinstance(kwargs['due'], (date, datetime)):
306
+ if isinstance(kwargs['due'], datetime):
307
+ kwargs['due'] = _RtmDatetime(kwargs['due'])
308
+ elif isinstance(kwargs['due'], date):
307
309
  kwargs['due'] = _RtmDate(kwargs['due'])
308
310
  else:
309
311
  assert isinstance(kwargs['due'], str)
@@ -340,7 +342,9 @@ class TasksSetStartDate(AuthorizedCall):
340
342
  if 'has_start_time' in kwargs:
341
343
  kwargs['has_start_time'] = '1' if kwargs['has_start_time'] else '0'
342
344
  if 'start' in kwargs:
343
- if isinstance(kwargs['start'], (date, datetime)):
345
+ if isinstance(kwargs['start'], datetime):
346
+ kwargs['start'] = _RtmDatetime(kwargs['start'])
347
+ elif isinstance(kwargs['start'], date):
344
348
  kwargs['start'] = _RtmDate(kwargs['start'])
345
349
  else:
346
350
  assert isinstance(kwargs['start'], str)
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from typing import Annotated, TypeVar
4
4
 
5
5
  from pydantic import BeforeValidator
6
- from pydantic.networks import Url, UrlConstraints
6
+ from pydantic.networks import HttpUrl, UrlConstraints
7
7
 
8
8
  def EmptyStringToNone(value):
9
9
  if value == '':
@@ -18,5 +18,5 @@ EmptyStrToNone = Annotated[
18
18
  ]
19
19
 
20
20
  HttpsUrl = Annotated[
21
- Url, UrlConstraints(allowed_schemes=['https'])
21
+ HttpUrl, UrlConstraints(allowed_schemes=['https'])
22
22
  ]
@@ -53,6 +53,13 @@ class Task:
53
53
  def FilterDate(date_):
54
54
  return datetime.strftime(date_, '%m/%d/%Y')
55
55
 
56
+ def _LoadDate(rtmDate, hasTime):
57
+ if rtmDate is None:
58
+ return None
59
+ if hasTime:
60
+ return rtmDate
61
+ return rtmDate.date()
62
+
56
63
  def _CreateFromTaskSeries(client, listId, taskSeries):
57
64
  _log.info(f'{taskSeries=}')
58
65
  task0 = taskSeries.task[0]
@@ -60,8 +67,8 @@ def _CreateFromTaskSeries(client, listId, taskSeries):
60
67
 
61
68
  result.name._LoadValue(taskSeries.name)
62
69
  result.tags._LoadValue(set(taskSeries.tags.tag) if hasattr(taskSeries.tags, 'tag') else set(taskSeries.tags))
63
- result.startDate._LoadValue(task0.start.date() if task0.start is not None else None) # None means no change
64
- result.dueDate._LoadValue(task0.due.date() if task0.due is not None else None) # None means no change
70
+ result.startDate._LoadValue(_LoadDate(task0.start, task0.has_start_time))
71
+ result.dueDate._LoadValue(_LoadDate(task0.due, task0.has_due_time))
65
72
  result.complete._LoadValue(task0.completed is not None)
66
73
  result.notes._LoadValue([] if isinstance(taskSeries.notes, list) else taskSeries.notes.note)
67
74
  result.createTime = taskSeries.created
@@ -1,4 +1,4 @@
1
- from datetime import date, timedelta
1
+ from datetime import date, datetime, time, timedelta, timezone
2
2
  from uuid import uuid4
3
3
 
4
4
  from pydantic import ValidationError
@@ -58,6 +58,18 @@ def testClientSync(client):
58
58
  assert newTaskToo.startDate.value == dueDate, 'Start date should have been updated'
59
59
  assert newTaskToo.dueDate.value is None, 'Due date should have been updated'
60
60
 
61
+ # Update dates to datetimes
62
+ startDateTime = datetime.combine(dueDate, time(12, 42, 0), timezone.utc) # RTM discards the seconds
63
+ newTask.startDate.Set(startDateTime)
64
+ dueDateTime = datetime.combine(dueDate, time(13, 43, 0), timezone.utc) # RTM discards the seconds
65
+ newTask.dueDate.Set(dueDateTime)
66
+
67
+ tasksWithTitle = client.Get(f'name:"{name}"')
68
+ newTaskToo = tasksWithTitle[0]
69
+ assert len(tasksWithTitle) == 1, f'Should be only 1 task with name: "{name}"\n{tasksWithTitle}'
70
+ assert newTaskToo.startDate.value == startDateTime, 'Start date should have been updated with the time'
71
+ assert newTaskToo.dueDate.value == dueDateTime, 'Due date should have been updated with the time'
72
+
61
73
  newTaskToo.Delete()
62
74
 
63
75
  @mark.asyncio
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes