sqlite-export-for-ynab 2.8.0__tar.gz → 2.9.1__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 (25) hide show
  1. {sqlite_export_for_ynab-2.8.0/sqlite_export_for_ynab.egg-info → sqlite_export_for_ynab-2.9.1}/PKG-INFO +5 -11
  2. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/README.md +1 -1
  3. sqlite_export_for_ynab-2.9.1/pyproject.toml +133 -0
  4. sqlite_export_for_ynab-2.9.1/setup.cfg +4 -0
  5. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/sqlite_export_for_ynab/_main.py +38 -87
  6. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1/sqlite_export_for_ynab.egg-info}/PKG-INFO +5 -11
  7. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/sqlite_export_for_ynab.egg-info/SOURCES.txt +0 -2
  8. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/sqlite_export_for_ynab.egg-info/requires.txt +0 -6
  9. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/sqlite_export_for_ynab.egg-info/top_level.txt +1 -0
  10. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/tests/_main_test.py +32 -8
  11. sqlite_export_for_ynab-2.8.0/pyproject.toml +0 -63
  12. sqlite_export_for_ynab-2.8.0/setup.cfg +0 -71
  13. sqlite_export_for_ynab-2.8.0/setup.py +0 -5
  14. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/LICENSE +0 -0
  15. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/sqlite_export_for_ynab/__init__.py +0 -0
  16. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/sqlite_export_for_ynab/__main__.py +0 -0
  17. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/sqlite_export_for_ynab/ddl/__init__.py +0 -0
  18. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/sqlite_export_for_ynab/ddl/create-relations.sql +0 -0
  19. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/sqlite_export_for_ynab/ddl/drop-relations.sql +0 -0
  20. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/sqlite_export_for_ynab/py.typed +0 -0
  21. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/sqlite_export_for_ynab.egg-info/dependency_links.txt +0 -0
  22. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/sqlite_export_for_ynab.egg-info/entry_points.txt +0 -0
  23. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/testing/__init__.py +0 -0
  24. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/testing/fixtures.py +0 -0
  25. {sqlite_export_for_ynab-2.8.0 → sqlite_export_for_ynab-2.9.1}/tests/__init__.py +0 -0
@@ -1,11 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlite_export_for_ynab
3
- Version: 2.8.0
3
+ Version: 2.9.1
4
4
  Summary: SQLite Export for YNAB - Export YNAB Data to SQLite
5
- Home-page: https://github.com/mxr/sqlite-export-for-ynab
6
- Author: Max R
7
- Author-email: maxr@outlook.com
8
- License: MIT
5
+ Author-email: Max R <mxr@users.noreply.github.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/mxr/sqlite-export-for-ynab
9
8
  Keywords: ynab,sqlite,sql,budget,plan,cli
10
9
  Classifier: Programming Language :: Python :: 3
11
10
  Classifier: Programming Language :: Python :: 3 :: Only
@@ -21,11 +20,6 @@ Requires-Dist: asyncio-for-ynab~=1.84.0
21
20
  Requires-Dist: fasteners
22
21
  Requires-Dist: rich>=10
23
22
  Requires-Dist: tenacity
24
- Provides-Extra: dev
25
- Requires-Dist: covdefaults>=2.1.0; extra == "dev"
26
- Requires-Dist: coverage; extra == "dev"
27
- Requires-Dist: pytest; extra == "dev"
28
- Requires-Dist: pytest-asyncio; extra == "dev"
29
23
  Dynamic: license-file
30
24
 
31
25
  # sqlite-export-for-ynab
