Plugins#
lunchable
plugins are Python packages outside of the lunchable
package that
can be installed into the same environment as lunchable
to add additional
functionality to the CLI. To install all the known plugins, and their dependencies, install
lunchable with the plugins
extra:
lunchable supports CLI plugins with other external packages. See below for what's been built already. If you can't find what you're looking for, consider building it yourself and opening a pull-request to add it to the list:
- PushLunch: Push Notifications via Pushover
- SplitLunch: Splitwise Integration
- PrimeLunch: Amazon Transaction Updater
LunchableApp#
Lunchable provides a LunchableApp
class that can be used to easily build plugins, apps,
and more. Notice a few of the main attributes / methods of the LunchableApp
class:
attribute / method | description | type |
---|---|---|
lunch |
The LunchMoney client |
LunchMoney |
data ¹ |
The LunchableData object |
LunchableData |
refresh_data | Refresh all data (besides Transactions) | method |
refresh_transactions | Refresh transactions, takes same parameters as LunchMoney.get_transactions() |
method |
refresh ² | Refresh the data for one particular model, takes **kwargs | method |
clear_transactions ³ | Clear all transactions from the internal data | method |
¹ This attribute contains all of the data that is loaded from LunchMoney. It has attributes for
assets
,categories
,plaid_accounts
,tags
,transactions
,crypto
anduser
. These attributes (except foruser
) aredict[int, LunchableModel]
objects, where the key is the ID of the object and the value is the object itself.² This method refreshes all of the data for one particular model. For example,
refresh(AssetsObject)
will refresh the assets on the underlingdata.assets
attribute and return adict[int, AssetsObject]
object.³ This the same as running
app.data.transactions.clear()
An Example App#
from __future__ import annotations
from typing import Any
from lunchable.models import AssetsObject, TransactionUpdateObject
from lunchable.plugins import LunchableApp
class MyCustomApp(LunchableApp):
"""
My Custom App
"""
def do_something_with_assets(self) -> None:
"""
Do something with the assets
"""
if not self.data.assets:
# If the data hasn't been loaded yet, load it
# The following method loads all of the data besides Transactions
# (Assets, Categories, Plaid Accounts, Tags, Crypto, User)
self.refresh_data()
for asset_id, asset in self.data.assets.items():
# Do something with the asset
print(asset_id, asset)
def do_something_with_transactions(self) -> None:
"""
Do something with the transactions
"""
if not self.data.transactions:
# If the transactions haven't been loaded yet, load them
self.refresh_transactions(start_date="2021-01-01", end_date="2021-01-31")
# Refresh the latest assets
latest_assets: dict[int, AssetsObject] = self.refresh(model=AssetsObject)
for transaction_id, transaction in self.data.transactions.items():
if transaction.asset_id:
asset = latest_assets[transaction.asset_id]
print(transaction_id, transaction, asset)
def update_transaction(self, transaction_id: int, payee: str) -> dict[str, Any]:
"""
You can do anything you want with the `self
"""
update_transaction = TransactionUpdateObject(payee=payee)
response = self.lunch.update_transaction(transaction_id=transaction_id,
transaction=update_transaction)
return response
if __name__ == "__main__":
app = MyCustomApp(access_token="xxxxxxxx")
app.do_something_with_assets()
app.do_something_with_transactions()
app.update_transaction(transaction_id=12345, payee="New Payee")
Choose a subset of data to load#
If you don't want to load all of the data, you can specify which data you want to load by
specifying the lunchable_models
attribute of the LunchableApp
class. The following example
will only sync the assets
and plaid_accounts
data when the refresh_data()
method is called:
from __future__ import annotations
from typing import ClassVar
from lunchable.models import AssetsObject, PlaidAccountObject, LunchableModel
from lunchable.plugins import LunchableApp
class CustomApp(LunchableApp):
"""
Custom Lunchable App
This app syncs Plaid Accounts and Assets when its `refresh_data` method
is called.
"""
lunchable_models: ClassVar[list[type[LunchableModel]]] = [
PlaidAccountObject,
AssetsObject,
]
def do_something_with_assets(self) -> None:
"""
Do something with the assets
"""
if not self.data.plaid_accounts:
self.refresh_data()
for plaid_account_id, plaid_account in self.data.plaid_accounts.items():
print(plaid_account_id, plaid_account)
Building a Plugin#
Plugins are built separate Python packages and are detected by lunchable via
the lunchable.cli
entrypoint, these are
click command line applications.
To add your own plugin to lunchable you'll need to add a new entrypoint to
your package. The below example shows how to do this with hatch, a modern,
standards-based Python package manager:
import click
@click.group
def plugin_name():
"""
Plugin description
"""
pass
@plugin_name.command
def command():
"""
Plugin description
"""
pass
The above example will add a new command
/ group
to the lunchable plugins
CLI. When
your package is installed into the same environment as lunchable, your plugin will be
accessible via the lunchable plugins
command:
API Documentation#
Pre-Built Lunchable App
This app comes with a data
property which represents all the base data
the app should need.
This app comes with a refresh_data
method which will refresh all of the
data in the app, except for transactions. To refresh transactions, use the
refresh_transactions
method.
__init__(access_token=None)
#
Lunchable App Initialization
Parameters:
Name | Type | Description | Default |
---|---|---|---|
access_token |
str | None
|
Lunchmoney Developer API Access Token. Inherited from
|
None
|
clear_transactions()
#
Clear Transactions from the App
refresh(model, **kwargs)
#
Refresh a Lunchable Model
Parameters:
Name | Type | Description | Default |
---|---|---|---|
model |
Type[LunchableModel]
|
Type of Lunchable Model to refresh |
required |
kwargs |
Any
|
Additional keyword arguments to pass to the function that fetches the data. |
{}
|
Returns:
Type | Description |
---|---|
LunchableModel | Dict[int, LunchableModel]
|
Unless you're requesting the |
Examples:
refresh_data(models=None)
#
Refresh the data in the Lunchable App
Parameters:
Name | Type | Description | Default |
---|---|---|---|
models |
List[Type[LunchableModel]] | None
|
Explicit list of Lunchable Models to refresh. If not provided, all models defined in will be refreshed (which by default is all of them except for transactions) |
None
|
Examples:
refresh_transactions(start_date=None, end_date=None, tag_id=None, recurring_id=None, plaid_account_id=None, category_id=None, asset_id=None, group_id=None, is_group=None, status=None, debit_as_negative=None, pending=None, params=None)
#
Refresh App data with the latest transactions
Parameters:
Name | Type | Description | Default |
---|---|---|---|
start_date |
date | datetime | str | None
|
Denotes the beginning of the time period to fetch transactions for. Defaults to beginning of current month. Required if end_date exists. Format: YYYY-MM-DD. |
None
|
end_date |
date | datetime | str | None
|
Denotes the end of the time period you'd like to get transactions for. Defaults to end of current month. Required if start_date exists. |
None
|
tag_id |
int | None
|
Filter by tag. Only accepts IDs, not names. |
None
|
recurring_id |
int | None
|
Filter by recurring expense |
None
|
plaid_account_id |
int | None
|
Filter by Plaid account |
None
|
category_id |
int | None
|
Filter by category. Will also match category groups. |
None
|
asset_id |
int | None
|
Filter by asset |
None
|
group_id |
int | None
|
Filter by group_id (if the transaction is part of a specific group) |
None
|
is_group |
bool | None
|
Filter by group (returns transaction groups) |
None
|
status |
str | None
|
Filter by status (Can be cleared or uncleared. For recurring transactions, use recurring) |
None
|
debit_as_negative |
bool | None
|
Pass in true if you'd like expenses to be returned as negative amounts and credits as positive amounts. Defaults to false. |
None
|
pending |
bool | None
|
Pass in true if you'd like to include imported transactions with a pending status. |
None
|
params |
Dict[str, Any] | None
|
Additional Query String Params |
None
|
Returns:
Type | Description |
---|---|
Dict[int, TransactionObject]
|
|
Examples:
Data Container for Lunchable App Data
Parameters:
Name | Type | Description | Default |
---|---|---|---|
plaid_accounts |
Dict[int, PlaidAccountObject]
|
Plaid Accounts |
{}
|
transactions |
Dict[int, TransactionObject]
|
Transactions |
{}
|
categories |
Dict[int, CategoriesObject]
|
Categories |
{}
|
assets |
Dict[int, AssetsObject]
|
Assets |
{}
|
tags |
Dict[int, TagsObject]
|
Tags |
{}
|
crypto |
Dict[int, CryptoObject]
|
Crypto |
{}
|
user |
UserObject
|
User |
UserObject(user_id=0, user_name='', user_email='', account_id=0, budget_name='', api_key_label=None)
|
asset_map: Dict[int, PlaidAccountObject | AssetsObject]
property
#
Asset Mapping Across Plaid Accounts and Assets
Returns:
Type | Description |
---|---|
Dict[int, Union[PlaidAccountObject, AssetsObject]]
|
|