lunchmoney-python-async 2.15.0__py3-none-any.whl → 2.18.2__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.
lunchmoney/__init__.py CHANGED
@@ -15,7 +15,7 @@
15
15
  """ # noqa: E501
16
16
 
17
17
 
18
- __version__ = "2.15.0"
18
+ __version__ = "2.18.2"
19
19
 
20
20
  # Define package exports
21
21
  __all__ = [
lunchmoney/api_client.py CHANGED
@@ -92,7 +92,7 @@ class ApiClient:
92
92
  self.default_headers[header_name] = header_value
93
93
  self.cookie = cookie
94
94
  # Set default User-Agent.
95
- self.user_agent = 'OpenAPI-Generator/2.15.0/python'
95
+ self.user_agent = 'OpenAPI-Generator/2.18.2/python'
96
96
  self.client_side_validation = configuration.client_side_validation
97
97
 
98
98
  async def __aenter__(self):
lunchmoney/app.py ADDED
@@ -0,0 +1,589 @@
1
+ """
2
+ Base Classes for LunchMoneyApp
3
+ """
4
+
5
+ import asyncio
6
+ import datetime
7
+ import logging
8
+ from collections.abc import AsyncIterable, Iterable
9
+ from dataclasses import dataclass, field
10
+ from functools import cached_property
11
+ from os import getenv
12
+ from typing import Any, Callable, ClassVar, NamedTuple, TypeVar, overload
13
+
14
+ import lunchmoney
15
+ from lunchmoney import GetAllTransactions200Response
16
+ from lunchmoney.models import ( # type: ignore[attr-defined]
17
+ CategoryObject,
18
+ ManualAccountObject,
19
+ PlaidAccountObject,
20
+ TagObject,
21
+ TransactionObject,
22
+ UserObject,
23
+ )
24
+ from pydantic import BaseModel
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+
29
+ LunchableModelType = TypeVar("LunchableModelType", bound=BaseModel)
30
+
31
+
32
+ @dataclass(slots=True)
33
+ class LunchableData:
34
+ """
35
+ Data Container for Lunchable App Data
36
+ """
37
+
38
+ plaid_accounts: dict[int, PlaidAccountObject] = field(default_factory=dict)
39
+ """Plaid Accounts"""
40
+ transactions: dict[int, TransactionObject] = field(default_factory=dict)
41
+ """Transactions"""
42
+ categories: dict[int, CategoryObject] = field(default_factory=dict)
43
+ """Categories"""
44
+ manual_accounts: dict[int, ManualAccountObject] = field(default_factory=dict)
45
+ """Manual Accounts"""
46
+ tags: dict[int, TagObject] = field(default_factory=dict)
47
+ """Tags"""
48
+ user: UserObject | None = None
49
+ """User"""
50
+
51
+ @property
52
+ def current_user(self) -> UserObject:
53
+ """
54
+ Current User Object
55
+
56
+ Returns
57
+ -------
58
+ UserObject
59
+ """
60
+ if not self.user:
61
+ raise ValueError("User data has not been loaded.")
62
+ return self.user
63
+
64
+ @property
65
+ def asset_map(self) -> dict[int, PlaidAccountObject | ManualAccountObject]:
66
+ """
67
+ Asset Mapping Across Plaid Accounts and Assets
68
+
69
+ Returns
70
+ -------
71
+ dict[int, Union[PlaidAccountObject, ManualAccountObject]]
72
+ """
73
+ return {
74
+ **self.plaid_accounts,
75
+ **self.manual_accounts,
76
+ }
77
+
78
+ @property
79
+ def plaid_accounts_list(self) -> list[PlaidAccountObject]:
80
+ """
81
+ List of Plaid Accounts
82
+
83
+ Returns
84
+ -------
85
+ list[PlaidAccountObject]
86
+ """
87
+ return list(self.plaid_accounts.values())
88
+
89
+ @property
90
+ def manual_accounts_list(self) -> list[ManualAccountObject]:
91
+ """
92
+ List of Manual Accounts
93
+
94
+ Returns
95
+ -------
96
+ list[ManualAccountObject]
97
+ """
98
+ return list(self.manual_accounts.values())
99
+
100
+ @property
101
+ def transactions_list(self) -> list[TransactionObject]:
102
+ """
103
+ List of Transactions
104
+
105
+ Returns
106
+ -------
107
+ list[TransactionObject]
108
+ """
109
+ return list(self.transactions.values())
110
+
111
+ @property
112
+ def categories_list(self) -> list[CategoryObject]:
113
+ """
114
+ List of Categories
115
+
116
+ Returns
117
+ -------
118
+ list[CategoryObject]
119
+ """
120
+ return list(self.categories.values())
121
+
122
+ @property
123
+ def tags_list(self) -> list[TagObject]:
124
+ """
125
+ List of Tags
126
+
127
+ Returns
128
+ -------
129
+ list[TagObject]
130
+ """
131
+ return list(self.tags.values())
132
+
133
+
134
+ class _ObjectMapper(NamedTuple):
135
+ """
136
+ Object Mapper for Lunchable Models
137
+ """
138
+
139
+ func: Callable[..., Any]
140
+ data_attr: str
141
+
142
+
143
+ @dataclass(slots=True)
144
+ class LunchableApi:
145
+ """
146
+ API Container for Lunchable App APIs
147
+ """
148
+
149
+ plaid: lunchmoney.PlaidAccountsApi
150
+ transactions: lunchmoney.TransactionsApi
151
+ transactions_bulk: lunchmoney.TransactionsBulkApi
152
+ categories: lunchmoney.CategoriesApi
153
+ manual_accounts: lunchmoney.ManualAccountsApi
154
+ tags: lunchmoney.TagsApi
155
+ me: lunchmoney.MeApi
156
+ recurring_items: lunchmoney.RecurringItemsApi
157
+ summary: lunchmoney.SummaryApi
158
+ transactions_files: lunchmoney.TransactionsFilesApi
159
+ transactions_group: lunchmoney.TransactionsGroupApi
160
+ transactions_split: lunchmoney.TransactionsSplitApi
161
+
162
+ @classmethod
163
+ def from_client(cls, client: lunchmoney.ApiClient) -> "LunchableApi":
164
+ """
165
+ Initialize LunchableApi from ApiClient
166
+ """
167
+ return cls(
168
+ plaid=lunchmoney.PlaidAccountsApi(client),
169
+ transactions=lunchmoney.TransactionsApi(client),
170
+ transactions_bulk=lunchmoney.TransactionsBulkApi(client),
171
+ categories=lunchmoney.CategoriesApi(client),
172
+ manual_accounts=lunchmoney.ManualAccountsApi(client),
173
+ tags=lunchmoney.TagsApi(client),
174
+ me=lunchmoney.MeApi(client),
175
+ recurring_items=lunchmoney.RecurringItemsApi(client),
176
+ summary=lunchmoney.SummaryApi(client),
177
+ transactions_files=lunchmoney.TransactionsFilesApi(client),
178
+ transactions_group=lunchmoney.TransactionsGroupApi(client),
179
+ transactions_split=lunchmoney.TransactionsSplitApi(client),
180
+ )
181
+
182
+
183
+ class LunchMoneyApp:
184
+ """
185
+ Base LunchMoney App Class
186
+ """
187
+
188
+ lunchable_models: ClassVar[Iterable[type[BaseModel]]] = [
189
+ PlaidAccountObject,
190
+ CategoryObject,
191
+ ManualAccountObject,
192
+ TagObject,
193
+ UserObject,
194
+ ]
195
+ """Every LunchableApp should define which data objects it depends on"""
196
+ lunchable_models_kwargs: ClassVar[dict[type[BaseModel], dict[str, Any]]] = {}
197
+ """Optional keyword arguments to pass to model constructors (supports callables)"""
198
+ transaction_pagination: ClassVar[int] = 500
199
+ """Number of Transactions to fetch per page during pagination"""
200
+
201
+ def __init__(
202
+ self,
203
+ access_token: str | None = None,
204
+ lunchable_models: Iterable[type[BaseModel]] | None = None,
205
+ lunchable_models_kwargs: dict[type[BaseModel], dict[str, Any]] | None = None,
206
+ transaction_pagination: int | None = None,
207
+ ) -> None:
208
+ """
209
+ Initialize LunchMoneyApp
210
+
211
+ Parameters
212
+ ----------
213
+ access_token: str | None
214
+ LunchMoney Access Token. If not provided, will attempt to read from
215
+ `LUNCHMONEY_ACCESS_TOKEN` environment variable.
216
+ lunchable_models: Iterable[type[LunchableModelType]] | None
217
+ Explicit list of Lunchable Models to use in this app. If not provided,
218
+ will default to the class variable `lunchable_models`.
219
+ lunchable_models_kwargs: dict[type[LunchableModelType], dict[str, Any]] | None
220
+ Optional keyword arguments to pass to model constructors. If not provided,
221
+ will default to the class variable `lunchable_models_kwargs`.
222
+ transaction_pagination: int | None
223
+ Number of Transactions to fetch per page during pagination. If not provided,
224
+ will default to the class variable `transaction_pagination`.
225
+ """
226
+ access_token = access_token or getenv("LUNCHMONEY_ACCESS_TOKEN")
227
+ if not access_token:
228
+ raise ValueError(
229
+ "LunchMoney API key must be provided via "
230
+ "parameter or LUNCHMONEY_ACCESS_TOKEN environment "
231
+ "variable."
232
+ )
233
+ configuration = lunchmoney.Configuration(
234
+ host="https://api.lunchmoney.dev/v2", access_token=access_token
235
+ )
236
+ self.client: lunchmoney.ApiClient = lunchmoney.ApiClient(
237
+ configuration=configuration
238
+ )
239
+ self.api: LunchableApi = LunchableApi.from_client(self.client)
240
+ self.data: LunchableData = LunchableData()
241
+ self._lunchable_models: Iterable[type[BaseModel]] = (
242
+ lunchable_models or self.__class__.lunchable_models
243
+ )
244
+ self._lunchable_models_kwargs: dict[type[BaseModel], dict[str, Any]] = (
245
+ lunchable_models_kwargs or self.__class__.lunchable_models_kwargs
246
+ )
247
+ self._transaction_pagination: int = (
248
+ transaction_pagination or self.__class__.transaction_pagination
249
+ )
250
+
251
+ @cached_property
252
+ def _model_mapping(self) -> dict[type[BaseModel], _ObjectMapper]:
253
+ """
254
+ Model Class -> _ObjectMapper Mapping
255
+ """
256
+ return {
257
+ PlaidAccountObject: _ObjectMapper(
258
+ func=self.api.plaid.get_all_plaid_accounts,
259
+ data_attr="plaid_accounts",
260
+ ),
261
+ TransactionObject: _ObjectMapper(
262
+ func=self.api.transactions_bulk.get_all_transactions,
263
+ data_attr="transactions",
264
+ ),
265
+ CategoryObject: _ObjectMapper(
266
+ func=self.api.categories.get_all_categories,
267
+ data_attr="categories",
268
+ ),
269
+ ManualAccountObject: _ObjectMapper(
270
+ func=self.api.manual_accounts.get_all_manual_accounts,
271
+ data_attr="manual_accounts",
272
+ ),
273
+ TagObject: _ObjectMapper(
274
+ func=self.api.tags.get_all_tags,
275
+ data_attr="tags",
276
+ ),
277
+ UserObject: _ObjectMapper(
278
+ func=self.api.me.get_me,
279
+ data_attr="me",
280
+ ),
281
+ }
282
+
283
+ def _get_model_mapper(self, model: type[LunchableModelType]) -> _ObjectMapper:
284
+ """
285
+ Get the appropriate function for a given Lunchable Model
286
+
287
+ Parameters
288
+ ----------
289
+ model: Type[LunchableModelType]
290
+ Type of Lunchable Model to get the function for
291
+
292
+ Returns
293
+ -------
294
+ _ObjectMapper
295
+ _ObjectMapper containing the function and data attribute name
296
+ """
297
+ mapper = self._model_mapping.get(model)
298
+ if not mapper:
299
+ msg = f"Model {model.__name__} is not supported for refresh."
300
+ raise NotImplementedError(msg)
301
+ return mapper
302
+
303
+ def _resolve_model_kwargs(
304
+ self, model: type[LunchableModelType], **kwargs: Any
305
+ ) -> dict[str, Any]:
306
+ """
307
+ Resolve Any Model Kwargs that Are Callable
308
+ """
309
+ model_kwargs = self._lunchable_models_kwargs.get(model, {}).copy()
310
+ model_kwargs.update(kwargs)
311
+ resolved_kwargs: dict[str, Any] = {}
312
+ for key, value in model_kwargs.items():
313
+ if callable(value):
314
+ resolved_value = value()
315
+ else:
316
+ resolved_value = value
317
+ resolved_kwargs[key] = resolved_value
318
+ return resolved_kwargs
319
+
320
+ @overload
321
+ async def refresh(self, model: type[UserObject], **kwargs: Any) -> UserObject: ...
322
+
323
+ @overload
324
+ async def refresh(
325
+ self, model: type[TransactionObject], **kwargs: Any
326
+ ) -> dict[int, TransactionObject]: ...
327
+
328
+ @overload
329
+ async def refresh(
330
+ self, model: type[LunchableModelType], **kwargs: Any
331
+ ) -> dict[int, LunchableModelType]: ...
332
+
333
+ async def refresh(
334
+ self, model: type[LunchableModelType], **kwargs: Any
335
+ ) -> LunchableModelType | dict[int, LunchableModelType]:
336
+ """
337
+ Refresh a Lunchable Model
338
+
339
+ Parameters
340
+ ----------
341
+ model: Type[LunchableModelType]
342
+ Type of Lunchable Model to refresh
343
+ kwargs: Any
344
+ Additional keyword arguments to pass to the function that
345
+ fetches the data.
346
+
347
+ Returns
348
+ -------
349
+ LunchableModelType | dict[int, LunchableModelType]
350
+ Unless you're requesting the `UserObject`, this method will return a
351
+ dictionary of the refreshed data, keyed by the object's ID.
352
+
353
+ Examples
354
+ --------
355
+ ```python
356
+ from lunchable.models import CategoriesObject
357
+ from lunchable.plugins import LunchableApp
358
+
359
+ app = LunchableApp()
360
+ categories: dict[int, CategoriesObject] = app.refresh(CategoriesObject)
361
+ ```
362
+ """
363
+ mapper = self._get_model_mapper(model)
364
+ model_kwargs = self._resolve_model_kwargs(model=model, **kwargs)
365
+ logger.info("Refreshing LunchMoney Data: %s", mapper.data_attr)
366
+ if model is UserObject:
367
+ user = await mapper.func(**model_kwargs)
368
+ self.data.user = user
369
+ return user
370
+ elif model is TransactionObject:
371
+ transaction_map: dict[int, TransactionObject] = {
372
+ obj.id: obj async for obj in self._paginate_transactions(**model_kwargs)
373
+ }
374
+ logger.info("Refreshed LunchMoney Transactions (%s)", len(transaction_map))
375
+ self.data.transactions.update(transaction_map)
376
+ return transaction_map # type: ignore[return-value]
377
+ else:
378
+ response = await mapper.func(**model_kwargs)
379
+ data_dict = {obj.id: obj for obj in getattr(response, mapper.data_attr)}
380
+ setattr(self.data, mapper.data_attr, data_dict)
381
+ return getattr(self.data, mapper.data_attr)
382
+
383
+ async def refresh_data(
384
+ self, models: Iterable[type[LunchableModelType]] | None = None
385
+ ) -> None:
386
+ """
387
+ Refresh the data in the Lunchable App
388
+
389
+ Parameters
390
+ ----------
391
+ models: Iterable[type[LunchableModelType]] | None
392
+ Explicit list of Lunchable Models to refresh. If not provided,
393
+ all models defined in will be refreshed (which by default is
394
+ all of them except for transactions)
395
+
396
+ Examples
397
+ --------
398
+ ```python
399
+ from lunchable.models import PlaidAccountObject
400
+ from lunchable.plugins import LunchableApp
401
+
402
+ app = LunchableApp()
403
+ app.refresh_data()
404
+ plaid_accounts: dict[int, PlaidAccountObject] = app.data.plaid_accounts
405
+ ```
406
+
407
+ ```python
408
+ from lunchable.models import AssetsObject
409
+ from lunchable.plugins import LunchableApp
410
+
411
+ app = LunchableApp()
412
+ app.refresh_data(models=[AssetsObject])
413
+ assets: dict[int, AssetsObject] = app.data.assets
414
+ ```
415
+ """
416
+ refresh_models = models or self._lunchable_models
417
+ await asyncio.gather(*[self.refresh(model) for model in set(refresh_models)])
418
+
419
+ async def refresh_transactions(
420
+ self,
421
+ start_date: datetime.date | None = None,
422
+ end_date: datetime.date | None = None,
423
+ created_since: datetime.date | str | None = None,
424
+ updated_since: datetime.date | str | None = None,
425
+ manual_account_id: int | None = None,
426
+ plaid_account_id: int | None = None,
427
+ recurring_id: int | None = None,
428
+ category_id: int | None = None,
429
+ tag_id: int | None = None,
430
+ is_group_parent: bool | None = None,
431
+ status: str | None = None,
432
+ is_pending: bool | None = None,
433
+ include_pending: bool | None = None,
434
+ include_metadata: bool | None = None,
435
+ include_split_parents: bool | None = None,
436
+ include_group_children: bool | None = None,
437
+ include_files: bool | None = None,
438
+ ) -> dict[int, TransactionObject]:
439
+ """
440
+ Refresh Transactions in the App
441
+
442
+ Parameters
443
+ ----------
444
+ start_date: datetime.date | None
445
+ Denotes the beginning of the time period to fetch transactions for. If
446
+ omitted, the most recent transactions will be returned. See `limit`.
447
+ Required if end_date exists.
448
+ end_date: datetime.date | None
449
+ Denotes the end of the time period you'd like to get transactions for.
450
+ Required if start_date exists.
451
+ created_since: datetime.date | str | None
452
+ Filter transactions to those created after the specified timestamp.
453
+ Accepts either a date (YYYY-MM-DD) or ISO 8601 datetime string.
454
+ Date-only values are interpreted as midnight UTC (00:00:00Z).
455
+ updated_since: datetime.date | str | None
456
+ Filter transactions to those updated after the specified timestamp.
457
+ Accepts either a date (YYYY-MM-DD) or ISO 8601 datetime string.
458
+ Date-only values are interpreted as midnight UTC (00:00:00Z).
459
+ manual_account_id: int | None
460
+ Filter transactions to those associated with specified manual account ID
461
+ or set this to 0 to omit any transactions from manual accounts. Setting
462
+ both this and `plaid_account_id` to 0 will return transactions with no
463
+ account. These are listed as "Cash Transactions" in the Lunch Money GUI.
464
+ Note that transaction groups are not associated with any account. If you
465
+ want the response to include transactions from transaction groups, set
466
+ the `include_group_children` query parameter to `true` when filtering
467
+ by manual accounts.
468
+ plaid_account_id: int | None
469
+ Filter transactions to those associated with specified plaid account ID
470
+ or set this to 0 to omit any transactions from plaid accounts. Setting
471
+ both this and `manual_account_id` to 0 will return transactions with no
472
+ account. These are listed as "Cash Transactions" in the Lunch Money GUI.
473
+ Note that transaction groups are not associated with any account. If you
474
+ want the response to include transactions from transaction groups, set
475
+ the `include_group_children` query parameter to `true` when filtering
476
+ by plaid accounts.
477
+ recurring_id: int | None
478
+ Filter transactions to those associated with specified Recurring Item ID
479
+ category_id: int | None
480
+ Filter transactions to those associated with the specified category ID.
481
+ Will also match category groups. Set this to 0 to return only
482
+ un-categorized transactions.
483
+ tag_id: int | None
484
+ Filter transactions to those that have a tag with the specified Tag ID.
485
+ is_group_parent: bool | None
486
+ Filter by group (returns only transaction groups if `true`).
487
+ status: str | None
488
+ Filter transactions to those with the specified status:
489
+ - `reviewed`: Only user reviewed transactions or those that were
490
+ automatically marked as reviewed due to reviewed recurring_item logic
491
+ - `unreviewed`: Only transactions that need to be reviewed
492
+ - `delete_pending`: Only transactions that require manual intervention
493
+ because the plaid account deleted this transaction after it was
494
+ updated by the user.
495
+ is_pending: bool | None
496
+ Filter transactions by pending status. Set to `true` to return only
497
+ pending transactions, or `false` to return only non-pending
498
+ transactions. When this parameter is set, it takes precedence over
499
+ `include_pending`. Note: Pending transactions always have a status of
500
+ `unreviewed`, so when setting this parameter to `true`, either omit the
501
+ `status` parameter or set it to `unreviewed`.
502
+ include_pending: bool | None
503
+ By default, pending transactions are excluded from results. Set to
504
+ `true` to include imported transactions with a pending status in the
505
+ results. This query param is ignored if the `is_pending` query param is
506
+ also set.
507
+ include_metadata: bool | None
508
+ By default, custom and plaid metadata are not included in the response.
509
+ Set to true if you'd like the returned transactions objects to include
510
+ any metadata associated with the transactions.
511
+ include_split_parents: bool | None
512
+ By default, transactions that were split into multiple transactions are
513
+ not included in the response. Set to true if you'd like the returned
514
+ transactions objects to include any transactions that were split into
515
+ multiple transactions. Use with caution as this data is normally not
516
+ exposed after the split transactions are created.
517
+ include_group_children: bool | None
518
+ By default, individual transactions that joined into a transaction group
519
+ are not included in the response. Set to true if you'd like the returned
520
+ transactions objects to include any transactions that joined into a
521
+ transaction group.
522
+ include_files: bool | None
523
+ By default, the `files` property is not included in the response. Set to
524
+ true if you'd like the responses to include a list of objects that
525
+ describe any files attached to the transactions.
526
+
527
+ Returns
528
+ -------
529
+ dict[int, TransactionObject]
530
+ Dictionary of Transactions keyed by Transaction ID
531
+ """
532
+ kwargs: dict[str, Any] = {
533
+ "start_date": start_date,
534
+ "end_date": end_date,
535
+ "created_since": created_since,
536
+ "updated_since": updated_since,
537
+ "manual_account_id": manual_account_id,
538
+ "plaid_account_id": plaid_account_id,
539
+ "recurring_id": recurring_id,
540
+ "category_id": category_id,
541
+ "tag_id": tag_id,
542
+ "is_group_parent": is_group_parent,
543
+ "status": status,
544
+ "is_pending": is_pending,
545
+ "include_pending": include_pending,
546
+ "include_metadata": include_metadata,
547
+ "include_split_parents": include_split_parents,
548
+ "include_group_children": include_group_children,
549
+ "include_files": include_files,
550
+ }
551
+ filtered_kwargs: dict[str, Any] = {
552
+ k: v for k, v in kwargs.items() if v is not None
553
+ }
554
+ transaction_map: dict[int, TransactionObject] = {
555
+ obj.id: obj async for obj in self._paginate_transactions(**filtered_kwargs)
556
+ }
557
+ logger.info("Refreshed LunchMoney Transactions (%s)", len(transaction_map))
558
+ self.data.transactions.update(transaction_map)
559
+ return transaction_map
560
+
561
+ async def _paginate_transactions(
562
+ self, **kwargs: Any
563
+ ) -> AsyncIterable[TransactionObject]:
564
+ """
565
+ Paginate Transactions from the App
566
+ """
567
+ offset = 0
568
+ while True:
569
+ paginated_kwargs = {
570
+ **kwargs,
571
+ "offset": offset,
572
+ "limit": self._transaction_pagination,
573
+ }
574
+ response: GetAllTransactions200Response = (
575
+ await self.api.transactions_bulk.get_all_transactions(
576
+ **paginated_kwargs
577
+ )
578
+ )
579
+ for transaction in response.transactions:
580
+ yield transaction
581
+ if not response.has_more:
582
+ break
583
+ offset += self._transaction_pagination
584
+
585
+ def clear_transactions(self) -> None:
586
+ """
587
+ Clear Transactions from the App
588
+ """
589
+ self.data.transactions.clear()
@@ -541,7 +541,7 @@ conf = lunchmoney.Configuration(
541
541
  "OS: {env}\n"\
542
542
  "Python Version: {pyversion}\n"\
543
543
  "Version of the API: 2.8.4\n"\
544
- "SDK Package Version: 2.15.0".\
544
+ "SDK Package Version: 2.18.2".\
545
545
  format(env=sys.platform, pyversion=sys.version)
546
546
 
547
547
  def get_host_settings(self) -> List[HostSetting]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lunchmoney-python-async
3
- Version: 2.15.0
3
+ Version: 2.18.2
4
4
  Summary: Lunch Money API - v2
5
5
  Home-page:
6
6
  Author: OpenAPI Generator community
@@ -57,7 +57,7 @@ If you have been providing feedback on the API during our iterative design proce
57
57
  This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
58
58
 
59
59
  - API version: 2.8.4
60
- - Package version: 2.15.0
60
+ - Package version: 2.18.2
61
61
  - Generator version: 7.17.0
62
62
  - Build package: org.openapitools.codegen.languages.PythonClientCodegen
63
63
 
@@ -1,7 +1,8 @@
1
- lunchmoney/__init__.py,sha256=EsrIBHb1TT-bpquxpkKrJ7Afl3ZybzVhHkfjh66ain4,15137
2
- lunchmoney/api_client.py,sha256=A-sEEqwFKi80N0NCb8i77oIhVkklGRsFHp3YG_Sxdm8,30027
1
+ lunchmoney/__init__.py,sha256=ph9DotwKYRxIcqYRzStAY_Cj48_fTk09gLBU-xEhOUE,15137
2
+ lunchmoney/api_client.py,sha256=ayN8SwQViode6dySfjlMbdrtTze12Ot8_d6Q65pO2xU,30027
3
3
  lunchmoney/api_response.py,sha256=eMxw1mpmJcoGZ3gs9z6jM4oYoZ10Gjk333s9sKxGv7s,652
4
- lunchmoney/configuration.py,sha256=scA8X4GBzwzjdj6GPRCITdSqoW3MN_rTx97AEgfyiXI,21495
4
+ lunchmoney/app.py,sha256=NSmXjsRvgoWE49OEKwbJ6AfP88v9VjF29JwXUkyLzII,22516
5
+ lunchmoney/configuration.py,sha256=PFHs2iGGHifUcTaBPIzWvTkeqove1-LXTJ0HLXhHwNg,21495
5
6
  lunchmoney/exceptions.py,sha256=wwqToE7BTr_gLnBIhciaFC3gcLWTgecvw_n-LczGluc,8624
6
7
  lunchmoney/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
8
  lunchmoney/rest.py,sha256=srXSZvn9tu3_g7brC3IewCwaGDj1LOlz4nJ1-mDTtyA,8448
@@ -86,7 +87,7 @@ lunchmoney/models/update_transactions200_response.py,sha256=M2EGiFnVSgVTZxxwpfSE
86
87
  lunchmoney/models/update_transactions_request.py,sha256=QFe3PXgGMyuD0fj7s5ZBKj_fwa9SmTig1EjC9bc-0mg,5570
87
88
  lunchmoney/models/update_transactions_request_transactions_inner.py,sha256=l99tTbS64eraCuzpZWG0jRf069xIn08oha6PKezEysI,16674
88
89
  lunchmoney/models/user_object.py,sha256=8Wz8vkuygfmkqJTu8hA-_l0usvkwvJMEyp7Wd7NYrzY,5899
89
- lunchmoney_python_async-2.15.0.dist-info/METADATA,sha256=zkT6q_CyPS4wrp7VI_Qe54UZkqYAVAvry0p074nKe8U,16481
90
- lunchmoney_python_async-2.15.0.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
91
- lunchmoney_python_async-2.15.0.dist-info/top_level.txt,sha256=zZag3NCnXp76Ay6xplmjroAfUH_hWWJzZNxTjxk3CdM,11
92
- lunchmoney_python_async-2.15.0.dist-info/RECORD,,
90
+ lunchmoney_python_async-2.18.2.dist-info/METADATA,sha256=hpySPw51zFd0cDPVEABpDekkrs9DZZt-yNX89dZ7KWA,16481
91
+ lunchmoney_python_async-2.18.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
92
+ lunchmoney_python_async-2.18.2.dist-info/top_level.txt,sha256=zZag3NCnXp76Ay6xplmjroAfUH_hWWJzZNxTjxk3CdM,11
93
+ lunchmoney_python_async-2.18.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.10.1)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5