sqlite-export-for-ynab 2.9.6__tar.gz → 2.9.8__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 (23) hide show
  1. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/LICENSE +0 -2
  2. {sqlite_export_for_ynab-2.9.6/sqlite_export_for_ynab.egg-info → sqlite_export_for_ynab-2.9.8}/PKG-INFO +37 -20
  3. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/README.md +32 -16
  4. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/pyproject.toml +51 -53
  5. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/sqlite_export_for_ynab/_main.py +27 -7
  6. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8/sqlite_export_for_ynab.egg-info}/PKG-INFO +37 -20
  7. sqlite_export_for_ynab-2.9.8/sqlite_export_for_ynab.egg-info/requires.txt +10 -0
  8. sqlite_export_for_ynab-2.9.6/sqlite_export_for_ynab.egg-info/requires.txt +0 -7
  9. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/setup.cfg +0 -0
  10. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/sqlite_export_for_ynab/__init__.py +0 -0
  11. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/sqlite_export_for_ynab/__main__.py +0 -0
  12. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/sqlite_export_for_ynab/ddl/__init__.py +0 -0
  13. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/sqlite_export_for_ynab/ddl/create-relations.sql +0 -0
  14. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/sqlite_export_for_ynab/ddl/drop-relations.sql +0 -0
  15. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/sqlite_export_for_ynab/py.typed +0 -0
  16. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/sqlite_export_for_ynab.egg-info/SOURCES.txt +0 -0
  17. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/sqlite_export_for_ynab.egg-info/dependency_links.txt +0 -0
  18. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/sqlite_export_for_ynab.egg-info/entry_points.txt +0 -0
  19. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/sqlite_export_for_ynab.egg-info/top_level.txt +0 -0
  20. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/testing/__init__.py +0 -0
  21. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/testing/fixtures.py +0 -0
  22. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/tests/__init__.py +0 -0
  23. {sqlite_export_for_ynab-2.9.6 → sqlite_export_for_ynab-2.9.8}/tests/_main_test.py +0 -0
@@ -1,5 +1,3 @@
1
- MIT License
2
-
3
1
  Copyright (c) 2024 Max R
4
2
 
5
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1,36 +1,39 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlite_export_for_ynab
3
- Version: 2.9.6
3
+ Version: 2.9.8
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
7
7
  Project-URL: Homepage, https://github.com/mxr/sqlite-export-for-ynab
8
- Keywords: ynab,sqlite,sql,budget,plan,cli
8
+ Keywords: budget,cli,plan,sql,sqlite,ynab
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Programming Language :: Python :: 3 :: Only
11
11
  Classifier: Programming Language :: Python :: Implementation :: CPython
12
12
  Classifier: Programming Language :: Python :: Implementation :: PyPy
13
- Requires-Python: >=3.12
13
+ Requires-Python: >=3.11
14
14
  Description-Content-Type: text/markdown
15
15
  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.86.0
19
+ Requires-Dist: asyncio-for-ynab~=1.87.0
20
20
  Requires-Dist: fasteners
21
21
  Requires-Dist: rich>=10
22
22
  Requires-Dist: tenacity
23
+ Requires-Dist: typing-extensions; python_version < "3.12"
23
24
  Dynamic: license-file
24
25
 
25
26
  # sqlite-export-for-ynab
26
27
 
