ynab-cli 0.3.0__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 (227) hide show
  1. ynab_cli-0.3.0/.env-sample +7 -0
  2. ynab_cli-0.3.0/.github/FUNDING.yml +1 -0
  3. ynab_cli-0.3.0/.github/workflows/pr.yml +22 -0
  4. ynab_cli-0.3.0/.github/workflows/publish-to-pypi.yml +43 -0
  5. ynab_cli-0.3.0/.gitignore +10 -0
  6. ynab_cli-0.3.0/.python-version +1 -0
  7. ynab_cli-0.3.0/CHANGELOG.md +35 -0
  8. ynab_cli-0.3.0/LICENSE.md +21 -0
  9. ynab_cli-0.3.0/Makefile +30 -0
  10. ynab_cli-0.3.0/PKG-INFO +102 -0
  11. ynab_cli-0.3.0/README.md +82 -0
  12. ynab_cli-0.3.0/docs/index.md +40 -0
  13. ynab_cli-0.3.0/docs/transaction_rules.md +42 -0
  14. ynab_cli-0.3.0/mkdocs.yml +28 -0
  15. ynab_cli-0.3.0/pyproject.toml +117 -0
  16. ynab_cli-0.3.0/src/ynab_cli/__init__.py +0 -0
  17. ynab_cli-0.3.0/src/ynab_cli/adapters/__init__.py +0 -0
  18. ynab_cli-0.3.0/src/ynab_cli/adapters/rich/__init__.py +0 -0
  19. ynab_cli-0.3.0/src/ynab_cli/adapters/rich/io.py +38 -0
  20. ynab_cli-0.3.0/src/ynab_cli/adapters/textual/__init__.py +0 -0
  21. ynab_cli-0.3.0/src/ynab_cli/adapters/textual/io.py +62 -0
  22. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/__init__.py +8 -0
  23. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/__init__.py +1 -0
  24. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/accounts/__init__.py +1 -0
  25. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/accounts/create_account.py +186 -0
  26. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/accounts/get_account_by_id.py +177 -0
  27. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/accounts/get_accounts.py +184 -0
  28. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/budgets/__init__.py +1 -0
  29. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/budgets/get_budget_by_id.py +188 -0
  30. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/budgets/get_budget_settings_by_id.py +163 -0
  31. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/budgets/get_budgets.py +171 -0
  32. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/categories/__init__.py +1 -0
  33. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/categories/get_categories.py +188 -0
  34. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/categories/get_category_by_id.py +180 -0
  35. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/categories/get_month_category_by_id.py +194 -0
  36. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/categories/update_category.py +199 -0
  37. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/categories/update_month_category.py +213 -0
  38. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/months/__init__.py +1 -0
  39. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/months/get_budget_month.py +177 -0
  40. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/months/get_budget_months.py +184 -0
  41. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payee_locations/__init__.py +1 -0
  42. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payee_locations/get_payee_location_by_id.py +176 -0
  43. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payee_locations/get_payee_locations.py +163 -0
  44. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payee_locations/get_payee_locations_by_payee.py +176 -0
  45. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payees/__init__.py +1 -0
  46. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payees/get_payee_by_id.py +176 -0
  47. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payees/get_payees.py +184 -0
  48. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payees/update_payee.py +199 -0
  49. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/scheduled_transactions/__init__.py +1 -0
  50. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/scheduled_transactions/create_scheduled_transaction.py +186 -0
  51. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/scheduled_transactions/delete_scheduled_transaction.py +176 -0
  52. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/scheduled_transactions/get_scheduled_transaction_by_id.py +176 -0
  53. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/scheduled_transactions/get_scheduled_transactions.py +184 -0
  54. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/scheduled_transactions/update_scheduled_transaction.py +199 -0
  55. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/__init__.py +1 -0
  56. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/create_transaction.py +202 -0
  57. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/delete_transaction.py +176 -0
  58. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/get_transaction_by_id.py +176 -0
  59. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/get_transactions.py +227 -0
  60. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_account.py +236 -0
  61. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_category.py +236 -0
  62. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_month.py +236 -0
  63. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_payee.py +236 -0
  64. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/import_transactions.py +183 -0
  65. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/update_transaction.py +199 -0
  66. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/update_transactions.py +177 -0
  67. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/user/__init__.py +1 -0
  68. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/user/get_user.py +130 -0
  69. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/client.py +268 -0
  70. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/errors.py +16 -0
  71. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/__init__.py +229 -0
  72. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/account.py +345 -0
  73. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/account_response.py +65 -0
  74. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/account_response_data.py +65 -0
  75. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/account_type.py +23 -0
  76. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/accounts_response.py +65 -0
  77. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/accounts_response_data.py +81 -0
  78. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_detail.py +405 -0
  79. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_detail_response.py +65 -0
  80. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_detail_response_data.py +73 -0
  81. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_settings.py +115 -0
  82. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_settings_response.py +65 -0
  83. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_settings_response_data.py +65 -0
  84. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_summary.py +216 -0
  85. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_summary_response.py +65 -0
  86. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_summary_response_data.py +91 -0
  87. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/bulk_response.py +65 -0
  88. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/bulk_response_data.py +65 -0
  89. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/bulk_response_data_bulk.py +68 -0
  90. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/bulk_transactions.py +75 -0
  91. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/categories_response.py +65 -0
  92. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/categories_response_data.py +81 -0
  93. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category.py +519 -0
  94. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category_goal_type_type_1.py +15 -0
  95. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category_goal_type_type_2_type_1.py +15 -0
  96. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category_goal_type_type_3_type_1.py +15 -0
  97. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category_group.py +85 -0
  98. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category_group_with_categories.py +108 -0
  99. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category_response.py +65 -0
  100. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category_response_data.py +65 -0
  101. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/currency_format_type_0.py +117 -0
  102. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/date_format_type_0.py +61 -0
  103. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/error_detail.py +75 -0
  104. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/error_response.py +65 -0
  105. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/existing_transaction.py +322 -0
  106. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/get_transactions_by_account_type.py +12 -0
  107. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/get_transactions_by_category_type.py +12 -0
  108. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/get_transactions_by_month_type.py +12 -0
  109. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/get_transactions_by_payee_type.py +12 -0
  110. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/get_transactions_type.py +12 -0
  111. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/hybrid_transaction.py +567 -0
  112. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/hybrid_transaction_type.py +12 -0
  113. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/hybrid_transactions_response.py +65 -0
  114. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/hybrid_transactions_response_data.py +84 -0
  115. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/loan_account_periodic_value_type_0.py +44 -0
  116. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/month_detail.py +168 -0
  117. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/month_detail_response.py +65 -0
  118. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/month_detail_response_data.py +65 -0
  119. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/month_summaries_response.py +65 -0
  120. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/month_summaries_response_data.py +81 -0
  121. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/month_summary.py +145 -0
  122. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/new_transaction.py +352 -0
  123. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/patch_category_wrapper.py +65 -0
  124. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/patch_month_category_wrapper.py +65 -0
  125. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/patch_payee_wrapper.py +65 -0
  126. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/patch_transactions_wrapper.py +73 -0
  127. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee.py +100 -0
  128. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee_location.py +93 -0
  129. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee_location_response.py +65 -0
  130. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee_location_response_data.py +65 -0
  131. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee_locations_response.py +65 -0
  132. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee_locations_response_data.py +73 -0
  133. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee_response.py +65 -0
  134. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee_response_data.py +65 -0
  135. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payees_response.py +65 -0
  136. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payees_response_data.py +81 -0
  137. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/post_account_wrapper.py +65 -0
  138. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/post_scheduled_transaction_wrapper.py +65 -0
  139. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/post_transactions_wrapper.py +91 -0
  140. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/put_scheduled_transaction_wrapper.py +65 -0
  141. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/put_transaction_wrapper.py +65 -0
  142. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_account.py +77 -0
  143. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_category.py +129 -0
  144. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_category_response.py +65 -0
  145. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_category_response_data.py +73 -0
  146. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_month_category.py +59 -0
  147. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_payee.py +59 -0
  148. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_payee_response.py +65 -0
  149. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_payee_response_data.py +73 -0
  150. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_scheduled_transaction.py +269 -0
  151. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_sub_transaction.py +166 -0
  152. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_transaction_with_id_or_import_id.py +366 -0
  153. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_transaction_with_optional_fields.py +322 -0
  154. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_transactions_response.py +65 -0
  155. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_transactions_response_data.py +123 -0
  156. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_sub_transaction.py +238 -0
  157. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transaction_detail.py +381 -0
  158. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transaction_frequency.py +23 -0
  159. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transaction_response.py +65 -0
  160. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transaction_response_data.py +65 -0
  161. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transaction_summary.py +310 -0
  162. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transaction_summary_frequency.py +23 -0
  163. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transactions_response.py +65 -0
  164. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transactions_response_data.py +81 -0
  165. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/sub_transaction.py +259 -0
  166. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_cleared_status.py +13 -0
  167. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_detail.py +570 -0
  168. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_flag_color_type_1.py +16 -0
  169. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_flag_color_type_2_type_1.py +16 -0
  170. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_flag_color_type_3_type_1.py +16 -0
  171. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_response.py +65 -0
  172. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_response_data.py +65 -0
  173. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_summary.py +499 -0
  174. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_summary_debt_transaction_type_type_1.py +18 -0
  175. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_summary_debt_transaction_type_type_2_type_1.py +18 -0
  176. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_summary_debt_transaction_type_type_3_type_1.py +18 -0
  177. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transactions_import_response.py +65 -0
  178. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transactions_import_response_data.py +59 -0
  179. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transactions_response.py +65 -0
  180. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transactions_response_data.py +81 -0
  181. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/user.py +60 -0
  182. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/user_response.py +65 -0
  183. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/user_response_data.py +65 -0
  184. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/types.py +46 -0
  185. ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/util.py +78 -0
  186. ynab_cli-0.3.0/src/ynab_cli/domain/__init__.py +0 -0
  187. ynab_cli-0.3.0/src/ynab_cli/domain/constants.py +3 -0
  188. ynab_cli-0.3.0/src/ynab_cli/domain/models/__init__.py +0 -0
  189. ynab_cli-0.3.0/src/ynab_cli/domain/models/rules.py +37 -0
  190. ynab_cli-0.3.0/src/ynab_cli/domain/ports/__init__.py +5 -0
  191. ynab_cli-0.3.0/src/ynab_cli/domain/ports/io.py +63 -0
  192. ynab_cli-0.3.0/src/ynab_cli/domain/settings.py +16 -0
  193. ynab_cli-0.3.0/src/ynab_cli/domain/use_cases/__init__.py +0 -0
  194. ynab_cli-0.3.0/src/ynab_cli/domain/use_cases/categories.py +105 -0
  195. ynab_cli-0.3.0/src/ynab_cli/domain/use_cases/payees.py +232 -0
  196. ynab_cli-0.3.0/src/ynab_cli/domain/use_cases/transactions.py +93 -0
  197. ynab_cli-0.3.0/src/ynab_cli/host/__init__.py +14 -0
  198. ynab_cli-0.3.0/src/ynab_cli/host/cli.py +37 -0
  199. ynab_cli-0.3.0/src/ynab_cli/host/click/__init__.py +0 -0
  200. ynab_cli-0.3.0/src/ynab_cli/host/click/cli.py +44 -0
  201. ynab_cli-0.3.0/src/ynab_cli/host/click/commands/__init__.py +0 -0
  202. ynab_cli-0.3.0/src/ynab_cli/host/click/commands/categories.py +92 -0
  203. ynab_cli-0.3.0/src/ynab_cli/host/click/commands/payees.py +157 -0
  204. ynab_cli-0.3.0/src/ynab_cli/host/click/commands/rich/__init__.py +0 -0
  205. ynab_cli-0.3.0/src/ynab_cli/host/click/commands/rich/progress_table.py +37 -0
  206. ynab_cli-0.3.0/src/ynab_cli/host/click/commands/transactions.py +76 -0
  207. ynab_cli-0.3.0/src/ynab_cli/host/constants.py +3 -0
  208. ynab_cli-0.3.0/src/ynab_cli/host/textual/__init__.py +0 -0
  209. ynab_cli-0.3.0/src/ynab_cli/host/textual/app.py +98 -0
  210. ynab_cli-0.3.0/src/ynab_cli/host/textual/app.tcss +47 -0
  211. ynab_cli-0.3.0/src/ynab_cli/host/textual/cli.py +42 -0
  212. ynab_cli-0.3.0/src/ynab_cli/host/textual/widgets/__init__.py +58 -0
  213. ynab_cli-0.3.0/src/ynab_cli/host/textual/widgets/categories.py +90 -0
  214. ynab_cli-0.3.0/src/ynab_cli/host/textual/widgets/payees.py +154 -0
  215. ynab_cli-0.3.0/src/ynab_cli/host/textual/widgets/transactions.py +89 -0
  216. ynab_cli-0.3.0/src/ynab_cli/py.typed +0 -0
  217. ynab_cli-0.3.0/tests/__init__.py +0 -0
  218. ynab_cli-0.3.0/tests/factories/__init__.py +0 -0
  219. ynab_cli-0.3.0/tests/factories/ynab.py +18 -0
  220. ynab_cli-0.3.0/tests/unit/__init__.py +0 -0
  221. ynab_cli-0.3.0/tests/unit/conftest.py +17 -0
  222. ynab_cli-0.3.0/tests/unit/domain/__init__.py +0 -0
  223. ynab_cli-0.3.0/tests/unit/domain/use_cases/__init__.py +0 -0
  224. ynab_cli-0.3.0/tests/unit/domain/use_cases/test_categories.py +68 -0
  225. ynab_cli-0.3.0/tests/unit/domain/use_cases/test_payees.py +72 -0
  226. ynab_cli-0.3.0/tests/unit/domain/use_cases/test_transactions.py +106 -0
  227. ynab_cli-0.3.0/uv.lock +1567 -0
