ynab-cli 0.6.2__tar.gz → 0.6.3__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.6.2 → ynab_cli-0.6.3}/CHANGELOG.md +7 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/PKG-INFO +1 -1
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/pyproject.toml +1 -1
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/domain/settings.py +0 -3
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/domain/use_cases/payees.py +8 -5
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/domain/use_cases/transactions.py +2 -1
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/cli.py +3 -4
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/click/cli.py +3 -2
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/click/commands/payees.py +16 -9
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/click/commands/transactions.py +7 -4
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/constants.py +1 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/app.py +2 -9
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/cli.py +3 -2
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/payees/list_unused.py +5 -2
- ynab_cli-0.6.3/src/ynab_cli/host/textual/widgets/payees/normalize_names.py +74 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/transactions/apply_rules.py +4 -1
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/transactions/tabs.py +2 -2
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/domain/use_cases/test_payees.py +9 -3
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/host/click/commands/test_payees.py +3 -2
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/host/click/commands/test_transactions.py +1 -1
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/host/test_cli.py +0 -1
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/host/textual/test_app.py +0 -3
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/uv.lock +1 -1
- ynab_cli-0.6.2/src/ynab_cli/host/textual/widgets/payees/normalize_names.py +0 -38
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/.env-sample +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/.github/.copilot-instructions.md +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/.github/FUNDING.yml +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/.github/dependabot.yml +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/.github/workflows/pr.yml +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/.github/workflows/publish-to-pypi.yml +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/.gitignore +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/.python-version +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/LICENSE.md +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/Makefile +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/README.md +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/docs/index.md +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/docs/transaction_rules.md +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/mkdocs.yml +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/rich/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/rich/io.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/textual/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/textual/io.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/accounts/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/accounts/create_account.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/accounts/get_account_by_id.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/accounts/get_accounts.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/budgets/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/budgets/get_budget_by_id.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/budgets/get_budget_settings_by_id.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/budgets/get_budgets.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/categories/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/categories/get_categories.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/categories/get_category_by_id.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/categories/get_month_category_by_id.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/categories/update_category.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/categories/update_month_category.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/months/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/months/get_budget_month.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/months/get_budget_months.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/payee_locations/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/payee_locations/get_payee_location_by_id.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/payee_locations/get_payee_locations.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/payee_locations/get_payee_locations_by_payee.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/payees/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/payees/get_payee_by_id.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/payees/get_payees.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/payees/update_payee.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/scheduled_transactions/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/scheduled_transactions/create_scheduled_transaction.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/scheduled_transactions/delete_scheduled_transaction.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/scheduled_transactions/get_scheduled_transaction_by_id.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/scheduled_transactions/get_scheduled_transactions.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/scheduled_transactions/update_scheduled_transaction.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/transactions/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/transactions/create_transaction.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/transactions/delete_transaction.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/transactions/get_transaction_by_id.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/transactions/get_transactions.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_account.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_category.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_month.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_payee.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/transactions/import_transactions.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/transactions/update_transaction.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/transactions/update_transactions.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/user/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/api/user/get_user.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/client.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/errors.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/account.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/account_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/account_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/account_type.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/accounts_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/accounts_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/budget_detail.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/budget_detail_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/budget_detail_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/budget_settings.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/budget_settings_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/budget_settings_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/budget_summary.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/budget_summary_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/budget_summary_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/bulk_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/bulk_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/bulk_response_data_bulk.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/bulk_transactions.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/categories_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/categories_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/category.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/category_goal_type_type_1.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/category_goal_type_type_2_type_1.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/category_goal_type_type_3_type_1.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/category_group.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/category_group_with_categories.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/category_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/category_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/currency_format_type_0.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/date_format_type_0.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/error_detail.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/error_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/existing_transaction.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/get_transactions_by_account_type.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/get_transactions_by_category_type.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/get_transactions_by_month_type.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/get_transactions_by_payee_type.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/get_transactions_type.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/hybrid_transaction.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/hybrid_transaction_type.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/hybrid_transactions_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/hybrid_transactions_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/loan_account_periodic_value_type_0.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/month_detail.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/month_detail_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/month_detail_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/month_summaries_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/month_summaries_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/month_summary.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/new_transaction.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/patch_category_wrapper.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/patch_month_category_wrapper.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/patch_payee_wrapper.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/patch_transactions_wrapper.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/payee.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/payee_location.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/payee_location_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/payee_location_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/payee_locations_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/payee_locations_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/payee_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/payee_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/payees_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/payees_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/post_account_wrapper.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/post_scheduled_transaction_wrapper.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/post_transactions_wrapper.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/put_scheduled_transaction_wrapper.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/put_transaction_wrapper.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/save_account.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/save_category.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/save_category_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/save_category_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/save_month_category.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/save_payee.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/save_payee_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/save_payee_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/save_scheduled_transaction.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/save_sub_transaction.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/save_transaction_with_id_or_import_id.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/save_transaction_with_optional_fields.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/save_transactions_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/save_transactions_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/scheduled_sub_transaction.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/scheduled_transaction_detail.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/scheduled_transaction_frequency.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/scheduled_transaction_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/scheduled_transaction_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/scheduled_transaction_summary.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/scheduled_transaction_summary_frequency.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/scheduled_transactions_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/scheduled_transactions_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/sub_transaction.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/transaction_cleared_status.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/transaction_detail.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/transaction_flag_color_type_1.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/transaction_flag_color_type_2_type_1.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/transaction_flag_color_type_3_type_1.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/transaction_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/transaction_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/transaction_summary.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/transaction_summary_debt_transaction_type_type_1.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/transaction_summary_debt_transaction_type_type_2_type_1.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/transaction_summary_debt_transaction_type_type_3_type_1.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/transactions_import_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/transactions_import_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/transactions_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/transactions_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/user.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/user_response.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/models/user_response_data.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/types.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/adapters/ynab/util.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/domain/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/domain/constants.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/domain/models/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/domain/models/rules.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/domain/ports/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/domain/ports/io.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/domain/use_cases/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/domain/use_cases/budgets.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/domain/use_cases/categories.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/click/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/click/commands/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/click/commands/budgets.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/click/commands/categories.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/click/commands/rich/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/click/commands/rich/progress_table.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/click/container.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/container.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/app.tcss +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/container.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/categories/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/categories/list_all.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/categories/list_unused.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/categories/tabs.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/common/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/common/command_widget.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/common/dialogs/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/common/dialogs/dialog.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/common/dialogs/form.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/common/dialogs/screen.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/payees/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/payees/list_all.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/payees/list_duplicates.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/payees/tabs.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/tabs.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/transactions/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/py.typed +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/conftest.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/factories/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/factories/ynab.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/adapters/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/adapters/rich/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/adapters/rich/test_io.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/adapters/textual/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/adapters/textual/test_io.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/conftest.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/domain/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/domain/models/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/domain/models/test_rules.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/domain/ports/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/domain/ports/test_io.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/domain/use_cases/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/domain/use_cases/test_budgets.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/domain/use_cases/test_categories.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/domain/use_cases/test_transactions.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/host/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/host/click/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/host/click/commands/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/host/click/commands/test_budgets.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/host/click/commands/test_categories.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/host/click/conftest.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/host/conftest.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/host/textual/__init__.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/host/textual/conftest.py +0 -0
- {ynab_cli-0.6.2 → ynab_cli-0.6.3}/tests/unit/host/textual/test_cli.py +0 -0
|
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## v0.6.3 (2025-07-11)
|
|
9
|
+
|
|
10
|
+
### Refactor
|
|
11
|
+
|
|
12
|
+
- clean up the dry_run parameters
|
|
13
|
+
- clean up debug option
|
|
14
|
+
|
|
8
15
|
## v0.6.2 (2025-07-09)
|
|
9
16
|
|
|
10
17
|
### Fix
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ynab-cli
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.3
|
|
4
4
|
Summary: YNAB Command Line Interface
|
|
5
5
|
Project-URL: Changelog, https://github.com/jeffsawatzky/ynab-cli/blob/main/CHANGELOG.md
|
|
6
6
|
Project-URL: Documentation, https://jeffsawatzky.github.io/ynab-cli/
|
|
@@ -41,7 +41,7 @@ def _normalize_name(name: str) -> str:
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
class NormalizeNamesParams(TypedDict):
|
|
44
|
-
|
|
44
|
+
dry_run: bool
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
class NormalizeNames:
|
|
@@ -76,7 +76,7 @@ class NormalizeNames:
|
|
|
76
76
|
if normalized_name != payee.name:
|
|
77
77
|
yield (payee, normalized_name)
|
|
78
78
|
|
|
79
|
-
if not
|
|
79
|
+
if not params["dry_run"]:
|
|
80
80
|
await util.run_asyncio_detailed(
|
|
81
81
|
self._io,
|
|
82
82
|
update_payee.asyncio_detailed,
|
|
@@ -166,6 +166,7 @@ class ListDuplicates:
|
|
|
166
166
|
|
|
167
167
|
|
|
168
168
|
class ListUnusedParams(TypedDict):
|
|
169
|
+
dry_run: bool
|
|
169
170
|
prefix_unused: bool
|
|
170
171
|
|
|
171
172
|
|
|
@@ -208,18 +209,20 @@ class ListUnused:
|
|
|
208
209
|
|
|
209
210
|
# List unused payee if no transactions
|
|
210
211
|
if not num_transactions:
|
|
212
|
+
if params["prefix_unused"]:
|
|
213
|
+
payee.name = f"{UNUSED_PREFIX} {payee.name}"
|
|
214
|
+
|
|
211
215
|
yield payee
|
|
212
216
|
|
|
213
217
|
# If prefix_unused is True, rename the payee
|
|
214
|
-
if not
|
|
215
|
-
new_name = f"{UNUSED_PREFIX} {payee.name}"
|
|
218
|
+
if not params["dry_run"] and params["prefix_unused"]:
|
|
216
219
|
await util.run_asyncio_detailed(
|
|
217
220
|
self._io,
|
|
218
221
|
update_payee.asyncio_detailed,
|
|
219
222
|
settings.ynab.budget_id,
|
|
220
223
|
str(payee.id),
|
|
221
224
|
client=self._client,
|
|
222
|
-
body=models.PatchPayeeWrapper(payee=models.SavePayee(name=
|
|
225
|
+
body=models.PatchPayeeWrapper(payee=models.SavePayee(name=payee.name)),
|
|
223
226
|
)
|
|
224
227
|
|
|
225
228
|
except Exception as e:
|
|
@@ -39,6 +39,7 @@ def _get_save_transaction(
|
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
class ApplyRulesParams(TypedDict):
|
|
42
|
+
dry_run: bool
|
|
42
43
|
transaction_rules: rules.TransactionRules
|
|
43
44
|
|
|
44
45
|
|
|
@@ -82,7 +83,7 @@ class ApplyRules:
|
|
|
82
83
|
if save_transaction:
|
|
83
84
|
yield (transaction, save_transaction)
|
|
84
85
|
|
|
85
|
-
if not
|
|
86
|
+
if not params["dry_run"]:
|
|
86
87
|
save_transactions.append(save_transaction)
|
|
87
88
|
|
|
88
89
|
if save_transactions:
|
|
@@ -3,24 +3,23 @@ from click_default_group import DefaultGroup
|
|
|
3
3
|
|
|
4
4
|
from ynab_cli.domain.settings import Settings
|
|
5
5
|
from ynab_cli.host.click.cli import run
|
|
6
|
-
from ynab_cli.host.constants import CONTEXT_KEY_SETTINGS, ENV_PREFIX
|
|
6
|
+
from ynab_cli.host.constants import CONTEXT_KEY_DEBUG, CONTEXT_KEY_SETTINGS, ENV_PREFIX
|
|
7
7
|
from ynab_cli.host.textual.cli import tui
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
@click.group(cls=DefaultGroup, default="tui", default_if_no_args=True)
|
|
11
|
-
@click.option("--dry-run", is_flag=True, default=False, help="Run without making any changes.")
|
|
12
11
|
@click.option("--debug", is_flag=True, default=False, help="Enable debug mode for more verbose output.")
|
|
13
12
|
@click.version_option()
|
|
14
13
|
@click.pass_context
|
|
15
14
|
def cli(
|
|
16
15
|
ctx: click.Context,
|
|
17
|
-
dry_run: bool,
|
|
18
16
|
debug: bool,
|
|
19
17
|
) -> None:
|
|
20
18
|
"""Main entrypoint."""
|
|
21
19
|
|
|
22
20
|
ctx.ensure_object(dict)
|
|
23
|
-
ctx.obj[
|
|
21
|
+
ctx.obj[CONTEXT_KEY_DEBUG] = debug
|
|
22
|
+
ctx.obj[CONTEXT_KEY_SETTINGS] = Settings()
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
cli.add_command(run)
|
|
@@ -5,7 +5,7 @@ from rich.logging import RichHandler
|
|
|
5
5
|
|
|
6
6
|
from ynab_cli.domain.settings import Settings
|
|
7
7
|
from ynab_cli.host.click.commands import budgets, categories, payees, transactions
|
|
8
|
-
from ynab_cli.host.constants import CONTEXT_KEY_SETTINGS, ENV_PREFIX
|
|
8
|
+
from ynab_cli.host.constants import CONTEXT_KEY_DEBUG, CONTEXT_KEY_SETTINGS, ENV_PREFIX
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
@click.group()
|
|
@@ -25,12 +25,13 @@ def run(
|
|
|
25
25
|
"""Main entrypoint for YNAB CLI commands."""
|
|
26
26
|
|
|
27
27
|
ctx.ensure_object(dict)
|
|
28
|
+
debug: bool = ctx.obj.get(CONTEXT_KEY_DEBUG, False)
|
|
28
29
|
settings: Settings = ctx.obj.get(CONTEXT_KEY_SETTINGS, Settings())
|
|
29
30
|
settings.ynab.access_token = access_token
|
|
30
31
|
ctx.obj[CONTEXT_KEY_SETTINGS] = settings
|
|
31
32
|
|
|
32
33
|
logging.basicConfig(
|
|
33
|
-
level="DEBUG" if
|
|
34
|
+
level="DEBUG" if debug else "WARNING", # NOTSET, DEBUG, INFO, WARNING, ERROR, CRITICAL
|
|
34
35
|
format="%(message)s",
|
|
35
36
|
datefmt="[%X]",
|
|
36
37
|
handlers=[RichHandler()],
|
|
@@ -19,8 +19,10 @@ class NormalizeNamesCommand:
|
|
|
19
19
|
self._progress_table.table.add_column("Payee Name")
|
|
20
20
|
self._progress_table.table.add_column("Normalized Name")
|
|
21
21
|
|
|
22
|
-
async def __call__(self, settings: Settings) -> None:
|
|
23
|
-
params: use_cases.NormalizeNamesParams = {
|
|
22
|
+
async def __call__(self, settings: Settings, dry_run: bool) -> None:
|
|
23
|
+
params: use_cases.NormalizeNamesParams = {
|
|
24
|
+
"dry_run": dry_run,
|
|
25
|
+
}
|
|
24
26
|
|
|
25
27
|
console = None
|
|
26
28
|
with self._progress_table:
|
|
@@ -76,8 +78,9 @@ class ListUnusedCommand:
|
|
|
76
78
|
self._progress_table.table.add_column("Payee Id")
|
|
77
79
|
self._progress_table.table.add_column("Payee Name")
|
|
78
80
|
|
|
79
|
-
async def __call__(self, settings: Settings, prefix_unused: bool) -> None:
|
|
81
|
+
async def __call__(self, settings: Settings, dry_run: bool, prefix_unused: bool) -> None:
|
|
80
82
|
params: use_cases.ListUnusedParams = {
|
|
83
|
+
"dry_run": dry_run,
|
|
81
84
|
"prefix_unused": prefix_unused,
|
|
82
85
|
}
|
|
83
86
|
|
|
@@ -122,13 +125,14 @@ class ListAllCommand:
|
|
|
122
125
|
|
|
123
126
|
|
|
124
127
|
@containerize
|
|
125
|
-
async def _normalize_names(container: Container) -> None:
|
|
126
|
-
await container[NormalizeNamesCommand](container[Settings])
|
|
128
|
+
async def _normalize_names(container: Container, dry_run: bool) -> None:
|
|
129
|
+
await container[NormalizeNamesCommand](container[Settings], dry_run)
|
|
127
130
|
|
|
128
131
|
|
|
129
132
|
@click.command()
|
|
133
|
+
@click.option("--dry-run", is_flag=True, default=False, help="Run without making any changes.")
|
|
130
134
|
@click.pass_context
|
|
131
|
-
def normalize_names(ctx: click.Context) -> None:
|
|
135
|
+
def normalize_names(ctx: click.Context, dry_run: bool) -> None:
|
|
132
136
|
"""Normalize payee names in the YNAB budget."""
|
|
133
137
|
|
|
134
138
|
ctx.ensure_object(dict)
|
|
@@ -138,6 +142,7 @@ def normalize_names(ctx: click.Context) -> None:
|
|
|
138
142
|
anyio.run(
|
|
139
143
|
_normalize_names,
|
|
140
144
|
settings,
|
|
145
|
+
dry_run,
|
|
141
146
|
backend_options={"use_uvloop": True},
|
|
142
147
|
)
|
|
143
148
|
|
|
@@ -164,14 +169,15 @@ def list_duplicates(ctx: click.Context) -> None:
|
|
|
164
169
|
|
|
165
170
|
|
|
166
171
|
@containerize
|
|
167
|
-
async def _list_unused(container: Container, prefix_unused: bool) -> None:
|
|
168
|
-
await container[ListUnusedCommand](container[Settings], prefix_unused)
|
|
172
|
+
async def _list_unused(container: Container, dry_run: bool, prefix_unused: bool) -> None:
|
|
173
|
+
await container[ListUnusedCommand](container[Settings], dry_run, prefix_unused)
|
|
169
174
|
|
|
170
175
|
|
|
171
176
|
@click.command()
|
|
177
|
+
@click.option("--dry-run", is_flag=True, default=False, help="Run without making any changes.")
|
|
172
178
|
@click.option("--prefix-unused", is_flag=True, default=False, help="Add a prefix to the unused payee names.")
|
|
173
179
|
@click.pass_context
|
|
174
|
-
def list_unused(ctx: click.Context, prefix_unused: bool) -> None:
|
|
180
|
+
def list_unused(ctx: click.Context, dry_run: bool, prefix_unused: bool) -> None:
|
|
175
181
|
"""List unused payees in the YNAB budget."""
|
|
176
182
|
|
|
177
183
|
ctx.ensure_object(dict)
|
|
@@ -181,6 +187,7 @@ def list_unused(ctx: click.Context, prefix_unused: bool) -> None:
|
|
|
181
187
|
anyio.run(
|
|
182
188
|
_list_unused,
|
|
183
189
|
settings,
|
|
190
|
+
dry_run,
|
|
184
191
|
prefix_unused,
|
|
185
192
|
backend_options={"use_uvloop": True},
|
|
186
193
|
)
|
|
@@ -27,8 +27,9 @@ class ApplyRulesCommand:
|
|
|
27
27
|
self._progress_table.table.add_column("Transaction Amount")
|
|
28
28
|
self._progress_table.table.add_column("Transaction Changes")
|
|
29
29
|
|
|
30
|
-
async def __call__(self, settings: Settings, transaction_rules: rules.TransactionRules) -> None:
|
|
30
|
+
async def __call__(self, settings: Settings, dry_run: bool, transaction_rules: rules.TransactionRules) -> None:
|
|
31
31
|
params: use_cases.ApplyRulesParams = {
|
|
32
|
+
"dry_run": dry_run,
|
|
32
33
|
"transaction_rules": transaction_rules,
|
|
33
34
|
}
|
|
34
35
|
|
|
@@ -52,14 +53,15 @@ class ApplyRulesCommand:
|
|
|
52
53
|
|
|
53
54
|
|
|
54
55
|
@containerize
|
|
55
|
-
async def _apply_rules(container: Container, transaction_rules: rules.TransactionRules) -> None:
|
|
56
|
-
await container[ApplyRulesCommand](container[Settings], transaction_rules)
|
|
56
|
+
async def _apply_rules(container: Container, dry_run: bool, transaction_rules: rules.TransactionRules) -> None:
|
|
57
|
+
await container[ApplyRulesCommand](container[Settings], dry_run, transaction_rules)
|
|
57
58
|
|
|
58
59
|
|
|
59
60
|
@click.command()
|
|
61
|
+
@click.option("--dry-run", is_flag=True, default=False, help="Run without making any changes.")
|
|
60
62
|
@click.argument("rules-file", type=click.File())
|
|
61
63
|
@click.pass_context
|
|
62
|
-
def apply_rules(ctx: click.Context, rules_file: IO[Any]) -> None:
|
|
64
|
+
def apply_rules(ctx: click.Context, dry_run: bool, rules_file: IO[Any]) -> None:
|
|
63
65
|
"""Apply transaction rules from a JSON RULES_FILE to transactions in the YNAB budget.
|
|
64
66
|
|
|
65
67
|
RULES_FILE should be a JSON file containing transaction rules.
|
|
@@ -74,6 +76,7 @@ def apply_rules(ctx: click.Context, rules_file: IO[Any]) -> None:
|
|
|
74
76
|
anyio.run(
|
|
75
77
|
_apply_rules,
|
|
76
78
|
settings,
|
|
79
|
+
dry_run,
|
|
77
80
|
transaction_rules,
|
|
78
81
|
backend_options={"use_uvloop": True},
|
|
79
82
|
)
|
|
@@ -5,7 +5,7 @@ from textual.app import App, ComposeResult
|
|
|
5
5
|
from textual.binding import Binding, BindingType
|
|
6
6
|
from textual.containers import Horizontal, Vertical
|
|
7
7
|
from textual.reactive import reactive
|
|
8
|
-
from textual.widgets import
|
|
8
|
+
from textual.widgets import Footer, Header, Input, Label, TabbedContent
|
|
9
9
|
from typing_extensions import override
|
|
10
10
|
|
|
11
11
|
from ynab_cli.adapters.ynab.client import AuthenticatedClient
|
|
@@ -29,25 +29,18 @@ class SettingsDialogForm(DialogForm[Settings]):
|
|
|
29
29
|
with Vertical():
|
|
30
30
|
yield Label("Budget Id")
|
|
31
31
|
yield Input(self._settings.ynab.budget_id, placeholder="Budget Id", id="budget_id")
|
|
32
|
-
with Horizontal():
|
|
33
|
-
yield Checkbox("Debug", self._settings.debug, id="debug")
|
|
34
|
-
yield Checkbox("Dry Run", self._settings.dry_run, id="dry_run")
|
|
35
32
|
|
|
36
33
|
@override
|
|
37
34
|
async def get_result(self) -> Settings:
|
|
38
35
|
"""Get the result from the dialog form."""
|
|
39
36
|
access_token = self.query_one("#access_token", Input).value.strip()
|
|
40
37
|
budget_id = self.query_one("#budget_id", Input).value.strip()
|
|
41
|
-
debug = self.query_one("#debug", Checkbox).value
|
|
42
|
-
dry_run = self.query_one("#dry_run", Checkbox).value
|
|
43
38
|
|
|
44
39
|
return Settings(
|
|
45
40
|
ynab=YnabSettings(
|
|
46
41
|
access_token=access_token,
|
|
47
42
|
budget_id=budget_id,
|
|
48
|
-
)
|
|
49
|
-
debug=debug,
|
|
50
|
-
dry_run=dry_run,
|
|
43
|
+
)
|
|
51
44
|
)
|
|
52
45
|
|
|
53
46
|
|
|
@@ -7,7 +7,7 @@ from textual.logging import TextualHandler
|
|
|
7
7
|
|
|
8
8
|
from ynab_cli.adapters.ynab.client import AuthenticatedClient
|
|
9
9
|
from ynab_cli.domain.settings import Settings, YnabSettings
|
|
10
|
-
from ynab_cli.host.constants import CONTEXT_KEY_SETTINGS, ENV_PREFIX
|
|
10
|
+
from ynab_cli.host.constants import CONTEXT_KEY_DEBUG, CONTEXT_KEY_SETTINGS, ENV_PREFIX
|
|
11
11
|
from ynab_cli.host.textual.app import YnabCliApp
|
|
12
12
|
from ynab_cli.host.textual.container import containerize
|
|
13
13
|
|
|
@@ -32,11 +32,12 @@ def tui(
|
|
|
32
32
|
"""Run the Textual User Interface (TUI) for YNAB CLI."""
|
|
33
33
|
|
|
34
34
|
ctx.ensure_object(dict)
|
|
35
|
+
debug: bool = ctx.obj.get(CONTEXT_KEY_DEBUG, False)
|
|
35
36
|
settings: Settings = ctx.obj.get(CONTEXT_KEY_SETTINGS, Settings())
|
|
36
37
|
settings.ynab = YnabSettings(access_token=access_token, budget_id=budget_id)
|
|
37
38
|
|
|
38
39
|
logging.basicConfig(
|
|
39
|
-
level="DEBUG" if
|
|
40
|
+
level="DEBUG" if debug else "WARNING", # NOTSET, DEBUG, INFO, WARNING, ERROR, CRITICAL
|
|
40
41
|
format="%(message)s",
|
|
41
42
|
datefmt="[%X]",
|
|
42
43
|
handlers=[TextualHandler()],
|
|
@@ -20,12 +20,14 @@ class ListUnusedParamsDialogForm(DialogForm[use_cases.ListUnusedParams]):
|
|
|
20
20
|
|
|
21
21
|
@override
|
|
22
22
|
def compose(self) -> ComposeResult:
|
|
23
|
+
yield Checkbox("Dry Run", self._params["dry_run"], id="dry_run")
|
|
23
24
|
yield Checkbox("Prefix Unused Payees", self._params["prefix_unused"], id="prefix_unused")
|
|
24
25
|
|
|
25
26
|
@override
|
|
26
27
|
async def get_result(self) -> use_cases.ListUnusedParams:
|
|
27
28
|
return {
|
|
28
|
-
"
|
|
29
|
+
"dry_run": self.query_one("#dry_run", Checkbox).value,
|
|
30
|
+
"prefix_unused": self.query_one("#prefix_unused", Checkbox).value,
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
|
|
@@ -33,7 +35,8 @@ class ListUnusedCommand(CommandWidget):
|
|
|
33
35
|
def __init__(self) -> None:
|
|
34
36
|
super().__init__()
|
|
35
37
|
self._params: use_cases.ListUnusedParams = {
|
|
36
|
-
"
|
|
38
|
+
"dry_run": False,
|
|
39
|
+
"prefix_unused": False,
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
def on_mount(self) -> None:
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
2
|
+
|
|
3
|
+
from textual.app import ComposeResult
|
|
4
|
+
from textual.widgets import Checkbox, DataTable, Log, ProgressBar
|
|
5
|
+
from typing_extensions import override
|
|
6
|
+
|
|
7
|
+
from ynab_cli.adapters.textual.io import TextualIO
|
|
8
|
+
from ynab_cli.domain.use_cases import payees as use_cases
|
|
9
|
+
from ynab_cli.host.textual.widgets.common.command_widget import CommandWidget
|
|
10
|
+
from ynab_cli.host.textual.widgets.common.dialogs import CANCELLED, DialogForm, SaveCancelDialogScreen
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from ynab_cli.host.textual.app import YnabCliApp
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class NormalizeNamesParamsDialogForm(DialogForm[use_cases.NormalizeNamesParams]):
|
|
17
|
+
def __init__(self, params: use_cases.NormalizeNamesParams, *args: Any, **kwargs: Any) -> None:
|
|
18
|
+
super().__init__(*args, **kwargs)
|
|
19
|
+
self._params: use_cases.NormalizeNamesParams = {**params}
|
|
20
|
+
|
|
21
|
+
@override
|
|
22
|
+
def compose(self) -> ComposeResult:
|
|
23
|
+
yield Checkbox("Dry Run", self._params["dry_run"], id="dry_run")
|
|
24
|
+
|
|
25
|
+
@override
|
|
26
|
+
async def get_result(self) -> use_cases.NormalizeNamesParams:
|
|
27
|
+
return {
|
|
28
|
+
"dry_run": self.query_one("#dry_run", Checkbox).value,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class NormalizeNamesCommand(CommandWidget):
|
|
33
|
+
def __init__(self) -> None:
|
|
34
|
+
super().__init__()
|
|
35
|
+
self._params: use_cases.NormalizeNamesParams = {
|
|
36
|
+
"dry_run": False,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
def on_mount(self) -> None:
|
|
40
|
+
table = self.query_one(DataTable)
|
|
41
|
+
table.add_columns(
|
|
42
|
+
"Payee Id",
|
|
43
|
+
"Payee Name",
|
|
44
|
+
"Normalized Name",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
@override
|
|
48
|
+
async def _get_command_params(self) -> None:
|
|
49
|
+
result = await self.app.push_screen_wait(
|
|
50
|
+
SaveCancelDialogScreen(
|
|
51
|
+
NormalizeNamesParamsDialogForm(self._params), title="Payees: Normalize Names Parameters"
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
if result is not CANCELLED:
|
|
55
|
+
self._params = result
|
|
56
|
+
|
|
57
|
+
@override
|
|
58
|
+
async def _run_command(self) -> None:
|
|
59
|
+
params: use_cases.NormalizeNamesParams = {
|
|
60
|
+
"dry_run": False,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
progress_bar = self.query_one(ProgressBar)
|
|
64
|
+
table = self.query_one(DataTable)
|
|
65
|
+
log = self.query_one(Log)
|
|
66
|
+
|
|
67
|
+
async for payee, normalized_name in use_cases.NormalizeNames(
|
|
68
|
+
TextualIO(self.app, log, progress_bar), cast("YnabCliApp", self.app).client
|
|
69
|
+
)(self.settings, params):
|
|
70
|
+
table.add_row(
|
|
71
|
+
payee.id,
|
|
72
|
+
payee.name,
|
|
73
|
+
normalized_name,
|
|
74
|
+
)
|
{ynab_cli-0.6.2 → ynab_cli-0.6.3}/src/ynab_cli/host/textual/widgets/transactions/apply_rules.py
RENAMED
|
@@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, cast
|
|
|
4
4
|
from textual import on, work
|
|
5
5
|
from textual.app import ComposeResult
|
|
6
6
|
from textual.containers import ScrollableContainer
|
|
7
|
-
from textual.widgets import Button, DataTable, Log, Pretty, ProgressBar
|
|
7
|
+
from textual.widgets import Button, Checkbox, DataTable, Log, Pretty, ProgressBar
|
|
8
8
|
from textual_fspicker import FileOpen
|
|
9
9
|
from typing_extensions import override
|
|
10
10
|
|
|
@@ -25,6 +25,7 @@ class ApplyRulesParamsDialogForm(DialogForm[use_cases.ApplyRulesParams]):
|
|
|
25
25
|
|
|
26
26
|
@override
|
|
27
27
|
def compose(self) -> ComposeResult:
|
|
28
|
+
yield Checkbox("Dry Run", self._params["dry_run"], id="dry_run")
|
|
28
29
|
yield Button("Select Transaction Rules JSON File", id="select_rules", variant="primary")
|
|
29
30
|
with ScrollableContainer():
|
|
30
31
|
yield Pretty(self._params["transaction_rules"].to_dict())
|
|
@@ -52,6 +53,7 @@ class ApplyRulesParamsDialogForm(DialogForm[use_cases.ApplyRulesParams]):
|
|
|
52
53
|
@override
|
|
53
54
|
async def get_result(self) -> use_cases.ApplyRulesParams:
|
|
54
55
|
return {
|
|
56
|
+
"dry_run": self.query_one("#dry_run", Checkbox).value,
|
|
55
57
|
"transaction_rules": self._params["transaction_rules"],
|
|
56
58
|
}
|
|
57
59
|
|
|
@@ -60,6 +62,7 @@ class ApplyRulesCommand(CommandWidget):
|
|
|
60
62
|
def __init__(self) -> None:
|
|
61
63
|
super().__init__()
|
|
62
64
|
self._params: use_cases.ApplyRulesParams = {
|
|
65
|
+
"dry_run": False,
|
|
63
66
|
"transaction_rules": rules.TransactionRules(transaction_rules=[]),
|
|
64
67
|
}
|
|
65
68
|
|
|
@@ -16,13 +16,13 @@ class TransactionsTabs(Widget):
|
|
|
16
16
|
@override
|
|
17
17
|
def compose(self) -> ComposeResult:
|
|
18
18
|
with TabbedContent():
|
|
19
|
-
with TabPane("
|
|
19
|
+
with TabPane("Apply Rules", id="apply_rules"):
|
|
20
20
|
yield ApplyRulesCommand().data_bind(settings=TransactionsTabs.settings)
|
|
21
21
|
|
|
22
22
|
def active_command(self) -> CommandWidget:
|
|
23
23
|
tabbed_content = self.query_one(TabbedContent)
|
|
24
24
|
if tabbed_content.active_pane:
|
|
25
|
-
if tabbed_content.active_pane.id == "
|
|
25
|
+
if tabbed_content.active_pane.id == "apply_rules":
|
|
26
26
|
return self.query_one(ApplyRulesCommand)
|
|
27
27
|
|
|
28
28
|
raise ValueError("No active command found in TransactionsTabs.")
|
|
@@ -131,7 +131,9 @@ async def test_normalize_names(mocker: MockerFixture, mock_io: MagicMock, empty_
|
|
|
131
131
|
mock_update_payee.asyncio_detailed = AsyncMock()
|
|
132
132
|
|
|
133
133
|
settings = Settings()
|
|
134
|
-
params: use_cases.NormalizeNamesParams = {
|
|
134
|
+
params: use_cases.NormalizeNamesParams = {
|
|
135
|
+
"dry_run": False,
|
|
136
|
+
}
|
|
135
137
|
|
|
136
138
|
results: list[tuple[models.Payee, str]] = []
|
|
137
139
|
async for result in use_cases.NormalizeNames(mock_io, MagicMock())(settings, params):
|
|
@@ -163,7 +165,9 @@ async def test_normalize_names_exception(
|
|
|
163
165
|
mock_get_payees.asyncio_detailed.side_effect = exception
|
|
164
166
|
|
|
165
167
|
settings = Settings()
|
|
166
|
-
params: use_cases.NormalizeNamesParams = {
|
|
168
|
+
params: use_cases.NormalizeNamesParams = {
|
|
169
|
+
"dry_run": False,
|
|
170
|
+
}
|
|
167
171
|
|
|
168
172
|
async for _ in use_cases.NormalizeNames(mock_io, MagicMock())(settings, params):
|
|
169
173
|
pass
|
|
@@ -268,13 +272,14 @@ async def test_list_unused(mocker: MockerFixture, mock_io: MagicMock, empty_uuid
|
|
|
268
272
|
|
|
269
273
|
settings = Settings()
|
|
270
274
|
params: use_cases.ListUnusedParams = {
|
|
275
|
+
"dry_run": False,
|
|
271
276
|
"prefix_unused": True,
|
|
272
277
|
}
|
|
273
278
|
|
|
274
279
|
results: list[models.Payee] = []
|
|
275
280
|
async for result in use_cases.ListUnused(mock_io, MagicMock())(settings, params):
|
|
276
281
|
assert isinstance(result, models.Payee)
|
|
277
|
-
assert result.name in ["Payee 1"]
|
|
282
|
+
assert result.name in ["[UNUSED] Payee 1"]
|
|
278
283
|
results.append(result)
|
|
279
284
|
|
|
280
285
|
assert len(results) == 1
|
|
@@ -299,6 +304,7 @@ async def test_list_unused_exception(
|
|
|
299
304
|
|
|
300
305
|
settings = Settings()
|
|
301
306
|
params: use_cases.ListUnusedParams = {
|
|
307
|
+
"dry_run": False,
|
|
302
308
|
"prefix_unused": True,
|
|
303
309
|
}
|
|
304
310
|
|
|
@@ -33,7 +33,7 @@ def test_normalize_names(runner: CliRunner, container: Container, empty_uuid: UU
|
|
|
33
33
|
assert result.exit_code == 0
|
|
34
34
|
|
|
35
35
|
use_case.assert_called_once_with(
|
|
36
|
-
Settings(ynab=YnabSettings(access_token="test_token", budget_id="test_budget")), {}
|
|
36
|
+
Settings(ynab=YnabSettings(access_token="test_token", budget_id="test_budget")), {"dry_run": False}
|
|
37
37
|
)
|
|
38
38
|
|
|
39
39
|
|
|
@@ -82,7 +82,8 @@ def test_list_unused(runner: CliRunner, container: Container, empty_uuid: UUID)
|
|
|
82
82
|
|
|
83
83
|
assert result.exit_code == 0
|
|
84
84
|
use_case.assert_called_once_with(
|
|
85
|
-
Settings(ynab=YnabSettings(access_token="test_token", budget_id="test_budget")),
|
|
85
|
+
Settings(ynab=YnabSettings(access_token="test_token", budget_id="test_budget")),
|
|
86
|
+
{"dry_run": False, "prefix_unused": False},
|
|
86
87
|
)
|
|
87
88
|
|
|
88
89
|
|
|
@@ -26,7 +26,6 @@ async def test_settings_dialog_form_get_result(monkeypatch: pytest.MonkeyPatch)
|
|
|
26
26
|
("#access_token", Input): mock.Mock(spec=Input, value="newtoken "),
|
|
27
27
|
("#budget_id", Input): mock.Mock(spec=Input, value=" newbudget"),
|
|
28
28
|
("#debug", Checkbox): mock.Mock(spec=Checkbox, value=True),
|
|
29
|
-
("#dry_run", Checkbox): mock.Mock(spec=Checkbox, value=True),
|
|
30
29
|
}[(selector, cls)],
|
|
31
30
|
)
|
|
32
31
|
|
|
@@ -34,8 +33,6 @@ async def test_settings_dialog_form_get_result(monkeypatch: pytest.MonkeyPatch)
|
|
|
34
33
|
assert isinstance(result, Settings)
|
|
35
34
|
assert result.ynab.access_token == "newtoken"
|
|
36
35
|
assert result.ynab.budget_id == "newbudget"
|
|
37
|
-
assert result.debug is True
|
|
38
|
-
assert result.dry_run is True
|
|
39
36
|
|
|
40
37
|
|
|
41
38
|
def test_ynab_cli_app_initialization() -> None:
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING, cast
|
|
2
|
-
|
|
3
|
-
from textual.widgets import DataTable, Log, ProgressBar
|
|
4
|
-
from typing_extensions import override
|
|
5
|
-
|
|
6
|
-
from ynab_cli.adapters.textual.io import TextualIO
|
|
7
|
-
from ynab_cli.domain.use_cases import payees as use_cases
|
|
8
|
-
from ynab_cli.host.textual.widgets.common.command_widget import CommandWidget
|
|
9
|
-
|
|
10
|
-
if TYPE_CHECKING:
|
|
11
|
-
from ynab_cli.host.textual.app import YnabCliApp
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class NormalizeNamesCommand(CommandWidget):
|
|
15
|
-
def on_mount(self) -> None:
|
|
16
|
-
table = self.query_one(DataTable)
|
|
17
|
-
table.add_columns(
|
|
18
|
-
"Payee Id",
|
|
19
|
-
"Payee Name",
|
|
20
|
-
"Normalized Name",
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
@override
|
|
24
|
-
async def _run_command(self) -> None:
|
|
25
|
-
params: use_cases.NormalizeNamesParams = {}
|
|
26
|
-
|
|
27
|
-
progress_bar = self.query_one(ProgressBar)
|
|
28
|
-
table = self.query_one(DataTable)
|
|
29
|
-
log = self.query_one(Log)
|
|
30
|
-
|
|
31
|
-
async for payee, normalized_name in use_cases.NormalizeNames(
|
|
32
|
-
TextualIO(self.app, log, progress_bar), cast("YnabCliApp", self.app).client
|
|
33
|
-
)(self.settings, params):
|
|
34
|
-
table.add_row(
|
|
35
|
-
payee.id,
|
|
36
|
-
payee.name,
|
|
37
|
-
normalized_name,
|
|
38
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|