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.
- ynab_cli-0.3.0/.env-sample +7 -0
- ynab_cli-0.3.0/.github/FUNDING.yml +1 -0
- ynab_cli-0.3.0/.github/workflows/pr.yml +22 -0
- ynab_cli-0.3.0/.github/workflows/publish-to-pypi.yml +43 -0
- ynab_cli-0.3.0/.gitignore +10 -0
- ynab_cli-0.3.0/.python-version +1 -0
- ynab_cli-0.3.0/CHANGELOG.md +35 -0
- ynab_cli-0.3.0/LICENSE.md +21 -0
- ynab_cli-0.3.0/Makefile +30 -0
- ynab_cli-0.3.0/PKG-INFO +102 -0
- ynab_cli-0.3.0/README.md +82 -0
- ynab_cli-0.3.0/docs/index.md +40 -0
- ynab_cli-0.3.0/docs/transaction_rules.md +42 -0
- ynab_cli-0.3.0/mkdocs.yml +28 -0
- ynab_cli-0.3.0/pyproject.toml +117 -0
- ynab_cli-0.3.0/src/ynab_cli/__init__.py +0 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/__init__.py +0 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/rich/__init__.py +0 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/rich/io.py +38 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/textual/__init__.py +0 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/textual/io.py +62 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/__init__.py +8 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/__init__.py +1 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/accounts/__init__.py +1 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/accounts/create_account.py +186 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/accounts/get_account_by_id.py +177 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/accounts/get_accounts.py +184 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/budgets/__init__.py +1 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/budgets/get_budget_by_id.py +188 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/budgets/get_budget_settings_by_id.py +163 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/budgets/get_budgets.py +171 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/categories/__init__.py +1 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/categories/get_categories.py +188 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/categories/get_category_by_id.py +180 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/categories/get_month_category_by_id.py +194 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/categories/update_category.py +199 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/categories/update_month_category.py +213 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/months/__init__.py +1 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/months/get_budget_month.py +177 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/months/get_budget_months.py +184 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payee_locations/__init__.py +1 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payee_locations/get_payee_location_by_id.py +176 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payee_locations/get_payee_locations.py +163 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payee_locations/get_payee_locations_by_payee.py +176 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payees/__init__.py +1 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payees/get_payee_by_id.py +176 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payees/get_payees.py +184 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/payees/update_payee.py +199 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/scheduled_transactions/__init__.py +1 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/scheduled_transactions/create_scheduled_transaction.py +186 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/scheduled_transactions/delete_scheduled_transaction.py +176 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/scheduled_transactions/get_scheduled_transaction_by_id.py +176 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/scheduled_transactions/get_scheduled_transactions.py +184 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/scheduled_transactions/update_scheduled_transaction.py +199 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/__init__.py +1 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/create_transaction.py +202 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/delete_transaction.py +176 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/get_transaction_by_id.py +176 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/get_transactions.py +227 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_account.py +236 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_category.py +236 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_month.py +236 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_payee.py +236 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/import_transactions.py +183 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/update_transaction.py +199 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/transactions/update_transactions.py +177 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/user/__init__.py +1 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/api/user/get_user.py +130 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/client.py +268 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/errors.py +16 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/__init__.py +229 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/account.py +345 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/account_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/account_response_data.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/account_type.py +23 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/accounts_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/accounts_response_data.py +81 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_detail.py +405 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_detail_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_detail_response_data.py +73 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_settings.py +115 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_settings_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_settings_response_data.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_summary.py +216 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_summary_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/budget_summary_response_data.py +91 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/bulk_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/bulk_response_data.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/bulk_response_data_bulk.py +68 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/bulk_transactions.py +75 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/categories_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/categories_response_data.py +81 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category.py +519 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category_goal_type_type_1.py +15 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category_goal_type_type_2_type_1.py +15 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category_goal_type_type_3_type_1.py +15 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category_group.py +85 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category_group_with_categories.py +108 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/category_response_data.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/currency_format_type_0.py +117 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/date_format_type_0.py +61 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/error_detail.py +75 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/error_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/existing_transaction.py +322 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/get_transactions_by_account_type.py +12 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/get_transactions_by_category_type.py +12 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/get_transactions_by_month_type.py +12 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/get_transactions_by_payee_type.py +12 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/get_transactions_type.py +12 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/hybrid_transaction.py +567 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/hybrid_transaction_type.py +12 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/hybrid_transactions_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/hybrid_transactions_response_data.py +84 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/loan_account_periodic_value_type_0.py +44 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/month_detail.py +168 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/month_detail_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/month_detail_response_data.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/month_summaries_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/month_summaries_response_data.py +81 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/month_summary.py +145 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/new_transaction.py +352 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/patch_category_wrapper.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/patch_month_category_wrapper.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/patch_payee_wrapper.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/patch_transactions_wrapper.py +73 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee.py +100 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee_location.py +93 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee_location_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee_location_response_data.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee_locations_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee_locations_response_data.py +73 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payee_response_data.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payees_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/payees_response_data.py +81 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/post_account_wrapper.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/post_scheduled_transaction_wrapper.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/post_transactions_wrapper.py +91 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/put_scheduled_transaction_wrapper.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/put_transaction_wrapper.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_account.py +77 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_category.py +129 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_category_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_category_response_data.py +73 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_month_category.py +59 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_payee.py +59 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_payee_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_payee_response_data.py +73 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_scheduled_transaction.py +269 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_sub_transaction.py +166 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_transaction_with_id_or_import_id.py +366 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_transaction_with_optional_fields.py +322 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_transactions_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/save_transactions_response_data.py +123 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_sub_transaction.py +238 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transaction_detail.py +381 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transaction_frequency.py +23 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transaction_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transaction_response_data.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transaction_summary.py +310 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transaction_summary_frequency.py +23 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transactions_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/scheduled_transactions_response_data.py +81 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/sub_transaction.py +259 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_cleared_status.py +13 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_detail.py +570 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_flag_color_type_1.py +16 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_flag_color_type_2_type_1.py +16 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_flag_color_type_3_type_1.py +16 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_response_data.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_summary.py +499 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_summary_debt_transaction_type_type_1.py +18 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_summary_debt_transaction_type_type_2_type_1.py +18 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transaction_summary_debt_transaction_type_type_3_type_1.py +18 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transactions_import_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transactions_import_response_data.py +59 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transactions_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/transactions_response_data.py +81 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/user.py +60 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/user_response.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/models/user_response_data.py +65 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/types.py +46 -0
- ynab_cli-0.3.0/src/ynab_cli/adapters/ynab/util.py +78 -0
- ynab_cli-0.3.0/src/ynab_cli/domain/__init__.py +0 -0
- ynab_cli-0.3.0/src/ynab_cli/domain/constants.py +3 -0
- ynab_cli-0.3.0/src/ynab_cli/domain/models/__init__.py +0 -0
- ynab_cli-0.3.0/src/ynab_cli/domain/models/rules.py +37 -0
- ynab_cli-0.3.0/src/ynab_cli/domain/ports/__init__.py +5 -0
- ynab_cli-0.3.0/src/ynab_cli/domain/ports/io.py +63 -0
- ynab_cli-0.3.0/src/ynab_cli/domain/settings.py +16 -0
- ynab_cli-0.3.0/src/ynab_cli/domain/use_cases/__init__.py +0 -0
- ynab_cli-0.3.0/src/ynab_cli/domain/use_cases/categories.py +105 -0
- ynab_cli-0.3.0/src/ynab_cli/domain/use_cases/payees.py +232 -0
- ynab_cli-0.3.0/src/ynab_cli/domain/use_cases/transactions.py +93 -0
- ynab_cli-0.3.0/src/ynab_cli/host/__init__.py +14 -0
- ynab_cli-0.3.0/src/ynab_cli/host/cli.py +37 -0
- ynab_cli-0.3.0/src/ynab_cli/host/click/__init__.py +0 -0
- ynab_cli-0.3.0/src/ynab_cli/host/click/cli.py +44 -0
- ynab_cli-0.3.0/src/ynab_cli/host/click/commands/__init__.py +0 -0
- ynab_cli-0.3.0/src/ynab_cli/host/click/commands/categories.py +92 -0
- ynab_cli-0.3.0/src/ynab_cli/host/click/commands/payees.py +157 -0
- ynab_cli-0.3.0/src/ynab_cli/host/click/commands/rich/__init__.py +0 -0
- ynab_cli-0.3.0/src/ynab_cli/host/click/commands/rich/progress_table.py +37 -0
- ynab_cli-0.3.0/src/ynab_cli/host/click/commands/transactions.py +76 -0
- ynab_cli-0.3.0/src/ynab_cli/host/constants.py +3 -0
- ynab_cli-0.3.0/src/ynab_cli/host/textual/__init__.py +0 -0
- ynab_cli-0.3.0/src/ynab_cli/host/textual/app.py +98 -0
- ynab_cli-0.3.0/src/ynab_cli/host/textual/app.tcss +47 -0
- ynab_cli-0.3.0/src/ynab_cli/host/textual/cli.py +42 -0
- ynab_cli-0.3.0/src/ynab_cli/host/textual/widgets/__init__.py +58 -0
- ynab_cli-0.3.0/src/ynab_cli/host/textual/widgets/categories.py +90 -0
- ynab_cli-0.3.0/src/ynab_cli/host/textual/widgets/payees.py +154 -0
- ynab_cli-0.3.0/src/ynab_cli/host/textual/widgets/transactions.py +89 -0
- ynab_cli-0.3.0/src/ynab_cli/py.typed +0 -0
- ynab_cli-0.3.0/tests/__init__.py +0 -0
- ynab_cli-0.3.0/tests/factories/__init__.py +0 -0
- ynab_cli-0.3.0/tests/factories/ynab.py +18 -0
- ynab_cli-0.3.0/tests/unit/__init__.py +0 -0
- ynab_cli-0.3.0/tests/unit/conftest.py +17 -0
- ynab_cli-0.3.0/tests/unit/domain/__init__.py +0 -0
- ynab_cli-0.3.0/tests/unit/domain/use_cases/__init__.py +0 -0
- ynab_cli-0.3.0/tests/unit/domain/use_cases/test_categories.py +68 -0
- ynab_cli-0.3.0/tests/unit/domain/use_cases/test_payees.py +72 -0
- ynab_cli-0.3.0/tests/unit/domain/use_cases/test_transactions.py +106 -0
- 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 @@
|
|
|
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.
|
ynab_cli-0.3.0/Makefile
ADDED
|
@@ -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
|
ynab_cli-0.3.0/PKG-INFO
ADDED
|
@@ -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)
|
ynab_cli-0.3.0/README.md
ADDED
|
@@ -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)
|
|
File without changes
|