@@ -0,0 +1,7 @@
1
+ # Make a copy of this file called `.env` and update the variables below if you want to use dotenv files
2
+
3
+ # Get this from your developer settings https://api.ynab.com/#personal-access-tokens
4
+ YNAB_CLI_ACCESS_TOKEN=YourAccessToken
5
+
6
+ # Uncomment the below line and update it if you only use ynab-cli with one budget
7
+ # YNAB_CLI_BUDGET_ID=YourBudgetID
@@ -0,0 +1 @@
1
+ github: jeffsawatzky
@@ -0,0 +1,22 @@
1
+ name: pr
2
+ on:
3
+ pull_request:
4
+ types: [opened, reopened, synchronize]
5
+ jobs:
6
+ test:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ matrix:
10
+ python-version: ['3.11', '3.12', '3.13']
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - name: Install the latest version of uv
14
+ uses: astral-sh/setup-uv@v6
15
+ with:
16
+ version: latest
17
+ python-version: ${{ matrix.python-version }}
18
+ - run: uv sync --locked # abort if the lockfile changes
19
+ - run: uv run ruff format --check . # check formatting is correct
20
+ - run: uv run ruff check --no-fix . # and linting
21
+ - run: uv run mypy . # typecheck too
22
+ - run: uv run pytest tests # then run your tests!
@@ -0,0 +1,43 @@
1
+ name: Publish to PyPI
2
+ on:
3
+ push:
4
+ tags:
5
+ - v*
6
+ jobs:
7
+ build:
8
+ name: Build distribution
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ with:
13
+ persist-credentials: false
14
+ - name: Install the latest version of uv
15
+ uses: astral-sh/setup-uv@v6
16
+ with:
17
+ version: latest
18
+ - name: Build a binary wheel and a source tarball
19
+ run: uv build
20
+ - name: Store the distribution packages
21
+ uses: actions/upload-artifact@v4
22
+ with:
23
+ name: python-package-distributions
24
+ path: dist/
25
+ publish-to-pypi:
26
+ name: Publish to PyPI
27
+ if: 'startsWith(github.ref, ''refs/tags/'')'
28
+ needs:
29
+ - build
30
+ runs-on: ubuntu-latest
31
+ environment:
32
+ name: pypi
33
+ url: 'https://pypi.org/p/ynab-cli'
34
+ permissions:
35
+ id-token: write
36
+ steps:
37
+ - name: Download all the dists
38
+ uses: actions/download-artifact@v4
39
+ with:
40
+ name: python-package-distributions
41
+ path: dist/
42
+ - name: Publish to PyPI
43
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,10 @@
1
+ .coverage
2
+ .env
3
+ rules.json
4
+
5
+ __pycache__/
6
+ .my_cache/
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+ .venv/
10
+ .vscode/
@@ -0,0 +1 @@
1
+ 3.11
@@ -0,0 +1,35 @@
1
+ ## 0.2.0 (2025-06-06)
2
+
3
+ ### BREAKING CHANGE
4
+
5
+ - changes the way the commands need to be run. You now need to specify the "run" command before any of the subcommands
6
+
7
+ ### Feat
8
+
9
+ - added a feature to prefix unused payees to make them easier to find and delete in ynab
10
+ - added a list all command to payees
11
+ - add a textual based tui
12
+ - use rich for better user feedback
13
+ - implement initial cli
14
+
15
+ ### Refactor
16
+
17
+ - cleaned up some code, sorted lists, and improved the file selector
18
+
19
+ ## v0.3.0 (2025-06-06)
20
+
21
+ ### BREAKING CHANGE
22
+
23
+ - changes the way the commands need to be run. You now need to specify the "run" command before any of the subcommands
24
+
25
+ ### Feat
26
+
27
+ - added a feature to prefix unused payees to make them easier to find and delete in ynab
28
+ - added a list all command to payees
29
+ - add a textual based tui
30
+ - use rich for better user feedback
31
+ - implement initial cli
32
+
33
+ ### Refactor
34
+
35
+ - cleaned up some code, sorted lists, and improved the file selector
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Jeff Sawatzky
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,30 @@
1
+ .PHONY: lint test clean
2
+
3
+ .venv: pyproject.toml
4
+ uv sync
5
+ touch .venv
6
+
7
+ lint: .venv
8
+ uv run ruff format .
9
+ uv run ruff check .
10
+ uv run mypy .
11
+
12
+ test: .venv lint
13
+ uv run pytest --cov=src tests
14
+
15
+ clean:
16
+ rm -f .coverage
17
+ rm -rf dist
18
+ rm -rf htmlcov
19
+ rm -rf site
20
+ find . -type f -name .DS_Store | xargs rm -rf
21
+ find . -type d -name __pycache__ | xargs rm -rf
22
+ find . -type d -name .mypy_cache | xargs rm -rf
23
+ find . -type d -name .pytest_cache | xargs rm -rf
24
+ find . -type d -name .ruff_cache | xargs rm -rf
25
+ find . -type d -empty -delete
26
+
27
+ ynab-sdk:
28
+ rm -rf ./src/ynab_cli/adapters/ynab
29
+ mkdir -p ./src/ynab_cli/adapters/ynab
30
+ uvx openapi-python-client generate --meta none --url https://api.ynab.com/papi/open_api_spec.yaml --output-path ./src/ynab_cli/adapters/ynab --overwrite
@@ -0,0 +1,102 @@
1
+ Metadata-Version: 2.4
2
+ Name: ynab-cli
3
+ Version: 0.3.0
4
+ Summary: YNAB Command Line Interface
5
+ Author: Jeff Sawatzky
6
+ License-File: LICENSE.md
7
+ Requires-Python: >=3.11
8
+ Requires-Dist: attrs~=25.3
9
+ Requires-Dist: click-default-group~=1.2
10
+ Requires-Dist: click~=8.2
11
+ Requires-Dist: httpx~=0.28
12
+ Requires-Dist: python-dotenv~=1.1
13
+ Requires-Dist: rapidfuzz~=3.13
14
+ Requires-Dist: rich~=14.0
15
+ Requires-Dist: rule-engine~=4.5
16
+ Requires-Dist: textual-fspicker~=0.4
17
+ Requires-Dist: textual~=3.3
18
+ Requires-Dist: typing-extensions~=4.14
19
+ Description-Content-Type: text/markdown
20
+
21
+ # YNAB CLI
22
+
23
+ A command-line interface for interacting with YNAB (You Need A Budget).
24
+
25
+ ## Usage
26
+
27
+ Full user documentation available [here](http://jeffsawatzky.github.io/ynab-cli)
28
+
29
+ ## Project Structure
30
+
31
+ - `src/ynab_cli/`: Main source code
32
+ - `tests/`: Unit and integration tests
33
+ - `docs/`: Documentation (built with MkDocs)
34
+
35
+ ## Getting Started
36
+
37
+ ### Prerequisites
38
+ - Python 3.11+
39
+ - [uv](https://docs.astral.sh/uv/)
40
+
41
+ ### Installation
42
+
43
+ Clone the repository:
44
+ ```sh
45
+ $ git clone https://github.com/jeffsawatzky/ynab-cli.git
46
+ $ cd ynab-cli
47
+ ```
48
+
49
+ Install dependencies with uv:
50
+ ```sh
51
+ $ uv sync
52
+ ```
53
+
54
+ ### Running the CLI
55
+
56
+ With uv:
57
+ ```sh
58
+ $ uv run ynab-cli --help
59
+ ```
60
+
61
+ ## Development
62
+
63
+ - Source code is in `src/ynab_cli/`.
64
+ - Use feature branches for new work.
65
+ - Follow PEP8 and use type hints where possible.
66
+
67
+ ### Linting & Formatting
68
+
69
+ ```sh
70
+ $ make lint
71
+ ```
72
+
73
+ ### Running Tests
74
+
75
+ ```sh
76
+ $ make test
77
+ ```
78
+ Or directly with pytest:
79
+ ```sh
80
+ uv run pytest
81
+ ```
82
+
83
+ ## Documentation
84
+
85
+ - Docs are in `docs/` and built with MkDocs.
86
+ - To serve docs locally:
87
+ ```sh
88
+ $ uv run mkdocs serve
89
+ ```
90
+
91
+ ## Contributing
92
+
93
+ 1. Fork the repository
94
+ 2. Create a feature branch (`git checkout -b feature/your-feature`)
95
+ 3. Commit your changes. Commits should follow conventional commits. The repo is configured with [commitizen](https://commitizen-tools.github.io/commitizen/)
96
+ 4. Push to your fork and open a pull request
97
+
98
+ Please include tests for new features and bug fixes.
99
+
100
+ ## License
101
+
102
+ See [LICENSE.md](LICENSE.md)
@@ -0,0 +1,82 @@
1
+ # YNAB CLI
2
+
3
+ A command-line interface for interacting with YNAB (You Need A Budget).
4
+
5
+ ## Usage
6
+
7
+ Full user documentation available [here](http://jeffsawatzky.github.io/ynab-cli)
8
+
9
+ ## Project Structure
10
+
11
+ - `src/ynab_cli/`: Main source code
12
+ - `tests/`: Unit and integration tests
13
+ - `docs/`: Documentation (built with MkDocs)
14
+
15
+ ## Getting Started
16
+
17
+ ### Prerequisites
18
+ - Python 3.11+
19
+ - [uv](https://docs.astral.sh/uv/)
20
+
21
+ ### Installation
22
+
23
+ Clone the repository:
24
+ ```sh
25
+ $ git clone https://github.com/jeffsawatzky/ynab-cli.git
26
+ $ cd ynab-cli
27
+ ```
28
+
29
+ Install dependencies with uv:
30
+ ```sh
31
+ $ uv sync
32
+ ```
33
+
34
+ ### Running the CLI
35
+
36
+ With uv:
37
+ ```sh
38
+ $ uv run ynab-cli --help
39
+ ```
40
+
41
+ ## Development
42
+
43
+ - Source code is in `src/ynab_cli/`.
44
+ - Use feature branches for new work.
45
+ - Follow PEP8 and use type hints where possible.
46
+
47
+ ### Linting & Formatting
48
+
49
+ ```sh
50
+ $ make lint
51
+ ```
52
+
53
+ ### Running Tests
54
+
55
+ ```sh
56
+ $ make test
57
+ ```
58
+ Or directly with pytest:
59
+ ```sh
60
+ uv run pytest
61
+ ```
62
+
63
+ ## Documentation
64
+
65
+ - Docs are in `docs/` and built with MkDocs.
66
+ - To serve docs locally:
67
+ ```sh
68
+ $ uv run mkdocs serve
69
+ ```
70
+
71
+ ## Contributing
72
+
73
+ 1. Fork the repository
74
+ 2. Create a feature branch (`git checkout -b feature/your-feature`)
75
+ 3. Commit your changes. Commits should follow conventional commits. The repo is configured with [commitizen](https://commitizen-tools.github.io/commitizen/)
76
+ 4. Push to your fork and open a pull request
77
+
78
+ Please include tests for new features and bug fixes.
79
+
80
+ ## License
81
+
82
+ See [LICENSE.md](LICENSE.md)
@@ -0,0 +1,40 @@
1
+ # Welcome to YNAB CLI
2
+
3
+ This is a simple cli/tui application written in python to help manage your YNAB data.
4
+
5
+ ## Requirements
6
+
7
+ - Python 3.11+
8
+ - [uv](https://docs.astral.sh/uv/)
9
+ - Your [YNAB developer access token](https://api.ynab.com/#personal-access-tokens)
10
+ - Your YNAB budget ID. You can get this from your browser URL while you have your budget open. For example, if the URL looks like `https://app.ynab.com/aaaaaaaa-1111-bbbb-2222-ddddddd` then the budget ID is `aaaaaaaa-1111-bbbb-2222-ddddddd`.
11
+
12
+ ## Installation
13
+ ```sh
14
+ $ git clone https://github.com/jeffsawatzky/ynab-cli.git
15
+ $ cd ynab-cli
16
+ $ uv sync
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ !!! warning
22
+ Developer access tokens are rate limited to 200 requests per hour. Some of the commands below will provide you an opportunity to enter a new developer access token when the current one has exceeded it's limit. It also seems like there is a limit to how many developer access tokens you can create from the developer settings UI.
23
+
24
+ !!! note
25
+ YNAB CLI supports environment variables and dotenv (`.env`) files for specifying options. See the `.env-sample` file for some examples. It looks for the `.env` file in current working directory.
26
+
27
+ To run the text ui, execute the following command:
28
+
29
+ ```sh
30
+ $ uv run ynab-cli
31
+ ```
32
+
33
+ Full command line usage is below.
34
+
35
+ ::: mkdocs-click
36
+ :module: ynab_cli.host.cli
37
+ :command: cli
38
+ :prog_name: ynab-cli
39
+ :style: table
40
+ :list_subcommands: True
@@ -0,0 +1,42 @@
1
+ !!! note
2
+ Amounts are in milliunits and can be either positive or negative depending on if they are inflow or outflow.
3
+
4
+ !!! note
5
+ To get the category IDs you can use the `ynab run categories list-all` command.
6
+
7
+ The rules use the [rule-engine](https://zerosteiner.github.io/rule-engine/getting_started.html) library, so read that documentation to figure out how to write the rules. If ANY of the rules in the `rules` list match a transaction then it will be updated with the `patch` details.
8
+ The rules are supplied an instance of a `TransactionDetail`, and the `patch` needs to be an instance of a `SaveTransactionWithIdOrImportId`. Read the [YNAB API documention](https://api.ynab.com/v1) to see what properties are available to base your rules on and update.
9
+
10
+ This assumes you have a `rules.json` file with your rules to apply. It could look something like this:
11
+ ```json
12
+ {
13
+ "transaction_rules": [
14
+ {
15
+ "rules": [
16
+ "payee_name == 'My Payee' and amount == -213490"
17
+ ],
18
+ "patch": {
19
+ "category_id": "insert the category id you want to assign it to here"
20
+ }
21
+ },
22
+ {
23
+ "rules": [
24
+ "payee_name == 'My Split Transaction Payee' and amount == -346500"
25
+ ],
26
+ "patch": {
27
+ "category_id": null,
28
+ "subtransactions": [
29
+ {
30
+ "category_id": "insert the first category id you want to assign it to here",
31
+ "amount": -51980
32
+ },
33
+ {
34
+ "category_id": "insert the other category id you want to assign it to here",
35
+ "amount": -294520
36
+ }
37
+ ]
38
+ }
39
+ }
40
+ ]
41
+ }
42
+ ```
@@ -0,0 +1,28 @@
1
+ site_name: YNAB CLI
2
+ site_url: http://jeffsawatzky.github.io/ynab-cli/
3
+ repo_url: https://github.com/jeffsawatzky/ynab-cli
4
+
5
+ theme:
6
+ name: material
7
+ features:
8
+ - content.code.copy
9
+
10
+ plugins:
11
+ - search
12
+
13
+ markdown_extensions:
14
+ - admonition
15
+ - attr_list
16
+ - mkdocs-click
17
+ - pymdownx.details
18
+ - pymdownx.highlight:
19
+ anchor_linenums: true
20
+ line_spans: __span
21
+ pygments_lang_class: true
22
+ - pymdownx.inlinehilite
23
+ - pymdownx.snippets
24
+ - pymdownx.superfences
25
+
26
+ nav:
27
+ - Home: index.md
28
+ - Transaction Rules: transaction_rules.md
@@ -0,0 +1,117 @@
1
+ [project]
2
+ name = "ynab-cli"
3
+ version = "0.3.0"
4
+ description = "YNAB Command Line Interface"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Jeff Sawatzky" }
8
+ ]
9
+ requires-python = ">=3.11"
10
+ dependencies = [
11
+ "attrs~=25.3",
12
+ "click-default-group~=1.2",
13
+ "click~=8.2",
14
+ "httpx~=0.28",
15
+ "python-dotenv~=1.1",
16
+ "rapidfuzz~=3.13",
17
+ "rich~=14.0",
18
+ "rule-engine~=4.5",
19
+ "textual-fspicker~=0.4",
20
+ "textual~=3.3",
21
+ "typing-extensions~=4.14",
22
+ ]
23
+
24
+ [project.scripts]
25
+ ynab-cli = "ynab_cli.host.cli:main"
26
+
27
+
28
+ [dependency-groups]
29
+ dev = [
30
+ "factory-boy>=3.3.3",
31
+ "mkdocs-click>=0.9.0",
32
+ "mkdocs-material>=9.6.14",
33
+ "mkdocs>=1.6.1",
34
+ "mypy>=1.16.0",
35
+ "pytest-asyncio>=1.0.0",
36
+ "pytest-cov>=6.1.1",
37
+ "pytest-mock>=3.14.1",
38
+ "pytest>=8.4.0",
39
+ "ruff>=0.11.12",
40
+ "textual-dev>=1.7.0",
41
+ "types-python-dateutil>=2.9.0.20250516",
42
+ ]
43
+
44
+
45
+ [tool.mypy]
46
+ python_version = "3.11"
47
+ exclude = [
48
+ '^tests/.*\.py$'
49
+ ]
50
+ pretty = true
51
+ show_column_numbers = true
52
+ show_error_codes = true
53
+ show_error_context = true
54
+ strict = true
55
+ warn_unreachable = true
56
+ enable_error_code = [
57
+ "explicit-override",
58
+ ]
59
+
60
+ [[tool.mypy.overrides]]
61
+ module = [
62
+ "click_default_group.*",
63
+ "factory.*",
64
+ "rule_engine.*",
65
+ ]
66
+ ignore_missing_imports = true
67
+
68
+
69
+ [tool.ruff]
70
+ fix = true
71
+ line-length = 120
72
+ target-version = "py311"
73
+
74
+ [tool.ruff.lint]
75
+ extend-select = [
76
+ "W", # warnings
77
+ "I", # isort
78
+ "C90", # mccabe
79
+ "N", # pep8-naming
80
+ "UP", # pyupgrade
81
+ "S", # flake8-bandit
82
+ "B", # flake8-bugbear
83
+ "A", # flake8-builtins
84
+ "DTZ", # flake8-datetimez
85
+ "PT", # flake8-pytest-style
86
+ "TID", # flake8-tidy-imports
87
+ "RUF", # ruff specific rules
88
+ ]
89
+ extend-ignore = [
90
+ "S110", # `try`-`except`-`pass` detected
91
+ ]
92
+
93
+ [tool.ruff.lint.per-file-ignores]
94
+ "tests/**/*.py" = ["S"]
95
+
96
+ [tool.ruff.lint.isort]
97
+ known-first-party = ["ynab_cli", "tests"]
98
+
99
+ [tool.ruff.lint.mccabe]
100
+ max-complexity = 70
101
+
102
+ [tool.ruff.lint.flake8-builtins]
103
+ builtins-ignorelist = ["type", "id"]
104
+
105
+
106
+ [tool.commitizen]
107
+ name = "cz_conventional_commits"
108
+ tag_format = "v$version"
109
+ version_scheme = "pep440"
110
+ version_provider = "uv"
111
+ update_changelog_on_bump = true
112
+ major_version_zero = true
113
+
114
+
115
+ [build-system]
116
+ requires = ["hatchling"]
117
+ build-backend = "hatchling.build"
File without changes
File without changes
File without changes
@@ -0,0 +1,38 @@
1
+ from rich import progress as rich_progress
2
+ from rich import prompt as rich_prompt
3
+ from typing_extensions import override
4
+
5
+ from ynab_cli.domain.ports.io import IO, Progress
6
+
7
+
8
+ class RichProgress(Progress):
9
+ def __init__(self, progress_info: tuple[rich_progress.Progress, rich_progress.TaskID]) -> None:
10
+ self._progress, self._task_id = progress_info
11
+
12
+ @override
13
+ async def update(
14
+ self, *, total: float | None = None, completed: float | None = None, advance: float | None = None
15
+ ) -> None:
16
+ task = self._progress.tasks[self._task_id]
17
+ if not task.started:
18
+ self._progress.start_task(self._task_id)
19
+ self._progress.update(self._task_id, total=total, completed=completed, advance=advance)
20
+
21
+
22
+ class RichIO(IO):
23
+ def __init__(self, progress_info: tuple[rich_progress.Progress, rich_progress.TaskID]) -> None:
24
+ progress, _ = progress_info
25
+ self._progress = progress
26
+ self.progress = RichProgress(progress_info)
27
+
28
+ @override
29
+ async def prompt(self, prompt: str, password: bool = False) -> str:
30
+ try:
31
+ self._progress.stop()
32
+ return rich_prompt.Prompt.ask(prompt, console=self._progress.console, password=password)
33
+ finally:
34
+ self._progress.start()
35
+
36
+ @override
37
+ async def print(self, message: str) -> None:
38
+ return self._progress.console.print(message)