ynab-cli 0.3.0__py3-none-any.whl

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 (206) hide show
  1. ynab_cli/__init__.py +0 -0
  2. ynab_cli/adapters/__init__.py +0 -0
  3. ynab_cli/adapters/rich/__init__.py +0 -0
  4. ynab_cli/adapters/rich/io.py +38 -0
  5. ynab_cli/adapters/textual/__init__.py +0 -0
  6. ynab_cli/adapters/textual/io.py +62 -0
  7. ynab_cli/adapters/ynab/__init__.py +8 -0
  8. ynab_cli/adapters/ynab/api/__init__.py +1 -0
  9. ynab_cli/adapters/ynab/api/accounts/__init__.py +1 -0
  10. ynab_cli/adapters/ynab/api/accounts/create_account.py +186 -0
  11. ynab_cli/adapters/ynab/api/accounts/get_account_by_id.py +177 -0
  12. ynab_cli/adapters/ynab/api/accounts/get_accounts.py +184 -0
  13. ynab_cli/adapters/ynab/api/budgets/__init__.py +1 -0
  14. ynab_cli/adapters/ynab/api/budgets/get_budget_by_id.py +188 -0
  15. ynab_cli/adapters/ynab/api/budgets/get_budget_settings_by_id.py +163 -0
  16. ynab_cli/adapters/ynab/api/budgets/get_budgets.py +171 -0
  17. ynab_cli/adapters/ynab/api/categories/__init__.py +1 -0
  18. ynab_cli/adapters/ynab/api/categories/get_categories.py +188 -0
  19. ynab_cli/adapters/ynab/api/categories/get_category_by_id.py +180 -0
  20. ynab_cli/adapters/ynab/api/categories/get_month_category_by_id.py +194 -0
  21. ynab_cli/adapters/ynab/api/categories/update_category.py +199 -0
  22. ynab_cli/adapters/ynab/api/categories/update_month_category.py +213 -0
  23. ynab_cli/adapters/ynab/api/months/__init__.py +1 -0
  24. ynab_cli/adapters/ynab/api/months/get_budget_month.py +177 -0
  25. ynab_cli/adapters/ynab/api/months/get_budget_months.py +184 -0
  26. ynab_cli/adapters/ynab/api/payee_locations/__init__.py +1 -0
  27. ynab_cli/adapters/ynab/api/payee_locations/get_payee_location_by_id.py +176 -0
  28. ynab_cli/adapters/ynab/api/payee_locations/get_payee_locations.py +163 -0
  29. ynab_cli/adapters/ynab/api/payee_locations/get_payee_locations_by_payee.py +176 -0
  30. ynab_cli/adapters/ynab/api/payees/__init__.py +1 -0
  31. ynab_cli/adapters/ynab/api/payees/get_payee_by_id.py +176 -0
  32. ynab_cli/adapters/ynab/api/payees/get_payees.py +184 -0
  33. ynab_cli/adapters/ynab/api/payees/update_payee.py +199 -0
  34. ynab_cli/adapters/ynab/api/scheduled_transactions/__init__.py +1 -0
  35. ynab_cli/adapters/ynab/api/scheduled_transactions/create_scheduled_transaction.py +186 -0
  36. ynab_cli/adapters/ynab/api/scheduled_transactions/delete_scheduled_transaction.py +176 -0
  37. ynab_cli/adapters/ynab/api/scheduled_transactions/get_scheduled_transaction_by_id.py +176 -0
  38. ynab_cli/adapters/ynab/api/scheduled_transactions/get_scheduled_transactions.py +184 -0
  39. ynab_cli/adapters/ynab/api/scheduled_transactions/update_scheduled_transaction.py +199 -0
  40. ynab_cli/adapters/ynab/api/transactions/__init__.py +1 -0
  41. ynab_cli/adapters/ynab/api/transactions/create_transaction.py +202 -0
  42. ynab_cli/adapters/ynab/api/transactions/delete_transaction.py +176 -0
  43. ynab_cli/adapters/ynab/api/transactions/get_transaction_by_id.py +176 -0
  44. ynab_cli/adapters/ynab/api/transactions/get_transactions.py +227 -0
  45. ynab_cli/adapters/ynab/api/transactions/get_transactions_by_account.py +236 -0
  46. ynab_cli/adapters/ynab/api/transactions/get_transactions_by_category.py +236 -0
  47. ynab_cli/adapters/ynab/api/transactions/get_transactions_by_month.py +236 -0
  48. ynab_cli/adapters/ynab/api/transactions/get_transactions_by_payee.py +236 -0
  49. ynab_cli/adapters/ynab/api/transactions/import_transactions.py +183 -0
  50. ynab_cli/adapters/ynab/api/transactions/update_transaction.py +199 -0
  51. ynab_cli/adapters/ynab/api/transactions/update_transactions.py +177 -0
  52. ynab_cli/adapters/ynab/api/user/__init__.py +1 -0
  53. ynab_cli/adapters/ynab/api/user/get_user.py +130 -0
  54. ynab_cli/adapters/ynab/client.py +268 -0
  55. ynab_cli/adapters/ynab/errors.py +16 -0
  56. ynab_cli/adapters/ynab/models/__init__.py +229 -0
  57. ynab_cli/adapters/ynab/models/account.py +345 -0
  58. ynab_cli/adapters/ynab/models/account_response.py +65 -0
  59. ynab_cli/adapters/ynab/models/account_response_data.py +65 -0
  60. ynab_cli/adapters/ynab/models/account_type.py +23 -0
  61. ynab_cli/adapters/ynab/models/accounts_response.py +65 -0
  62. ynab_cli/adapters/ynab/models/accounts_response_data.py +81 -0
  63. ynab_cli/adapters/ynab/models/budget_detail.py +405 -0
  64. ynab_cli/adapters/ynab/models/budget_detail_response.py +65 -0
  65. ynab_cli/adapters/ynab/models/budget_detail_response_data.py +73 -0
  66. ynab_cli/adapters/ynab/models/budget_settings.py +115 -0
  67. ynab_cli/adapters/ynab/models/budget_settings_response.py +65 -0
  68. ynab_cli/adapters/ynab/models/budget_settings_response_data.py +65 -0
  69. ynab_cli/adapters/ynab/models/budget_summary.py +216 -0
  70. ynab_cli/adapters/ynab/models/budget_summary_response.py +65 -0
  71. ynab_cli/adapters/ynab/models/budget_summary_response_data.py +91 -0
  72. ynab_cli/adapters/ynab/models/bulk_response.py +65 -0
  73. ynab_cli/adapters/ynab/models/bulk_response_data.py +65 -0
  74. ynab_cli/adapters/ynab/models/bulk_response_data_bulk.py +68 -0
  75. ynab_cli/adapters/ynab/models/bulk_transactions.py +75 -0
  76. ynab_cli/adapters/ynab/models/categories_response.py +65 -0
  77. ynab_cli/adapters/ynab/models/categories_response_data.py +81 -0
  78. ynab_cli/adapters/ynab/models/category.py +519 -0
  79. ynab_cli/adapters/ynab/models/category_goal_type_type_1.py +15 -0
  80. ynab_cli/adapters/ynab/models/category_goal_type_type_2_type_1.py +15 -0
  81. ynab_cli/adapters/ynab/models/category_goal_type_type_3_type_1.py +15 -0
  82. ynab_cli/adapters/ynab/models/category_group.py +85 -0
  83. ynab_cli/adapters/ynab/models/category_group_with_categories.py +108 -0
  84. ynab_cli/adapters/ynab/models/category_response.py +65 -0
  85. ynab_cli/adapters/ynab/models/category_response_data.py +65 -0
  86. ynab_cli/adapters/ynab/models/currency_format_type_0.py +117 -0
  87. ynab_cli/adapters/ynab/models/date_format_type_0.py +61 -0
  88. ynab_cli/adapters/ynab/models/error_detail.py +75 -0
  89. ynab_cli/adapters/ynab/models/error_response.py +65 -0
  90. ynab_cli/adapters/ynab/models/existing_transaction.py +322 -0
  91. ynab_cli/adapters/ynab/models/get_transactions_by_account_type.py +12 -0
  92. ynab_cli/adapters/ynab/models/get_transactions_by_category_type.py +12 -0
  93. ynab_cli/adapters/ynab/models/get_transactions_by_month_type.py +12 -0
  94. ynab_cli/adapters/ynab/models/get_transactions_by_payee_type.py +12 -0
  95. ynab_cli/adapters/ynab/models/get_transactions_type.py +12 -0
  96. ynab_cli/adapters/ynab/models/hybrid_transaction.py +567 -0
  97. ynab_cli/adapters/ynab/models/hybrid_transaction_type.py +12 -0
  98. ynab_cli/adapters/ynab/models/hybrid_transactions_response.py +65 -0
  99. ynab_cli/adapters/ynab/models/hybrid_transactions_response_data.py +84 -0
  100. ynab_cli/adapters/ynab/models/loan_account_periodic_value_type_0.py +44 -0
  101. ynab_cli/adapters/ynab/models/month_detail.py +168 -0
  102. ynab_cli/adapters/ynab/models/month_detail_response.py +65 -0
  103. ynab_cli/adapters/ynab/models/month_detail_response_data.py +65 -0
  104. ynab_cli/adapters/ynab/models/month_summaries_response.py +65 -0
  105. ynab_cli/adapters/ynab/models/month_summaries_response_data.py +81 -0
  106. ynab_cli/adapters/ynab/models/month_summary.py +145 -0
  107. ynab_cli/adapters/ynab/models/new_transaction.py +352 -0
  108. ynab_cli/adapters/ynab/models/patch_category_wrapper.py +65 -0
  109. ynab_cli/adapters/ynab/models/patch_month_category_wrapper.py +65 -0
  110. ynab_cli/adapters/ynab/models/patch_payee_wrapper.py +65 -0
  111. ynab_cli/adapters/ynab/models/patch_transactions_wrapper.py +73 -0
  112. ynab_cli/adapters/ynab/models/payee.py +100 -0
  113. ynab_cli/adapters/ynab/models/payee_location.py +93 -0
  114. ynab_cli/adapters/ynab/models/payee_location_response.py +65 -0
  115. ynab_cli/adapters/ynab/models/payee_location_response_data.py +65 -0
  116. ynab_cli/adapters/ynab/models/payee_locations_response.py +65 -0
  117. ynab_cli/adapters/ynab/models/payee_locations_response_data.py +73 -0
  118. ynab_cli/adapters/ynab/models/payee_response.py +65 -0
  119. ynab_cli/adapters/ynab/models/payee_response_data.py +65 -0
  120. ynab_cli/adapters/ynab/models/payees_response.py +65 -0
  121. ynab_cli/adapters/ynab/models/payees_response_data.py +81 -0
  122. ynab_cli/adapters/ynab/models/post_account_wrapper.py +65 -0
  123. ynab_cli/adapters/ynab/models/post_scheduled_transaction_wrapper.py +65 -0
  124. ynab_cli/adapters/ynab/models/post_transactions_wrapper.py +91 -0
  125. ynab_cli/adapters/ynab/models/put_scheduled_transaction_wrapper.py +65 -0
  126. ynab_cli/adapters/ynab/models/put_transaction_wrapper.py +65 -0
  127. ynab_cli/adapters/ynab/models/save_account.py +77 -0
  128. ynab_cli/adapters/ynab/models/save_category.py +129 -0
  129. ynab_cli/adapters/ynab/models/save_category_response.py +65 -0
  130. ynab_cli/adapters/ynab/models/save_category_response_data.py +73 -0
  131. ynab_cli/adapters/ynab/models/save_month_category.py +59 -0
  132. ynab_cli/adapters/ynab/models/save_payee.py +59 -0
  133. ynab_cli/adapters/ynab/models/save_payee_response.py +65 -0
  134. ynab_cli/adapters/ynab/models/save_payee_response_data.py +73 -0
  135. ynab_cli/adapters/ynab/models/save_scheduled_transaction.py +269 -0
  136. ynab_cli/adapters/ynab/models/save_sub_transaction.py +166 -0
  137. ynab_cli/adapters/ynab/models/save_transaction_with_id_or_import_id.py +366 -0
  138. ynab_cli/adapters/ynab/models/save_transaction_with_optional_fields.py +322 -0
  139. ynab_cli/adapters/ynab/models/save_transactions_response.py +65 -0
  140. ynab_cli/adapters/ynab/models/save_transactions_response_data.py +123 -0
  141. ynab_cli/adapters/ynab/models/scheduled_sub_transaction.py +238 -0
  142. ynab_cli/adapters/ynab/models/scheduled_transaction_detail.py +381 -0
  143. ynab_cli/adapters/ynab/models/scheduled_transaction_frequency.py +23 -0
  144. ynab_cli/adapters/ynab/models/scheduled_transaction_response.py +65 -0
  145. ynab_cli/adapters/ynab/models/scheduled_transaction_response_data.py +65 -0
  146. ynab_cli/adapters/ynab/models/scheduled_transaction_summary.py +310 -0
  147. ynab_cli/adapters/ynab/models/scheduled_transaction_summary_frequency.py +23 -0
  148. ynab_cli/adapters/ynab/models/scheduled_transactions_response.py +65 -0
  149. ynab_cli/adapters/ynab/models/scheduled_transactions_response_data.py +81 -0
  150. ynab_cli/adapters/ynab/models/sub_transaction.py +259 -0
  151. ynab_cli/adapters/ynab/models/transaction_cleared_status.py +13 -0
  152. ynab_cli/adapters/ynab/models/transaction_detail.py +570 -0
  153. ynab_cli/adapters/ynab/models/transaction_flag_color_type_1.py +16 -0
  154. ynab_cli/adapters/ynab/models/transaction_flag_color_type_2_type_1.py +16 -0
  155. ynab_cli/adapters/ynab/models/transaction_flag_color_type_3_type_1.py +16 -0
  156. ynab_cli/adapters/ynab/models/transaction_response.py +65 -0
  157. ynab_cli/adapters/ynab/models/transaction_response_data.py +65 -0
  158. ynab_cli/adapters/ynab/models/transaction_summary.py +499 -0
  159. ynab_cli/adapters/ynab/models/transaction_summary_debt_transaction_type_type_1.py +18 -0
  160. ynab_cli/adapters/ynab/models/transaction_summary_debt_transaction_type_type_2_type_1.py +18 -0
  161. ynab_cli/adapters/ynab/models/transaction_summary_debt_transaction_type_type_3_type_1.py +18 -0
  162. ynab_cli/adapters/ynab/models/transactions_import_response.py +65 -0
  163. ynab_cli/adapters/ynab/models/transactions_import_response_data.py +59 -0
  164. ynab_cli/adapters/ynab/models/transactions_response.py +65 -0
  165. ynab_cli/adapters/ynab/models/transactions_response_data.py +81 -0
  166. ynab_cli/adapters/ynab/models/user.py +60 -0
  167. ynab_cli/adapters/ynab/models/user_response.py +65 -0
  168. ynab_cli/adapters/ynab/models/user_response_data.py +65 -0
  169. ynab_cli/adapters/ynab/types.py +46 -0
  170. ynab_cli/adapters/ynab/util.py +78 -0
  171. ynab_cli/domain/__init__.py +0 -0
  172. ynab_cli/domain/constants.py +3 -0
  173. ynab_cli/domain/models/__init__.py +0 -0
  174. ynab_cli/domain/models/rules.py +37 -0
  175. ynab_cli/domain/ports/__init__.py +5 -0
  176. ynab_cli/domain/ports/io.py +63 -0
  177. ynab_cli/domain/settings.py +16 -0
  178. ynab_cli/domain/use_cases/__init__.py +0 -0
  179. ynab_cli/domain/use_cases/categories.py +105 -0
  180. ynab_cli/domain/use_cases/payees.py +232 -0
  181. ynab_cli/domain/use_cases/transactions.py +93 -0
  182. ynab_cli/host/__init__.py +14 -0
  183. ynab_cli/host/cli.py +37 -0
  184. ynab_cli/host/click/__init__.py +0 -0
  185. ynab_cli/host/click/cli.py +44 -0
  186. ynab_cli/host/click/commands/__init__.py +0 -0
  187. ynab_cli/host/click/commands/categories.py +92 -0
  188. ynab_cli/host/click/commands/payees.py +157 -0
  189. ynab_cli/host/click/commands/rich/__init__.py +0 -0
  190. ynab_cli/host/click/commands/rich/progress_table.py +37 -0
  191. ynab_cli/host/click/commands/transactions.py +76 -0
  192. ynab_cli/host/constants.py +3 -0
  193. ynab_cli/host/textual/__init__.py +0 -0
  194. ynab_cli/host/textual/app.py +98 -0
  195. ynab_cli/host/textual/app.tcss +47 -0
  196. ynab_cli/host/textual/cli.py +42 -0
  197. ynab_cli/host/textual/widgets/__init__.py +58 -0
  198. ynab_cli/host/textual/widgets/categories.py +90 -0
  199. ynab_cli/host/textual/widgets/payees.py +154 -0
  200. ynab_cli/host/textual/widgets/transactions.py +89 -0
  201. ynab_cli/py.typed +0 -0
  202. ynab_cli-0.3.0.dist-info/METADATA +102 -0
  203. ynab_cli-0.3.0.dist-info/RECORD +206 -0
  204. ynab_cli-0.3.0.dist-info/WHEEL +4 -0
  205. ynab_cli-0.3.0.dist-info/entry_points.txt +2 -0
  206. ynab_cli-0.3.0.dist-info/licenses/LICENSE.md +21 -0