27
- [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/mxr/sqlite-export-for-ynab/main.svg)](https://results.pre-commit.ci/latest/github/mxr/sqlite-export-for-ynab/main) [![codecov](https://codecov.io/github/mxr/sqlite-export-for-ynab/graph/badge.svg?token=NVCP6RDKSH)](https://codecov.io/github/mxr/sqlite-export-for-ynab)
28
+ [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/mxr/sqlite-export-for-ynab/main.svg)](https://results.pre-commit.ci/latest/github/mxr/sqlite-export-for-ynab/main)
29
+ [![codecov](https://codecov.io/github/mxr/sqlite-export-for-ynab/graph/badge.svg?token=NVCP6RDKSH)](https://codecov.io/github/mxr/sqlite-export-for-ynab)
28
30
 
29
31
  SQLite Export for YNAB - Export YNAB Budget Data to SQLite
30
32
 
31
33
  ## What This Does
32
34
 
33
- Export all your [YNAB](https://ynab.com/) plans to a local [SQLite](https://www.sqlite.org/) DB. Then you can query your data with any tools compatible with SQLite.
35
+ Export all your [YNAB](https://ynab.com/) plans to a local [SQLite](https://www.sqlite.org/) DB. Then you can query your
36
+ data with any tools compatible with SQLite.
34
37
 
35
38
  ## Installation
36
39
 
@@ -42,7 +45,8 @@ $ pip install sqlite-export-for-ynab
42
45
 
43
46
  ### CLI
44
47
 
45
- Provision a [YNAB Personal Access Token](https://api.ynab.com/#personal-access-tokens) and save it as an environment variable.
48
+ Provision a [YNAB Personal Access Token](https://api.ynab.com/#personal-access-tokens) and save it as an environment
49
+ variable.
46
50
 
47
51
  ```console
48
52
  $ export YNAB_PERSONAL_ACCESS_TOKEN="..."
@@ -54,17 +58,22 @@ Run the tool from the terminal to download your plans:
54
58
  $ sqlite-export-for-ynab
55
59
  ```
56
60
 
57
- Running it again will pull only data that changed since the last pull (this is done with [Delta Requests](https://api.ynab.com/#deltas)). If you want to wipe the DB and pull all data again use the `--full-refresh` flag.
58
- Pass `--quiet` to suppress all CLI output, including progress bars.
61
+ Running it again will pull only data that changed since the last pull (this is done with
62
+ [Delta Requests](https://api.ynab.com/#deltas)). If you want to wipe the DB and pull all data again use the
63
+ `--full-refresh` flag. Pass `--quiet` to suppress all CLI output, including progress bars.
59
64
 
60
65
  <a id="db-path"></a>You can specify the DB path with the following options
66
+
61
67
  1. The `--db` flag.
62
- 1. The `XDG_DATA_HOME` variable (see the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/latest/index.html)). In that case the DB is saved in `"${XDG_DATA_HOME}"/sqlite-export-for-ynab/db.sqlite`.
63
- 1. If neither is set, the DB is saved in `~/.local/share/sqlite-export-for-ynab/db.sqlite`.
68
+ 2. The `XDG_DATA_HOME` variable (see the
69
+ [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/latest/index.html)). In that
70
+ case the DB is saved in `"${XDG_DATA_HOME}"/sqlite-export-for-ynab/db.sqlite`.
71
+ 3. If neither is set, the DB is saved in `~/.local/share/sqlite-export-for-ynab/db.sqlite`.
64
72
 
65
73
  ### Library
66
74
 
67
- The library exposes the package `sqlite_export_for_ynab` and two functions - `default_db_path` and `sync`. You can use them as follows:
75
+ The library exposes the package `sqlite_export_for_ynab` and two functions - `default_db_path` and `sync`. You can use
76
+ them as follows:
68
77
 
69
78
  ```python
70
79
  import asyncio
@@ -82,11 +91,17 @@ asyncio.run(sync(token, db, full_refresh))
82
91
 
83
92
  ## Relations
84
93
 
85
- The relations are defined in [create-relations.sql](sqlite_export_for_ynab/ddl/create-relations.sql). They are 1:1 with [YNAB's OpenAPI Spec](https://api.ynab.com/papi/open_api_spec.yaml) (ex: transactions, accounts, etc) with some additions:
94
+ The relations are defined in [create-relations.sql](sqlite_export_for_ynab/ddl/create-relations.sql). They are 1:1 with
95
+ [YNAB's OpenAPI Spec](https://api.ynab.com/papi/open_api_spec.yaml) (ex: transactions, accounts, etc) with some
96
+ additions:
86
97
 
87
- 1. Some objects are pulled out into their own tables so they can be more cleanly modeled in SQLite (ex: subtransactions, loan account periodic values).
88
- 1. Foreign keys are added as needed (ex: plan ID, transaction ID) so data across plans remains separate.
89
- 1. Two new views called `flat_transactions` and `scheduled_flat_transactions`. These allow you to query split and non-split transactions easily, without needing to also query `subtransactions` and `scheduled_subtransactions` respectively. They also filter out deleted/unapproved transactions/subtransactions and project payee/category fields to make querying more ergonomic.
98
+ 1. Some objects are pulled out into their own tables so they can be more cleanly modeled in SQLite (ex: subtransactions,
99
+ loan account periodic values).
100
+ 2. Foreign keys are added as needed (ex: plan ID, transaction ID) so data across plans remains separate.
101
+ 3. Two new views called `flat_transactions` and `scheduled_flat_transactions`. These allow you to query split and
102
+ non-split transactions easily, without needing to also query `subtransactions` and `scheduled_subtransactions`
103
+ respectively. They also filter out deleted/unapproved transactions/subtransactions and project payee/category fields
104
+ to make querying more ergonomic.
90
105
 
91
106
  ## Querying
92
107
 
@@ -96,10 +111,10 @@ You can issue queries with typical SQLite tools. *`sqlite-export-for-ynab` delib
96
111
 
97
112
  You can run the queries from this README using a tool like [`mdq`](https://github.com/yshavit/mdq). For example:
98
113
 
99
- ```console
114
+ ````console
100
115
  $ mdq '```sql dupes' path/to/sqlite-export-for-ynab/README.md -o plain \
101
116
  | sqlite3 path/to/sqlite-export-for-ynab/db.sqlite
102
- ```
117
+ ````
103
118
 
104
119
  The DB path is documented [above](#db-path).
105
120
 
@@ -233,7 +248,7 @@ FROM (
233
248
  ;
234
249
  ```
235
250
 
236
- To estimate taxable interest for a given year[^1]:
251
+ To estimate taxable interest for a given year\[^1\]:
237
252
 
238
253
  ```sql
239
254
  -- Parameters expected by this query:
@@ -591,4 +606,6 @@ WHERE
591
606
  ;
592
607
  ```
593
608
 
594
- [^1]: This query is a rough estimate based on YNAB data and optional user inputs. It is not financial advice, tax advice, or a substitute for Forms 1099-INT, brokerage statements, bank records, or guidance from a qualified professional.
609
+ \[^1\]: This query is a rough estimate based on YNAB data and optional user inputs. It is not financial advice, tax
610
+ advice, or a substitute for Forms 1099-INT, brokerage statements, bank records, or guidance from a qualified
611
+ professional.
@@ -1,12 +1,14 @@
1
1
  # sqlite-export-for-ynab
2
2
 
3
- [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/mxr/sqlite-export-for-ynab/main.svg)](https://results.pre-commit.ci/latest/github/mxr/sqlite-export-for-ynab/main) [![codecov](https://codecov.io/github/mxr/sqlite-export-for-ynab/graph/badge.svg?token=NVCP6RDKSH)](https://codecov.io/github/mxr/sqlite-export-for-ynab)
3
+ [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/mxr/sqlite-export-for-ynab/main.svg)](https://results.pre-commit.ci/latest/github/mxr/sqlite-export-for-ynab/main)
4
+ [![codecov](https://codecov.io/github/mxr/sqlite-export-for-ynab/graph/badge.svg?token=NVCP6RDKSH)](https://codecov.io/github/mxr/sqlite-export-for-ynab)
4
5
 
5
6
  SQLite Export for YNAB - Export YNAB Budget Data to SQLite
6
7
 
7
8
  ## What This Does
8
9
 
9
- Export all your [YNAB](https://ynab.com/) plans to a local [SQLite](https://www.sqlite.org/) DB. Then you can query your data with any tools compatible with SQLite.
10
+ Export all your [YNAB](https://ynab.com/) plans to a local [SQLite](https://www.sqlite.org/) DB. Then you can query your
11
+ data with any tools compatible with SQLite.
10
12
 
11
13
  ## Installation
12
14
 
@@ -18,7 +20,8 @@ $ pip install sqlite-export-for-ynab
18
20
 
19
21
  ### CLI
20
22
 
21
- Provision a [YNAB Personal Access Token](https://api.ynab.com/#personal-access-tokens) and save it as an environment variable.
23
+ Provision a [YNAB Personal Access Token](https://api.ynab.com/#personal-access-tokens) and save it as an environment
24
+ variable.
22
25
 
23
26
  ```console
24
27
  $ export YNAB_PERSONAL_ACCESS_TOKEN="..."
@@ -30,17 +33,22 @@ Run the tool from the terminal to download your plans:
30
33
  $ sqlite-export-for-ynab
31
34
  ```
32
35
 
33
- Running it again will pull only data that changed since the last pull (this is done with [Delta Requests](https://api.ynab.com/#deltas)). If you want to wipe the DB and pull all data again use the `--full-refresh` flag.
34
- Pass `--quiet` to suppress all CLI output, including progress bars.
36
+ Running it again will pull only data that changed since the last pull (this is done with
37
+ [Delta Requests](https://api.ynab.com/#deltas)). If you want to wipe the DB and pull all data again use the
38
+ `--full-refresh` flag. Pass `--quiet` to suppress all CLI output, including progress bars.
35
39
 
36
40
  <a id="db-path"></a>You can specify the DB path with the following options
41
+
37
42
  1. The `--db` flag.
38
- 1. The `XDG_DATA_HOME` variable (see the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/latest/index.html)). In that case the DB is saved in `"${XDG_DATA_HOME}"/sqlite-export-for-ynab/db.sqlite`.
39
- 1. If neither is set, the DB is saved in `~/.local/share/sqlite-export-for-ynab/db.sqlite`.
43
+ 2. The `XDG_DATA_HOME` variable (see the
44
+ [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/latest/index.html)). In that
45
+ case the DB is saved in `"${XDG_DATA_HOME}"/sqlite-export-for-ynab/db.sqlite`.
46
+ 3. If neither is set, the DB is saved in `~/.local/share/sqlite-export-for-ynab/db.sqlite`.
40
47
 
41
48
  ### Library
42
49
 
43
- The library exposes the package `sqlite_export_for_ynab` and two functions - `default_db_path` and `sync`. You can use them as follows:
50
+ The library exposes the package `sqlite_export_for_ynab` and two functions - `default_db_path` and `sync`. You can use
51
+ them as follows:
44
52
 
45
53
  ```python
46
54
  import asyncio
@@ -58,11 +66,17 @@ asyncio.run(sync(token, db, full_refresh))
58
66
 
59
67
  ## Relations
60
68
 
61
- The relations are defined in [create-relations.sql](sqlite_export_for_ynab/ddl/create-relations.sql). They are 1:1 with [YNAB's OpenAPI Spec](https://api.ynab.com/papi/open_api_spec.yaml) (ex: transactions, accounts, etc) with some additions:
69
+ The relations are defined in [create-relations.sql](sqlite_export_for_ynab/ddl/create-relations.sql). They are 1:1 with
70
+ [YNAB's OpenAPI Spec](https://api.ynab.com/papi/open_api_spec.yaml) (ex: transactions, accounts, etc) with some
71
+ additions:
62
72
 
63
- 1. Some objects are pulled out into their own tables so they can be more cleanly modeled in SQLite (ex: subtransactions, loan account periodic values).
64
- 1. Foreign keys are added as needed (ex: plan ID, transaction ID) so data across plans remains separate.
65
- 1. Two new views called `flat_transactions` and `scheduled_flat_transactions`. These allow you to query split and non-split transactions easily, without needing to also query `subtransactions` and `scheduled_subtransactions` respectively. They also filter out deleted/unapproved transactions/subtransactions and project payee/category fields to make querying more ergonomic.
73
+ 1. Some objects are pulled out into their own tables so they can be more cleanly modeled in SQLite (ex: subtransactions,
74
+ loan account periodic values).
75
+ 2. Foreign keys are added as needed (ex: plan ID, transaction ID) so data across plans remains separate.
76
+ 3. Two new views called `flat_transactions` and `scheduled_flat_transactions`. These allow you to query split and
77
+ non-split transactions easily, without needing to also query `subtransactions` and `scheduled_subtransactions`
78
+ respectively. They also filter out deleted/unapproved transactions/subtransactions and project payee/category fields
79
+ to make querying more ergonomic.
66
80
 
67
81
  ## Querying
68
82
 
@@ -72,10 +86,10 @@ You can issue queries with typical SQLite tools. *`sqlite-export-for-ynab` delib
72
86
 
73
87
  You can run the queries from this README using a tool like [`mdq`](https://github.com/yshavit/mdq). For example:
74
88
 
75
- ```console
89
+ ````console
76
90
  $ mdq '```sql dupes' path/to/sqlite-export-for-ynab/README.md -o plain \
77
91
  | sqlite3 path/to/sqlite-export-for-ynab/db.sqlite
78
- ```
92
+ ````
79
93
 
80
94
  The DB path is documented [above](#db-path).
81
95
 
@@ -209,7 +223,7 @@ FROM (
209
223
  ;
210
224
  ```
211
225
 
212
- To estimate taxable interest for a given year[^1]:
226
+ To estimate taxable interest for a given year\[^1\]:
213
227
 
214
228
  ```sql
215
229
  -- Parameters expected by this query:
@@ -567,4 +581,6 @@ WHERE
567
581
  ;
568
582
  ```
569
583
 
570
- [^1]: This query is a rough estimate based on YNAB data and optional user inputs. It is not financial advice, tax advice, or a substitute for Forms 1099-INT, brokerage statements, bank records, or guidance from a qualified professional.
584
+ \[^1\]: This query is a rough estimate based on YNAB data and optional user inputs. It is not financial advice, tax
585
+ advice, or a substitute for Forms 1099-INT, brokerage statements, bank records, or guidance from a qualified
586
+ professional.
@@ -1,17 +1,13 @@
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
1
  [project]
14
- authors = [{name = "Max R", email = "mxr@users.noreply.github.com"}]
2
+ name = "sqlite_export_for_ynab"
3
+ version = "2.9.8"
4
+ description = "SQLite Export for YNAB - Export YNAB Data to SQLite"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11" # generated by mxr/base
7
+ license = "MIT" # generated by mxr/base
8
+ license-files = ["LICENSE"] # generated by mxr/base
9
+ authors = [{ name = "Max R", email = "mxr@users.noreply.github.com" }] # generated by mxr/base
10
+ keywords = ["budget", "cli", "plan", "sql", "sqlite", "ynab"]
15
11
  classifiers = [
16
12
  "Programming Language :: Python :: 3",
17
13
  "Programming Language :: Python :: 3 :: Only",
@@ -22,30 +18,35 @@ dependencies = [
22
18
  "aiohttp>=3",
23
19
  "aiopathlib",
24
20
  "aiosqlite",
25
- "asyncio-for-ynab~=1.86.0",
21
+ "asyncio-for-ynab~=1.87.0",
26
22
  "fasteners",
27
23
  "rich>=10",
28
24
  "tenacity",
25
+ "typing-extensions; python_version<'3.12'",
29
26
  ]
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.6"
27
+
28
+ [project.urls] # generated by mxr/base
29
+ Homepage = "https://github.com/mxr/sqlite-export-for-ynab"
38
30
 
39
31
  [project.scripts]
40
32
  sqlite-export-for-ynab = "sqlite_export_for_ynab._main:main"
41
33
 
42
- [project.urls]
43
- Homepage = "https://github.com/mxr/sqlite-export-for-ynab"
34
+ [dependency-groups]
35
+ dev = [
36
+ "covdefaults>=2.1.0",
37
+ "coverage",
38
+ "pytest",
39
+ "pytest-asyncio",
40
+ ]
44
41
 
45
- [tool.coverage.run]
42
+ [build-system] # generated by mxr/base
43
+ requires = ["setuptools"]
44
+ build-backend = "setuptools.build_meta"
45
+
46
+ [tool.coverage.run] # generated by mxr/base
46
47
  plugins = ["covdefaults"]
47
48
 
48
- [tool.mypy]
49
+ [tool.mypy] # generated by mxr/base
49
50
  check_untyped_defs = true
50
51
  disallow_any_generics = true
51
52
  disallow_incomplete_defs = true
@@ -53,21 +54,18 @@ disallow_untyped_defs = true
53
54
  warn_redundant_casts = true
54
55
  warn_unused_ignores = true
55
56
 
56
- [[tool.mypy.overrides]]
57
+ [[tool.mypy.overrides]] # generated by mxr/base
57
58
  disallow_untyped_defs = false
58
59
  module = "testing.*"
59
60
 
60
- [[tool.mypy.overrides]]
61
+ [[tool.mypy.overrides]] # generated by mxr/base
61
62
  disallow_untyped_defs = false
62
63
  module = "tests.*"
63
64
 
64
65
  [tool.pytest.ini_options]
65
66
  asyncio_default_fixture_loop_scope = "function"
66
67
 
67
- [tool.ruff]
68
- target-version = "py312"
69
-
70
- [tool.ruff.lint]
68
+ [tool.ruff.lint] # generated by mxr/base
71
69
  extend-select = [
72
70
  "A", # see flake8-builtins
73
71
  "B", # see flake8-bugbear
@@ -78,7 +76,7 @@ extend-select = [
78
76
  "UP", # see pyupgrade
79
77
  ]
80
78
 
81
- [tool.ruff.lint.isort]
79
+ [tool.ruff.lint.isort] # generated by mxr/base
82
80
  force-single-line = true
83
81
  required-imports = ["from __future__ import annotations"]
84
82
 
@@ -86,50 +84,50 @@ required-imports = ["from __future__ import annotations"]
86
84
  sqlite_export_for_ynab = ["py.typed"]
87
85
  "sqlite_export_for_ynab.ddl" = ["*.sql"]
88
86
 
89
- [tool.setuptools.packages]
87
+ [tool.setuptools.packages] # generated by mxr/base
90
88
  find = {}
91
89
 
92
- [tool.sqlfluff.layout.type.comma]
90
+ [tool.sqlfluff.layout.type.comma] # generated by mxr/base
93
91
  line_position = "leading"
94
92
  spacing_before = "touch"
95
93
 
96
- [tool.sqlfluff.layout.type.from_clause]
94
+ [tool.sqlfluff.layout.type.from_clause] # generated by mxr/base
97
95
  keyword_line_position = "leading"
98
96
 
99
- [tool.sqlfluff.layout.type.when_clause]
97
+ [tool.sqlfluff.layout.type.when_clause] # generated by mxr/base
100
98
  keyword_line_position = "leading"
101
99
 
102
- [tool.sqlfluff.rules.capitalisation.functions]
103
- extended_capitalisation_policy = 'upper'
100
+ [tool.sqlfluff.rules.capitalisation.functions] # generated by mxr/base
101
+ extended_capitalisation_policy = "upper"
104
102
 
105
- [tool.sqlfluff.rules.capitalisation.identifiers]
106
- extended_capitalisation_policy = 'lower'
103
+ [tool.sqlfluff.rules.capitalisation.identifiers] # generated by mxr/base
104
+ extended_capitalisation_policy = "lower"
107
105
 
108
- [tool.sqlfluff.rules.capitalisation.keywords]
109
- capitalisation_policy = 'upper'
106
+ [tool.sqlfluff.rules.capitalisation.keywords] # generated by mxr/base
107
+ capitalisation_policy = "upper"
110
108
 
111
- [tool.sqlfluff.rules.capitalisation.literals]
112
- capitalisation_policy = 'upper'
109
+ [tool.sqlfluff.rules.capitalisation.literals] # generated by mxr/base
110
+ capitalisation_policy = "upper"
113
111
 
114
- [tool.sqlfluff.rules.convention.not_equal]
112
+ [tool.sqlfluff.rules.convention.not_equal] # generated by mxr/base
115
113
  preferred_not_equal_style = "c_style"
116
114
 
117
- [tool.sqlfluff.rules.convention.terminator]
115
+ [tool.sqlfluff.rules.convention.terminator] # generated by mxr/base
118
116
  multiline_newline = true
119
117
  require_final_semicolon = true
120
118
 
121
- [tool.sqlfluff.rules.references.quoting]
119
+ [tool.sqlfluff.rules.references.quoting] # generated by mxr/base
122
120
  prefer_quoted_keywords = true
123
121
 
124
- [tool.tox]
125
- env_list = ["py", "pypy3", "pre-commit"]
122
+ [tool.tox] # generated by mxr/base
123
+ env_list = ["py", "pre-commit"]
126
124
 
127
- [tool.tox.env.pre-commit]
125
+ [tool.tox.env.pre-commit] # generated by mxr/base
128
126
  commands = [["pre-commit", "run", "--all-files", "--show-diff-on-failure"]]
129
127
  deps = ["pre-commit-uv"]
130
128
  skip_install = true
131
129
 
132
- [tool.tox.env_run_base]
130
+ [tool.tox.env_run_base] # generated by mxr/base
133
131
  commands = [
134
132
  ["coverage", "erase"],
135
133
  ["coverage", "run", "-m", "pytest", "{posargs:tests}"],
@@ -137,5 +135,5 @@ commands = [
137
135
  ]
138
136
  dependency_groups = ["dev"]
139
137
 
140
- [tool.ty.rules]
138
+ [tool.ty.rules] # generated by mxr/base
141
139
  all = "error"
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  import argparse
4
4
  import asyncio
5
5
  import os
6
+ import sys
6
7
  from contextlib import asynccontextmanager
7
8
  from contextlib import contextmanager
8
9
  from dataclasses import dataclass
@@ -12,14 +13,14 @@ from datetime import datetime
12
13
  from datetime import timedelta
13
14
  from importlib import resources
14
15
  from importlib.metadata import version
15
- from itertools import batched
16
16
  from pathlib import Path
17
17
  from typing import TYPE_CHECKING
18
18
  from typing import Any
19
19
  from typing import Literal
20
+ from typing import TypeVar
21
+ from typing import cast
20
22
  from typing import get_args
21
23
  from typing import overload
22
- from typing import override
23
24
 
24
25
  import aiosqlite
25
26
  import asyncio_for_ynab # noqa: F401
@@ -55,11 +56,30 @@ if TYPE_CHECKING:
55
56
  from collections.abc import AsyncIterator
56
57
  from collections.abc import Awaitable
57
58
  from collections.abc import Callable
59
+ from collections.abc import Iterable
58
60
  from collections.abc import Iterator
59
61
  from collections.abc import Sequence
60
62
 
63
+ _T = TypeVar("_T")
64
+
65
+ if sys.version_info >= (3, 12): # pragma: >=3.12 cover
66
+ from itertools import batched
67
+ from typing import override
68
+ else: # pragma: <3.12 cover
69
+ from itertools import islice
70
+
71
+ from typing_extensions import override
72
+
73
+ def batched(iterable: Iterable[_T], n: int) -> Iterator[tuple[_T, ...]]:
74
+ it = iter(iterable)
75
+ while batch := tuple(islice(it, n)):
76
+ yield batch
77
+
78
+
61
79
  try:
62
- from rich.progress import MofNCompleteColumn
80
+ from rich.progress import (
81
+ MofNCompleteColumn, # pyright: ignore[reportAssignmentType]
82
+ )
63
83
  # https://github.com/benleb/surepy/issues/240
64
84
  except ImportError: # pragma: no cover
65
85
  from rich.progress import ProgressColumn
@@ -157,9 +177,9 @@ async def async_main(
157
177
  )
158
178
 
159
179
  args = parser.parse_args(argv)
160
- db: Path = args.db
161
- full_refresh: bool = args.full_refresh
162
- quiet: bool = args.quiet
180
+ db = cast("Path", args.db)
181
+ full_refresh = cast("bool", args.full_refresh)
182
+ quiet = cast("bool", args.quiet)
163
183
 
164
184
  token = resolve_token(token_override)
165
185
 
@@ -674,7 +694,7 @@ class _ProgressYnab:
674
694
  task_id: TaskID
675
695
 
676
696
  @retry(stop=stop_after_attempt(3))
677
- async def get[T](self, endpoint: Callable[..., Awaitable[T]]) -> T:
697
+ async def get(self, endpoint: Callable[..., Awaitable[_T]]) -> _T:
678
698
  try:
679
699
  return await endpoint(
680
700
  plan_id=self.plan_id,
@@ -1,36 +1,39 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlite_export_for_ynab
3
- Version: 2.9.6
3
+ Version: 2.9.8
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
7
7
  Project-URL: Homepage, https://github.com/mxr/sqlite-export-for-ynab
8
- Keywords: ynab,sqlite,sql,budget,plan,cli
8
+ Keywords: budget,cli,plan,sql,sqlite,ynab
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Programming Language :: Python :: 3 :: Only
11
11
  Classifier: Programming Language :: Python :: Implementation :: CPython
12
12
  Classifier: Programming Language :: Python :: Implementation :: PyPy
13
- Requires-Python: >=3.12
13
+ Requires-Python: >=3.11
14
14
  Description-Content-Type: text/markdown
15
15
  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.86.0
19
+ Requires-Dist: asyncio-for-ynab~=1.87.0
20
20
  Requires-Dist: fasteners
21
21
  Requires-Dist: rich>=10
22
22
  Requires-Dist: tenacity
23
+ Requires-Dist: typing-extensions; python_version < "3.12"
23
24
  Dynamic: license-file
24
25
 
25
26
  # sqlite-export-for-ynab
26
27
 
27
- [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/mxr/sqlite-export-for-ynab/main.svg)](https://results.pre-commit.ci/latest/github/mxr/sqlite-export-for-ynab/main) [![codecov](https://codecov.io/github/mxr/sqlite-export-for-ynab/graph/badge.svg?token=NVCP6RDKSH)](https://codecov.io/github/mxr/sqlite-export-for-ynab)
28
+ [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/mxr/sqlite-export-for-ynab/main.svg)](https://results.pre-commit.ci/latest/github/mxr/sqlite-export-for-ynab/main)
29
+ [![codecov](https://codecov.io/github/mxr/sqlite-export-for-ynab/graph/badge.svg?token=NVCP6RDKSH)](https://codecov.io/github/mxr/sqlite-export-for-ynab)
28
30
 
29
31
  SQLite Export for YNAB - Export YNAB Budget Data to SQLite
30
32
 
31
33
  ## What This Does
32
34
 
33
- Export all your [YNAB](https://ynab.com/) plans to a local [SQLite](https://www.sqlite.org/) DB. Then you can query your data with any tools compatible with SQLite.
35
+ Export all your [YNAB](https://ynab.com/) plans to a local [SQLite](https://www.sqlite.org/) DB. Then you can query your
36
+ data with any tools compatible with SQLite.
34
37
 
35
38
  ## Installation
36
39
 
@@ -42,7 +45,8 @@ $ pip install sqlite-export-for-ynab
42
45
 
43
46
  ### CLI
44
47
 
45
- Provision a [YNAB Personal Access Token](https://api.ynab.com/#personal-access-tokens) and save it as an environment variable.
48
+ Provision a [YNAB Personal Access Token](https://api.ynab.com/#personal-access-tokens) and save it as an environment
49
+ variable.
46
50
 
47
51
  ```console
48
52
  $ export YNAB_PERSONAL_ACCESS_TOKEN="..."
@@ -54,17 +58,22 @@ Run the tool from the terminal to download your plans:
54
58
  $ sqlite-export-for-ynab
55
59
  ```
56
60
 
57
- Running it again will pull only data that changed since the last pull (this is done with [Delta Requests](https://api.ynab.com/#deltas)). If you want to wipe the DB and pull all data again use the `--full-refresh` flag.
58
- Pass `--quiet` to suppress all CLI output, including progress bars.
61
+ Running it again will pull only data that changed since the last pull (this is done with
62
+ [Delta Requests](https://api.ynab.com/#deltas)). If you want to wipe the DB and pull all data again use the
63
+ `--full-refresh` flag. Pass `--quiet` to suppress all CLI output, including progress bars.
59
64
 
60
65
  <a id="db-path"></a>You can specify the DB path with the following options
66
+
61
67
  1. The `--db` flag.
62
- 1. The `XDG_DATA_HOME` variable (see the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/latest/index.html)). In that case the DB is saved in `"${XDG_DATA_HOME}"/sqlite-export-for-ynab/db.sqlite`.
63
- 1. If neither is set, the DB is saved in `~/.local/share/sqlite-export-for-ynab/db.sqlite`.
68
+ 2. The `XDG_DATA_HOME` variable (see the
69
+ [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/latest/index.html)). In that
70
+ case the DB is saved in `"${XDG_DATA_HOME}"/sqlite-export-for-ynab/db.sqlite`.
71
+ 3. If neither is set, the DB is saved in `~/.local/share/sqlite-export-for-ynab/db.sqlite`.
64
72
 
65
73
  ### Library
66
74
 
67
- The library exposes the package `sqlite_export_for_ynab` and two functions - `default_db_path` and `sync`. You can use them as follows:
75
+ The library exposes the package `sqlite_export_for_ynab` and two functions - `default_db_path` and `sync`. You can use
76
+ them as follows:
68
77
 
69
78
  ```python
70
79
  import asyncio
@@ -82,11 +91,17 @@ asyncio.run(sync(token, db, full_refresh))
82
91
 
83
92
  ## Relations
84
93
 
85
- The relations are defined in [create-relations.sql](sqlite_export_for_ynab/ddl/create-relations.sql). They are 1:1 with [YNAB's OpenAPI Spec](https://api.ynab.com/papi/open_api_spec.yaml) (ex: transactions, accounts, etc) with some additions:
94
+ The relations are defined in [create-relations.sql](sqlite_export_for_ynab/ddl/create-relations.sql). They are 1:1 with
95
+ [YNAB's OpenAPI Spec](https://api.ynab.com/papi/open_api_spec.yaml) (ex: transactions, accounts, etc) with some
96
+ additions:
86
97
 
87
- 1. Some objects are pulled out into their own tables so they can be more cleanly modeled in SQLite (ex: subtransactions, loan account periodic values).
88
- 1. Foreign keys are added as needed (ex: plan ID, transaction ID) so data across plans remains separate.
89
- 1. Two new views called `flat_transactions` and `scheduled_flat_transactions`. These allow you to query split and non-split transactions easily, without needing to also query `subtransactions` and `scheduled_subtransactions` respectively. They also filter out deleted/unapproved transactions/subtransactions and project payee/category fields to make querying more ergonomic.
98
+ 1. Some objects are pulled out into their own tables so they can be more cleanly modeled in SQLite (ex: subtransactions,
99
+ loan account periodic values).
100
+ 2. Foreign keys are added as needed (ex: plan ID, transaction ID) so data across plans remains separate.
101
+ 3. Two new views called `flat_transactions` and `scheduled_flat_transactions`. These allow you to query split and
102
+ non-split transactions easily, without needing to also query `subtransactions` and `scheduled_subtransactions`
103
+ respectively. They also filter out deleted/unapproved transactions/subtransactions and project payee/category fields
104
+ to make querying more ergonomic.
90
105
 
91
106
  ## Querying
92
107
 
@@ -96,10 +111,10 @@ You can issue queries with typical SQLite tools. *`sqlite-export-for-ynab` delib
96
111
 
97
112
  You can run the queries from this README using a tool like [`mdq`](https://github.com/yshavit/mdq). For example:
98
113
 
99
- ```console
114
+ ````console
100
115
  $ mdq '```sql dupes' path/to/sqlite-export-for-ynab/README.md -o plain \
101
116
  | sqlite3 path/to/sqlite-export-for-ynab/db.sqlite
102
- ```
117
+ ````
103
118
 
104
119
  The DB path is documented [above](#db-path).
105
120
 
@@ -233,7 +248,7 @@ FROM (
233
248
  ;
234
249
  ```
235
250
 
236
- To estimate taxable interest for a given year[^1]:
251
+ To estimate taxable interest for a given year\[^1\]:
237
252
 
238
253
  ```sql
239
254
  -- Parameters expected by this query:
@@ -591,4 +606,6 @@ WHERE
591
606
  ;
592
607
  ```
593
608
 
594
- [^1]: This query is a rough estimate based on YNAB data and optional user inputs. It is not financial advice, tax advice, or a substitute for Forms 1099-INT, brokerage statements, bank records, or guidance from a qualified professional.
609
+ \[^1\]: This query is a rough estimate based on YNAB data and optional user inputs. It is not financial advice, tax
610
+ advice, or a substitute for Forms 1099-INT, brokerage statements, bank records, or guidance from a qualified
611
+ professional.
@@ -0,0 +1,10 @@
1
+ aiohttp>=3
2
+ aiopathlib
3
+ aiosqlite
4
+ asyncio-for-ynab~=1.87.0
5
+ fasteners
6
+ rich>=10
7
+ tenacity
8
+
9
+ [:python_version < "3.12"]
10
+ typing-extensions
@@ -1,7 +0,0 @@
1
- aiohttp>=3
2
- aiopathlib
3
- aiosqlite
4
- asyncio-for-ynab~=1.86.0
5
- fasteners
6
- rich>=10
7
- tenacity