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.
- {rtmilk-3.0.0 → rtmilk-3.0.2}/.github/workflows/ci.yml +3 -5
- {rtmilk-3.0.0 → rtmilk-3.0.2}/PKG-INFO +2 -3
- {rtmilk-3.0.0 → rtmilk-3.0.2}/pyproject.toml +2 -2
- {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/_sansio.py +6 -2
- {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/_utils.py +2 -2
- {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/client.py +9 -2
- {rtmilk-3.0.0 → rtmilk-3.0.2}/tests/test_client.py +13 -1
- {rtmilk-3.0.0 → rtmilk-3.0.2}/.gitignore +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/LICENSE +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/README.md +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/__init__.py +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/_properties.py +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/_secrets.py +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/api_async.py +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/api_base.py +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/api_sync.py +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/authorization.py +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/filter.py +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/mirror.py +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/models.py +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/src/rtmilk/py.typed +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/tests/conftest.py +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/tests/generate_credentials.py +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/tests/test_api_wrapper.py +0 -0
- {rtmilk-3.0.0 → rtmilk-3.0.2}/tests/test_filter.py +0 -0
- {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:
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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'],
|
|
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'],
|
|
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
|
|
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
|
-
|
|
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
|
|
64
|
-
result.dueDate._LoadValue(task0.due
|
|
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
|
|
File without changes
|
|
File without changes
|