sqlite-export-for-ynab 2.9.2__tar.gz → 2.9.4__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.
- {sqlite_export_for_ynab-2.9.2/sqlite_export_for_ynab.egg-info → sqlite_export_for_ynab-2.9.4}/PKG-INFO +2 -2
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/pyproject.toml +5 -2
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab/_main.py +85 -8
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4/sqlite_export_for_ynab.egg-info}/PKG-INFO +2 -2
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab.egg-info/requires.txt +1 -1
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/testing/fixtures.py +7 -0
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/tests/_main_test.py +92 -1
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/LICENSE +0 -0
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/README.md +0 -0
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/setup.cfg +0 -0
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab/__init__.py +0 -0
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab/__main__.py +0 -0
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab/ddl/__init__.py +0 -0
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab/ddl/create-relations.sql +0 -0
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab/ddl/drop-relations.sql +0 -0
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab/py.typed +0 -0
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab.egg-info/SOURCES.txt +0 -0
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab.egg-info/dependency_links.txt +0 -0
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab.egg-info/entry_points.txt +0 -0
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab.egg-info/top_level.txt +0 -0
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/testing/__init__.py +0 -0
- {sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/tests/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlite_export_for_ynab
|
|
3
|
-
Version: 2.9.
|
|
3
|
+
Version: 2.9.4
|
|
4
4
|
Summary: SQLite Export for YNAB - Export YNAB Data to SQLite
|
|
5
5
|
Author-email: Max R <mxr@users.noreply.github.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -16,7 +16,7 @@ License-File: LICENSE
|
|
|
16
16
|
Requires-Dist: aiohttp>=3
|
|
17
17
|
Requires-Dist: aiopathlib
|
|
18
18
|
Requires-Dist: aiosqlite
|
|
19
|
-
Requires-Dist: asyncio-for-ynab~=1.
|
|
19
|
+
Requires-Dist: asyncio-for-ynab~=1.85.0
|
|
20
20
|
Requires-Dist: fasteners
|
|
21
21
|
Requires-Dist: rich>=10
|
|
22
22
|
Requires-Dist: tenacity
|
|
@@ -22,7 +22,7 @@ dependencies = [
|
|
|
22
22
|
"aiohttp>=3",
|
|
23
23
|
"aiopathlib",
|
|
24
24
|
"aiosqlite",
|
|
25
|
-
"asyncio-for-ynab~=1.
|
|
25
|
+
"asyncio-for-ynab~=1.85.0",
|
|
26
26
|
"fasteners",
|
|
27
27
|
"rich>=10",
|
|
28
28
|
"tenacity",
|
|
@@ -34,7 +34,7 @@ license-files = ["LICENSE"]
|
|
|
34
34
|
name = "sqlite_export_for_ynab"
|
|
35
35
|
readme = "README.md"
|
|
36
36
|
requires-python = ">=3.12"
|
|
37
|
-
version = "2.9.
|
|
37
|
+
version = "2.9.4"
|
|
38
38
|
|
|
39
39
|
[project.scripts]
|
|
40
40
|
sqlite-export-for-ynab = "sqlite_export_for_ynab._main:main"
|
|
@@ -131,3 +131,6 @@ commands = [
|
|
|
131
131
|
["coverage", "report"],
|
|
132
132
|
]
|
|
133
133
|
dependency_groups = ["dev"]
|
|
134
|
+
|
|
135
|
+
[tool.ty.rules]
|
|
136
|
+
all = "error"
|
{sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab/_main.py
RENAMED
|
@@ -7,6 +7,8 @@ from contextlib import asynccontextmanager
|
|
|
7
7
|
from contextlib import contextmanager
|
|
8
8
|
from dataclasses import dataclass
|
|
9
9
|
from dataclasses import fields
|
|
10
|
+
from datetime import date
|
|
11
|
+
from datetime import timedelta
|
|
10
12
|
from importlib import resources
|
|
11
13
|
from importlib.metadata import version
|
|
12
14
|
from itertools import batched
|
|
@@ -14,6 +16,7 @@ from pathlib import Path
|
|
|
14
16
|
from typing import Any
|
|
15
17
|
from typing import Literal
|
|
16
18
|
from typing import overload
|
|
19
|
+
from typing import override
|
|
17
20
|
from typing import TYPE_CHECKING
|
|
18
21
|
|
|
19
22
|
import aiosqlite
|
|
@@ -34,6 +37,8 @@ from asyncio_for_ynab import ScheduledTransactionDetail
|
|
|
34
37
|
from asyncio_for_ynab import ScheduledTransactionsApi
|
|
35
38
|
from asyncio_for_ynab import TransactionDetail
|
|
36
39
|
from asyncio_for_ynab import TransactionsApi
|
|
40
|
+
from asyncio_for_ynab import TransactionsResponse
|
|
41
|
+
from asyncio_for_ynab import TransactionsResponseData
|
|
37
42
|
from rich.progress import BarColumn
|
|
38
43
|
from rich.progress import Progress
|
|
39
44
|
from rich.progress import TaskID
|
|
@@ -67,6 +72,7 @@ except ImportError: # pragma: no cover
|
|
|
67
72
|
self.separator = separator
|
|
68
73
|
super().__init__(table_column=table_column)
|
|
69
74
|
|
|
75
|
+
@override
|
|
70
76
|
def render(self, task: Task) -> Text:
|
|
71
77
|
"""Show completed/total."""
|
|
72
78
|
completed = int(task.completed)
|
|
@@ -217,8 +223,11 @@ async def _context(
|
|
|
217
223
|
progress = Progress(*_PROGRESS_COLUMNS, disable=quiet)
|
|
218
224
|
lock_path = db.parent / f"{db.name}.lock"
|
|
219
225
|
lock = fasteners.InterProcessLock(lock_path)
|
|
226
|
+
# ApiClient's constructor builds an SSL context (loads certs from disk),
|
|
227
|
+
# so build it off the event loop thread.
|
|
228
|
+
api_client = await asyncio.to_thread(ApiClient, configuration)
|
|
220
229
|
async with (
|
|
221
|
-
|
|
230
|
+
api_client,
|
|
222
231
|
aiosqlite.connect(db) as con,
|
|
223
232
|
):
|
|
224
233
|
con.row_factory = aiosqlite.Row
|
|
@@ -290,9 +299,7 @@ async def sync(
|
|
|
290
299
|
"Plan Data", total=len(plans) * len(_ENDPOINTS)
|
|
291
300
|
)
|
|
292
301
|
|
|
293
|
-
all_data = await _get_all_ynab(
|
|
294
|
-
context, [str(plan.id) for plan in plans], lkos, task
|
|
295
|
-
)
|
|
302
|
+
all_data = await _get_all_ynab(context, plans, lkos, task)
|
|
296
303
|
|
|
297
304
|
_print("Done", quiet=quiet)
|
|
298
305
|
|
|
@@ -630,24 +637,30 @@ async def _get_plan_summaries(api_client: ApiClient) -> list[PlanSummary]:
|
|
|
630
637
|
|
|
631
638
|
|
|
632
639
|
async def _get_all_ynab(
|
|
633
|
-
context: _Context,
|
|
640
|
+
context: _Context, plans: list[PlanSummary], lkos: dict[str, int], task_id: TaskID
|
|
634
641
|
) -> dict[str, _YnabPlanData]:
|
|
635
642
|
return dict(
|
|
636
643
|
await asyncio.gather(
|
|
637
|
-
*(_get_plan_data(context,
|
|
644
|
+
*(_get_plan_data(context, plan, lkos, task_id) for plan in plans)
|
|
638
645
|
)
|
|
639
646
|
)
|
|
640
647
|
|
|
641
648
|
|
|
642
649
|
async def _get_plan_data(
|
|
643
|
-
context: _Context,
|
|
650
|
+
context: _Context, plan: PlanSummary, lkos: dict[str, int], task_id: TaskID
|
|
644
651
|
) -> tuple[str, _YnabPlanData]:
|
|
652
|
+
plan_id = str(plan.id)
|
|
653
|
+
assert plan.first_month is not None
|
|
645
654
|
py = _ProgressYnab(context, plan_id, lkos, task_id)
|
|
646
655
|
accounts, categories, payees, transactions, scheduled = await asyncio.gather(
|
|
647
656
|
py.get(AccountsApi(context.api_client).get_accounts),
|
|
648
657
|
py.get(CategoriesApi(context.api_client).get_categories),
|
|
649
658
|
py.get(PayeesApi(context.api_client).get_payees),
|
|
650
|
-
py.get(
|
|
659
|
+
py.get(
|
|
660
|
+
ChunkedTransactionsApi(
|
|
661
|
+
context.api_client, plan.first_month
|
|
662
|
+
).get_transactions
|
|
663
|
+
),
|
|
651
664
|
py.get(ScheduledTransactionsApi(context.api_client).get_scheduled_transactions),
|
|
652
665
|
)
|
|
653
666
|
return (
|
|
@@ -681,6 +694,70 @@ class _ProgressYnab:
|
|
|
681
694
|
self.context.progress.update(self.task_id, advance=1)
|
|
682
695
|
|
|
683
696
|
|
|
697
|
+
@dataclass(slots=True, frozen=True)
|
|
698
|
+
class ChunkedTransactionsApi:
|
|
699
|
+
api_client: ApiClient
|
|
700
|
+
first_month: date
|
|
701
|
+
|
|
702
|
+
async def get_transactions(
|
|
703
|
+
self, *, plan_id: str, last_knowledge_of_server: int | None
|
|
704
|
+
) -> TransactionsResponse:
|
|
705
|
+
transactions_api = TransactionsApi(self.api_client)
|
|
706
|
+
if last_knowledge_of_server is not None:
|
|
707
|
+
return await transactions_api.get_transactions(
|
|
708
|
+
plan_id=plan_id,
|
|
709
|
+
last_knowledge_of_server=last_knowledge_of_server,
|
|
710
|
+
)
|
|
711
|
+
return await self._get(transactions_api, plan_id)
|
|
712
|
+
|
|
713
|
+
async def _get(
|
|
714
|
+
self, transactions_api: TransactionsApi, plan_id: str
|
|
715
|
+
) -> TransactionsResponse:
|
|
716
|
+
today = date.today()
|
|
717
|
+
responses = await asyncio.gather(
|
|
718
|
+
*(
|
|
719
|
+
self._chunk(transactions_api, plan_id, sd, ud)
|
|
720
|
+
for sd, ud in _quarterly(self.first_month, today)
|
|
721
|
+
)
|
|
722
|
+
)
|
|
723
|
+
transactions = [t for r in responses for t in r.data.transactions]
|
|
724
|
+
ids = [t.id for t in transactions]
|
|
725
|
+
assert len(set(ids)) == len(ids) # paranoid check for no overlap across chunks
|
|
726
|
+
return TransactionsResponse(
|
|
727
|
+
data=TransactionsResponseData(
|
|
728
|
+
transactions=transactions,
|
|
729
|
+
server_knowledge=max(r.data.server_knowledge for r in responses),
|
|
730
|
+
)
|
|
731
|
+
)
|
|
732
|
+
|
|
733
|
+
@retry(stop=stop_after_attempt(3))
|
|
734
|
+
async def _chunk(
|
|
735
|
+
self,
|
|
736
|
+
transactions_api: TransactionsApi,
|
|
737
|
+
plan_id: str,
|
|
738
|
+
since_date: date,
|
|
739
|
+
until_date: date,
|
|
740
|
+
) -> TransactionsResponse:
|
|
741
|
+
return await transactions_api.get_transactions(
|
|
742
|
+
plan_id=plan_id,
|
|
743
|
+
since_date=since_date,
|
|
744
|
+
until_date=until_date,
|
|
745
|
+
)
|
|
746
|
+
|
|
747
|
+
|
|
748
|
+
def _add_months(d: date, months: int) -> date:
|
|
749
|
+
month_index = d.month - 1 + months
|
|
750
|
+
return date(d.year + month_index // 12, month_index % 12 + 1, 1)
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
def _quarterly(first_month: date, today: date) -> Iterator[tuple[date, date]]:
|
|
754
|
+
since_date = first_month
|
|
755
|
+
while since_date <= today:
|
|
756
|
+
until_date = min(_add_months(since_date, 3) - timedelta(days=1), today)
|
|
757
|
+
yield since_date, until_date
|
|
758
|
+
since_date = until_date + timedelta(days=1)
|
|
759
|
+
|
|
760
|
+
|
|
684
761
|
def main(
|
|
685
762
|
argv: Sequence[str] | None = None, *, token_override: str | None = None
|
|
686
763
|
) -> int:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlite_export_for_ynab
|
|
3
|
-
Version: 2.9.
|
|
3
|
+
Version: 2.9.4
|
|
4
4
|
Summary: SQLite Export for YNAB - Export YNAB Data to SQLite
|
|
5
5
|
Author-email: Max R <mxr@users.noreply.github.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -16,7 +16,7 @@ License-File: LICENSE
|
|
|
16
16
|
Requires-Dist: aiohttp>=3
|
|
17
17
|
Requires-Dist: aiopathlib
|
|
18
18
|
Requires-Dist: aiosqlite
|
|
19
|
-
Requires-Dist: asyncio-for-ynab~=1.
|
|
19
|
+
Requires-Dist: asyncio-for-ynab~=1.85.0
|
|
20
20
|
Requires-Dist: fasteners
|
|
21
21
|
Requires-Dist: rich>=10
|
|
22
22
|
Requires-Dist: tenacity
|
|
@@ -37,6 +37,7 @@ PLANS: list[PlanSummary] = [
|
|
|
37
37
|
PlanSummary(
|
|
38
38
|
id=UUID(PLAN_ID_1),
|
|
39
39
|
name="Plan 1",
|
|
40
|
+
first_month=date.fromisoformat("2024-01-01"),
|
|
40
41
|
currency_format=CurrencyFormat(
|
|
41
42
|
currency_symbol="$",
|
|
42
43
|
decimal_digits=2,
|
|
@@ -51,6 +52,7 @@ PLANS: list[PlanSummary] = [
|
|
|
51
52
|
PlanSummary(
|
|
52
53
|
id=UUID(PLAN_ID_2),
|
|
53
54
|
name="Plan 2",
|
|
55
|
+
first_month=date.fromisoformat("2024-01-01"),
|
|
54
56
|
currency_format=CurrencyFormat(
|
|
55
57
|
currency_symbol="$",
|
|
56
58
|
decimal_digits=2,
|
|
@@ -67,6 +69,11 @@ PLANS: list[PlanSummary] = [
|
|
|
67
69
|
SERVER_KNOWLEDGE_1 = 107667
|
|
68
70
|
SERVER_KNOWLEDGE_2 = 107668
|
|
69
71
|
|
|
72
|
+
TRANSACTION_CHUNKS = [
|
|
73
|
+
(date(2021, 1, 1), date(2021, 3, 31)),
|
|
74
|
+
(date(2021, 4, 1), date(2021, 6, 30)),
|
|
75
|
+
]
|
|
76
|
+
|
|
70
77
|
LKOS = {
|
|
71
78
|
PLAN_ID_1: SERVER_KNOWLEDGE_1,
|
|
72
79
|
PLAN_ID_2: SERVER_KNOWLEDGE_2,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import tomllib
|
|
4
|
+
from datetime import date
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
from unittest.mock import AsyncMock
|
|
6
7
|
from unittest.mock import Mock
|
|
@@ -20,8 +21,10 @@ from sqlite_export_for_ynab._main import _ENV_TOKEN
|
|
|
20
21
|
from sqlite_export_for_ynab._main import _get_plan_summaries
|
|
21
22
|
from sqlite_export_for_ynab._main import _PACKAGE
|
|
22
23
|
from sqlite_export_for_ynab._main import _PROGRESS_COLUMNS
|
|
24
|
+
from sqlite_export_for_ynab._main import _quarterly
|
|
23
25
|
from sqlite_export_for_ynab._main import async_main
|
|
24
26
|
from sqlite_export_for_ynab._main import asyncio_for_ynab
|
|
27
|
+
from sqlite_export_for_ynab._main import ChunkedTransactionsApi
|
|
25
28
|
from sqlite_export_for_ynab._main import contents
|
|
26
29
|
from sqlite_export_for_ynab._main import get_last_knowledge_of_server
|
|
27
30
|
from sqlite_export_for_ynab._main import get_relations
|
|
@@ -71,9 +74,11 @@ from testing.fixtures import SCHEDULED_TRANSACTION_ID_3
|
|
|
71
74
|
from testing.fixtures import SCHEDULED_TRANSACTIONS
|
|
72
75
|
from testing.fixtures import scheduled_transactions_response
|
|
73
76
|
from testing.fixtures import SERVER_KNOWLEDGE_1
|
|
77
|
+
from testing.fixtures import SERVER_KNOWLEDGE_2
|
|
74
78
|
from testing.fixtures import SUBTRANSACTION_ID_1
|
|
75
79
|
from testing.fixtures import SUBTRANSACTION_ID_2
|
|
76
80
|
from testing.fixtures import TOKEN
|
|
81
|
+
from testing.fixtures import TRANSACTION_CHUNKS
|
|
77
82
|
from testing.fixtures import TRANSACTION_ID_1
|
|
78
83
|
from testing.fixtures import TRANSACTION_ID_2
|
|
79
84
|
from testing.fixtures import TRANSACTION_ID_3
|
|
@@ -106,6 +111,87 @@ async def context(tmp_path):
|
|
|
106
111
|
yield _Context(progress, con, lock, Mock(spec=asyncio_for_ynab.ApiClient))
|
|
107
112
|
|
|
108
113
|
|
|
114
|
+
@patch("sqlite_export_for_ynab._main.TransactionsApi.get_transactions")
|
|
115
|
+
@pytest.mark.asyncio
|
|
116
|
+
async def test_chunked_transactions_api_uses_last_knowledge_of_server_when_present(
|
|
117
|
+
get_transactions, context
|
|
118
|
+
):
|
|
119
|
+
get_transactions.return_value = transactions_response(
|
|
120
|
+
TRANSACTIONS, SERVER_KNOWLEDGE_1
|
|
121
|
+
)
|
|
122
|
+
chunked_transactions_api = ChunkedTransactionsApi(
|
|
123
|
+
context.api_client, date(2020, 1, 1)
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
response = await chunked_transactions_api.get_transactions(
|
|
127
|
+
plan_id=PLAN_ID_1, last_knowledge_of_server=LKOS[PLAN_ID_1]
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
get_transactions.assert_awaited_once_with(
|
|
131
|
+
plan_id=PLAN_ID_1, last_knowledge_of_server=LKOS[PLAN_ID_1]
|
|
132
|
+
)
|
|
133
|
+
assert response.data.transactions == TRANSACTIONS
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@pytest.mark.parametrize(
|
|
137
|
+
("first_month", "today", "expected_chunks"),
|
|
138
|
+
(
|
|
139
|
+
pytest.param(
|
|
140
|
+
date(2021, 4, 1),
|
|
141
|
+
date(2022, 1, 15),
|
|
142
|
+
[
|
|
143
|
+
(date(2021, 4, 1), date(2021, 6, 30)),
|
|
144
|
+
(date(2021, 7, 1), date(2021, 9, 30)),
|
|
145
|
+
(date(2021, 10, 1), date(2021, 12, 31)),
|
|
146
|
+
(date(2022, 1, 1), date(2022, 1, 15)),
|
|
147
|
+
],
|
|
148
|
+
id="spans-multiple-quarters-with-partial-last-chunk",
|
|
149
|
+
),
|
|
150
|
+
pytest.param(
|
|
151
|
+
date(2024, 1, 1),
|
|
152
|
+
date(2024, 1, 1),
|
|
153
|
+
[(date(2024, 1, 1), date(2024, 1, 1))],
|
|
154
|
+
id="single-day-range",
|
|
155
|
+
),
|
|
156
|
+
),
|
|
157
|
+
)
|
|
158
|
+
def test_quarterly(first_month, today, expected_chunks):
|
|
159
|
+
assert list(_quarterly(first_month, today)) == expected_chunks
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _chunk_merge_test_side_effect(*, plan_id, since_date, until_date):
|
|
163
|
+
assert plan_id == PLAN_ID_1
|
|
164
|
+
assert (since_date, until_date) in TRANSACTION_CHUNKS
|
|
165
|
+
old_transaction, new_transaction, _ = TRANSACTIONS
|
|
166
|
+
if since_date == TRANSACTION_CHUNKS[0][0]:
|
|
167
|
+
return transactions_response([old_transaction], SERVER_KNOWLEDGE_1)
|
|
168
|
+
return transactions_response([new_transaction], SERVER_KNOWLEDGE_2)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@patch("sqlite_export_for_ynab._main._quarterly")
|
|
172
|
+
@patch("sqlite_export_for_ynab._main.TransactionsApi.get_transactions")
|
|
173
|
+
@pytest.mark.asyncio
|
|
174
|
+
async def test_chunked_transactions_api_merges_chunk_responses(
|
|
175
|
+
get_transactions, quarterly_chunks, context
|
|
176
|
+
):
|
|
177
|
+
get_transactions.side_effect = _chunk_merge_test_side_effect
|
|
178
|
+
quarterly_chunks.return_value = iter(TRANSACTION_CHUNKS)
|
|
179
|
+
chunked_transactions_api = ChunkedTransactionsApi(
|
|
180
|
+
context.api_client, date(2021, 1, 1)
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
response = await chunked_transactions_api.get_transactions(
|
|
184
|
+
plan_id=PLAN_ID_1, last_knowledge_of_server=None
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
old_transaction, new_transaction, _ = TRANSACTIONS
|
|
188
|
+
assert {t.id for t in response.data.transactions} == {
|
|
189
|
+
old_transaction.id,
|
|
190
|
+
new_transaction.id,
|
|
191
|
+
}
|
|
192
|
+
assert response.data.server_knowledge == SERVER_KNOWLEDGE_2
|
|
193
|
+
|
|
194
|
+
|
|
109
195
|
@pytest.mark.parametrize(
|
|
110
196
|
("xdg_data_home", "expected_prefix"),
|
|
111
197
|
(
|
|
@@ -1109,7 +1195,12 @@ async def test_sync_no_data_quiet(tmp_path, capsys):
|
|
|
1109
1195
|
)
|
|
1110
1196
|
@patch(
|
|
1111
1197
|
"sqlite_export_for_ynab._main.TransactionsApi.get_transactions",
|
|
1112
|
-
new=AsyncMock(
|
|
1198
|
+
new=AsyncMock(
|
|
1199
|
+
side_effect=lambda *, plan_id, since_date, until_date: transactions_response(
|
|
1200
|
+
[t for t in TRANSACTIONS if since_date <= t.var_date <= until_date],
|
|
1201
|
+
SERVER_KNOWLEDGE_1,
|
|
1202
|
+
)
|
|
1203
|
+
),
|
|
1113
1204
|
)
|
|
1114
1205
|
@patch(
|
|
1115
1206
|
"sqlite_export_for_ynab._main.ScheduledTransactionsApi.get_scheduled_transactions",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab/__init__.py
RENAMED
|
File without changes
|
{sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab/__main__.py
RENAMED
|
File without changes
|
{sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab/ddl/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sqlite_export_for_ynab-2.9.2 → sqlite_export_for_ynab-2.9.4}/sqlite_export_for_ynab/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|