@@ -272,7 +266,7 @@ WITH interest_by_account AS (
272
266
  SELECT
273
267
  plan_id
274
268
  , account_name
275
- , SUM(-amount_currency) AS total
269
+ , SUM(amount_currency) AS total
276
270
  FROM flat_transactions
277
271
  WHERE
278
272
  TRUE
@@ -242,7 +242,7 @@ WITH interest_by_account AS (
242
242
  SELECT
243
243
  plan_id
244
244
  , account_name
245
- , SUM(-amount_currency) AS total
245
+ , SUM(amount_currency) AS total
246
246
  FROM flat_transactions
247
247
  WHERE
248
248
  TRUE
@@ -0,0 +1,133 @@
1
+ [build-system]
2
+ build-backend = "setuptools.build_meta"
3
+ requires = ["setuptools"]
4
+
5
+ [dependency-groups]
6
+ dev = [
7
+ "covdefaults>=2.1.0",
8
+ "coverage",
9
+ "pytest",
10
+ "pytest-asyncio",
11
+ ]
12
+
13
+ [project]
14
+ authors = [{name = "Max R", email = "mxr@users.noreply.github.com"}]
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3 :: Only",
18
+ "Programming Language :: Python :: Implementation :: CPython",
19
+ "Programming Language :: Python :: Implementation :: PyPy",
20
+ ]
21
+ dependencies = [
22
+ "aiohttp>=3",
23
+ "aiopathlib",
24
+ "aiosqlite",
25
+ "asyncio-for-ynab~=1.84.0",
26
+ "fasteners",
27
+ "rich>=10",
28
+ "tenacity",
29
+ ]
30
+ description = "SQLite Export for YNAB - Export YNAB Data to SQLite"
31
+ keywords = ["ynab", "sqlite", "sql", "budget", "plan", "cli"]
32
+ license = "MIT"
33
+ license-files = ["LICENSE"]
34
+ name = "sqlite_export_for_ynab"
35
+ readme = "README.md"
36
+ requires-python = ">=3.12"
37
+ version = "2.9.1"
38
+
39
+ [project.scripts]
40
+ sqlite-export-for-ynab = "sqlite_export_for_ynab._main:main"
41
+
42
+ [project.urls]
43
+ Homepage = "https://github.com/mxr/sqlite-export-for-ynab"
44
+
45
+ [tool.coverage.run]
46
+ plugins = ["covdefaults"]
47
+
48
+ [tool.mypy]
49
+ check_untyped_defs = true
50
+ disallow_any_generics = true
51
+ disallow_incomplete_defs = true
52
+ disallow_untyped_defs = true
53
+ warn_redundant_casts = true
54
+ warn_unused_ignores = true
55
+
56
+ [[tool.mypy.overrides]]
57
+ disallow_untyped_defs = false
58
+ module = "testing.*"
59
+
60
+ [[tool.mypy.overrides]]
61
+ disallow_untyped_defs = false
62
+ module = "tests.*"
63
+
64
+ [tool.pytest.ini_options]
65
+ asyncio_default_fixture_loop_scope = "function"
66
+
67
+ [tool.ruff]
68
+ target-version = "py312"
69
+
70
+ [tool.ruff.lint]
71
+ extend-select = [
72
+ "UP", # see pyupgrade
73
+ "B", # see flake8-bugbear
74
+ "A", # see flake8-builtins
75
+ "C4", # see flake8-comprehension
76
+ "SIM", # see flake8-simplify
77
+ "TC", # see flake8-type-checking
78
+ ]
79
+
80
+ [tool.setuptools.package-data]
81
+ "*" = ["*.sql"]
82
+ sqlite_export_for_ynab = ["py.typed"]
83
+
84
+ [tool.setuptools.packages]
85
+ find = {}
86
+
87
+ [tool.sqlfluff.layout.type.comma]
88
+ line_position = "leading"
89
+ spacing_before = "touch"
90
+
91
+ [tool.sqlfluff.layout.type.from_clause]
92
+ keyword_line_position = "leading"
93
+
94
+ [tool.sqlfluff.layout.type.when_clause]
95
+ keyword_line_position = "leading"
96
+
97
+ [tool.sqlfluff.rules.capitalisation.functions]
98
+ extended_capitalisation_policy = 'upper'
99
+
100
+ [tool.sqlfluff.rules.capitalisation.identifiers]
101
+ extended_capitalisation_policy = 'lower'
102
+
103
+ [tool.sqlfluff.rules.capitalisation.keywords]
104
+ capitalisation_policy = 'upper'
105
+
106
+ [tool.sqlfluff.rules.capitalisation.literals]
107
+ capitalisation_policy = 'upper'
108
+
109
+ [tool.sqlfluff.rules.convention.not_equal]
110
+ preferred_not_equal_style = "c_style"
111
+
112
+ [tool.sqlfluff.rules.convention.terminator]
113
+ multiline_newline = true
114
+ require_final_semicolon = true
115
+
116
+ [tool.sqlfluff.rules.references.quoting]
117
+ prefer_quoted_keywords = true
118
+
119
+ [tool.tox]
120
+ env_list = ["py", "pypy3", "pre-commit"]
121
+
122
+ [tool.tox.env.pre-commit]
123
+ commands = [["pre-commit", "run", "--all-files", "--show-diff-on-failure"]]
124
+ deps = ["pre-commit-uv"]
125
+ skip_install = true
126
+
127
+ [tool.tox.env_run_base]
128
+ commands = [
129
+ ["coverage", "erase"],
130
+ ["coverage", "run", "-m", "pytest", "{posargs:tests}"],
131
+ ["coverage", "report"],
132
+ ]
133
+ dependency_groups = ["dev"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -46,6 +46,8 @@ from sqlite_export_for_ynab import ddl
46
46
 
47
47
  if TYPE_CHECKING:
48
48
  from collections.abc import AsyncIterator
49
+ from collections.abc import Awaitable
50
+ from collections.abc import Callable
49
51
  from collections.abc import Iterator
50
52
  from collections.abc import Sequence
51
53
 
@@ -305,7 +307,7 @@ async def sync(
305
307
 
306
308
 
307
309
  async def contents(filename: str) -> str:
308
- return await AsyncPath(resources.files(ddl) / filename).read_text()
310
+ return await AsyncPath(str(resources.files(ddl) / filename)).read_text()
309
311
 
310
312
 
311
313
  async def get_relations(cur: aiosqlite.Cursor) -> set[str]:
@@ -603,7 +605,13 @@ async def insert_entries(
603
605
  if not entries:
604
606
  return
605
607
 
606
- entry_keys = tuple(entries[0])
608
+ async with context.con.cursor() as cur:
609
+ await cur.execute(f"PRAGMA table_info({table})")
610
+ table_columns = {row["name"] async for row in cur}
611
+
612
+ # Ignore any keys the YNAB API returns that aren't columns in the DDL so
613
+ # newly-added API fields don't break the insert.
614
+ entry_keys = tuple(k for k in entries[0] if k in table_columns)
607
615
  sql = f"INSERT OR REPLACE INTO {table} ({', '.join(entry_keys + ('plan_id',))}) VALUES ({', '.join('?' * (len(entry_keys) + 1))})"
608
616
 
609
617
  async with context.con.cursor() as cur:
@@ -634,100 +642,43 @@ async def _get_all_ynab(
634
642
  async def _get_plan_data(
635
643
  context: _Context, plan_id: str, lkos: dict[str, int], task_id: TaskID
636
644
  ) -> tuple[str, _YnabPlanData]:
637
- (
638
- accounts,
639
- categories,
640
- payees,
641
- transactions_serverknowledge,
642
- scheduled_transactions,
643
- ) = await asyncio.gather(
644
- _get_accounts(context, plan_id, lkos, task_id),
645
- _get_categories(context, plan_id, lkos, task_id),
646
- _get_payees(context, plan_id, lkos, task_id),
647
- _get_transactions(context, plan_id, lkos, task_id),
648
- _get_scheduled_transactions(context, plan_id, lkos, task_id),
645
+ py = _ProgressYnab(context, plan_id, lkos, task_id)
646
+ accounts, categories, payees, transactions, scheduled = await asyncio.gather(
647
+ py.get(AccountsApi(context.api_client).get_accounts),
648
+ py.get(CategoriesApi(context.api_client).get_categories),
649
+ py.get(PayeesApi(context.api_client).get_payees),
650
+ py.get(TransactionsApi(context.api_client).get_transactions),
651
+ py.get(ScheduledTransactionsApi(context.api_client).get_scheduled_transactions),
649
652
  )
650
- transactions, server_knowledge = transactions_serverknowledge
651
653
  return (
652
654
  plan_id,
653
655
  _YnabPlanData(
654
- accounts=accounts,
655
- category_groups=categories,
656
- payees=payees,
657
- transactions=transactions,
658
- server_knowledge=server_knowledge,
659
- scheduled_transactions=scheduled_transactions,
656
+ accounts=accounts.data.accounts,
657
+ category_groups=categories.data.category_groups,
658
+ payees=payees.data.payees,
659
+ transactions=transactions.data.transactions,
660
+ server_knowledge=transactions.data.server_knowledge,
661
+ scheduled_transactions=scheduled.data.scheduled_transactions,
660
662
  ),
661
663
  )
662
664
 
663
665
 
664
- @retry(stop=stop_after_attempt(3))
665
- async def _get_accounts(
666
- context: _Context, plan_id: str, lkos: dict[str, int], task_id: TaskID
667
- ) -> list[Account]:
668
- resp = await AccountsApi(context.api_client).get_accounts(
669
- plan_id=plan_id, last_knowledge_of_server=lkos.get(plan_id)
670
- )
671
- context.progress.update(task_id, advance=1)
672
- return resp.data.accounts
673
-
674
-
675
- @retry(stop=stop_after_attempt(3))
676
- async def _get_categories(
677
- context: _Context, plan_id: str, lkos: dict[str, int], task_id: TaskID
678
- ) -> list[CategoryGroupWithCategories]:
679
- resp = await CategoriesApi(context.api_client).get_categories(
680
- plan_id=plan_id, last_knowledge_of_server=lkos.get(plan_id)
681
- )
682
- context.progress.update(task_id, advance=1)
683
- return resp.data.category_groups
684
-
666
+ @dataclass(slots=True)
667
+ class _ProgressYnab:
668
+ context: _Context
669
+ plan_id: str
670
+ lkos: dict[str, int]
671
+ task_id: TaskID
685
672
 
686
- @retry(stop=stop_after_attempt(3))
687
- async def _get_payees(
688
- context: _Context, plan_id: str, lkos: dict[str, int], task_id: TaskID
689
- ) -> list[Payee]:
690
- resp = await PayeesApi(context.api_client).get_payees(
691
- plan_id=plan_id, last_knowledge_of_server=lkos.get(plan_id)
692
- )
693
- context.progress.update(task_id, advance=1)
694
- return resp.data.payees
695
-
696
-
697
- @retry(stop=stop_after_attempt(3))
698
- async def _get_transactions(
699
- context: _Context, plan_id: str, lkos: dict[str, int], task_id: TaskID
700
- ) -> tuple[list[TransactionDetail], int]:
701
- resp = await TransactionsApi(context.api_client).get_transactions(
702
- plan_id=plan_id, last_knowledge_of_server=lkos.get(plan_id)
703
- )
704
- context.progress.update(task_id, advance=1)
705
- return resp.data.transactions, resp.data.server_knowledge
706
-
707
-
708
- @retry(stop=stop_after_attempt(3))
709
- async def _get_scheduled_transactions(
710
- context: _Context, plan_id: str, lkos: dict[str, int], task_id: TaskID
711
- ) -> list[ScheduledTransactionDetail]:
712
- resp = await ScheduledTransactionsApi(
713
- context.api_client
714
- ).get_scheduled_transactions(
715
- plan_id=plan_id, last_knowledge_of_server=lkos.get(plan_id)
716
- )
717
- context.progress.update(task_id, advance=1)
718
- return resp.data.scheduled_transactions
719
-
720
-
721
- # @retry(stop=stop_after_attempt(3))
722
- # async def _get_ynab[T](
723
- # context: _Context,
724
- # getter: Callable[..., Awaitable[T]],
725
- # task_id: TaskID,
726
- # ) -> T:
727
- # try:
728
- # return await getter()
729
- # finally:
730
- # context.progress.update(task_id, advance=1)
673
+ @retry(stop=stop_after_attempt(3))
674
+ async def get[T](self, endpoint: Callable[..., Awaitable[T]]) -> T:
675
+ try:
676
+ return await endpoint(
677
+ plan_id=self.plan_id,
678
+ last_knowledge_of_server=self.lkos.get(self.plan_id),
679
+ )
680
+ finally:
681
+ self.context.progress.update(self.task_id, advance=1)
731
682
 
732
683
 
733
684
  def main(
@@ -1,11 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlite_export_for_ynab
3
- Version: 2.8.0
3
+ Version: 2.9.1
4
4
  Summary: SQLite Export for YNAB - Export YNAB Data to SQLite
5
- Home-page: https://github.com/mxr/sqlite-export-for-ynab
6
- Author: Max R
7
- Author-email: maxr@outlook.com
8
- License: MIT
5
+ Author-email: Max R <mxr@users.noreply.github.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/mxr/sqlite-export-for-ynab
9
8
  Keywords: ynab,sqlite,sql,budget,plan,cli
10
9
  Classifier: Programming Language :: Python :: 3
11
10
  Classifier: Programming Language :: Python :: 3 :: Only
@@ -21,11 +20,6 @@ Requires-Dist: asyncio-for-ynab~=1.84.0
21
20
  Requires-Dist: fasteners
22
21
  Requires-Dist: rich>=10
23
22
  Requires-Dist: tenacity
24
- Provides-Extra: dev
25
- Requires-Dist: covdefaults>=2.1.0; extra == "dev"
26
- Requires-Dist: coverage; extra == "dev"
27
- Requires-Dist: pytest; extra == "dev"
28
- Requires-Dist: pytest-asyncio; extra == "dev"
29
23
  Dynamic: license-file
30
24
 
31
25
  # sqlite-export-for-ynab
@@ -272,7 +266,7 @@ WITH interest_by_account AS (
272
266
  SELECT
273
267
  plan_id
274
268
  , account_name
275
- , SUM(-amount_currency) AS total
269
+ , SUM(amount_currency) AS total
276
270
  FROM flat_transactions
277
271
  WHERE
278
272
  TRUE
@@ -1,8 +1,6 @@
1
1
  LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
- setup.cfg
5
- setup.py
6
4
  sqlite_export_for_ynab/__init__.py
7
5
  sqlite_export_for_ynab/__main__.py
8
6
  sqlite_export_for_ynab/_main.py
@@ -5,9 +5,3 @@ asyncio-for-ynab~=1.84.0
5
5
  fasteners
6
6
  rich>=10
7
7
  tenacity
8
-
9
- [dev]
10
- covdefaults>=2.1.0
11
- coverage
12
- pytest
13
- pytest-asyncio
@@ -1,9 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
- from configparser import ConfigParser
3
+ import tomllib
4
4
  from pathlib import Path
5
- from typing import Any
6
- from typing import cast
7
5
  from unittest.mock import AsyncMock
8
6
  from unittest.mock import Mock
9
7
  from unittest.mock import patch
@@ -29,6 +27,7 @@ from sqlite_export_for_ynab._main import get_last_knowledge_of_server
29
27
  from sqlite_export_for_ynab._main import get_relations
30
28
  from sqlite_export_for_ynab._main import insert_accounts
31
29
  from sqlite_export_for_ynab._main import insert_category_groups
30
+ from sqlite_export_for_ynab._main import insert_entries
32
31
  from sqlite_export_for_ynab._main import insert_payees
33
32
  from sqlite_export_for_ynab._main import insert_plans
34
33
  from sqlite_export_for_ynab._main import insert_scheduled_transactions
@@ -453,7 +452,7 @@ async def test_insert_category_group_without_categories(context):
453
452
  await insert_category_groups(
454
453
  context,
455
454
  PLAN_ID_1,
456
- cast("Any", [CATEGORY_GROUPS[0].model_copy(update={"categories": []})]),
455
+ [CATEGORY_GROUPS[0].model_copy(update={"categories": []})],
457
456
  )
458
457
 
459
458
  assert_rows(
@@ -499,6 +498,31 @@ async def test_insert_payees(context):
499
498
  )
500
499
 
501
500
 
501
+ @pytest.mark.asyncio
502
+ async def test_insert_entries_ignores_unknown_keys(context):
503
+ task_id = context.progress.add_task("Payees", total=1)
504
+ entry = {
505
+ "id": PAYEE_ID_1,
506
+ "name": "Payee",
507
+ "transfer_account_id": None,
508
+ "deleted": False,
509
+ "brand_new_api_field": "surprise",
510
+ }
511
+ await insert_entries(context, "payees", PLAN_ID_1, [entry], task_id)
512
+ assert_rows(
513
+ await fetchall(context.con, "SELECT * FROM payees"),
514
+ [
515
+ {
516
+ "id": PAYEE_ID_1,
517
+ "plan_id": PLAN_ID_1,
518
+ "name": "Payee",
519
+ "transfer_account_id": None,
520
+ "deleted": False,
521
+ }
522
+ ],
523
+ )
524
+
525
+
502
526
  @pytest.mark.asyncio
503
527
  async def test_insert_transactions(context):
504
528
  await insert_transactions(context, PLAN_ID_1, [])
@@ -834,7 +858,7 @@ async def test_insert_scheduled_transactions(context):
834
858
  )
835
859
  @pytest.mark.asyncio
836
860
  async def test_get_plan_summaries_retries():
837
- assert await _get_plan_summaries(object()) == PLANS
861
+ assert await _get_plan_summaries(Mock(spec=asyncio_for_ynab.ApiClient)) == PLANS
838
862
 
839
863
 
840
864
  @patch("sqlite_export_for_ynab._main.sync")
@@ -851,9 +875,9 @@ async def test_async_main_parses_full_refresh_and_quiet(sync, tmp_path, monkeypa
851
875
 
852
876
 
853
877
  def test_main_version(capsys):
854
- cp = ConfigParser()
855
- cp.read(Path(__file__).parent.parent / "setup.cfg")
856
- expected_version = cp["metadata"]["version"]
878
+ with open(Path(__file__).parent.parent / "pyproject.toml", "rb") as f:
879
+ data = tomllib.load(f)
880
+ expected_version = data["project"]["version"]
857
881
 
858
882
  with pytest.raises(SystemExit) as excinfo:
859
883
  main(("--version",))
@@ -1,63 +0,0 @@
1
- [tool.mypy]
2
- check_untyped_defs = true
3
- disallow_any_generics = true
4
- disallow_incomplete_defs = true
5
- disallow_untyped_defs = true
6
- warn_redundant_casts = true
7
- warn_unused_ignores = true
8
-
9
- [[tool.mypy.overrides]]
10
- disallow_untyped_defs = false
11
- module = "testing.*"
12
-
13
- [[tool.mypy.overrides]]
14
- disallow_untyped_defs = false
15
- module = "tests.*"
16
-
17
- [tool.pytest.ini_options]
18
- asyncio_default_fixture_loop_scope = "function"
19
-
20
- [tool.ruff]
21
- target-version = "py312"
22
-
23
- [tool.ruff.lint]
24
- extend-select = [
25
- "UP", # see pyupgrade
26
- "B", # see flake8-bugbear
27
- "A", # see flake8-builtins
28
- "C4", # see flake8-comprehension
29
- "SIM", # see flake8-simplify
30
- "TC", # see flake8-type-checking
31
- ]
32
-
33
- [tool.sqlfluff.layout.type.comma]
34
- line_position = "leading"
35
- spacing_before = "touch"
36
-
37
- [tool.sqlfluff.layout.type.from_clause]
38
- keyword_line_position = "leading"
39
-
40
- [tool.sqlfluff.layout.type.when_clause]
41
- keyword_line_position = "leading"
42
-
43
- [tool.sqlfluff.rules.capitalisation.functions]
44
- extended_capitalisation_policy = 'upper'
45
-
46
- [tool.sqlfluff.rules.capitalisation.identifiers]
47
- extended_capitalisation_policy = 'lower'
48
-
49
- [tool.sqlfluff.rules.capitalisation.keywords]
50
- capitalisation_policy = 'upper'
51
-
52
- [tool.sqlfluff.rules.capitalisation.literals]
53
- capitalisation_policy = 'upper'
54
-
55
- [tool.sqlfluff.rules.convention.not_equal]
56
- preferred_not_equal_style = "c_style"
57
-
58
- [tool.sqlfluff.rules.convention.terminator]
59
- multiline_newline = true
60
- require_final_semicolon = true
61
-
62
- [tool.sqlfluff.rules.references.quoting]
63
- prefer_quoted_keywords = true
@@ -1,71 +0,0 @@
1
- [metadata]
2
- name = sqlite_export_for_ynab
3
- version = 2.8.0
4
- description = SQLite Export for YNAB - Export YNAB Data to SQLite
5
- long_description = file: README.md
6
- long_description_content_type = text/markdown
7
- url = https://github.com/mxr/sqlite-export-for-ynab
8
- author = Max R
9
- author_email = maxr@outlook.com
10
- license = MIT
11
- license_files = LICENSE
12
- classifiers =
13
- Programming Language :: Python :: 3
14
- Programming Language :: Python :: 3 :: Only
15
- Programming Language :: Python :: Implementation :: CPython
16
- Programming Language :: Python :: Implementation :: PyPy
17
- keywords = ynab, sqlite, sql, budget, plan, cli
18
-
19
- [options]
20
- packages = find:
21
- install_requires =
22
- aiohttp>=3
23
- aiopathlib
24
- aiosqlite
25
- asyncio-for-ynab~=1.84.0
26
- fasteners
27
- rich>=10
28
- tenacity
29
- python_requires = >=3.12
30
-
31
- [options.entry_points]
32
- console_scripts =
33
- sqlite-export-for-ynab = sqlite_export_for_ynab._main:main
34
-
35
- [options.extras_require]
36
- dev =
37
- covdefaults>=2.1.0
38
- coverage
39
- pytest
40
- pytest-asyncio
41
-
42
- [options.package_data]
43
- * = *.sql
44
- sqlite_export_for_ynab =
45
- py.typed
46
-
47
- [bdist_wheel]
48
- universal = True
49
-
50
- [coverage:run]
51
- plugins = covdefaults
52
-
53
- [tox:tox]
54
- envlist = py,pypy3,pre-commit
55
-
56
- [testenv]
57
- extras = dev
58
- commands =
59
- coverage erase
60
- coverage run -m pytest {posargs:tests}
61
- coverage report
62
-
63
- [testenv:pre-commit]
64
- skip_install = true
65
- deps = pre-commit-uv
66
- commands = pre-commit run --all-files --show-diff-on-failure
67
-
68
- [egg_info]
69
- tag_build =
70
- tag_date = 0
71
-
@@ -1,5 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from setuptools import setup
4
-
5
- setup()