@@ -0,0 +1,180 @@
1
+ from http import HTTPStatus
2
+ from typing import Any
3
+
4
+ import httpx
5
+
6
+ from ynab_cli.adapters.ynab import errors
7
+ from ynab_cli.adapters.ynab.client import AuthenticatedClient, Client
8
+ from ynab_cli.adapters.ynab.models.category_response import CategoryResponse
9
+ from ynab_cli.adapters.ynab.models.error_response import ErrorResponse
10
+ from ynab_cli.adapters.ynab.types import Response
11
+
12
+
13
+ def _get_kwargs(
14
+ budget_id: str,
15
+ category_id: str,
16
+ ) -> dict[str, Any]:
17
+ _kwargs: dict[str, Any] = {
18
+ "method": "get",
19
+ "url": f"/budgets/{budget_id}/categories/{category_id}",
20
+ }
21
+
22
+ return _kwargs
23
+
24
+
25
+ def _parse_response(
26
+ *, client: AuthenticatedClient | Client, response: httpx.Response
27
+ ) -> CategoryResponse | ErrorResponse | None:
28
+ if response.status_code == 200:
29
+ response_200 = CategoryResponse.from_dict(response.json())
30
+
31
+ return response_200
32
+ if response.status_code == 404:
33
+ response_404 = ErrorResponse.from_dict(response.json())
34
+
35
+ return response_404
36
+ if client.raise_on_unexpected_status:
37
+ raise errors.UnexpectedStatusError(response.status_code, response.content)
38
+ else:
39
+ return None
40
+
41
+
42
+ def _build_response(
43
+ *, client: AuthenticatedClient | Client, response: httpx.Response
44
+ ) -> Response[CategoryResponse | ErrorResponse]:
45
+ return Response(
46
+ status_code=HTTPStatus(response.status_code),
47
+ content=response.content,
48
+ headers=response.headers,
49
+ parsed=_parse_response(client=client, response=response),
50
+ )
51
+
52
+
53
+ def sync_detailed(
54
+ budget_id: str,
55
+ category_id: str,
56
+ *,
57
+ client: AuthenticatedClient | Client,
58
+ ) -> Response[CategoryResponse | ErrorResponse]:
59
+ """Single category
60
+
61
+ Returns a single category. Amounts (budgeted, activity, balance, etc.) are specific to the current
62
+ budget month (UTC).
63
+
64
+ Args:
65
+ budget_id (str):
66
+ category_id (str):
67
+
68
+ Raises:
69
+ errors.UnexpectedStatusError: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
70
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
71
+
72
+ Returns:
73
+ Response[Union[CategoryResponse, ErrorResponse]]
74
+ """
75
+
76
+ kwargs = _get_kwargs(
77
+ budget_id=budget_id,
78
+ category_id=category_id,
79
+ )
80
+
81
+ response = client.get_httpx_client().request(
82
+ **kwargs,
83
+ )
84
+
85
+ return _build_response(client=client, response=response)
86
+
87
+
88
+ def sync(
89
+ budget_id: str,
90
+ category_id: str,
91
+ *,
92
+ client: AuthenticatedClient | Client,
93
+ ) -> CategoryResponse | ErrorResponse | None:
94
+ """Single category
95
+
96
+ Returns a single category. Amounts (budgeted, activity, balance, etc.) are specific to the current
97
+ budget month (UTC).
98
+
99
+ Args:
100
+ budget_id (str):
101
+ category_id (str):
102
+
103
+ Raises:
104
+ errors.UnexpectedStatusError: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
105
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
106
+
107
+ Returns:
108
+ Union[CategoryResponse, ErrorResponse]
109
+ """
110
+
111
+ return sync_detailed(
112
+ budget_id=budget_id,
113
+ category_id=category_id,
114
+ client=client,
115
+ ).parsed
116
+
117
+
118
+ async def asyncio_detailed(
119
+ budget_id: str,
120
+ category_id: str,
121
+ *,
122
+ client: AuthenticatedClient | Client,
123
+ ) -> Response[CategoryResponse | ErrorResponse]:
124
+ """Single category
125
+
126
+ Returns a single category. Amounts (budgeted, activity, balance, etc.) are specific to the current
127
+ budget month (UTC).
128
+
129
+ Args:
130
+ budget_id (str):
131
+ category_id (str):
132
+
133
+ Raises:
134
+ errors.UnexpectedStatusError: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
135
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
136
+
137
+ Returns:
138
+ Response[Union[CategoryResponse, ErrorResponse]]
139
+ """
140
+
141
+ kwargs = _get_kwargs(
142
+ budget_id=budget_id,
143
+ category_id=category_id,
144
+ )
145
+
146
+ response = await client.get_async_httpx_client().request(**kwargs)
147
+
148
+ return _build_response(client=client, response=response)
149
+
150
+
151
+ async def asyncio(
152
+ budget_id: str,
153
+ category_id: str,
154
+ *,
155
+ client: AuthenticatedClient | Client,
156
+ ) -> CategoryResponse | ErrorResponse | None:
157
+ """Single category
158
+
159
+ Returns a single category. Amounts (budgeted, activity, balance, etc.) are specific to the current
160
+ budget month (UTC).
161
+
162
+ Args:
163
+ budget_id (str):
164
+ category_id (str):
165
+
166
+ Raises:
167
+ errors.UnexpectedStatusError: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
168
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
169
+
170
+ Returns:
171
+ Union[CategoryResponse, ErrorResponse]
172
+ """
173
+
174
+ return (
175
+ await asyncio_detailed(
176
+ budget_id=budget_id,
177
+ category_id=category_id,
178
+ client=client,
179
+ )
180
+ ).parsed
@@ -0,0 +1,194 @@
1
+ import datetime
2
+ from http import HTTPStatus
3
+ from typing import Any
4
+
5
+ import httpx
6
+
7
+ from ynab_cli.adapters.ynab import errors
8
+ from ynab_cli.adapters.ynab.client import AuthenticatedClient, Client
9
+ from ynab_cli.adapters.ynab.models.category_response import CategoryResponse
10
+ from ynab_cli.adapters.ynab.models.error_response import ErrorResponse
11
+ from ynab_cli.adapters.ynab.types import Response
12
+
13
+
14
+ def _get_kwargs(
15
+ budget_id: str,
16
+ month: datetime.date,
17
+ category_id: str,
18
+ ) -> dict[str, Any]:
19
+ _kwargs: dict[str, Any] = {
20
+ "method": "get",
21
+ "url": f"/budgets/{budget_id}/months/{month}/categories/{category_id}",
22
+ }
23
+
24
+ return _kwargs
25
+
26
+
27
+ def _parse_response(
28
+ *, client: AuthenticatedClient | Client, response: httpx.Response
29
+ ) -> CategoryResponse | ErrorResponse | None:
30
+ if response.status_code == 200:
31
+ response_200 = CategoryResponse.from_dict(response.json())
32
+
33
+ return response_200
34
+ if response.status_code == 404:
35
+ response_404 = ErrorResponse.from_dict(response.json())
36
+
37
+ return response_404
38
+ if client.raise_on_unexpected_status:
39
+ raise errors.UnexpectedStatusError(response.status_code, response.content)
40
+ else:
41
+ return None
42
+
43
+
44
+ def _build_response(
45
+ *, client: AuthenticatedClient | Client, response: httpx.Response
46
+ ) -> Response[CategoryResponse | ErrorResponse]:
47
+ return Response(
48
+ status_code=HTTPStatus(response.status_code),
49
+ content=response.content,
50
+ headers=response.headers,
51
+ parsed=_parse_response(client=client, response=response),
52
+ )
53
+
54
+
55
+ def sync_detailed(
56
+ budget_id: str,
57
+ month: datetime.date,
58
+ category_id: str,
59
+ *,
60
+ client: AuthenticatedClient | Client,
61
+ ) -> Response[CategoryResponse | ErrorResponse]:
62
+ """Single category for a specific budget month
63
+
64
+ Returns a single category for a specific budget month. Amounts (budgeted, activity, balance, etc.)
65
+ are specific to the current budget month (UTC).
66
+
67
+ Args:
68
+ budget_id (str):
69
+ month (datetime.date):
70
+ category_id (str):
71
+
72
+ Raises:
73
+ errors.UnexpectedStatusError: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
74
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
75
+
76
+ Returns:
77
+ Response[Union[CategoryResponse, ErrorResponse]]
78
+ """
79
+
80
+ kwargs = _get_kwargs(
81
+ budget_id=budget_id,
82
+ month=month,
83
+ category_id=category_id,
84
+ )
85
+
86
+ response = client.get_httpx_client().request(
87
+ **kwargs,
88
+ )
89
+
90
+ return _build_response(client=client, response=response)
91
+
92
+
93
+ def sync(
94
+ budget_id: str,
95
+ month: datetime.date,
96
+ category_id: str,
97
+ *,
98
+ client: AuthenticatedClient | Client,
99
+ ) -> CategoryResponse | ErrorResponse | None:
100
+ """Single category for a specific budget month
101
+
102
+ Returns a single category for a specific budget month. Amounts (budgeted, activity, balance, etc.)
103
+ are specific to the current budget month (UTC).
104
+
105
+ Args:
106
+ budget_id (str):
107
+ month (datetime.date):
108
+ category_id (str):
109
+
110
+ Raises:
111
+ errors.UnexpectedStatusError: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
112
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
113
+
114
+ Returns:
115
+ Union[CategoryResponse, ErrorResponse]
116
+ """
117
+
118
+ return sync_detailed(
119
+ budget_id=budget_id,
120
+ month=month,
121
+ category_id=category_id,
122
+ client=client,
123
+ ).parsed
124
+
125
+
126
+ async def asyncio_detailed(
127
+ budget_id: str,
128
+ month: datetime.date,
129
+ category_id: str,
130
+ *,
131
+ client: AuthenticatedClient | Client,
132
+ ) -> Response[CategoryResponse | ErrorResponse]:
133
+ """Single category for a specific budget month
134
+
135
+ Returns a single category for a specific budget month. Amounts (budgeted, activity, balance, etc.)
136
+ are specific to the current budget month (UTC).
137
+
138
+ Args:
139
+ budget_id (str):
140
+ month (datetime.date):
141
+ category_id (str):
142
+
143
+ Raises:
144
+ errors.UnexpectedStatusError: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
145
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
146
+
147
+ Returns:
148
+ Response[Union[CategoryResponse, ErrorResponse]]
149
+ """
150
+
151
+ kwargs = _get_kwargs(
152
+ budget_id=budget_id,
153
+ month=month,
154
+ category_id=category_id,
155
+ )
156
+
157
+ response = await client.get_async_httpx_client().request(**kwargs)
158
+
159
+ return _build_response(client=client, response=response)
160
+
161
+
162
+ async def asyncio(
163
+ budget_id: str,
164
+ month: datetime.date,
165
+ category_id: str,
166
+ *,
167
+ client: AuthenticatedClient | Client,
168
+ ) -> CategoryResponse | ErrorResponse | None:
169
+ """Single category for a specific budget month
170
+
171
+ Returns a single category for a specific budget month. Amounts (budgeted, activity, balance, etc.)
172
+ are specific to the current budget month (UTC).
173
+
174
+ Args:
175
+ budget_id (str):
176
+ month (datetime.date):
177
+ category_id (str):
178
+
179
+ Raises:
180
+ errors.UnexpectedStatusError: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
181
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
182
+
183
+ Returns:
184
+ Union[CategoryResponse, ErrorResponse]
185
+ """
186
+
187
+ return (
188
+ await asyncio_detailed(
189
+ budget_id=budget_id,
190
+ month=month,
191
+ category_id=category_id,
192
+ client=client,
193
+ )
194
+ ).parsed
@@ -0,0 +1,199 @@
1
+ from http import HTTPStatus
2
+ from typing import Any
3
+
4
+ import httpx
5
+
6
+ from ynab_cli.adapters.ynab import errors
7
+ from ynab_cli.adapters.ynab.client import AuthenticatedClient, Client
8
+ from ynab_cli.adapters.ynab.models.error_response import ErrorResponse
9
+ from ynab_cli.adapters.ynab.models.patch_category_wrapper import PatchCategoryWrapper
10
+ from ynab_cli.adapters.ynab.models.save_category_response import SaveCategoryResponse
11
+ from ynab_cli.adapters.ynab.types import Response
12
+
13
+
14
+ def _get_kwargs(
15
+ budget_id: str,
16
+ category_id: str,
17
+ *,
18
+ body: PatchCategoryWrapper,
19
+ ) -> dict[str, Any]:
20
+ headers: dict[str, Any] = {}
21
+
22
+ _kwargs: dict[str, Any] = {
23
+ "method": "patch",
24
+ "url": f"/budgets/{budget_id}/categories/{category_id}",
25
+ }
26
+
27
+ _body = body.to_dict()
28
+
29
+ _kwargs["json"] = _body
30
+ headers["Content-Type"] = "application/json"
31
+
32
+ _kwargs["headers"] = headers
33
+ return _kwargs
34
+
35
+
36
+ def _parse_response(
37
+ *, client: AuthenticatedClient | Client, response: httpx.Response
38
+ ) -> ErrorResponse | SaveCategoryResponse | None:
39
+ if response.status_code == 200:
40
+ response_200 = SaveCategoryResponse.from_dict(response.json())
41
+
42
+ return response_200
43
+ if response.status_code == 400:
44
+ response_400 = ErrorResponse.from_dict(response.json())
45
+
46
+ return response_400
47
+ if client.raise_on_unexpected_status:
48
+ raise errors.UnexpectedStatusError(response.status_code, response.content)
49
+ else:
50
+ return None
51
+
52
+
53
+ def _build_response(
54
+ *, client: AuthenticatedClient | Client, response: httpx.Response
55
+ ) -> Response[ErrorResponse | SaveCategoryResponse]:
56
+ return Response(
57
+ status_code=HTTPStatus(response.status_code),
58
+ content=response.content,
59
+ headers=response.headers,
60
+ parsed=_parse_response(client=client, response=response),
61
+ )
62
+
63
+
64
+ def sync_detailed(
65
+ budget_id: str,
66
+ category_id: str,
67
+ *,
68
+ client: AuthenticatedClient | Client,
69
+ body: PatchCategoryWrapper,
70
+ ) -> Response[ErrorResponse | SaveCategoryResponse]:
71
+ """Update a category
72
+
73
+ Update a category
74
+
75
+ Args:
76
+ budget_id (str):
77
+ category_id (str):
78
+ body (PatchCategoryWrapper):
79
+
80
+ Raises:
81
+ errors.UnexpectedStatusError: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
82
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
83
+
84
+ Returns:
85
+ Response[Union[ErrorResponse, SaveCategoryResponse]]
86
+ """
87
+
88
+ kwargs = _get_kwargs(
89
+ budget_id=budget_id,
90
+ category_id=category_id,
91
+ body=body,
92
+ )
93
+
94
+ response = client.get_httpx_client().request(
95
+ **kwargs,
96
+ )
97
+
98
+ return _build_response(client=client, response=response)
99
+
100
+
101
+ def sync(
102
+ budget_id: str,
103
+ category_id: str,
104
+ *,
105
+ client: AuthenticatedClient | Client,
106
+ body: PatchCategoryWrapper,
107
+ ) -> ErrorResponse | SaveCategoryResponse | None:
108
+ """Update a category
109
+
110
+ Update a category
111
+
112
+ Args:
113
+ budget_id (str):
114
+ category_id (str):
115
+ body (PatchCategoryWrapper):
116
+
117
+ Raises:
118
+ errors.UnexpectedStatusError: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
119
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
120
+
121
+ Returns:
122
+ Union[ErrorResponse, SaveCategoryResponse]
123
+ """
124
+
125
+ return sync_detailed(
126
+ budget_id=budget_id,
127
+ category_id=category_id,
128
+ client=client,
129
+ body=body,
130
+ ).parsed
131
+
132
+
133
+ async def asyncio_detailed(
134
+ budget_id: str,
135
+ category_id: str,
136
+ *,
137
+ client: AuthenticatedClient | Client,
138
+ body: PatchCategoryWrapper,
139
+ ) -> Response[ErrorResponse | SaveCategoryResponse]:
140
+ """Update a category
141
+
142
+ Update a category
143
+
144
+ Args:
145
+ budget_id (str):
146
+ category_id (str):
147
+ body (PatchCategoryWrapper):
148
+
149
+ Raises:
150
+ errors.UnexpectedStatusError: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
151
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
152
+
153
+ Returns:
154
+ Response[Union[ErrorResponse, SaveCategoryResponse]]
155
+ """
156
+
157
+ kwargs = _get_kwargs(
158
+ budget_id=budget_id,
159
+ category_id=category_id,
160
+ body=body,
161
+ )
162
+
163
+ response = await client.get_async_httpx_client().request(**kwargs)
164
+
165
+ return _build_response(client=client, response=response)
166
+
167
+
168
+ async def asyncio(
169
+ budget_id: str,
170
+ category_id: str,
171
+ *,
172
+ client: AuthenticatedClient | Client,
173
+ body: PatchCategoryWrapper,
174
+ ) -> ErrorResponse | SaveCategoryResponse | None:
175
+ """Update a category
176
+
177
+ Update a category
178
+
179
+ Args:
180
+ budget_id (str):
181
+ category_id (str):
182
+ body (PatchCategoryWrapper):
183
+
184
+ Raises:
185
+ errors.UnexpectedStatusError: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
186
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
187
+
188
+ Returns:
189
+ Union[ErrorResponse, SaveCategoryResponse]
190
+ """
191
+
192
+ return (
193
+ await asyncio_detailed(
194
+ budget_id=budget_id,
195
+ category_id=category_id,
196
+ client=client,
197
+ body=body,
198
+ )
199
+ ).parsed