From e4f567cb7f4d3ac971c5d58c9c44b7c5511d5911 Mon Sep 17 00:00:00 2001 From: Brady Holt Date: Mon, 2 Nov 2026 08:06:26 -0600 Subject: [PATCH 1/3] Regenerate SDK from server specification version 1.88.0 Regenerated the client from the YNAB API spec 1.88.0 (previously 1.86.0) using openapi-generator 7.27.0 (previously 7.23.0), and bumped the package version to 4.5.0. --- .openapi-generator/VERSION | 2 +- docs/ExistingCategory.md | 8 +- docs/ExistingTransaction.md | 2 +- docs/NewCategory.md | 8 +- docs/NewTransaction.md | 2 +- docs/SaveCategory.md | 8 +- docs/SaveTransactionWithIdOrImportId.md | 2 +- docs/SaveTransactionWithOptionalFields.md | 2 +- docs/TransactionsApi.md | 5 +- open_api_spec.yaml | 38 ++++---- openapi-generator-config.yaml | 2 +- pyproject.toml | 4 +- test-requirements.txt | 2 +- ynab/__init__.py | 4 +- ynab/api/accounts_api.py | 18 ++-- ynab/api/categories_api.py | 54 +++++------ ynab/api/money_movements_api.py | 18 ++-- ynab/api/months_api.py | 10 +- ynab/api/payee_locations_api.py | 14 +-- ynab/api/payees_api.py | 26 ++--- ynab/api/plans_api.py | 14 +-- ynab/api/scheduled_transactions_api.py | 30 +++--- ynab/api/transactions_api.py | 76 +++++++-------- ynab/api/user_api.py | 6 +- ynab/api_client.py | 97 +++++++++++++++---- ynab/configuration.py | 6 +- ynab/exceptions.py | 2 +- ynab/models/__init__.py | 2 +- ynab/models/account.py | 39 +++++++- ynab/models/account_base.py | 17 +++- ynab/models/account_response.py | 2 +- ynab/models/account_response_data.py | 2 +- ynab/models/account_type.py | 2 +- ynab/models/accounts_response.py | 2 +- ynab/models/accounts_response_data.py | 5 +- ynab/models/bulk_response.py | 2 +- ynab/models/bulk_response_data.py | 2 +- ynab/models/bulk_response_data_bulk.py | 2 +- ynab/models/bulk_transactions.py | 5 +- ynab/models/categories_response.py | 2 +- ynab/models/categories_response_data.py | 5 +- ynab/models/category.py | 82 +++++++++++++++- ynab/models/category_base.py | 2 +- ynab/models/category_group.py | 2 +- ynab/models/category_group_with_categories.py | 5 +- ynab/models/category_response.py | 2 +- ynab/models/category_response_data.py | 2 +- ynab/models/currency_format.py | 2 +- ynab/models/date_format.py | 2 +- ynab/models/error_detail.py | 2 +- ynab/models/error_response.py | 2 +- ynab/models/existing_category.py | 35 ++++++- ynab/models/existing_transaction.py | 27 +++++- ynab/models/hybrid_transaction.py | 52 +++++++++- ynab/models/hybrid_transactions_response.py | 2 +- .../hybrid_transactions_response_data.py | 5 +- ynab/models/money_movement.py | 37 ++++++- ynab/models/money_movement_base.py | 2 +- ynab/models/money_movement_group.py | 2 +- ynab/models/money_movement_groups_response.py | 2 +- .../money_movement_groups_response_data.py | 5 +- ynab/models/money_movements_response.py | 2 +- ynab/models/money_movements_response_data.py | 5 +- ynab/models/month_detail.py | 15 ++- ynab/models/month_detail_base.py | 15 ++- ynab/models/month_detail_response.py | 2 +- ynab/models/month_detail_response_data.py | 2 +- ynab/models/month_summaries_response.py | 2 +- ynab/models/month_summaries_response_data.py | 5 +- ynab/models/month_summary.py | 12 ++- ynab/models/month_summary_base.py | 2 +- ynab/models/new_category.py | 35 ++++++- ynab/models/new_transaction.py | 27 +++++- ynab/models/patch_category_group_wrapper.py | 2 +- ynab/models/patch_category_wrapper.py | 2 +- ynab/models/patch_month_category_wrapper.py | 2 +- ynab/models/patch_payee_wrapper.py | 2 +- ynab/models/patch_transactions_wrapper.py | 5 +- ynab/models/payee.py | 2 +- ynab/models/payee_location.py | 2 +- ynab/models/payee_location_response.py | 2 +- ynab/models/payee_location_response_data.py | 2 +- ynab/models/payee_locations_response.py | 2 +- ynab/models/payee_locations_response_data.py | 5 +- ynab/models/payee_response.py | 2 +- ynab/models/payee_response_data.py | 2 +- ynab/models/payees_response.py | 2 +- ynab/models/payees_response_data.py | 5 +- ynab/models/plan_detail.py | 42 ++++---- ynab/models/plan_detail_response.py | 2 +- ynab/models/plan_detail_response_data.py | 2 +- ynab/models/plan_settings.py | 18 +++- ynab/models/plan_settings_response.py | 2 +- ynab/models/plan_settings_response_data.py | 2 +- ynab/models/plan_summary.py | 15 ++- ynab/models/plan_summary_response.py | 2 +- ynab/models/plan_summary_response_data.py | 5 +- ynab/models/post_account_wrapper.py | 2 +- ynab/models/post_category_group_wrapper.py | 2 +- ynab/models/post_category_wrapper.py | 2 +- ynab/models/post_payee.py | 2 +- ynab/models/post_payee_wrapper.py | 2 +- .../post_scheduled_transaction_wrapper.py | 2 +- ynab/models/post_transactions_wrapper.py | 5 +- .../put_scheduled_transaction_wrapper.py | 2 +- ynab/models/put_transaction_wrapper.py | 2 +- ynab/models/save_account.py | 2 +- ynab/models/save_account_type.py | 2 +- ynab/models/save_category.py | 10 +- ynab/models/save_category_group.py | 2 +- ynab/models/save_category_group_response.py | 2 +- .../save_category_group_response_data.py | 2 +- ynab/models/save_category_response.py | 2 +- ynab/models/save_category_response_data.py | 2 +- ynab/models/save_month_category.py | 2 +- ynab/models/save_payee.py | 2 +- ynab/models/save_payee_response.py | 2 +- ynab/models/save_payee_response_data.py | 2 +- ynab/models/save_scheduled_transaction.py | 2 +- ynab/models/save_sub_transaction.py | 2 +- .../save_transaction_with_id_or_import_id.py | 27 +++++- .../save_transaction_with_optional_fields.py | 7 +- ynab/models/save_transactions_response.py | 2 +- .../models/save_transactions_response_data.py | 5 +- ynab/models/scheduled_sub_transaction.py | 32 +++++- ynab/models/scheduled_sub_transaction_base.py | 2 +- ynab/models/scheduled_transaction_detail.py | 30 +++++- .../models/scheduled_transaction_frequency.py | 2 +- ynab/models/scheduled_transaction_response.py | 2 +- .../scheduled_transaction_response_data.py | 2 +- ynab/models/scheduled_transaction_summary.py | 27 +++++- .../scheduled_transaction_summary_base.py | 2 +- .../models/scheduled_transactions_response.py | 2 +- .../scheduled_transactions_response_data.py | 5 +- ynab/models/sub_transaction.py | 37 ++++++- ynab/models/sub_transaction_base.py | 2 +- ynab/models/transaction_cleared_status.py | 2 +- ynab/models/transaction_detail.py | 55 ++++++++++- ynab/models/transaction_flag_color.py | 2 +- ynab/models/transaction_response.py | 2 +- ynab/models/transaction_response_data.py | 2 +- ynab/models/transaction_summary.py | 52 +++++++++- ynab/models/transaction_summary_base.py | 2 +- ynab/models/transactions_import_response.py | 2 +- .../transactions_import_response_data.py | 2 +- ynab/models/transactions_response.py | 2 +- ynab/models/transactions_response_data.py | 5 +- ynab/models/user.py | 2 +- ynab/models/user_response.py | 2 +- ynab/models/user_response_data.py | 2 +- ynab/rest.py | 2 +- 151 files changed, 1038 insertions(+), 415 deletions(-) diff --git a/.openapi-generator/VERSION b/.openapi-generator/VERSION index 14d6b5d..f6b1800 100644 --- a/.openapi-generator/VERSION +++ b/.openapi-generator/VERSION @@ -1 +1 @@ -7.23.0 +7.27.0 diff --git a/docs/ExistingCategory.md b/docs/ExistingCategory.md index 93e12b3..ee8815c 100644 --- a/docs/ExistingCategory.md +++ b/docs/ExistingCategory.md @@ -8,10 +8,10 @@ Name | Type | Description | Notes **name** | **str** | | [optional] **note** | **str** | | [optional] **category_group_id** | **UUID** | The id of the category group to which this category belongs. An internal category group may not be specified. | [optional] -**goal_target** | **int** | The goal target amount in milliunits format. If value is specified and goal has not already been configured for category, a monthly goal will be created for the category with this target amount. If goal_type is not specified, it will default to 'NEED' or 'MF' for Credit Card Payment categories. When updating a category, passing null removes any existing target. | [optional] -**goal_target_date** | **date** | The goal target date in ISO format (e.g. 2016-12-01). | [optional] -**goal_needs_whole_amount** | **bool** | Whether the goal requires the full target amount each period. Only supported for 'NEED' goals. When true, the goal is configured as 'Set aside another...'. When false, the goal is configured as 'Refill up to...'. | [optional] -**goal_frequency** | **str** | When specified, configures a recurring 'NEED' target of goal_target that repeats at this frequency, replacing any existing target. Requires goal_target. Cannot be combined with goal_target_date and is not supported for Credit Card Payment categories. Omit to leave an existing target's cadence unchanged. | [optional] +**goal_target** | **int** | The goal target amount in milliunits format. If value is specified and goal has not already been configured for category, a monthly goal will be created for the category with this target amount. If goal_type is not specified, it will default to 'NEED', or to 'MF' for Credit Card Payment categories and 'DEBT' for categories paired to a loan account. When updating a category, passing null removes any existing target. | [optional] +**goal_target_date** | **date** | The goal target date in ISO format (e.g. 2016-12-01). Not supported for categories paired to a loan account. | [optional] +**goal_needs_whole_amount** | **bool** | Whether the goal requires the full target amount each period. Only supported for 'NEED' goals, and not supported for Credit Card Payment categories or categories paired to a loan account. When true, the goal is configured as 'Set aside another...'. When false, the goal is configured as 'Refill up to...'. | [optional] +**goal_frequency** | **str** | When specified, configures a recurring 'NEED' target of goal_target that repeats at this frequency, replacing any existing target. Requires goal_target. Cannot be combined with goal_target_date and is not supported for Credit Card Payment categories or categories paired to a loan account. Omit to leave an existing target's cadence unchanged. | [optional] ## Example diff --git a/docs/ExistingTransaction.md b/docs/ExistingTransaction.md index a19dc1e..d2842f9 100644 --- a/docs/ExistingTransaction.md +++ b/docs/ExistingTransaction.md @@ -15,7 +15,7 @@ Name | Type | Description | Notes **cleared** | [**TransactionClearedStatus**](TransactionClearedStatus.md) | | [optional] **approved** | **bool** | Whether or not the transaction is approved. If not supplied, transaction will be unapproved by default. | [optional] **flag_color** | [**TransactionFlagColor**](TransactionFlagColor.md) | | [optional] -**subtransactions** | [**List[SaveSubTransaction]**](SaveSubTransaction.md) | An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported. | [optional] +**subtransactions** | [**List[SaveSubTransaction]**](SaveSubTransaction.md) | An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported and will return an error. Splits are not allowed on tracking accounts or on transfers between on-budget accounts; a transfer to a tracking account can be a split. | [optional] ## Example diff --git a/docs/NewCategory.md b/docs/NewCategory.md index d970d5a..a002f79 100644 --- a/docs/NewCategory.md +++ b/docs/NewCategory.md @@ -8,10 +8,10 @@ Name | Type | Description | Notes **name** | **str** | | [optional] **note** | **str** | | [optional] **category_group_id** | **UUID** | The id of the category group to which this category belongs. An internal category group may not be specified. | [optional] -**goal_target** | **int** | The goal target amount in milliunits format. If value is specified and goal has not already been configured for category, a monthly goal will be created for the category with this target amount. If goal_type is not specified, it will default to 'NEED' or 'MF' for Credit Card Payment categories. When updating a category, passing null removes any existing target. | [optional] -**goal_target_date** | **date** | The goal target date in ISO format (e.g. 2016-12-01). | [optional] -**goal_needs_whole_amount** | **bool** | Whether the goal requires the full target amount each period. Only supported for 'NEED' goals. When true, the goal is configured as 'Set aside another...'. When false, the goal is configured as 'Refill up to...'. | [optional] -**goal_frequency** | **str** | When specified, configures a recurring 'NEED' target of goal_target that repeats at this frequency, replacing any existing target. Requires goal_target. Cannot be combined with goal_target_date and is not supported for Credit Card Payment categories. Omit to leave an existing target's cadence unchanged. | [optional] +**goal_target** | **int** | The goal target amount in milliunits format. If value is specified and goal has not already been configured for category, a monthly goal will be created for the category with this target amount. If goal_type is not specified, it will default to 'NEED', or to 'MF' for Credit Card Payment categories and 'DEBT' for categories paired to a loan account. When updating a category, passing null removes any existing target. | [optional] +**goal_target_date** | **date** | The goal target date in ISO format (e.g. 2016-12-01). Not supported for categories paired to a loan account. | [optional] +**goal_needs_whole_amount** | **bool** | Whether the goal requires the full target amount each period. Only supported for 'NEED' goals, and not supported for Credit Card Payment categories or categories paired to a loan account. When true, the goal is configured as 'Set aside another...'. When false, the goal is configured as 'Refill up to...'. | [optional] +**goal_frequency** | **str** | When specified, configures a recurring 'NEED' target of goal_target that repeats at this frequency, replacing any existing target. Requires goal_target. Cannot be combined with goal_target_date and is not supported for Credit Card Payment categories or categories paired to a loan account. Omit to leave an existing target's cadence unchanged. | [optional] ## Example diff --git a/docs/NewTransaction.md b/docs/NewTransaction.md index 7ce3d22..4f8c501 100644 --- a/docs/NewTransaction.md +++ b/docs/NewTransaction.md @@ -15,7 +15,7 @@ Name | Type | Description | Notes **cleared** | [**TransactionClearedStatus**](TransactionClearedStatus.md) | | [optional] **approved** | **bool** | Whether or not the transaction is approved. If not supplied, transaction will be unapproved by default. | [optional] **flag_color** | [**TransactionFlagColor**](TransactionFlagColor.md) | | [optional] -**subtransactions** | [**List[SaveSubTransaction]**](SaveSubTransaction.md) | An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported. | [optional] +**subtransactions** | [**List[SaveSubTransaction]**](SaveSubTransaction.md) | An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported and will return an error. Splits are not allowed on tracking accounts or on transfers between on-budget accounts; a transfer to a tracking account can be a split. | [optional] **import_id** | **str** | If specified, a new transaction will be assigned this `import_id` and considered \"imported\". We will also attempt to match this imported transaction to an existing \"user-entered\" transaction on the same account, with the same amount, and with a date +/-10 days from the imported transaction date.<br><br>Transactions imported through File Based Import or Direct Import (not through the API) are assigned an import_id in the format: 'YNAB:[milliunit_amount]:[iso_date]:[occurrence]'. For example, a transaction dated 2015-12-30 in the amount of -$294.23 USD would have an import_id of 'YNAB:-294230:2015-12-30:1'. If a second transaction on the same account was imported and had the same date and same amount, its import_id would be 'YNAB:-294230:2015-12-30:2'. Using a consistent format will prevent duplicates through Direct Import and File Based Import.<br><br>If import_id is omitted or specified as null, the transaction will be treated as a \"user-entered\" transaction. As such, it will be eligible to be matched against transactions later being imported (via DI, FBI, or API). | [optional] ## Example diff --git a/docs/SaveCategory.md b/docs/SaveCategory.md index 08f1462..234d129 100644 --- a/docs/SaveCategory.md +++ b/docs/SaveCategory.md @@ -8,10 +8,10 @@ Name | Type | Description | Notes **name** | **str** | | [optional] **note** | **str** | | [optional] **category_group_id** | **UUID** | The id of the category group to which this category belongs. An internal category group may not be specified. | [optional] -**goal_target** | **int** | The goal target amount in milliunits format. If value is specified and goal has not already been configured for category, a monthly goal will be created for the category with this target amount. If goal_type is not specified, it will default to 'NEED' or 'MF' for Credit Card Payment categories. When updating a category, passing null removes any existing target. | [optional] -**goal_target_date** | **date** | The goal target date in ISO format (e.g. 2016-12-01). | [optional] -**goal_needs_whole_amount** | **bool** | Whether the goal requires the full target amount each period. Only supported for 'NEED' goals. When true, the goal is configured as 'Set aside another...'. When false, the goal is configured as 'Refill up to...'. | [optional] -**goal_frequency** | **str** | When specified, configures a recurring 'NEED' target of goal_target that repeats at this frequency, replacing any existing target. Requires goal_target. Cannot be combined with goal_target_date and is not supported for Credit Card Payment categories. Omit to leave an existing target's cadence unchanged. | [optional] +**goal_target** | **int** | The goal target amount in milliunits format. If value is specified and goal has not already been configured for category, a monthly goal will be created for the category with this target amount. If goal_type is not specified, it will default to 'NEED', or to 'MF' for Credit Card Payment categories and 'DEBT' for categories paired to a loan account. When updating a category, passing null removes any existing target. | [optional] +**goal_target_date** | **date** | The goal target date in ISO format (e.g. 2016-12-01). Not supported for categories paired to a loan account. | [optional] +**goal_needs_whole_amount** | **bool** | Whether the goal requires the full target amount each period. Only supported for 'NEED' goals, and not supported for Credit Card Payment categories or categories paired to a loan account. When true, the goal is configured as 'Set aside another...'. When false, the goal is configured as 'Refill up to...'. | [optional] +**goal_frequency** | **str** | When specified, configures a recurring 'NEED' target of goal_target that repeats at this frequency, replacing any existing target. Requires goal_target. Cannot be combined with goal_target_date and is not supported for Credit Card Payment categories or categories paired to a loan account. Omit to leave an existing target's cadence unchanged. | [optional] ## Example diff --git a/docs/SaveTransactionWithIdOrImportId.md b/docs/SaveTransactionWithIdOrImportId.md index dffc7be..a8448d3 100644 --- a/docs/SaveTransactionWithIdOrImportId.md +++ b/docs/SaveTransactionWithIdOrImportId.md @@ -15,7 +15,7 @@ Name | Type | Description | Notes **cleared** | [**TransactionClearedStatus**](TransactionClearedStatus.md) | | [optional] **approved** | **bool** | Whether or not the transaction is approved. If not supplied, transaction will be unapproved by default. | [optional] **flag_color** | [**TransactionFlagColor**](TransactionFlagColor.md) | | [optional] -**subtransactions** | [**List[SaveSubTransaction]**](SaveSubTransaction.md) | An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported. | [optional] +**subtransactions** | [**List[SaveSubTransaction]**](SaveSubTransaction.md) | An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported and will return an error. Splits are not allowed on tracking accounts or on transfers between on-budget accounts; a transfer to a tracking account can be a split. | [optional] **id** | **str** | If specified, this id will be used to lookup a transaction by its `id` for the purpose of updating the transaction itself. If not specified, an `import_id` should be supplied. | [optional] **import_id** | **str** | If specified, this id will be used to lookup a transaction by its `import_id` for the purpose of updating the transaction itself. If not specified, an `id` should be supplied. You may not provide both an `id` and an `import_id` and updating an `import_id` on an existing transaction is not allowed. | [optional] diff --git a/docs/SaveTransactionWithOptionalFields.md b/docs/SaveTransactionWithOptionalFields.md index 83c2b95..a4fd28c 100644 --- a/docs/SaveTransactionWithOptionalFields.md +++ b/docs/SaveTransactionWithOptionalFields.md @@ -15,7 +15,7 @@ Name | Type | Description | Notes **cleared** | [**TransactionClearedStatus**](TransactionClearedStatus.md) | | [optional] **approved** | **bool** | Whether or not the transaction is approved. If not supplied, transaction will be unapproved by default. | [optional] **flag_color** | [**TransactionFlagColor**](TransactionFlagColor.md) | | [optional] -**subtransactions** | [**List[SaveSubTransaction]**](SaveSubTransaction.md) | An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported. | [optional] +**subtransactions** | [**List[SaveSubTransaction]**](SaveSubTransaction.md) | An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported and will return an error. Splits are not allowed on tracking accounts or on transfers between on-budget accounts; a transfer to a tracking account can be a split. | [optional] ## Example diff --git a/docs/TransactionsApi.md b/docs/TransactionsApi.md index 74bdf7d..25e36da 100644 --- a/docs/TransactionsApi.md +++ b/docs/TransactionsApi.md @@ -711,7 +711,7 @@ Name | Type | Description | Notes Import transactions -Imports available transactions on all linked accounts for the given plan. Linked accounts allow transactions to be imported directly from a specified financial institution and this endpoint initiates that import. Sending a request to this endpoint is the equivalent of clicking "Import" on each account in the web application or tapping the "New Transactions" banner in the mobile applications. The response for this endpoint contains the transaction ids that have been imported. +DEPRECATED: This endpoint is no longer needed because YNAB now automatically imports transactions on linked accounts. Requests are still accepted for backwards compatibility but no import is performed and the response will always contain an empty list of transaction ids. ### Example @@ -780,8 +780,7 @@ Name | Type | Description | Notes | Status code | Description | Response headers | |-------------|-------------|------------------| -**200** | The request was successful but there were no transactions to import | - | -**201** | One or more transactions were imported successfully | - | +**200** | The request was successful. No transactions are imported. | - | **400** | The request could not be understood due to malformed syntax or validation error(s) | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) diff --git a/open_api_spec.yaml b/open_api_spec.yaml index e666b52..bdf99db 100644 --- a/open_api_spec.yaml +++ b/open_api_spec.yaml @@ -5,7 +5,7 @@ info: Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - version: 1.86.0 + version: 1.88.0 servers: - url: https://api.ynab.com/v1 security: @@ -1231,14 +1231,12 @@ paths: tags: - Transactions summary: Import transactions - description: Imports available transactions on all linked accounts for the given - plan. Linked accounts allow transactions to be imported directly from a - specified financial institution and this endpoint initiates that - import. Sending a request to this endpoint is the equivalent of - clicking "Import" on each account in the web application or tapping the - "New Transactions" banner in the mobile applications. The response for - this endpoint contains the transaction ids that have been imported. + description: "DEPRECATED: This endpoint is no longer needed because YNAB now + automatically imports transactions on linked accounts. Requests are + still accepted for backwards compatibility but no import is performed + and the response will always contain an empty list of transaction ids." operationId: importTransactions + deprecated: true parameters: - name: plan_id in: path @@ -1250,13 +1248,7 @@ paths: type: string responses: "200": - description: The request was successful but there were no transactions to import - content: - application/json: - schema: - $ref: "#/components/schemas/TransactionsImportResponse" - "201": - description: One or more transactions were imported successfully + description: The request was successful. No transactions are imported. content: application/json: schema: @@ -2905,7 +2897,9 @@ components: type: array description: An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not - supported. + supported and will return an error. Splits are not allowed on + tracking accounts or on transfers between on-budget accounts; a + transfer to a tracking account can be a split. items: $ref: "#/components/schemas/SaveSubTransaction" SaveSubTransaction: @@ -3269,20 +3263,23 @@ components: description: The goal target amount in milliunits format. If value is specified and goal has not already been configured for category, a monthly goal will be created for the category with this target amount. If goal_type is - not specified, it will default to 'NEED' or 'MF' for Credit Card Payment categories. + not specified, it will default to 'NEED', or to 'MF' for Credit Card Payment categories and + 'DEBT' for categories paired to a loan account. When updating a category, passing null removes any existing target. format: int64 goal_target_date: type: - string - "null" - description: The goal target date in ISO format (e.g. 2016-12-01). + description: The goal target date in ISO format (e.g. 2016-12-01). Not supported for categories + paired to a loan account. format: date goal_needs_whole_amount: type: - boolean - "null" - description: Whether the goal requires the full target amount each period. Only supported for 'NEED' goals. + description: Whether the goal requires the full target amount each period. Only supported for 'NEED' goals, + and not supported for Credit Card Payment categories or categories paired to a loan account. When true, the goal is configured as 'Set aside another...'. When false, the goal is configured as 'Refill up to...'. goal_frequency: @@ -3293,7 +3290,8 @@ components: - yearly description: When specified, configures a recurring 'NEED' target of goal_target that repeats at this frequency, replacing any existing target. Requires goal_target. Cannot be combined with goal_target_date - and is not supported for Credit Card Payment categories. Omit to leave an existing target's cadence unchanged. + and is not supported for Credit Card Payment categories or categories paired to a loan account. + Omit to leave an existing target's cadence unchanged. ExistingCategory: allOf: - $ref: "#/components/schemas/SaveCategory" diff --git a/openapi-generator-config.yaml b/openapi-generator-config.yaml index 7900bae..b1bd7d5 100644 --- a/openapi-generator-config.yaml +++ b/openapi-generator-config.yaml @@ -1,5 +1,5 @@ packageName: ynab -packageVersion: 4.4.1 +packageVersion: 4.5.0 packageDescription: Official Python client for the YNAB API. API documentation available at https://api.ynab.com. licenseInfo: name: Apache-2.0 diff --git a/pyproject.toml b/pyproject.toml index e0acfc1..e9a62f1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "ynab" -version = "4.4.1" -description = "Official Python client for the YNAB API. API documentation available at https://api.ynab.com. Generated from server specification version 1.86.0" +version = "4.5.0" +description = "Official Python client for the YNAB API. API documentation available at https://api.ynab.com. Generated from server specification version 1.88.0" authors = ["YNAB"] license = "Apache-2.0" readme = "README.md" diff --git a/test-requirements.txt b/test-requirements.txt index e98555c..9cb0629 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,4 +1,4 @@ -pytest >= 7.2.1 +pytest >= 9.0.3 pytest-cov >= 2.8.1 tox >= 3.9.0 flake8 >= 4.0.0 diff --git a/ynab/__init__.py b/ynab/__init__.py index 8836c94..49d5fac 100644 --- a/ynab/__init__.py +++ b/ynab/__init__.py @@ -7,14 +7,14 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. """ # noqa: E501 -__version__ = "4.2.0" +__version__ = "4.5.0" # Define package exports __all__ = [ diff --git a/ynab/api/accounts_api.py b/ynab/api/accounts_api.py index d44d9e0..3d395fc 100644 --- a/ynab/api/accounts_api.py +++ b/ynab/api/accounts_api.py @@ -3,7 +3,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -270,7 +270,7 @@ def _create_account_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -289,7 +289,7 @@ def _create_account_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -298,7 +298,7 @@ def _create_account_serialize( # set the HTTP header `Content-Type` if _content_type: - _header_params['Content-Type'] = _content_type + self.api_client._set_header(_header_params, 'Content-Type', _content_type) else: _default_content_type = ( self.api_client.select_header_content_type( @@ -308,7 +308,7 @@ def _create_account_serialize( ) ) if _default_content_type is not None: - _header_params['Content-Type'] = _default_content_type + self.api_client._set_header(_header_params, 'Content-Type', _default_content_type) # authentication setting _auth_settings: List[str] = [ @@ -562,7 +562,7 @@ def _get_account_by_id_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -581,7 +581,7 @@ def _get_account_by_id_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -841,7 +841,7 @@ def _get_accounts_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -862,7 +862,7 @@ def _get_accounts_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' diff --git a/ynab/api/categories_api.py b/ynab/api/categories_api.py index a502a29..ffc6df9 100644 --- a/ynab/api/categories_api.py +++ b/ynab/api/categories_api.py @@ -3,7 +3,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -276,7 +276,7 @@ def _create_category_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -295,7 +295,7 @@ def _create_category_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -304,7 +304,7 @@ def _create_category_serialize( # set the HTTP header `Content-Type` if _content_type: - _header_params['Content-Type'] = _content_type + self.api_client._set_header(_header_params, 'Content-Type', _content_type) else: _default_content_type = ( self.api_client.select_header_content_type( @@ -314,7 +314,7 @@ def _create_category_serialize( ) ) if _default_content_type is not None: - _header_params['Content-Type'] = _default_content_type + self.api_client._set_header(_header_params, 'Content-Type', _default_content_type) # authentication setting _auth_settings: List[str] = [ @@ -568,7 +568,7 @@ def _create_category_group_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -587,7 +587,7 @@ def _create_category_group_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -596,7 +596,7 @@ def _create_category_group_serialize( # set the HTTP header `Content-Type` if _content_type: - _header_params['Content-Type'] = _content_type + self.api_client._set_header(_header_params, 'Content-Type', _content_type) else: _default_content_type = ( self.api_client.select_header_content_type( @@ -606,7 +606,7 @@ def _create_category_group_serialize( ) ) if _default_content_type is not None: - _header_params['Content-Type'] = _default_content_type + self.api_client._set_header(_header_params, 'Content-Type', _default_content_type) # authentication setting _auth_settings: List[str] = [ @@ -860,7 +860,7 @@ def _get_categories_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -881,7 +881,7 @@ def _get_categories_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -1141,7 +1141,7 @@ def _get_category_by_id_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -1160,7 +1160,7 @@ def _get_category_by_id_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -1433,7 +1433,7 @@ def _get_month_category_by_id_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -1454,7 +1454,7 @@ def _get_month_category_by_id_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -1727,7 +1727,7 @@ def _update_category_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -1748,7 +1748,7 @@ def _update_category_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -1757,7 +1757,7 @@ def _update_category_serialize( # set the HTTP header `Content-Type` if _content_type: - _header_params['Content-Type'] = _content_type + self.api_client._set_header(_header_params, 'Content-Type', _content_type) else: _default_content_type = ( self.api_client.select_header_content_type( @@ -1767,7 +1767,7 @@ def _update_category_serialize( ) ) if _default_content_type is not None: - _header_params['Content-Type'] = _default_content_type + self.api_client._set_header(_header_params, 'Content-Type', _default_content_type) # authentication setting _auth_settings: List[str] = [ @@ -2034,7 +2034,7 @@ def _update_category_group_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -2055,7 +2055,7 @@ def _update_category_group_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -2064,7 +2064,7 @@ def _update_category_group_serialize( # set the HTTP header `Content-Type` if _content_type: - _header_params['Content-Type'] = _content_type + self.api_client._set_header(_header_params, 'Content-Type', _content_type) else: _default_content_type = ( self.api_client.select_header_content_type( @@ -2074,7 +2074,7 @@ def _update_category_group_serialize( ) ) if _default_content_type is not None: - _header_params['Content-Type'] = _default_content_type + self.api_client._set_header(_header_params, 'Content-Type', _default_content_type) # authentication setting _auth_settings: List[str] = [ @@ -2354,7 +2354,7 @@ def _update_month_category_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -2377,7 +2377,7 @@ def _update_month_category_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -2386,7 +2386,7 @@ def _update_month_category_serialize( # set the HTTP header `Content-Type` if _content_type: - _header_params['Content-Type'] = _content_type + self.api_client._set_header(_header_params, 'Content-Type', _content_type) else: _default_content_type = ( self.api_client.select_header_content_type( @@ -2396,7 +2396,7 @@ def _update_month_category_serialize( ) ) if _default_content_type is not None: - _header_params['Content-Type'] = _default_content_type + self.api_client._set_header(_header_params, 'Content-Type', _default_content_type) # authentication setting _auth_settings: List[str] = [ diff --git a/ynab/api/money_movements_api.py b/ynab/api/money_movements_api.py index eb3a11a..f207294 100644 --- a/ynab/api/money_movements_api.py +++ b/ynab/api/money_movements_api.py @@ -3,7 +3,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -255,7 +255,7 @@ def _get_money_movement_groups_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -272,7 +272,7 @@ def _get_money_movement_groups_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -532,7 +532,7 @@ def _get_money_movement_groups_by_month_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -551,7 +551,7 @@ def _get_money_movement_groups_by_month_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -798,7 +798,7 @@ def _get_money_movements_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -815,7 +815,7 @@ def _get_money_movements_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -1075,7 +1075,7 @@ def _get_money_movements_by_month_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -1094,7 +1094,7 @@ def _get_money_movements_by_month_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' diff --git a/ynab/api/months_api.py b/ynab/api/months_api.py index fb2717a..b61ca00 100644 --- a/ynab/api/months_api.py +++ b/ynab/api/months_api.py @@ -3,7 +3,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -269,7 +269,7 @@ def _get_plan_month_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -288,7 +288,7 @@ def _get_plan_month_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -548,7 +548,7 @@ def _get_plan_months_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -569,7 +569,7 @@ def _get_plan_months_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' diff --git a/ynab/api/payee_locations_api.py b/ynab/api/payee_locations_api.py index 2277326..b6d944b 100644 --- a/ynab/api/payee_locations_api.py +++ b/ynab/api/payee_locations_api.py @@ -3,7 +3,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -267,7 +267,7 @@ def _get_payee_location_by_id_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -286,7 +286,7 @@ def _get_payee_location_by_id_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -533,7 +533,7 @@ def _get_payee_locations_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -550,7 +550,7 @@ def _get_payee_locations_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -810,7 +810,7 @@ def _get_payee_locations_by_payee_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -829,7 +829,7 @@ def _get_payee_locations_by_payee_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' diff --git a/ynab/api/payees_api.py b/ynab/api/payees_api.py index 99f6189..88762a4 100644 --- a/ynab/api/payees_api.py +++ b/ynab/api/payees_api.py @@ -3,7 +3,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -271,7 +271,7 @@ def _create_payee_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -290,7 +290,7 @@ def _create_payee_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -299,7 +299,7 @@ def _create_payee_serialize( # set the HTTP header `Content-Type` if _content_type: - _header_params['Content-Type'] = _content_type + self.api_client._set_header(_header_params, 'Content-Type', _content_type) else: _default_content_type = ( self.api_client.select_header_content_type( @@ -309,7 +309,7 @@ def _create_payee_serialize( ) ) if _default_content_type is not None: - _header_params['Content-Type'] = _default_content_type + self.api_client._set_header(_header_params, 'Content-Type', _default_content_type) # authentication setting _auth_settings: List[str] = [ @@ -563,7 +563,7 @@ def _get_payee_by_id_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -582,7 +582,7 @@ def _get_payee_by_id_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -842,7 +842,7 @@ def _get_payees_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -863,7 +863,7 @@ def _get_payees_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -1136,7 +1136,7 @@ def _update_payee_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -1157,7 +1157,7 @@ def _update_payee_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -1166,7 +1166,7 @@ def _update_payee_serialize( # set the HTTP header `Content-Type` if _content_type: - _header_params['Content-Type'] = _content_type + self.api_client._set_header(_header_params, 'Content-Type', _content_type) else: _default_content_type = ( self.api_client.select_header_content_type( @@ -1176,7 +1176,7 @@ def _update_payee_serialize( ) ) if _default_content_type is not None: - _header_params['Content-Type'] = _default_content_type + self.api_client._set_header(_header_params, 'Content-Type', _default_content_type) # authentication setting _auth_settings: List[str] = [ diff --git a/ynab/api/plans_api.py b/ynab/api/plans_api.py index e8e62c3..11c87d2 100644 --- a/ynab/api/plans_api.py +++ b/ynab/api/plans_api.py @@ -3,7 +3,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -269,7 +269,7 @@ def _get_plan_by_id_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -290,7 +290,7 @@ def _get_plan_by_id_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -537,7 +537,7 @@ def _get_plan_settings_by_id_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -554,7 +554,7 @@ def _get_plan_settings_by_id_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -801,7 +801,7 @@ def _get_plans_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -820,7 +820,7 @@ def _get_plans_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' diff --git a/ynab/api/scheduled_transactions_api.py b/ynab/api/scheduled_transactions_api.py index 051349a..cc9f58a 100644 --- a/ynab/api/scheduled_transactions_api.py +++ b/ynab/api/scheduled_transactions_api.py @@ -3,7 +3,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -270,7 +270,7 @@ def _create_scheduled_transaction_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -289,7 +289,7 @@ def _create_scheduled_transaction_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -298,7 +298,7 @@ def _create_scheduled_transaction_serialize( # set the HTTP header `Content-Type` if _content_type: - _header_params['Content-Type'] = _content_type + self.api_client._set_header(_header_params, 'Content-Type', _content_type) else: _default_content_type = ( self.api_client.select_header_content_type( @@ -308,7 +308,7 @@ def _create_scheduled_transaction_serialize( ) ) if _default_content_type is not None: - _header_params['Content-Type'] = _default_content_type + self.api_client._set_header(_header_params, 'Content-Type', _default_content_type) # authentication setting _auth_settings: List[str] = [ @@ -562,7 +562,7 @@ def _delete_scheduled_transaction_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -581,7 +581,7 @@ def _delete_scheduled_transaction_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -841,7 +841,7 @@ def _get_scheduled_transaction_by_id_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -860,7 +860,7 @@ def _get_scheduled_transaction_by_id_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -1120,7 +1120,7 @@ def _get_scheduled_transactions_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -1141,7 +1141,7 @@ def _get_scheduled_transactions_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -1414,7 +1414,7 @@ def _update_scheduled_transaction_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -1435,7 +1435,7 @@ def _update_scheduled_transaction_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -1444,7 +1444,7 @@ def _update_scheduled_transaction_serialize( # set the HTTP header `Content-Type` if _content_type: - _header_params['Content-Type'] = _content_type + self.api_client._set_header(_header_params, 'Content-Type', _content_type) else: _default_content_type = ( self.api_client.select_header_content_type( @@ -1454,7 +1454,7 @@ def _update_scheduled_transaction_serialize( ) ) if _default_content_type is not None: - _header_params['Content-Type'] = _default_content_type + self.api_client._set_header(_header_params, 'Content-Type', _default_content_type) # authentication setting _auth_settings: List[str] = [ diff --git a/ynab/api/transactions_api.py b/ynab/api/transactions_api.py index 01366d3..d8b51a6 100644 --- a/ynab/api/transactions_api.py +++ b/ynab/api/transactions_api.py @@ -3,7 +3,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -278,7 +278,7 @@ def _create_transaction_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -297,7 +297,7 @@ def _create_transaction_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -306,7 +306,7 @@ def _create_transaction_serialize( # set the HTTP header `Content-Type` if _content_type: - _header_params['Content-Type'] = _content_type + self.api_client._set_header(_header_params, 'Content-Type', _content_type) else: _default_content_type = ( self.api_client.select_header_content_type( @@ -316,7 +316,7 @@ def _create_transaction_serialize( ) ) if _default_content_type is not None: - _header_params['Content-Type'] = _default_content_type + self.api_client._set_header(_header_params, 'Content-Type', _default_content_type) # authentication setting _auth_settings: List[str] = [ @@ -570,7 +570,7 @@ def _delete_transaction_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -589,7 +589,7 @@ def _delete_transaction_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -849,7 +849,7 @@ def _get_transaction_by_id_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -868,7 +868,7 @@ def _get_transaction_by_id_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -1170,7 +1170,7 @@ def _get_transactions_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -1221,7 +1221,7 @@ def _get_transactions_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -1533,7 +1533,7 @@ def _get_transactions_by_account_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -1586,7 +1586,7 @@ def _get_transactions_by_account_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -1898,7 +1898,7 @@ def _get_transactions_by_category_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -1951,7 +1951,7 @@ def _get_transactions_by_category_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -2263,7 +2263,7 @@ def _get_transactions_by_month_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -2316,7 +2316,7 @@ def _get_transactions_by_month_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -2628,7 +2628,7 @@ def _get_transactions_by_payee_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -2681,7 +2681,7 @@ def _get_transactions_by_payee_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -2729,9 +2729,9 @@ def import_transactions( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> TransactionsImportResponse: - """Import transactions + """(Deprecated) Import transactions - Imports available transactions on all linked accounts for the given plan. Linked accounts allow transactions to be imported directly from a specified financial institution and this endpoint initiates that import. Sending a request to this endpoint is the equivalent of clicking \"Import\" on each account in the web application or tapping the \"New Transactions\" banner in the mobile applications. The response for this endpoint contains the transaction ids that have been imported. + DEPRECATED: This endpoint is no longer needed because YNAB now automatically imports transactions on linked accounts. Requests are still accepted for backwards compatibility but no import is performed and the response will always contain an empty list of transaction ids. :param plan_id: The id of the plan. \"last-used\" can be used to specify the last used plan and \"default\" can be used if default plan selection is enabled (see: https://api.ynab.com/#oauth-default-plan). (required) :type plan_id: str @@ -2756,6 +2756,7 @@ def import_transactions( :type _host_index: int, optional :return: Returns the result object. """ # noqa: E501 + warnings.warn("POST /plans/{plan_id}/transactions/import is deprecated.", DeprecationWarning) _param = self._import_transactions_serialize( plan_id=plan_id, @@ -2767,7 +2768,6 @@ def import_transactions( _response_types_map: Dict[str, Optional[str]] = { '200': "TransactionsImportResponse", - '201': "TransactionsImportResponse", '400': "ErrorResponse", } response_data = self.api_client.call_api( @@ -2798,9 +2798,9 @@ def import_transactions_with_http_info( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> ApiResponse[TransactionsImportResponse]: - """Import transactions + """(Deprecated) Import transactions - Imports available transactions on all linked accounts for the given plan. Linked accounts allow transactions to be imported directly from a specified financial institution and this endpoint initiates that import. Sending a request to this endpoint is the equivalent of clicking \"Import\" on each account in the web application or tapping the \"New Transactions\" banner in the mobile applications. The response for this endpoint contains the transaction ids that have been imported. + DEPRECATED: This endpoint is no longer needed because YNAB now automatically imports transactions on linked accounts. Requests are still accepted for backwards compatibility but no import is performed and the response will always contain an empty list of transaction ids. :param plan_id: The id of the plan. \"last-used\" can be used to specify the last used plan and \"default\" can be used if default plan selection is enabled (see: https://api.ynab.com/#oauth-default-plan). (required) :type plan_id: str @@ -2825,6 +2825,7 @@ def import_transactions_with_http_info( :type _host_index: int, optional :return: Returns the result object. """ # noqa: E501 + warnings.warn("POST /plans/{plan_id}/transactions/import is deprecated.", DeprecationWarning) _param = self._import_transactions_serialize( plan_id=plan_id, @@ -2836,7 +2837,6 @@ def import_transactions_with_http_info( _response_types_map: Dict[str, Optional[str]] = { '200': "TransactionsImportResponse", - '201': "TransactionsImportResponse", '400': "ErrorResponse", } response_data = self.api_client.call_api( @@ -2867,9 +2867,9 @@ def import_transactions_without_preload_content( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> RESTResponseType: - """Import transactions + """(Deprecated) Import transactions - Imports available transactions on all linked accounts for the given plan. Linked accounts allow transactions to be imported directly from a specified financial institution and this endpoint initiates that import. Sending a request to this endpoint is the equivalent of clicking \"Import\" on each account in the web application or tapping the \"New Transactions\" banner in the mobile applications. The response for this endpoint contains the transaction ids that have been imported. + DEPRECATED: This endpoint is no longer needed because YNAB now automatically imports transactions on linked accounts. Requests are still accepted for backwards compatibility but no import is performed and the response will always contain an empty list of transaction ids. :param plan_id: The id of the plan. \"last-used\" can be used to specify the last used plan and \"default\" can be used if default plan selection is enabled (see: https://api.ynab.com/#oauth-default-plan). (required) :type plan_id: str @@ -2894,6 +2894,7 @@ def import_transactions_without_preload_content( :type _host_index: int, optional :return: Returns the result object. """ # noqa: E501 + warnings.warn("POST /plans/{plan_id}/transactions/import is deprecated.", DeprecationWarning) _param = self._import_transactions_serialize( plan_id=plan_id, @@ -2905,7 +2906,6 @@ def import_transactions_without_preload_content( _response_types_map: Dict[str, Optional[str]] = { '200': "TransactionsImportResponse", - '201': "TransactionsImportResponse", '400': "ErrorResponse", } response_data = self.api_client.call_api( @@ -2931,7 +2931,7 @@ def _import_transactions_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -2948,7 +2948,7 @@ def _import_transactions_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -3221,7 +3221,7 @@ def _update_transaction_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -3242,7 +3242,7 @@ def _update_transaction_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -3251,7 +3251,7 @@ def _update_transaction_serialize( # set the HTTP header `Content-Type` if _content_type: - _header_params['Content-Type'] = _content_type + self.api_client._set_header(_header_params, 'Content-Type', _content_type) else: _default_content_type = ( self.api_client.select_header_content_type( @@ -3261,7 +3261,7 @@ def _update_transaction_serialize( ) ) if _default_content_type is not None: - _header_params['Content-Type'] = _default_content_type + self.api_client._set_header(_header_params, 'Content-Type', _default_content_type) # authentication setting _auth_settings: List[str] = [ @@ -3515,7 +3515,7 @@ def _update_transactions_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -3534,7 +3534,7 @@ def _update_transactions_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' @@ -3543,7 +3543,7 @@ def _update_transactions_serialize( # set the HTTP header `Content-Type` if _content_type: - _header_params['Content-Type'] = _content_type + self.api_client._set_header(_header_params, 'Content-Type', _content_type) else: _default_content_type = ( self.api_client.select_header_content_type( @@ -3553,7 +3553,7 @@ def _update_transactions_serialize( ) ) if _default_content_type is not None: - _header_params['Content-Type'] = _default_content_type + self.api_client._set_header(_header_params, 'Content-Type', _default_content_type) # authentication setting _auth_settings: List[str] = [ diff --git a/ynab/api/user_api.py b/ynab/api/user_api.py index 5623b90..c52e567 100644 --- a/ynab/api/user_api.py +++ b/ynab/api/user_api.py @@ -3,7 +3,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -235,7 +235,7 @@ def _get_user_serialize( _path_params: Dict[str, str] = {} _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} + _header_params: Dict[str, Any] = self.api_client._merge_headers(_headers) _form_params: List[Tuple[str, str]] = [] _files: Dict[ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] @@ -250,7 +250,7 @@ def _get_user_serialize( # set the HTTP header `Accept` - if 'Accept' not in _header_params: + if not any(key.lower() == 'accept' for key in _header_params): _header_params['Accept'] = self.api_client.select_header_accept( [ 'application/json' diff --git a/ynab/api_client.py b/ynab/api_client.py index dd23f2e..3d06d5f 100644 --- a/ynab/api_client.py +++ b/ynab/api_client.py @@ -3,7 +3,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -23,7 +23,7 @@ import uuid from urllib.parse import quote -from typing import Tuple, Optional, List, Dict, Union +from typing import Any, Tuple, Optional, List, Dict, Union from pydantic import SecretStr from ynab.configuration import Configuration @@ -91,7 +91,7 @@ def __init__( self.default_headers[header_name] = header_value self.cookie = cookie # Set default User-Agent. - self.user_agent = 'OpenAPI-Generator/4.2.0/python' + self.user_agent = 'OpenAPI-Generator/4.5.0/python' self.client_side_validation = configuration.client_side_validation def __enter__(self): @@ -103,16 +103,36 @@ def __exit__(self, exc_type, exc_value, traceback): @property def user_agent(self): """User agent for this API client""" - return self.default_headers['User-Agent'] + for name, value in reversed(self.default_headers.items()): + if name.lower() == 'user-agent': + return value + raise KeyError('User-Agent') @user_agent.setter def user_agent(self, value): - self.default_headers['User-Agent'] = value + self._set_header(self.default_headers, 'User-Agent', value) def set_default_header(self, header_name, header_value): - self.default_headers[header_name] = header_value + self._set_header(self.default_headers, header_name, header_value) + @staticmethod + def _set_header(headers: Dict[str, Any], name: str, value: Any) -> None: + """Replace a header case-insensitively, retaining the winning spelling.""" + for key in list(headers): + if key.lower() == name.lower(): + del headers[key] + headers[name] = value + + @classmethod + def _merge_headers(cls, *sources: Optional[Dict[str, Any]]) -> Dict[str, Any]: + """Copy headers; later sources and later entries in each dict win.""" + headers: Dict[str, Any] = {} + for source in sources: + for name, value in (source or {}).items(): + cls._set_header(headers, name, value) + return headers + _default = None @classmethod @@ -179,10 +199,9 @@ def param_serialize( config = self.configuration # header parameters - header_params = header_params or {} - header_params.update(self.default_headers) + header_params = self._merge_headers(header_params, self.default_headers) if self.cookie: - header_params['Cookie'] = self.cookie + self._set_header(header_params, 'Cookie', self.cookie) if header_params: header_params = self.sanitize_for_serialization(header_params) header_params = dict( @@ -247,7 +266,6 @@ def param_serialize( return method, url, header_params, body, post_params - def call_api( self, method, @@ -302,6 +320,12 @@ def response_deserialize( # if not found, look for '1XX', '2XX', etc. response_type = response_types_map.get(str(response_data.status)[0] + "XX", None) + # If the response_type has not matched (eg. did not match the previous if statements) and the default response is available, use it. + if response_type is None and str(response_data.status) not in response_types_map \ + and (not isinstance(response_data.status, int) or not 100 <= response_data.status <= 599 or str(response_data.status)[0] + "XX" not in response_types_map) \ + and 'default' in response_types_map: + response_type = response_types_map['default'] + # deserialize response data response_text = None return_data = None @@ -434,6 +458,12 @@ def __deserialize(self, data, klass): return None if isinstance(klass, str): + if klass.startswith('Optional['): + m = re.match(r'Optional\[(.*)]', klass) + assert m is not None, "Malformed Optional type definition" + # data is not None here, so the optionality is already resolved + return self.__deserialize(data, m.group(1)) + if klass.startswith('List['): m = re.match(r'List\[(.*)]', klass) assert m is not None, "Malformed List type definition" @@ -482,10 +512,15 @@ def parameters_to_tuples(self, params, collection_formats): if collection_formats is None: collection_formats = {} for k, v in params.items() if isinstance(params, dict) else params: + if isinstance(v, bool): + v = str(v).lower() if k in collection_formats: collection_format = collection_formats[k] if collection_format == 'multi': - new_params.extend((k, value) for value in v) + new_params.extend( + (k, str(value).lower() if isinstance(value, bool) else value) + for value in v + ) else: if collection_format == 'ssv': delimiter = ' ' @@ -496,11 +531,20 @@ def parameters_to_tuples(self, params, collection_formats): else: # csv is the default delimiter = ',' new_params.append( - (k, delimiter.join(str(value) for value in v))) + (k, delimiter.join( + str(value).lower() if isinstance(value, bool) else str(value) + for value in v))) else: new_params.append((k, v)) return new_params + def explode_query_object(self, name, obj): + """form style, explode: one query parameter per entry, keyed by the property name; a list repeats the name, None is left out""" + obj = self.sanitize_for_serialization(obj) + if not isinstance(obj, dict): + obj = {name: obj} + return [(k, item) for k, v in obj.items() for item in (v if isinstance(v, (list, tuple)) else [v]) if item is not None] + def parameters_to_url_query(self, params, collection_formats): """Get parameters as list of tuples, formatting collections. @@ -519,10 +563,14 @@ def parameters_to_url_query(self, params, collection_formats): if isinstance(v, dict): v = json.dumps(v) - if k in collection_formats: + # a collection format applies only to a list; an exploded entry may share a declared array parameter's name + if k in collection_formats and isinstance(v, (list, tuple)): collection_format = collection_formats[k] if collection_format == 'multi': - new_params.extend((k, quote(str(value))) for value in v) + new_params.extend( + (quote(str(k)), quote(str(value).lower() if isinstance(value, bool) else str(value))) + for value in v + ) else: if collection_format == 'ssv': delimiter = ' ' @@ -533,10 +581,13 @@ def parameters_to_url_query(self, params, collection_formats): else: # csv is the default delimiter = ',' new_params.append( - (k, delimiter.join(quote(str(value)) for value in v)) + (quote(str(k)), delimiter.join( + quote(str(value).lower() if isinstance(value, bool) else str(value)) + for value in v)) ) else: - new_params.append((k, quote(str(v)))) + # names are quoted too: an exploded object's names are runtime data + new_params.append((quote(str(k)), quote(str(v)))) return "&".join(["=".join(map(str, item)) for item in new_params]) @@ -672,10 +723,20 @@ def _apply_auth_params( :param auth_setting: auth settings for the endpoint """ if auth_setting['in'] == 'cookie': - headers['Cookie'] = auth_setting['value'] + for key in list(headers): + if key.lower() == 'cookie': + self._set_header(headers, 'Cookie', headers[key]) + break + if not headers.get('Cookie'): + headers['Cookie'] = "" + else: + headers['Cookie'] += "; " + # Account for cookie value containing spaces and special characters, excluding base64 delimiters + cookie_value = quote(str(auth_setting['value']), safe="!#$%&'()*+-./:<=>?@[]^_`{|}~%+/=") + headers['Cookie'] += f"{auth_setting['key']}={cookie_value}" elif auth_setting['in'] == 'header': if auth_setting['type'] != 'http-signature': - headers[auth_setting['key']] = auth_setting['value'] + self._set_header(headers, auth_setting['key'], auth_setting['value']) elif auth_setting['in'] == 'query': queries.append((auth_setting['key'], auth_setting['value'])) else: diff --git a/ynab/configuration.py b/ynab/configuration.py index ec85ec6..1abf999 100644 --- a/ynab/configuration.py +++ b/ynab/configuration.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -504,8 +504,8 @@ def to_debug_report(self) -> str: return "Python SDK Debug Report:\n"\ "OS: {env}\n"\ "Python Version: {pyversion}\n"\ - "Version of the API: 1.86.0\n"\ - "SDK Package Version: 4.2.0".\ + "Version of the API: 1.88.0\n"\ + "SDK Package Version: 4.5.0".\ format(env=sys.platform, pyversion=sys.version) def get_host_settings(self) -> List[HostSetting]: diff --git a/ynab/exceptions.py b/ynab/exceptions.py index f052beb..ebb89ec 100644 --- a/ynab/exceptions.py +++ b/ynab/exceptions.py @@ -3,7 +3,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/__init__.py b/ynab/models/__init__.py index ddef04d..4e74801 100644 --- a/ynab/models/__init__.py +++ b/ynab/models/__init__.py @@ -6,7 +6,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/account.py b/ynab/models/account.py index 4291a8c..7dd9a1d 100644 --- a/ynab/models/account.py +++ b/ynab/models/account.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -39,7 +39,7 @@ class Account(BaseModel): balance: StrictInt = Field(description="The current available balance of the account in milliunits format") cleared_balance: StrictInt = Field(description="The current cleared balance of the account in milliunits format") uncleared_balance: StrictInt = Field(description="The current uncleared balance of the account in milliunits format") - transfer_payee_id: UUID = Field(description="The payee id which should be used when transferring to this account") + transfer_payee_id: Optional[UUID] = Field(description="The payee id which should be used when transferring to this account") direct_import_linked: Optional[StrictBool] = Field(default=None, description="Whether or not the account is linked to a financial institution for automatic transaction import.") direct_import_in_error: Optional[StrictBool] = Field(default=None, description="If an account linked to a financial institution (direct_import_linked=true) and the linked connection is not in a healthy state, this will be true.") last_reconciled_at: Optional[datetime] = Field(default=None, description="A date/time specifying when the account was last reconciled.") @@ -95,6 +95,41 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if note (nullable) is None + # and model_fields_set contains the field + if self.note is None and "note" in self.model_fields_set: + _dict['note'] = None + + # set to None if transfer_payee_id (nullable) is None + # and model_fields_set contains the field + if self.transfer_payee_id is None and "transfer_payee_id" in self.model_fields_set: + _dict['transfer_payee_id'] = None + + # set to None if last_reconciled_at (nullable) is None + # and model_fields_set contains the field + if self.last_reconciled_at is None and "last_reconciled_at" in self.model_fields_set: + _dict['last_reconciled_at'] = None + + # set to None if debt_original_balance (nullable) is None + # and model_fields_set contains the field + if self.debt_original_balance is None and "debt_original_balance" in self.model_fields_set: + _dict['debt_original_balance'] = None + + # set to None if debt_interest_rates (nullable) is None + # and model_fields_set contains the field + if self.debt_interest_rates is None and "debt_interest_rates" in self.model_fields_set: + _dict['debt_interest_rates'] = None + + # set to None if debt_minimum_payments (nullable) is None + # and model_fields_set contains the field + if self.debt_minimum_payments is None and "debt_minimum_payments" in self.model_fields_set: + _dict['debt_minimum_payments'] = None + + # set to None if debt_escrow_amounts (nullable) is None + # and model_fields_set contains the field + if self.debt_escrow_amounts is None and "debt_escrow_amounts" in self.model_fields_set: + _dict['debt_escrow_amounts'] = None + return _dict @classmethod diff --git a/ynab/models/account_base.py b/ynab/models/account_base.py index 36ff1c4..96cfbc3 100644 --- a/ynab/models/account_base.py +++ b/ynab/models/account_base.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -109,6 +109,21 @@ def to_dict(self) -> Dict[str, Any]: if self.debt_original_balance is None and "debt_original_balance" in self.model_fields_set: _dict['debt_original_balance'] = None + # set to None if debt_interest_rates (nullable) is None + # and model_fields_set contains the field + if self.debt_interest_rates is None and "debt_interest_rates" in self.model_fields_set: + _dict['debt_interest_rates'] = None + + # set to None if debt_minimum_payments (nullable) is None + # and model_fields_set contains the field + if self.debt_minimum_payments is None and "debt_minimum_payments" in self.model_fields_set: + _dict['debt_minimum_payments'] = None + + # set to None if debt_escrow_amounts (nullable) is None + # and model_fields_set contains the field + if self.debt_escrow_amounts is None and "debt_escrow_amounts" in self.model_fields_set: + _dict['debt_escrow_amounts'] = None + return _dict @classmethod diff --git a/ynab/models/account_response.py b/ynab/models/account_response.py index d466de7..fa3ec0c 100644 --- a/ynab/models/account_response.py +++ b/ynab/models/account_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/account_response_data.py b/ynab/models/account_response_data.py index 97f2e71..8d5f8a1 100644 --- a/ynab/models/account_response_data.py +++ b/ynab/models/account_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/account_type.py b/ynab/models/account_type.py index 4412232..ae138cf 100644 --- a/ynab/models/account_type.py +++ b/ynab/models/account_type.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/accounts_response.py b/ynab/models/accounts_response.py index dcb2a7b..7f38466 100644 --- a/ynab/models/accounts_response.py +++ b/ynab/models/accounts_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/accounts_response_data.py b/ynab/models/accounts_response_data.py index c547428..c9ece93 100644 --- a/ynab/models/accounts_response_data.py +++ b/ynab/models/accounts_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -75,8 +75,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.accounts: for _item_accounts in self.accounts: - if _item_accounts: - _items.append(_item_accounts.to_dict()) + _items.append(_item_accounts.to_dict() if _item_accounts is not None else None) _dict['accounts'] = _items return _dict diff --git a/ynab/models/bulk_response.py b/ynab/models/bulk_response.py index ddf5f6b..a7438f0 100644 --- a/ynab/models/bulk_response.py +++ b/ynab/models/bulk_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/bulk_response_data.py b/ynab/models/bulk_response_data.py index 8cf14d1..ac9ab35 100644 --- a/ynab/models/bulk_response_data.py +++ b/ynab/models/bulk_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/bulk_response_data_bulk.py b/ynab/models/bulk_response_data_bulk.py index 45de9b2..a1b7871 100644 --- a/ynab/models/bulk_response_data_bulk.py +++ b/ynab/models/bulk_response_data_bulk.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/bulk_transactions.py b/ynab/models/bulk_transactions.py index 8926e09..571f268 100644 --- a/ynab/models/bulk_transactions.py +++ b/ynab/models/bulk_transactions.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -74,8 +74,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.transactions: for _item_transactions in self.transactions: - if _item_transactions: - _items.append(_item_transactions.to_dict()) + _items.append(_item_transactions.to_dict() if _item_transactions is not None else None) _dict['transactions'] = _items return _dict diff --git a/ynab/models/categories_response.py b/ynab/models/categories_response.py index 311621c..c952aea 100644 --- a/ynab/models/categories_response.py +++ b/ynab/models/categories_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/categories_response_data.py b/ynab/models/categories_response_data.py index a8252ca..749f6c8 100644 --- a/ynab/models/categories_response_data.py +++ b/ynab/models/categories_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -75,8 +75,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.category_groups: for _item_category_groups in self.category_groups: - if _item_category_groups: - _items.append(_item_category_groups.to_dict()) + _items.append(_item_category_groups.to_dict() if _item_category_groups is not None else None) _dict['category_groups'] = _items return _dict diff --git a/ynab/models/category.py b/ynab/models/category.py index 8053968..1b0b4a7 100644 --- a/ynab/models/category.py +++ b/ynab/models/category.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -121,11 +121,91 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if original_category_group_id (nullable) is None + # and model_fields_set contains the field + if self.original_category_group_id is None and "original_category_group_id" in self.model_fields_set: + _dict['original_category_group_id'] = None + + # set to None if note (nullable) is None + # and model_fields_set contains the field + if self.note is None and "note" in self.model_fields_set: + _dict['note'] = None + # set to None if goal_type (nullable) is None # and model_fields_set contains the field if self.goal_type is None and "goal_type" in self.model_fields_set: _dict['goal_type'] = None + # set to None if goal_needs_whole_amount (nullable) is None + # and model_fields_set contains the field + if self.goal_needs_whole_amount is None and "goal_needs_whole_amount" in self.model_fields_set: + _dict['goal_needs_whole_amount'] = None + + # set to None if goal_day (nullable) is None + # and model_fields_set contains the field + if self.goal_day is None and "goal_day" in self.model_fields_set: + _dict['goal_day'] = None + + # set to None if goal_cadence (nullable) is None + # and model_fields_set contains the field + if self.goal_cadence is None and "goal_cadence" in self.model_fields_set: + _dict['goal_cadence'] = None + + # set to None if goal_cadence_frequency (nullable) is None + # and model_fields_set contains the field + if self.goal_cadence_frequency is None and "goal_cadence_frequency" in self.model_fields_set: + _dict['goal_cadence_frequency'] = None + + # set to None if goal_creation_month (nullable) is None + # and model_fields_set contains the field + if self.goal_creation_month is None and "goal_creation_month" in self.model_fields_set: + _dict['goal_creation_month'] = None + + # set to None if goal_target (nullable) is None + # and model_fields_set contains the field + if self.goal_target is None and "goal_target" in self.model_fields_set: + _dict['goal_target'] = None + + # set to None if goal_target_month (nullable) is None + # and model_fields_set contains the field + if self.goal_target_month is None and "goal_target_month" in self.model_fields_set: + _dict['goal_target_month'] = None + + # set to None if goal_target_date (nullable) is None + # and model_fields_set contains the field + if self.goal_target_date is None and "goal_target_date" in self.model_fields_set: + _dict['goal_target_date'] = None + + # set to None if goal_percentage_complete (nullable) is None + # and model_fields_set contains the field + if self.goal_percentage_complete is None and "goal_percentage_complete" in self.model_fields_set: + _dict['goal_percentage_complete'] = None + + # set to None if goal_months_to_budget (nullable) is None + # and model_fields_set contains the field + if self.goal_months_to_budget is None and "goal_months_to_budget" in self.model_fields_set: + _dict['goal_months_to_budget'] = None + + # set to None if goal_under_funded (nullable) is None + # and model_fields_set contains the field + if self.goal_under_funded is None and "goal_under_funded" in self.model_fields_set: + _dict['goal_under_funded'] = None + + # set to None if goal_overall_funded (nullable) is None + # and model_fields_set contains the field + if self.goal_overall_funded is None and "goal_overall_funded" in self.model_fields_set: + _dict['goal_overall_funded'] = None + + # set to None if goal_overall_left (nullable) is None + # and model_fields_set contains the field + if self.goal_overall_left is None and "goal_overall_left" in self.model_fields_set: + _dict['goal_overall_left'] = None + + # set to None if goal_snoozed_at (nullable) is None + # and model_fields_set contains the field + if self.goal_snoozed_at is None and "goal_snoozed_at" in self.model_fields_set: + _dict['goal_snoozed_at'] = None + # set to None if goal_target_formatted (nullable) is None # and model_fields_set contains the field if self.goal_target_formatted is None and "goal_target_formatted" in self.model_fields_set: diff --git a/ynab/models/category_base.py b/ynab/models/category_base.py index 4685eb3..c4239b8 100644 --- a/ynab/models/category_base.py +++ b/ynab/models/category_base.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/category_group.py b/ynab/models/category_group.py index 54f8bb2..85a8e34 100644 --- a/ynab/models/category_group.py +++ b/ynab/models/category_group.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/category_group_with_categories.py b/ynab/models/category_group_with_categories.py index 67c1ef5..c73dba1 100644 --- a/ynab/models/category_group_with_categories.py +++ b/ynab/models/category_group_with_categories.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -80,8 +80,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.categories: for _item_categories in self.categories: - if _item_categories: - _items.append(_item_categories.to_dict()) + _items.append(_item_categories.to_dict() if _item_categories is not None else None) _dict['categories'] = _items return _dict diff --git a/ynab/models/category_response.py b/ynab/models/category_response.py index 8311148..44cf0c9 100644 --- a/ynab/models/category_response.py +++ b/ynab/models/category_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/category_response_data.py b/ynab/models/category_response_data.py index 6d4fc1e..e5a43df 100644 --- a/ynab/models/category_response_data.py +++ b/ynab/models/category_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/currency_format.py b/ynab/models/currency_format.py index 327670b..fa8c405 100644 --- a/ynab/models/currency_format.py +++ b/ynab/models/currency_format.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/date_format.py b/ynab/models/date_format.py index 8481b1e..227b10b 100644 --- a/ynab/models/date_format.py +++ b/ynab/models/date_format.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/error_detail.py b/ynab/models/error_detail.py index 7242496..b72a614 100644 --- a/ynab/models/error_detail.py +++ b/ynab/models/error_detail.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/error_response.py b/ynab/models/error_response.py index ba405ad..251075a 100644 --- a/ynab/models/error_response.py +++ b/ynab/models/error_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/existing_category.py b/ynab/models/existing_category.py index f827ea8..e96b994 100644 --- a/ynab/models/existing_category.py +++ b/ynab/models/existing_category.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -32,10 +32,10 @@ class ExistingCategory(BaseModel): name: Optional[StrictStr] = None note: Optional[StrictStr] = None category_group_id: Optional[UUID] = Field(default=None, description="The id of the category group to which this category belongs. An internal category group may not be specified.") - goal_target: Optional[StrictInt] = Field(default=None, description="The goal target amount in milliunits format. If value is specified and goal has not already been configured for category, a monthly goal will be created for the category with this target amount. If goal_type is not specified, it will default to 'NEED' or 'MF' for Credit Card Payment categories. When updating a category, passing null removes any existing target.") - goal_target_date: Optional[date] = Field(default=None, description="The goal target date in ISO format (e.g. 2016-12-01).") - goal_needs_whole_amount: Optional[StrictBool] = Field(default=None, description="Whether the goal requires the full target amount each period. Only supported for 'NEED' goals. When true, the goal is configured as 'Set aside another...'. When false, the goal is configured as 'Refill up to...'.") - goal_frequency: Optional[StrictStr] = Field(default=None, description="When specified, configures a recurring 'NEED' target of goal_target that repeats at this frequency, replacing any existing target. Requires goal_target. Cannot be combined with goal_target_date and is not supported for Credit Card Payment categories. Omit to leave an existing target's cadence unchanged.") + goal_target: Optional[StrictInt] = Field(default=None, description="The goal target amount in milliunits format. If value is specified and goal has not already been configured for category, a monthly goal will be created for the category with this target amount. If goal_type is not specified, it will default to 'NEED', or to 'MF' for Credit Card Payment categories and 'DEBT' for categories paired to a loan account. When updating a category, passing null removes any existing target.") + goal_target_date: Optional[date] = Field(default=None, description="The goal target date in ISO format (e.g. 2016-12-01). Not supported for categories paired to a loan account.") + goal_needs_whole_amount: Optional[StrictBool] = Field(default=None, description="Whether the goal requires the full target amount each period. Only supported for 'NEED' goals, and not supported for Credit Card Payment categories or categories paired to a loan account. When true, the goal is configured as 'Set aside another...'. When false, the goal is configured as 'Refill up to...'.") + goal_frequency: Optional[StrictStr] = Field(default=None, description="When specified, configures a recurring 'NEED' target of goal_target that repeats at this frequency, replacing any existing target. Requires goal_target. Cannot be combined with goal_target_date and is not supported for Credit Card Payment categories or categories paired to a loan account. Omit to leave an existing target's cadence unchanged.") __properties: ClassVar[List[str]] = ["name", "note", "category_group_id", "goal_target", "goal_target_date", "goal_needs_whole_amount", "goal_frequency"] @field_validator('goal_frequency') @@ -87,6 +87,31 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if name (nullable) is None + # and model_fields_set contains the field + if self.name is None and "name" in self.model_fields_set: + _dict['name'] = None + + # set to None if note (nullable) is None + # and model_fields_set contains the field + if self.note is None and "note" in self.model_fields_set: + _dict['note'] = None + + # set to None if goal_target (nullable) is None + # and model_fields_set contains the field + if self.goal_target is None and "goal_target" in self.model_fields_set: + _dict['goal_target'] = None + + # set to None if goal_target_date (nullable) is None + # and model_fields_set contains the field + if self.goal_target_date is None and "goal_target_date" in self.model_fields_set: + _dict['goal_target_date'] = None + + # set to None if goal_needs_whole_amount (nullable) is None + # and model_fields_set contains the field + if self.goal_needs_whole_amount is None and "goal_needs_whole_amount" in self.model_fields_set: + _dict['goal_needs_whole_amount'] = None + return _dict @classmethod diff --git a/ynab/models/existing_transaction.py b/ynab/models/existing_transaction.py index 527f955..3671e29 100644 --- a/ynab/models/existing_transaction.py +++ b/ynab/models/existing_transaction.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -43,7 +43,7 @@ class ExistingTransaction(BaseModel): cleared: Optional[TransactionClearedStatus] = None approved: Optional[StrictBool] = Field(default=None, description="Whether or not the transaction is approved. If not supplied, transaction will be unapproved by default.") flag_color: Optional[TransactionFlagColor] = None - subtransactions: Optional[List[SaveSubTransaction]] = Field(default=None, description="An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported.") + subtransactions: Optional[List[SaveSubTransaction]] = Field(default=None, description="An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported and will return an error. Splits are not allowed on tracking accounts or on transfers between on-budget accounts; a transfer to a tracking account can be a split.") __properties: ClassVar[List[str]] = ["account_id", "date", "amount", "payee_id", "payee_name", "category_id", "memo", "cleared", "approved", "flag_color", "subtransactions"] model_config = ConfigDict( @@ -89,9 +89,28 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.subtransactions: for _item_subtransactions in self.subtransactions: - if _item_subtransactions: - _items.append(_item_subtransactions.to_dict()) + _items.append(_item_subtransactions.to_dict() if _item_subtransactions is not None else None) _dict['subtransactions'] = _items + # set to None if payee_id (nullable) is None + # and model_fields_set contains the field + if self.payee_id is None and "payee_id" in self.model_fields_set: + _dict['payee_id'] = None + + # set to None if payee_name (nullable) is None + # and model_fields_set contains the field + if self.payee_name is None and "payee_name" in self.model_fields_set: + _dict['payee_name'] = None + + # set to None if category_id (nullable) is None + # and model_fields_set contains the field + if self.category_id is None and "category_id" in self.model_fields_set: + _dict['category_id'] = None + + # set to None if memo (nullable) is None + # and model_fields_set contains the field + if self.memo is None and "memo" in self.model_fields_set: + _dict['memo'] = None + # set to None if flag_color (nullable) is None # and model_fields_set contains the field if self.flag_color is None and "flag_color" in self.model_fields_set: diff --git a/ynab/models/hybrid_transaction.py b/ynab/models/hybrid_transaction.py index 32a0938..6964d10 100644 --- a/ynab/models/hybrid_transaction.py +++ b/ynab/models/hybrid_transaction.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -115,11 +115,61 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if memo (nullable) is None + # and model_fields_set contains the field + if self.memo is None and "memo" in self.model_fields_set: + _dict['memo'] = None + # set to None if flag_color (nullable) is None # and model_fields_set contains the field if self.flag_color is None and "flag_color" in self.model_fields_set: _dict['flag_color'] = None + # set to None if flag_name (nullable) is None + # and model_fields_set contains the field + if self.flag_name is None and "flag_name" in self.model_fields_set: + _dict['flag_name'] = None + + # set to None if payee_id (nullable) is None + # and model_fields_set contains the field + if self.payee_id is None and "payee_id" in self.model_fields_set: + _dict['payee_id'] = None + + # set to None if category_id (nullable) is None + # and model_fields_set contains the field + if self.category_id is None and "category_id" in self.model_fields_set: + _dict['category_id'] = None + + # set to None if transfer_account_id (nullable) is None + # and model_fields_set contains the field + if self.transfer_account_id is None and "transfer_account_id" in self.model_fields_set: + _dict['transfer_account_id'] = None + + # set to None if transfer_transaction_id (nullable) is None + # and model_fields_set contains the field + if self.transfer_transaction_id is None and "transfer_transaction_id" in self.model_fields_set: + _dict['transfer_transaction_id'] = None + + # set to None if matched_transaction_id (nullable) is None + # and model_fields_set contains the field + if self.matched_transaction_id is None and "matched_transaction_id" in self.model_fields_set: + _dict['matched_transaction_id'] = None + + # set to None if import_id (nullable) is None + # and model_fields_set contains the field + if self.import_id is None and "import_id" in self.model_fields_set: + _dict['import_id'] = None + + # set to None if import_payee_name (nullable) is None + # and model_fields_set contains the field + if self.import_payee_name is None and "import_payee_name" in self.model_fields_set: + _dict['import_payee_name'] = None + + # set to None if import_payee_name_original (nullable) is None + # and model_fields_set contains the field + if self.import_payee_name_original is None and "import_payee_name_original" in self.model_fields_set: + _dict['import_payee_name_original'] = None + # set to None if debt_transaction_type (nullable) is None # and model_fields_set contains the field if self.debt_transaction_type is None and "debt_transaction_type" in self.model_fields_set: diff --git a/ynab/models/hybrid_transactions_response.py b/ynab/models/hybrid_transactions_response.py index 1aa230d..c661ced 100644 --- a/ynab/models/hybrid_transactions_response.py +++ b/ynab/models/hybrid_transactions_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/hybrid_transactions_response_data.py b/ynab/models/hybrid_transactions_response_data.py index 042ca50..27de96e 100644 --- a/ynab/models/hybrid_transactions_response_data.py +++ b/ynab/models/hybrid_transactions_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -75,8 +75,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.transactions: for _item_transactions in self.transactions: - if _item_transactions: - _items.append(_item_transactions.to_dict()) + _items.append(_item_transactions.to_dict() if _item_transactions is not None else None) _dict['transactions'] = _items return _dict diff --git a/ynab/models/money_movement.py b/ynab/models/money_movement.py index 5c44ae7..5c282c4 100644 --- a/ynab/models/money_movement.py +++ b/ynab/models/money_movement.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -81,6 +81,41 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if month (nullable) is None + # and model_fields_set contains the field + if self.month is None and "month" in self.model_fields_set: + _dict['month'] = None + + # set to None if moved_at (nullable) is None + # and model_fields_set contains the field + if self.moved_at is None and "moved_at" in self.model_fields_set: + _dict['moved_at'] = None + + # set to None if note (nullable) is None + # and model_fields_set contains the field + if self.note is None and "note" in self.model_fields_set: + _dict['note'] = None + + # set to None if money_movement_group_id (nullable) is None + # and model_fields_set contains the field + if self.money_movement_group_id is None and "money_movement_group_id" in self.model_fields_set: + _dict['money_movement_group_id'] = None + + # set to None if performed_by_user_id (nullable) is None + # and model_fields_set contains the field + if self.performed_by_user_id is None and "performed_by_user_id" in self.model_fields_set: + _dict['performed_by_user_id'] = None + + # set to None if from_category_id (nullable) is None + # and model_fields_set contains the field + if self.from_category_id is None and "from_category_id" in self.model_fields_set: + _dict['from_category_id'] = None + + # set to None if to_category_id (nullable) is None + # and model_fields_set contains the field + if self.to_category_id is None and "to_category_id" in self.model_fields_set: + _dict['to_category_id'] = None + return _dict @classmethod diff --git a/ynab/models/money_movement_base.py b/ynab/models/money_movement_base.py index 046ecd6..ac08084 100644 --- a/ynab/models/money_movement_base.py +++ b/ynab/models/money_movement_base.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/money_movement_group.py b/ynab/models/money_movement_group.py index 2faf129..568b1fd 100644 --- a/ynab/models/money_movement_group.py +++ b/ynab/models/money_movement_group.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/money_movement_groups_response.py b/ynab/models/money_movement_groups_response.py index 7a9368c..4c05d00 100644 --- a/ynab/models/money_movement_groups_response.py +++ b/ynab/models/money_movement_groups_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/money_movement_groups_response_data.py b/ynab/models/money_movement_groups_response_data.py index bd30d91..03904da 100644 --- a/ynab/models/money_movement_groups_response_data.py +++ b/ynab/models/money_movement_groups_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -75,8 +75,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.money_movement_groups: for _item_money_movement_groups in self.money_movement_groups: - if _item_money_movement_groups: - _items.append(_item_money_movement_groups.to_dict()) + _items.append(_item_money_movement_groups.to_dict() if _item_money_movement_groups is not None else None) _dict['money_movement_groups'] = _items return _dict diff --git a/ynab/models/money_movements_response.py b/ynab/models/money_movements_response.py index 5580118..d94bc00 100644 --- a/ynab/models/money_movements_response.py +++ b/ynab/models/money_movements_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/money_movements_response_data.py b/ynab/models/money_movements_response_data.py index 2002567..dd099e5 100644 --- a/ynab/models/money_movements_response_data.py +++ b/ynab/models/money_movements_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -75,8 +75,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.money_movements: for _item_money_movements in self.money_movements: - if _item_money_movements: - _items.append(_item_money_movements.to_dict()) + _items.append(_item_money_movements.to_dict() if _item_money_movements is not None else None) _dict['money_movements'] = _items return _dict diff --git a/ynab/models/month_detail.py b/ynab/models/month_detail.py index 33eb8de..e667bce 100644 --- a/ynab/models/month_detail.py +++ b/ynab/models/month_detail.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -91,9 +91,18 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.categories: for _item_categories in self.categories: - if _item_categories: - _items.append(_item_categories.to_dict()) + _items.append(_item_categories.to_dict() if _item_categories is not None else None) _dict['categories'] = _items + # set to None if note (nullable) is None + # and model_fields_set contains the field + if self.note is None and "note" in self.model_fields_set: + _dict['note'] = None + + # set to None if age_of_money (nullable) is None + # and model_fields_set contains the field + if self.age_of_money is None and "age_of_money" in self.model_fields_set: + _dict['age_of_money'] = None + return _dict @classmethod diff --git a/ynab/models/month_detail_base.py b/ynab/models/month_detail_base.py index 3ed0779..4943ddc 100644 --- a/ynab/models/month_detail_base.py +++ b/ynab/models/month_detail_base.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -83,9 +83,18 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.categories: for _item_categories in self.categories: - if _item_categories: - _items.append(_item_categories.to_dict()) + _items.append(_item_categories.to_dict() if _item_categories is not None else None) _dict['categories'] = _items + # set to None if note (nullable) is None + # and model_fields_set contains the field + if self.note is None and "note" in self.model_fields_set: + _dict['note'] = None + + # set to None if age_of_money (nullable) is None + # and model_fields_set contains the field + if self.age_of_money is None and "age_of_money" in self.model_fields_set: + _dict['age_of_money'] = None + return _dict @classmethod diff --git a/ynab/models/month_detail_response.py b/ynab/models/month_detail_response.py index 0641dc3..ad0a60e 100644 --- a/ynab/models/month_detail_response.py +++ b/ynab/models/month_detail_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/month_detail_response_data.py b/ynab/models/month_detail_response_data.py index 3234ba1..74fb8cc 100644 --- a/ynab/models/month_detail_response_data.py +++ b/ynab/models/month_detail_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/month_summaries_response.py b/ynab/models/month_summaries_response.py index 25eba9f..51e2268 100644 --- a/ynab/models/month_summaries_response.py +++ b/ynab/models/month_summaries_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/month_summaries_response_data.py b/ynab/models/month_summaries_response_data.py index 91f9b52..5ffc6c0 100644 --- a/ynab/models/month_summaries_response_data.py +++ b/ynab/models/month_summaries_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -75,8 +75,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.months: for _item_months in self.months: - if _item_months: - _items.append(_item_months.to_dict()) + _items.append(_item_months.to_dict() if _item_months is not None else None) _dict['months'] = _items return _dict diff --git a/ynab/models/month_summary.py b/ynab/models/month_summary.py index 44bd5ee..952775f 100644 --- a/ynab/models/month_summary.py +++ b/ynab/models/month_summary.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -85,6 +85,16 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if note (nullable) is None + # and model_fields_set contains the field + if self.note is None and "note" in self.model_fields_set: + _dict['note'] = None + + # set to None if age_of_money (nullable) is None + # and model_fields_set contains the field + if self.age_of_money is None and "age_of_money" in self.model_fields_set: + _dict['age_of_money'] = None + return _dict @classmethod diff --git a/ynab/models/month_summary_base.py b/ynab/models/month_summary_base.py index f71bc3c..e0a5547 100644 --- a/ynab/models/month_summary_base.py +++ b/ynab/models/month_summary_base.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/new_category.py b/ynab/models/new_category.py index cb9d9d7..5995252 100644 --- a/ynab/models/new_category.py +++ b/ynab/models/new_category.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -32,10 +32,10 @@ class NewCategory(BaseModel): name: Optional[StrictStr] = None note: Optional[StrictStr] = None category_group_id: Optional[UUID] = Field(default=None, description="The id of the category group to which this category belongs. An internal category group may not be specified.") - goal_target: Optional[StrictInt] = Field(default=None, description="The goal target amount in milliunits format. If value is specified and goal has not already been configured for category, a monthly goal will be created for the category with this target amount. If goal_type is not specified, it will default to 'NEED' or 'MF' for Credit Card Payment categories. When updating a category, passing null removes any existing target.") - goal_target_date: Optional[date] = Field(default=None, description="The goal target date in ISO format (e.g. 2016-12-01).") - goal_needs_whole_amount: Optional[StrictBool] = Field(default=None, description="Whether the goal requires the full target amount each period. Only supported for 'NEED' goals. When true, the goal is configured as 'Set aside another...'. When false, the goal is configured as 'Refill up to...'.") - goal_frequency: Optional[StrictStr] = Field(default=None, description="When specified, configures a recurring 'NEED' target of goal_target that repeats at this frequency, replacing any existing target. Requires goal_target. Cannot be combined with goal_target_date and is not supported for Credit Card Payment categories. Omit to leave an existing target's cadence unchanged.") + goal_target: Optional[StrictInt] = Field(default=None, description="The goal target amount in milliunits format. If value is specified and goal has not already been configured for category, a monthly goal will be created for the category with this target amount. If goal_type is not specified, it will default to 'NEED', or to 'MF' for Credit Card Payment categories and 'DEBT' for categories paired to a loan account. When updating a category, passing null removes any existing target.") + goal_target_date: Optional[date] = Field(default=None, description="The goal target date in ISO format (e.g. 2016-12-01). Not supported for categories paired to a loan account.") + goal_needs_whole_amount: Optional[StrictBool] = Field(default=None, description="Whether the goal requires the full target amount each period. Only supported for 'NEED' goals, and not supported for Credit Card Payment categories or categories paired to a loan account. When true, the goal is configured as 'Set aside another...'. When false, the goal is configured as 'Refill up to...'.") + goal_frequency: Optional[StrictStr] = Field(default=None, description="When specified, configures a recurring 'NEED' target of goal_target that repeats at this frequency, replacing any existing target. Requires goal_target. Cannot be combined with goal_target_date and is not supported for Credit Card Payment categories or categories paired to a loan account. Omit to leave an existing target's cadence unchanged.") __properties: ClassVar[List[str]] = ["name", "note", "category_group_id", "goal_target", "goal_target_date", "goal_needs_whole_amount", "goal_frequency"] @field_validator('goal_frequency') @@ -87,6 +87,31 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if name (nullable) is None + # and model_fields_set contains the field + if self.name is None and "name" in self.model_fields_set: + _dict['name'] = None + + # set to None if note (nullable) is None + # and model_fields_set contains the field + if self.note is None and "note" in self.model_fields_set: + _dict['note'] = None + + # set to None if goal_target (nullable) is None + # and model_fields_set contains the field + if self.goal_target is None and "goal_target" in self.model_fields_set: + _dict['goal_target'] = None + + # set to None if goal_target_date (nullable) is None + # and model_fields_set contains the field + if self.goal_target_date is None and "goal_target_date" in self.model_fields_set: + _dict['goal_target_date'] = None + + # set to None if goal_needs_whole_amount (nullable) is None + # and model_fields_set contains the field + if self.goal_needs_whole_amount is None and "goal_needs_whole_amount" in self.model_fields_set: + _dict['goal_needs_whole_amount'] = None + return _dict @classmethod diff --git a/ynab/models/new_transaction.py b/ynab/models/new_transaction.py index be3215c..38f8f43 100644 --- a/ynab/models/new_transaction.py +++ b/ynab/models/new_transaction.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -43,7 +43,7 @@ class NewTransaction(BaseModel): cleared: Optional[TransactionClearedStatus] = None approved: Optional[StrictBool] = Field(default=None, description="Whether or not the transaction is approved. If not supplied, transaction will be unapproved by default.") flag_color: Optional[TransactionFlagColor] = None - subtransactions: Optional[List[SaveSubTransaction]] = Field(default=None, description="An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported.") + subtransactions: Optional[List[SaveSubTransaction]] = Field(default=None, description="An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported and will return an error. Splits are not allowed on tracking accounts or on transfers between on-budget accounts; a transfer to a tracking account can be a split.") import_id: Optional[Annotated[str, Field(strict=True, max_length=36)]] = Field(default=None, description="If specified, a new transaction will be assigned this `import_id` and considered \"imported\". We will also attempt to match this imported transaction to an existing \"user-entered\" transaction on the same account, with the same amount, and with a date +/-10 days from the imported transaction date.

Transactions imported through File Based Import or Direct Import (not through the API) are assigned an import_id in the format: 'YNAB:[milliunit_amount]:[iso_date]:[occurrence]'. For example, a transaction dated 2015-12-30 in the amount of -$294.23 USD would have an import_id of 'YNAB:-294230:2015-12-30:1'. If a second transaction on the same account was imported and had the same date and same amount, its import_id would be 'YNAB:-294230:2015-12-30:2'. Using a consistent format will prevent duplicates through Direct Import and File Based Import.

If import_id is omitted or specified as null, the transaction will be treated as a \"user-entered\" transaction. As such, it will be eligible to be matched against transactions later being imported (via DI, FBI, or API).") __properties: ClassVar[List[str]] = ["account_id", "date", "amount", "payee_id", "payee_name", "category_id", "memo", "cleared", "approved", "flag_color", "subtransactions", "import_id"] @@ -90,9 +90,28 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.subtransactions: for _item_subtransactions in self.subtransactions: - if _item_subtransactions: - _items.append(_item_subtransactions.to_dict()) + _items.append(_item_subtransactions.to_dict() if _item_subtransactions is not None else None) _dict['subtransactions'] = _items + # set to None if payee_id (nullable) is None + # and model_fields_set contains the field + if self.payee_id is None and "payee_id" in self.model_fields_set: + _dict['payee_id'] = None + + # set to None if payee_name (nullable) is None + # and model_fields_set contains the field + if self.payee_name is None and "payee_name" in self.model_fields_set: + _dict['payee_name'] = None + + # set to None if category_id (nullable) is None + # and model_fields_set contains the field + if self.category_id is None and "category_id" in self.model_fields_set: + _dict['category_id'] = None + + # set to None if memo (nullable) is None + # and model_fields_set contains the field + if self.memo is None and "memo" in self.model_fields_set: + _dict['memo'] = None + # set to None if flag_color (nullable) is None # and model_fields_set contains the field if self.flag_color is None and "flag_color" in self.model_fields_set: diff --git a/ynab/models/patch_category_group_wrapper.py b/ynab/models/patch_category_group_wrapper.py index 89f5e8d..12db8e6 100644 --- a/ynab/models/patch_category_group_wrapper.py +++ b/ynab/models/patch_category_group_wrapper.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/patch_category_wrapper.py b/ynab/models/patch_category_wrapper.py index f542096..bc6701a 100644 --- a/ynab/models/patch_category_wrapper.py +++ b/ynab/models/patch_category_wrapper.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/patch_month_category_wrapper.py b/ynab/models/patch_month_category_wrapper.py index 1d96b13..d0d267b 100644 --- a/ynab/models/patch_month_category_wrapper.py +++ b/ynab/models/patch_month_category_wrapper.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/patch_payee_wrapper.py b/ynab/models/patch_payee_wrapper.py index a700253..d76915f 100644 --- a/ynab/models/patch_payee_wrapper.py +++ b/ynab/models/patch_payee_wrapper.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/patch_transactions_wrapper.py b/ynab/models/patch_transactions_wrapper.py index 3dc00cb..ccab975 100644 --- a/ynab/models/patch_transactions_wrapper.py +++ b/ynab/models/patch_transactions_wrapper.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -74,8 +74,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.transactions: for _item_transactions in self.transactions: - if _item_transactions: - _items.append(_item_transactions.to_dict()) + _items.append(_item_transactions.to_dict() if _item_transactions is not None else None) _dict['transactions'] = _items return _dict diff --git a/ynab/models/payee.py b/ynab/models/payee.py index 3013e20..c376a0b 100644 --- a/ynab/models/payee.py +++ b/ynab/models/payee.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/payee_location.py b/ynab/models/payee_location.py index 3f154de..a3174fb 100644 --- a/ynab/models/payee_location.py +++ b/ynab/models/payee_location.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/payee_location_response.py b/ynab/models/payee_location_response.py index 2189ad5..ad5b2f1 100644 --- a/ynab/models/payee_location_response.py +++ b/ynab/models/payee_location_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/payee_location_response_data.py b/ynab/models/payee_location_response_data.py index 2da575b..b054748 100644 --- a/ynab/models/payee_location_response_data.py +++ b/ynab/models/payee_location_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/payee_locations_response.py b/ynab/models/payee_locations_response.py index be6525c..e7b5a61 100644 --- a/ynab/models/payee_locations_response.py +++ b/ynab/models/payee_locations_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/payee_locations_response_data.py b/ynab/models/payee_locations_response_data.py index dc2e42f..15c0db9 100644 --- a/ynab/models/payee_locations_response_data.py +++ b/ynab/models/payee_locations_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -74,8 +74,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.payee_locations: for _item_payee_locations in self.payee_locations: - if _item_payee_locations: - _items.append(_item_payee_locations.to_dict()) + _items.append(_item_payee_locations.to_dict() if _item_payee_locations is not None else None) _dict['payee_locations'] = _items return _dict diff --git a/ynab/models/payee_response.py b/ynab/models/payee_response.py index f058c4e..e16847d 100644 --- a/ynab/models/payee_response.py +++ b/ynab/models/payee_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/payee_response_data.py b/ynab/models/payee_response_data.py index 62aabb9..95350c6 100644 --- a/ynab/models/payee_response_data.py +++ b/ynab/models/payee_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/payees_response.py b/ynab/models/payees_response.py index 71b203a..940e7bd 100644 --- a/ynab/models/payees_response.py +++ b/ynab/models/payees_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/payees_response_data.py b/ynab/models/payees_response_data.py index 776e887..1b31256 100644 --- a/ynab/models/payees_response_data.py +++ b/ynab/models/payees_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -75,8 +75,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.payees: for _item_payees in self.payees: - if _item_payees: - _items.append(_item_payees.to_dict()) + _items.append(_item_payees.to_dict() if _item_payees is not None else None) _dict['payees'] = _items return _dict diff --git a/ynab/models/plan_detail.py b/ynab/models/plan_detail.py index 51a9273..54ec5f5 100644 --- a/ynab/models/plan_detail.py +++ b/ynab/models/plan_detail.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -109,72 +109,72 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.accounts: for _item_accounts in self.accounts: - if _item_accounts: - _items.append(_item_accounts.to_dict()) + _items.append(_item_accounts.to_dict() if _item_accounts is not None else None) _dict['accounts'] = _items # override the default output from pydantic by calling `to_dict()` of each item in payees (list) _items = [] if self.payees: for _item_payees in self.payees: - if _item_payees: - _items.append(_item_payees.to_dict()) + _items.append(_item_payees.to_dict() if _item_payees is not None else None) _dict['payees'] = _items # override the default output from pydantic by calling `to_dict()` of each item in payee_locations (list) _items = [] if self.payee_locations: for _item_payee_locations in self.payee_locations: - if _item_payee_locations: - _items.append(_item_payee_locations.to_dict()) + _items.append(_item_payee_locations.to_dict() if _item_payee_locations is not None else None) _dict['payee_locations'] = _items # override the default output from pydantic by calling `to_dict()` of each item in category_groups (list) _items = [] if self.category_groups: for _item_category_groups in self.category_groups: - if _item_category_groups: - _items.append(_item_category_groups.to_dict()) + _items.append(_item_category_groups.to_dict() if _item_category_groups is not None else None) _dict['category_groups'] = _items # override the default output from pydantic by calling `to_dict()` of each item in categories (list) _items = [] if self.categories: for _item_categories in self.categories: - if _item_categories: - _items.append(_item_categories.to_dict()) + _items.append(_item_categories.to_dict() if _item_categories is not None else None) _dict['categories'] = _items # override the default output from pydantic by calling `to_dict()` of each item in months (list) _items = [] if self.months: for _item_months in self.months: - if _item_months: - _items.append(_item_months.to_dict()) + _items.append(_item_months.to_dict() if _item_months is not None else None) _dict['months'] = _items # override the default output from pydantic by calling `to_dict()` of each item in transactions (list) _items = [] if self.transactions: for _item_transactions in self.transactions: - if _item_transactions: - _items.append(_item_transactions.to_dict()) + _items.append(_item_transactions.to_dict() if _item_transactions is not None else None) _dict['transactions'] = _items # override the default output from pydantic by calling `to_dict()` of each item in subtransactions (list) _items = [] if self.subtransactions: for _item_subtransactions in self.subtransactions: - if _item_subtransactions: - _items.append(_item_subtransactions.to_dict()) + _items.append(_item_subtransactions.to_dict() if _item_subtransactions is not None else None) _dict['subtransactions'] = _items # override the default output from pydantic by calling `to_dict()` of each item in scheduled_transactions (list) _items = [] if self.scheduled_transactions: for _item_scheduled_transactions in self.scheduled_transactions: - if _item_scheduled_transactions: - _items.append(_item_scheduled_transactions.to_dict()) + _items.append(_item_scheduled_transactions.to_dict() if _item_scheduled_transactions is not None else None) _dict['scheduled_transactions'] = _items # override the default output from pydantic by calling `to_dict()` of each item in scheduled_subtransactions (list) _items = [] if self.scheduled_subtransactions: for _item_scheduled_subtransactions in self.scheduled_subtransactions: - if _item_scheduled_subtransactions: - _items.append(_item_scheduled_subtransactions.to_dict()) + _items.append(_item_scheduled_subtransactions.to_dict() if _item_scheduled_subtransactions is not None else None) _dict['scheduled_subtransactions'] = _items + # set to None if date_format (nullable) is None + # and model_fields_set contains the field + if self.date_format is None and "date_format" in self.model_fields_set: + _dict['date_format'] = None + + # set to None if currency_format (nullable) is None + # and model_fields_set contains the field + if self.currency_format is None and "currency_format" in self.model_fields_set: + _dict['currency_format'] = None + return _dict @classmethod diff --git a/ynab/models/plan_detail_response.py b/ynab/models/plan_detail_response.py index e2b4f58..406b22b 100644 --- a/ynab/models/plan_detail_response.py +++ b/ynab/models/plan_detail_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/plan_detail_response_data.py b/ynab/models/plan_detail_response_data.py index 958df3f..cc14a2a 100644 --- a/ynab/models/plan_detail_response_data.py +++ b/ynab/models/plan_detail_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/plan_settings.py b/ynab/models/plan_settings.py index 818e232..1df3016 100644 --- a/ynab/models/plan_settings.py +++ b/ynab/models/plan_settings.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -18,7 +18,7 @@ import json from pydantic import BaseModel, ConfigDict -from typing import Any, ClassVar, Dict, List +from typing import Any, ClassVar, Dict, List, Optional from ynab.models.currency_format import CurrencyFormat from ynab.models.date_format import DateFormat from typing import Optional, Set @@ -29,8 +29,8 @@ class PlanSettings(BaseModel): """ PlanSettings """ # noqa: E501 - date_format: DateFormat - currency_format: CurrencyFormat + date_format: Optional[DateFormat] + currency_format: Optional[CurrencyFormat] __properties: ClassVar[List[str]] = ["date_format", "currency_format"] model_config = ConfigDict( @@ -78,6 +78,16 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of currency_format if self.currency_format: _dict['currency_format'] = self.currency_format.to_dict() + # set to None if date_format (nullable) is None + # and model_fields_set contains the field + if self.date_format is None and "date_format" in self.model_fields_set: + _dict['date_format'] = None + + # set to None if currency_format (nullable) is None + # and model_fields_set contains the field + if self.currency_format is None and "currency_format" in self.model_fields_set: + _dict['currency_format'] = None + return _dict @classmethod diff --git a/ynab/models/plan_settings_response.py b/ynab/models/plan_settings_response.py index 761593c..18d3a07 100644 --- a/ynab/models/plan_settings_response.py +++ b/ynab/models/plan_settings_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/plan_settings_response_data.py b/ynab/models/plan_settings_response_data.py index 219c10c..a961104 100644 --- a/ynab/models/plan_settings_response_data.py +++ b/ynab/models/plan_settings_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/plan_summary.py b/ynab/models/plan_summary.py index 9d5e7e3..4f77a40 100644 --- a/ynab/models/plan_summary.py +++ b/ynab/models/plan_summary.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -91,9 +91,18 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.accounts: for _item_accounts in self.accounts: - if _item_accounts: - _items.append(_item_accounts.to_dict()) + _items.append(_item_accounts.to_dict() if _item_accounts is not None else None) _dict['accounts'] = _items + # set to None if date_format (nullable) is None + # and model_fields_set contains the field + if self.date_format is None and "date_format" in self.model_fields_set: + _dict['date_format'] = None + + # set to None if currency_format (nullable) is None + # and model_fields_set contains the field + if self.currency_format is None and "currency_format" in self.model_fields_set: + _dict['currency_format'] = None + return _dict @classmethod diff --git a/ynab/models/plan_summary_response.py b/ynab/models/plan_summary_response.py index 80184ab..37c7e38 100644 --- a/ynab/models/plan_summary_response.py +++ b/ynab/models/plan_summary_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/plan_summary_response_data.py b/ynab/models/plan_summary_response_data.py index 4612bca..4e21f5d 100644 --- a/ynab/models/plan_summary_response_data.py +++ b/ynab/models/plan_summary_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -75,8 +75,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.plans: for _item_plans in self.plans: - if _item_plans: - _items.append(_item_plans.to_dict()) + _items.append(_item_plans.to_dict() if _item_plans is not None else None) _dict['plans'] = _items # override the default output from pydantic by calling `to_dict()` of default_plan if self.default_plan: diff --git a/ynab/models/post_account_wrapper.py b/ynab/models/post_account_wrapper.py index a5d2d9b..b6121d4 100644 --- a/ynab/models/post_account_wrapper.py +++ b/ynab/models/post_account_wrapper.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/post_category_group_wrapper.py b/ynab/models/post_category_group_wrapper.py index e583466..f307b0e 100644 --- a/ynab/models/post_category_group_wrapper.py +++ b/ynab/models/post_category_group_wrapper.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/post_category_wrapper.py b/ynab/models/post_category_wrapper.py index b11eaf2..f00c6c9 100644 --- a/ynab/models/post_category_wrapper.py +++ b/ynab/models/post_category_wrapper.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/post_payee.py b/ynab/models/post_payee.py index a168288..da3c9ac 100644 --- a/ynab/models/post_payee.py +++ b/ynab/models/post_payee.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/post_payee_wrapper.py b/ynab/models/post_payee_wrapper.py index 266f121..5005d03 100644 --- a/ynab/models/post_payee_wrapper.py +++ b/ynab/models/post_payee_wrapper.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/post_scheduled_transaction_wrapper.py b/ynab/models/post_scheduled_transaction_wrapper.py index 2c9657d..0b82f28 100644 --- a/ynab/models/post_scheduled_transaction_wrapper.py +++ b/ynab/models/post_scheduled_transaction_wrapper.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/post_transactions_wrapper.py b/ynab/models/post_transactions_wrapper.py index 3c7b6d5..e3977c3 100644 --- a/ynab/models/post_transactions_wrapper.py +++ b/ynab/models/post_transactions_wrapper.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -78,8 +78,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.transactions: for _item_transactions in self.transactions: - if _item_transactions: - _items.append(_item_transactions.to_dict()) + _items.append(_item_transactions.to_dict() if _item_transactions is not None else None) _dict['transactions'] = _items return _dict diff --git a/ynab/models/put_scheduled_transaction_wrapper.py b/ynab/models/put_scheduled_transaction_wrapper.py index 7ebbe4a..aa9b878 100644 --- a/ynab/models/put_scheduled_transaction_wrapper.py +++ b/ynab/models/put_scheduled_transaction_wrapper.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/put_transaction_wrapper.py b/ynab/models/put_transaction_wrapper.py index 6e5c629..d382946 100644 --- a/ynab/models/put_transaction_wrapper.py +++ b/ynab/models/put_transaction_wrapper.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/save_account.py b/ynab/models/save_account.py index 95249f7..06b3e4c 100644 --- a/ynab/models/save_account.py +++ b/ynab/models/save_account.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/save_account_type.py b/ynab/models/save_account_type.py index 0ef51ae..41c266d 100644 --- a/ynab/models/save_account_type.py +++ b/ynab/models/save_account_type.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/save_category.py b/ynab/models/save_category.py index 1762f6e..f539f82 100644 --- a/ynab/models/save_category.py +++ b/ynab/models/save_category.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -32,10 +32,10 @@ class SaveCategory(BaseModel): name: Optional[StrictStr] = None note: Optional[StrictStr] = None category_group_id: Optional[UUID] = Field(default=None, description="The id of the category group to which this category belongs. An internal category group may not be specified.") - goal_target: Optional[StrictInt] = Field(default=None, description="The goal target amount in milliunits format. If value is specified and goal has not already been configured for category, a monthly goal will be created for the category with this target amount. If goal_type is not specified, it will default to 'NEED' or 'MF' for Credit Card Payment categories. When updating a category, passing null removes any existing target.") - goal_target_date: Optional[date] = Field(default=None, description="The goal target date in ISO format (e.g. 2016-12-01).") - goal_needs_whole_amount: Optional[StrictBool] = Field(default=None, description="Whether the goal requires the full target amount each period. Only supported for 'NEED' goals. When true, the goal is configured as 'Set aside another...'. When false, the goal is configured as 'Refill up to...'.") - goal_frequency: Optional[StrictStr] = Field(default=None, description="When specified, configures a recurring 'NEED' target of goal_target that repeats at this frequency, replacing any existing target. Requires goal_target. Cannot be combined with goal_target_date and is not supported for Credit Card Payment categories. Omit to leave an existing target's cadence unchanged.") + goal_target: Optional[StrictInt] = Field(default=None, description="The goal target amount in milliunits format. If value is specified and goal has not already been configured for category, a monthly goal will be created for the category with this target amount. If goal_type is not specified, it will default to 'NEED', or to 'MF' for Credit Card Payment categories and 'DEBT' for categories paired to a loan account. When updating a category, passing null removes any existing target.") + goal_target_date: Optional[date] = Field(default=None, description="The goal target date in ISO format (e.g. 2016-12-01). Not supported for categories paired to a loan account.") + goal_needs_whole_amount: Optional[StrictBool] = Field(default=None, description="Whether the goal requires the full target amount each period. Only supported for 'NEED' goals, and not supported for Credit Card Payment categories or categories paired to a loan account. When true, the goal is configured as 'Set aside another...'. When false, the goal is configured as 'Refill up to...'.") + goal_frequency: Optional[StrictStr] = Field(default=None, description="When specified, configures a recurring 'NEED' target of goal_target that repeats at this frequency, replacing any existing target. Requires goal_target. Cannot be combined with goal_target_date and is not supported for Credit Card Payment categories or categories paired to a loan account. Omit to leave an existing target's cadence unchanged.") __properties: ClassVar[List[str]] = ["name", "note", "category_group_id", "goal_target", "goal_target_date", "goal_needs_whole_amount", "goal_frequency"] @field_validator('goal_frequency') diff --git a/ynab/models/save_category_group.py b/ynab/models/save_category_group.py index cdca4dd..0924912 100644 --- a/ynab/models/save_category_group.py +++ b/ynab/models/save_category_group.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/save_category_group_response.py b/ynab/models/save_category_group_response.py index 0b8122d..42b720e 100644 --- a/ynab/models/save_category_group_response.py +++ b/ynab/models/save_category_group_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/save_category_group_response_data.py b/ynab/models/save_category_group_response_data.py index de5c382..992fd39 100644 --- a/ynab/models/save_category_group_response_data.py +++ b/ynab/models/save_category_group_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/save_category_response.py b/ynab/models/save_category_response.py index d0588cd..6168b23 100644 --- a/ynab/models/save_category_response.py +++ b/ynab/models/save_category_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/save_category_response_data.py b/ynab/models/save_category_response_data.py index 922882c..5256a58 100644 --- a/ynab/models/save_category_response_data.py +++ b/ynab/models/save_category_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/save_month_category.py b/ynab/models/save_month_category.py index 991ce70..2cb954a 100644 --- a/ynab/models/save_month_category.py +++ b/ynab/models/save_month_category.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/save_payee.py b/ynab/models/save_payee.py index 8011c6f..342d71a 100644 --- a/ynab/models/save_payee.py +++ b/ynab/models/save_payee.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/save_payee_response.py b/ynab/models/save_payee_response.py index 0ed298e..5bc7c7f 100644 --- a/ynab/models/save_payee_response.py +++ b/ynab/models/save_payee_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/save_payee_response_data.py b/ynab/models/save_payee_response_data.py index 448f406..acc6462 100644 --- a/ynab/models/save_payee_response_data.py +++ b/ynab/models/save_payee_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/save_scheduled_transaction.py b/ynab/models/save_scheduled_transaction.py index ef8ecf0..f3ed798 100644 --- a/ynab/models/save_scheduled_transaction.py +++ b/ynab/models/save_scheduled_transaction.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/save_sub_transaction.py b/ynab/models/save_sub_transaction.py index e4f756d..e9528dd 100644 --- a/ynab/models/save_sub_transaction.py +++ b/ynab/models/save_sub_transaction.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/save_transaction_with_id_or_import_id.py b/ynab/models/save_transaction_with_id_or_import_id.py index d073de5..f84274a 100644 --- a/ynab/models/save_transaction_with_id_or_import_id.py +++ b/ynab/models/save_transaction_with_id_or_import_id.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -43,7 +43,7 @@ class SaveTransactionWithIdOrImportId(BaseModel): cleared: Optional[TransactionClearedStatus] = None approved: Optional[StrictBool] = Field(default=None, description="Whether or not the transaction is approved. If not supplied, transaction will be unapproved by default.") flag_color: Optional[TransactionFlagColor] = None - subtransactions: Optional[List[SaveSubTransaction]] = Field(default=None, description="An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported.") + subtransactions: Optional[List[SaveSubTransaction]] = Field(default=None, description="An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported and will return an error. Splits are not allowed on tracking accounts or on transfers between on-budget accounts; a transfer to a tracking account can be a split.") id: Optional[StrictStr] = Field(default=None, description="If specified, this id will be used to lookup a transaction by its `id` for the purpose of updating the transaction itself. If not specified, an `import_id` should be supplied.") import_id: Optional[Annotated[str, Field(strict=True, max_length=36)]] = Field(default=None, description="If specified, this id will be used to lookup a transaction by its `import_id` for the purpose of updating the transaction itself. If not specified, an `id` should be supplied. You may not provide both an `id` and an `import_id` and updating an `import_id` on an existing transaction is not allowed.") __properties: ClassVar[List[str]] = ["account_id", "date", "amount", "payee_id", "payee_name", "category_id", "memo", "cleared", "approved", "flag_color", "subtransactions", "id", "import_id"] @@ -91,9 +91,28 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.subtransactions: for _item_subtransactions in self.subtransactions: - if _item_subtransactions: - _items.append(_item_subtransactions.to_dict()) + _items.append(_item_subtransactions.to_dict() if _item_subtransactions is not None else None) _dict['subtransactions'] = _items + # set to None if payee_id (nullable) is None + # and model_fields_set contains the field + if self.payee_id is None and "payee_id" in self.model_fields_set: + _dict['payee_id'] = None + + # set to None if payee_name (nullable) is None + # and model_fields_set contains the field + if self.payee_name is None and "payee_name" in self.model_fields_set: + _dict['payee_name'] = None + + # set to None if category_id (nullable) is None + # and model_fields_set contains the field + if self.category_id is None and "category_id" in self.model_fields_set: + _dict['category_id'] = None + + # set to None if memo (nullable) is None + # and model_fields_set contains the field + if self.memo is None and "memo" in self.model_fields_set: + _dict['memo'] = None + # set to None if flag_color (nullable) is None # and model_fields_set contains the field if self.flag_color is None and "flag_color" in self.model_fields_set: diff --git a/ynab/models/save_transaction_with_optional_fields.py b/ynab/models/save_transaction_with_optional_fields.py index caa2098..0e6e3e0 100644 --- a/ynab/models/save_transaction_with_optional_fields.py +++ b/ynab/models/save_transaction_with_optional_fields.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -43,7 +43,7 @@ class SaveTransactionWithOptionalFields(BaseModel): cleared: Optional[TransactionClearedStatus] = None approved: Optional[StrictBool] = Field(default=None, description="Whether or not the transaction is approved. If not supplied, transaction will be unapproved by default.") flag_color: Optional[TransactionFlagColor] = None - subtransactions: Optional[List[SaveSubTransaction]] = Field(default=None, description="An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported.") + subtransactions: Optional[List[SaveSubTransaction]] = Field(default=None, description="An array of subtransactions to configure a transaction as a split. Updating `subtransactions` on an existing split transaction is not supported and will return an error. Splits are not allowed on tracking accounts or on transfers between on-budget accounts; a transfer to a tracking account can be a split.") __properties: ClassVar[List[str]] = ["account_id", "date", "amount", "payee_id", "payee_name", "category_id", "memo", "cleared", "approved", "flag_color", "subtransactions"] model_config = ConfigDict( @@ -89,8 +89,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.subtransactions: for _item_subtransactions in self.subtransactions: - if _item_subtransactions: - _items.append(_item_subtransactions.to_dict()) + _items.append(_item_subtransactions.to_dict() if _item_subtransactions is not None else None) _dict['subtransactions'] = _items # set to None if payee_id (nullable) is None # and model_fields_set contains the field diff --git a/ynab/models/save_transactions_response.py b/ynab/models/save_transactions_response.py index 8a687a7..fb3eb04 100644 --- a/ynab/models/save_transactions_response.py +++ b/ynab/models/save_transactions_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/save_transactions_response_data.py b/ynab/models/save_transactions_response_data.py index 1eba256..08e2dd6 100644 --- a/ynab/models/save_transactions_response_data.py +++ b/ynab/models/save_transactions_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -81,8 +81,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.transactions: for _item_transactions in self.transactions: - if _item_transactions: - _items.append(_item_transactions.to_dict()) + _items.append(_item_transactions.to_dict() if _item_transactions is not None else None) _dict['transactions'] = _items return _dict diff --git a/ynab/models/scheduled_sub_transaction.py b/ynab/models/scheduled_sub_transaction.py index eec4c99..01957ea 100644 --- a/ynab/models/scheduled_sub_transaction.py +++ b/ynab/models/scheduled_sub_transaction.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -81,6 +81,36 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if memo (nullable) is None + # and model_fields_set contains the field + if self.memo is None and "memo" in self.model_fields_set: + _dict['memo'] = None + + # set to None if payee_id (nullable) is None + # and model_fields_set contains the field + if self.payee_id is None and "payee_id" in self.model_fields_set: + _dict['payee_id'] = None + + # set to None if payee_name (nullable) is None + # and model_fields_set contains the field + if self.payee_name is None and "payee_name" in self.model_fields_set: + _dict['payee_name'] = None + + # set to None if category_id (nullable) is None + # and model_fields_set contains the field + if self.category_id is None and "category_id" in self.model_fields_set: + _dict['category_id'] = None + + # set to None if category_name (nullable) is None + # and model_fields_set contains the field + if self.category_name is None and "category_name" in self.model_fields_set: + _dict['category_name'] = None + + # set to None if transfer_account_id (nullable) is None + # and model_fields_set contains the field + if self.transfer_account_id is None and "transfer_account_id" in self.model_fields_set: + _dict['transfer_account_id'] = None + return _dict @classmethod diff --git a/ynab/models/scheduled_sub_transaction_base.py b/ynab/models/scheduled_sub_transaction_base.py index 12ae301..abc79c5 100644 --- a/ynab/models/scheduled_sub_transaction_base.py +++ b/ynab/models/scheduled_sub_transaction_base.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/scheduled_transaction_detail.py b/ynab/models/scheduled_transaction_detail.py index 6e03096..714c26b 100644 --- a/ynab/models/scheduled_transaction_detail.py +++ b/ynab/models/scheduled_transaction_detail.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -102,14 +102,38 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.subtransactions: for _item_subtransactions in self.subtransactions: - if _item_subtransactions: - _items.append(_item_subtransactions.to_dict()) + _items.append(_item_subtransactions.to_dict() if _item_subtransactions is not None else None) _dict['subtransactions'] = _items + # set to None if memo (nullable) is None + # and model_fields_set contains the field + if self.memo is None and "memo" in self.model_fields_set: + _dict['memo'] = None + # set to None if flag_color (nullable) is None # and model_fields_set contains the field if self.flag_color is None and "flag_color" in self.model_fields_set: _dict['flag_color'] = None + # set to None if flag_name (nullable) is None + # and model_fields_set contains the field + if self.flag_name is None and "flag_name" in self.model_fields_set: + _dict['flag_name'] = None + + # set to None if payee_id (nullable) is None + # and model_fields_set contains the field + if self.payee_id is None and "payee_id" in self.model_fields_set: + _dict['payee_id'] = None + + # set to None if category_id (nullable) is None + # and model_fields_set contains the field + if self.category_id is None and "category_id" in self.model_fields_set: + _dict['category_id'] = None + + # set to None if transfer_account_id (nullable) is None + # and model_fields_set contains the field + if self.transfer_account_id is None and "transfer_account_id" in self.model_fields_set: + _dict['transfer_account_id'] = None + # set to None if payee_name (nullable) is None # and model_fields_set contains the field if self.payee_name is None and "payee_name" in self.model_fields_set: diff --git a/ynab/models/scheduled_transaction_frequency.py b/ynab/models/scheduled_transaction_frequency.py index 9fe1335..5446be8 100644 --- a/ynab/models/scheduled_transaction_frequency.py +++ b/ynab/models/scheduled_transaction_frequency.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/scheduled_transaction_response.py b/ynab/models/scheduled_transaction_response.py index 492963e..84fc68a 100644 --- a/ynab/models/scheduled_transaction_response.py +++ b/ynab/models/scheduled_transaction_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/scheduled_transaction_response_data.py b/ynab/models/scheduled_transaction_response_data.py index 4366c7c..340aa8d 100644 --- a/ynab/models/scheduled_transaction_response_data.py +++ b/ynab/models/scheduled_transaction_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/scheduled_transaction_summary.py b/ynab/models/scheduled_transaction_summary.py index 941ce14..302494d 100644 --- a/ynab/models/scheduled_transaction_summary.py +++ b/ynab/models/scheduled_transaction_summary.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -93,11 +93,36 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if memo (nullable) is None + # and model_fields_set contains the field + if self.memo is None and "memo" in self.model_fields_set: + _dict['memo'] = None + # set to None if flag_color (nullable) is None # and model_fields_set contains the field if self.flag_color is None and "flag_color" in self.model_fields_set: _dict['flag_color'] = None + # set to None if flag_name (nullable) is None + # and model_fields_set contains the field + if self.flag_name is None and "flag_name" in self.model_fields_set: + _dict['flag_name'] = None + + # set to None if payee_id (nullable) is None + # and model_fields_set contains the field + if self.payee_id is None and "payee_id" in self.model_fields_set: + _dict['payee_id'] = None + + # set to None if category_id (nullable) is None + # and model_fields_set contains the field + if self.category_id is None and "category_id" in self.model_fields_set: + _dict['category_id'] = None + + # set to None if transfer_account_id (nullable) is None + # and model_fields_set contains the field + if self.transfer_account_id is None and "transfer_account_id" in self.model_fields_set: + _dict['transfer_account_id'] = None + return _dict @classmethod diff --git a/ynab/models/scheduled_transaction_summary_base.py b/ynab/models/scheduled_transaction_summary_base.py index b6d8a04..4572f44 100644 --- a/ynab/models/scheduled_transaction_summary_base.py +++ b/ynab/models/scheduled_transaction_summary_base.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/scheduled_transactions_response.py b/ynab/models/scheduled_transactions_response.py index 275cf85..872f960 100644 --- a/ynab/models/scheduled_transactions_response.py +++ b/ynab/models/scheduled_transactions_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/scheduled_transactions_response_data.py b/ynab/models/scheduled_transactions_response_data.py index c930fe4..2c540f9 100644 --- a/ynab/models/scheduled_transactions_response_data.py +++ b/ynab/models/scheduled_transactions_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -75,8 +75,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.scheduled_transactions: for _item_scheduled_transactions in self.scheduled_transactions: - if _item_scheduled_transactions: - _items.append(_item_scheduled_transactions.to_dict()) + _items.append(_item_scheduled_transactions.to_dict() if _item_scheduled_transactions is not None else None) _dict['scheduled_transactions'] = _items return _dict diff --git a/ynab/models/sub_transaction.py b/ynab/models/sub_transaction.py index d1aeb82..4174acb 100644 --- a/ynab/models/sub_transaction.py +++ b/ynab/models/sub_transaction.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -82,6 +82,41 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if memo (nullable) is None + # and model_fields_set contains the field + if self.memo is None and "memo" in self.model_fields_set: + _dict['memo'] = None + + # set to None if payee_id (nullable) is None + # and model_fields_set contains the field + if self.payee_id is None and "payee_id" in self.model_fields_set: + _dict['payee_id'] = None + + # set to None if payee_name (nullable) is None + # and model_fields_set contains the field + if self.payee_name is None and "payee_name" in self.model_fields_set: + _dict['payee_name'] = None + + # set to None if category_id (nullable) is None + # and model_fields_set contains the field + if self.category_id is None and "category_id" in self.model_fields_set: + _dict['category_id'] = None + + # set to None if category_name (nullable) is None + # and model_fields_set contains the field + if self.category_name is None and "category_name" in self.model_fields_set: + _dict['category_name'] = None + + # set to None if transfer_account_id (nullable) is None + # and model_fields_set contains the field + if self.transfer_account_id is None and "transfer_account_id" in self.model_fields_set: + _dict['transfer_account_id'] = None + + # set to None if transfer_transaction_id (nullable) is None + # and model_fields_set contains the field + if self.transfer_transaction_id is None and "transfer_transaction_id" in self.model_fields_set: + _dict['transfer_transaction_id'] = None + return _dict @classmethod diff --git a/ynab/models/sub_transaction_base.py b/ynab/models/sub_transaction_base.py index 6749f7c..6213fcb 100644 --- a/ynab/models/sub_transaction_base.py +++ b/ynab/models/sub_transaction_base.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/transaction_cleared_status.py b/ynab/models/transaction_cleared_status.py index 036c53a..fb1ff31 100644 --- a/ynab/models/transaction_cleared_status.py +++ b/ynab/models/transaction_cleared_status.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/transaction_detail.py b/ynab/models/transaction_detail.py index 6b218b4..a9a408e 100644 --- a/ynab/models/transaction_detail.py +++ b/ynab/models/transaction_detail.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -112,14 +112,63 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.subtransactions: for _item_subtransactions in self.subtransactions: - if _item_subtransactions: - _items.append(_item_subtransactions.to_dict()) + _items.append(_item_subtransactions.to_dict() if _item_subtransactions is not None else None) _dict['subtransactions'] = _items + # set to None if memo (nullable) is None + # and model_fields_set contains the field + if self.memo is None and "memo" in self.model_fields_set: + _dict['memo'] = None + # set to None if flag_color (nullable) is None # and model_fields_set contains the field if self.flag_color is None and "flag_color" in self.model_fields_set: _dict['flag_color'] = None + # set to None if flag_name (nullable) is None + # and model_fields_set contains the field + if self.flag_name is None and "flag_name" in self.model_fields_set: + _dict['flag_name'] = None + + # set to None if payee_id (nullable) is None + # and model_fields_set contains the field + if self.payee_id is None and "payee_id" in self.model_fields_set: + _dict['payee_id'] = None + + # set to None if category_id (nullable) is None + # and model_fields_set contains the field + if self.category_id is None and "category_id" in self.model_fields_set: + _dict['category_id'] = None + + # set to None if transfer_account_id (nullable) is None + # and model_fields_set contains the field + if self.transfer_account_id is None and "transfer_account_id" in self.model_fields_set: + _dict['transfer_account_id'] = None + + # set to None if transfer_transaction_id (nullable) is None + # and model_fields_set contains the field + if self.transfer_transaction_id is None and "transfer_transaction_id" in self.model_fields_set: + _dict['transfer_transaction_id'] = None + + # set to None if matched_transaction_id (nullable) is None + # and model_fields_set contains the field + if self.matched_transaction_id is None and "matched_transaction_id" in self.model_fields_set: + _dict['matched_transaction_id'] = None + + # set to None if import_id (nullable) is None + # and model_fields_set contains the field + if self.import_id is None and "import_id" in self.model_fields_set: + _dict['import_id'] = None + + # set to None if import_payee_name (nullable) is None + # and model_fields_set contains the field + if self.import_payee_name is None and "import_payee_name" in self.model_fields_set: + _dict['import_payee_name'] = None + + # set to None if import_payee_name_original (nullable) is None + # and model_fields_set contains the field + if self.import_payee_name_original is None and "import_payee_name_original" in self.model_fields_set: + _dict['import_payee_name_original'] = None + # set to None if debt_transaction_type (nullable) is None # and model_fields_set contains the field if self.debt_transaction_type is None and "debt_transaction_type" in self.model_fields_set: diff --git a/ynab/models/transaction_flag_color.py b/ynab/models/transaction_flag_color.py index c564872..948e5dd 100644 --- a/ynab/models/transaction_flag_color.py +++ b/ynab/models/transaction_flag_color.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/transaction_response.py b/ynab/models/transaction_response.py index 0b57ccb..2f787d1 100644 --- a/ynab/models/transaction_response.py +++ b/ynab/models/transaction_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/transaction_response_data.py b/ynab/models/transaction_response_data.py index 9ddc7f7..620671f 100644 --- a/ynab/models/transaction_response_data.py +++ b/ynab/models/transaction_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/transaction_summary.py b/ynab/models/transaction_summary.py index 0cf04d5..314ef1e 100644 --- a/ynab/models/transaction_summary.py +++ b/ynab/models/transaction_summary.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -103,11 +103,61 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # set to None if memo (nullable) is None + # and model_fields_set contains the field + if self.memo is None and "memo" in self.model_fields_set: + _dict['memo'] = None + # set to None if flag_color (nullable) is None # and model_fields_set contains the field if self.flag_color is None and "flag_color" in self.model_fields_set: _dict['flag_color'] = None + # set to None if flag_name (nullable) is None + # and model_fields_set contains the field + if self.flag_name is None and "flag_name" in self.model_fields_set: + _dict['flag_name'] = None + + # set to None if payee_id (nullable) is None + # and model_fields_set contains the field + if self.payee_id is None and "payee_id" in self.model_fields_set: + _dict['payee_id'] = None + + # set to None if category_id (nullable) is None + # and model_fields_set contains the field + if self.category_id is None and "category_id" in self.model_fields_set: + _dict['category_id'] = None + + # set to None if transfer_account_id (nullable) is None + # and model_fields_set contains the field + if self.transfer_account_id is None and "transfer_account_id" in self.model_fields_set: + _dict['transfer_account_id'] = None + + # set to None if transfer_transaction_id (nullable) is None + # and model_fields_set contains the field + if self.transfer_transaction_id is None and "transfer_transaction_id" in self.model_fields_set: + _dict['transfer_transaction_id'] = None + + # set to None if matched_transaction_id (nullable) is None + # and model_fields_set contains the field + if self.matched_transaction_id is None and "matched_transaction_id" in self.model_fields_set: + _dict['matched_transaction_id'] = None + + # set to None if import_id (nullable) is None + # and model_fields_set contains the field + if self.import_id is None and "import_id" in self.model_fields_set: + _dict['import_id'] = None + + # set to None if import_payee_name (nullable) is None + # and model_fields_set contains the field + if self.import_payee_name is None and "import_payee_name" in self.model_fields_set: + _dict['import_payee_name'] = None + + # set to None if import_payee_name_original (nullable) is None + # and model_fields_set contains the field + if self.import_payee_name_original is None and "import_payee_name_original" in self.model_fields_set: + _dict['import_payee_name_original'] = None + # set to None if debt_transaction_type (nullable) is None # and model_fields_set contains the field if self.debt_transaction_type is None and "debt_transaction_type" in self.model_fields_set: diff --git a/ynab/models/transaction_summary_base.py b/ynab/models/transaction_summary_base.py index 108d534..303ff8e 100644 --- a/ynab/models/transaction_summary_base.py +++ b/ynab/models/transaction_summary_base.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/transactions_import_response.py b/ynab/models/transactions_import_response.py index b17b06a..ab1265a 100644 --- a/ynab/models/transactions_import_response.py +++ b/ynab/models/transactions_import_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/transactions_import_response_data.py b/ynab/models/transactions_import_response_data.py index 01062b3..594e73e 100644 --- a/ynab/models/transactions_import_response_data.py +++ b/ynab/models/transactions_import_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/transactions_response.py b/ynab/models/transactions_response.py index 049691e..dd20126 100644 --- a/ynab/models/transactions_response.py +++ b/ynab/models/transactions_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/transactions_response_data.py b/ynab/models/transactions_response_data.py index d212e81..2e18717 100644 --- a/ynab/models/transactions_response_data.py +++ b/ynab/models/transactions_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -75,8 +75,7 @@ def to_dict(self) -> Dict[str, Any]: _items = [] if self.transactions: for _item_transactions in self.transactions: - if _item_transactions: - _items.append(_item_transactions.to_dict()) + _items.append(_item_transactions.to_dict() if _item_transactions is not None else None) _dict['transactions'] = _items return _dict diff --git a/ynab/models/user.py b/ynab/models/user.py index 2d30c71..d4f9cb1 100644 --- a/ynab/models/user.py +++ b/ynab/models/user.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/user_response.py b/ynab/models/user_response.py index 030fe83..1b65231 100644 --- a/ynab/models/user_response.py +++ b/ynab/models/user_response.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/models/user_response_data.py b/ynab/models/user_response_data.py index 7b6d641..e85f618 100644 --- a/ynab/models/user_response_data.py +++ b/ynab/models/user_response_data.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/ynab/rest.py b/ynab/rest.py index 5e99bfb..c92cf89 100644 --- a/ynab/rest.py +++ b/ynab/rest.py @@ -5,7 +5,7 @@ Our API uses a REST based design, leverages the JSON data format, and relies upon HTTPS for transport. We respond with meaningful HTTP response codes and if an error occurs, we include error details in the response body. Read the [API Documentation](https://api.ynab.com) for more information about the API, including how to obtain an access token and how to use it to make requests. - The version of the OpenAPI document: 1.86.0 + The version of the OpenAPI document: 1.88.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. From 94afa252690f21fa9e7af4ad049a071e97048a82 Mon Sep 17 00:00:00 2001 From: Brady Holt Date: Mon, 2 Nov 2026 12:48:24 -0600 Subject: [PATCH 2/3] Only pass present keys to model_validate in from_dict from_dict passed obj.get() for every field, so a missing key came through as an explicit None and counted as set. to_dict then sent null for it, clearing values on update requests built from a dict. --- templates/model_generic.mustache | 695 ++++++++++++++++++ tests/test_request_serialize.py | 13 + ynab/models/account.py | 4 +- ynab/models/account_base.py | 4 +- ynab/models/account_response.py | 4 +- ynab/models/account_response_data.py | 4 +- ynab/models/accounts_response.py | 4 +- ynab/models/accounts_response_data.py | 4 +- ynab/models/bulk_response.py | 4 +- ynab/models/bulk_response_data.py | 4 +- ynab/models/bulk_response_data_bulk.py | 4 +- ynab/models/bulk_transactions.py | 4 +- ynab/models/categories_response.py | 4 +- ynab/models/categories_response_data.py | 4 +- ynab/models/category.py | 4 +- ynab/models/category_base.py | 4 +- ynab/models/category_group.py | 4 +- ynab/models/category_group_with_categories.py | 4 +- ynab/models/category_response.py | 4 +- ynab/models/category_response_data.py | 4 +- ynab/models/currency_format.py | 4 +- ynab/models/date_format.py | 4 +- ynab/models/error_detail.py | 4 +- ynab/models/error_response.py | 4 +- ynab/models/existing_category.py | 4 +- ynab/models/existing_transaction.py | 4 +- ynab/models/hybrid_transaction.py | 4 +- ynab/models/hybrid_transactions_response.py | 4 +- .../hybrid_transactions_response_data.py | 4 +- ynab/models/money_movement.py | 4 +- ynab/models/money_movement_base.py | 4 +- ynab/models/money_movement_group.py | 4 +- ynab/models/money_movement_groups_response.py | 4 +- .../money_movement_groups_response_data.py | 4 +- ynab/models/money_movements_response.py | 4 +- ynab/models/money_movements_response_data.py | 4 +- ynab/models/month_detail.py | 4 +- ynab/models/month_detail_base.py | 4 +- ynab/models/month_detail_response.py | 4 +- ynab/models/month_detail_response_data.py | 4 +- ynab/models/month_summaries_response.py | 4 +- ynab/models/month_summaries_response_data.py | 4 +- ynab/models/month_summary.py | 4 +- ynab/models/month_summary_base.py | 4 +- ynab/models/new_category.py | 4 +- ynab/models/new_transaction.py | 4 +- ynab/models/patch_category_group_wrapper.py | 4 +- ynab/models/patch_category_wrapper.py | 4 +- ynab/models/patch_month_category_wrapper.py | 4 +- ynab/models/patch_payee_wrapper.py | 4 +- ynab/models/patch_transactions_wrapper.py | 4 +- ynab/models/payee.py | 4 +- ynab/models/payee_location.py | 4 +- ynab/models/payee_location_response.py | 4 +- ynab/models/payee_location_response_data.py | 4 +- ynab/models/payee_locations_response.py | 4 +- ynab/models/payee_locations_response_data.py | 4 +- ynab/models/payee_response.py | 4 +- ynab/models/payee_response_data.py | 4 +- ynab/models/payees_response.py | 4 +- ynab/models/payees_response_data.py | 4 +- ynab/models/plan_detail.py | 4 +- ynab/models/plan_detail_response.py | 4 +- ynab/models/plan_detail_response_data.py | 4 +- ynab/models/plan_settings.py | 4 +- ynab/models/plan_settings_response.py | 4 +- ynab/models/plan_settings_response_data.py | 4 +- ynab/models/plan_summary.py | 4 +- ynab/models/plan_summary_response.py | 4 +- ynab/models/plan_summary_response_data.py | 4 +- ynab/models/post_account_wrapper.py | 4 +- ynab/models/post_category_group_wrapper.py | 4 +- ynab/models/post_category_wrapper.py | 4 +- ynab/models/post_payee.py | 4 +- ynab/models/post_payee_wrapper.py | 4 +- .../post_scheduled_transaction_wrapper.py | 4 +- ynab/models/post_transactions_wrapper.py | 4 +- .../put_scheduled_transaction_wrapper.py | 4 +- ynab/models/put_transaction_wrapper.py | 4 +- ynab/models/save_account.py | 4 +- ynab/models/save_category.py | 4 +- ynab/models/save_category_group.py | 4 +- ynab/models/save_category_group_response.py | 4 +- .../save_category_group_response_data.py | 4 +- ynab/models/save_category_response.py | 4 +- ynab/models/save_category_response_data.py | 4 +- ynab/models/save_month_category.py | 4 +- ynab/models/save_payee.py | 4 +- ynab/models/save_payee_response.py | 4 +- ynab/models/save_payee_response_data.py | 4 +- ynab/models/save_scheduled_transaction.py | 4 +- ynab/models/save_sub_transaction.py | 4 +- .../save_transaction_with_id_or_import_id.py | 4 +- .../save_transaction_with_optional_fields.py | 4 +- ynab/models/save_transactions_response.py | 4 +- .../models/save_transactions_response_data.py | 4 +- ynab/models/scheduled_sub_transaction.py | 4 +- ynab/models/scheduled_sub_transaction_base.py | 4 +- ynab/models/scheduled_transaction_detail.py | 4 +- ynab/models/scheduled_transaction_response.py | 4 +- .../scheduled_transaction_response_data.py | 4 +- ynab/models/scheduled_transaction_summary.py | 4 +- .../scheduled_transaction_summary_base.py | 4 +- .../models/scheduled_transactions_response.py | 4 +- .../scheduled_transactions_response_data.py | 4 +- ynab/models/sub_transaction.py | 4 +- ynab/models/sub_transaction_base.py | 4 +- ynab/models/transaction_detail.py | 4 +- ynab/models/transaction_response.py | 4 +- ynab/models/transaction_response_data.py | 4 +- ynab/models/transaction_summary.py | 4 +- ynab/models/transaction_summary_base.py | 4 +- ynab/models/transactions_import_response.py | 4 +- .../transactions_import_response_data.py | 4 +- ynab/models/transactions_response.py | 4 +- ynab/models/transactions_response_data.py | 4 +- ynab/models/user.py | 4 +- ynab/models/user_response.py | 4 +- ynab/models/user_response_data.py | 4 +- 119 files changed, 942 insertions(+), 234 deletions(-) create mode 100644 templates/model_generic.mustache create mode 100644 tests/test_request_serialize.py diff --git a/templates/model_generic.mustache b/templates/model_generic.mustache new file mode 100644 index 0000000..bd61aa4 --- /dev/null +++ b/templates/model_generic.mustache @@ -0,0 +1,695 @@ +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +{{#vendorExtensions.x-py-other-imports}} +{{{.}}} +{{/vendorExtensions.x-py-other-imports}} +{{#vendorExtensions.x-py-model-imports}} +{{{.}}} +{{/vendorExtensions.x-py-model-imports}} +from typing import Optional, Set +from typing_extensions import Self +from pydantic_core import to_jsonable_python +{{#vendorExtensions.x-py-has-public-name-properties}} +from typing import TYPE_CHECKING +{{/vendorExtensions.x-py-has-public-name-properties}} + +{{^vendorExtensions.x-py-has-public-name-properties}} +{{#hasChildren}} +{{#discriminator}} +from typing import TYPE_CHECKING +{{/discriminator}} +{{/hasChildren}} +{{/vendorExtensions.x-py-has-public-name-properties}} +{{#hasChildren}} +{{#discriminator}} +{{! If this model is a super class, importlib is used. So import the necessary modules for the type here. }} +if TYPE_CHECKING: +{{#mappedModels}} + from {{packageName}}.models.{{model.classFilename}} import {{modelName}} +{{/mappedModels}} + +{{/discriminator}} +{{/hasChildren}} +{{#compatibleWithPythonLegacy}} + +{{#useLegacyModelHelpersModule}} +from {{packageName}}._legacy_model_helpers import ( + _OPENAPI_GENERATOR_TO_DICT, + _get_openapi_to_dict, + _to_legacy_value, + _to_openapi_value, +) +{{/useLegacyModelHelpersModule}} +{{^useLegacyModelHelpersModule}} +{{>_legacy_model_dict_helpers}} +{{/useLegacyModelHelpersModule}} + + +{{/compatibleWithPythonLegacy}} +class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}): + """ + {{#description}}{{{description}}}{{/description}}{{^description}}{{{classname}}}{{/description}} +{{#compatibleWithPythonLegacy}} +{{! +python-legacy generic models exposed metadata and value helpers: +https://github.com/OpenAPITools/openapi-generator/blob/c84b949df1a9ec04ba75989cb49b45c940c2f694/modules/openapi-generator/src/main/resources/python-legacy/model.mustache#L37-L55 +https://github.com/OpenAPITools/openapi-generator/blob/c84b949df1a9ec04ba75989cb49b45c940c2f694/modules/openapi-generator/src/main/resources/python-legacy/model.mustache#L203-L255 +}} + + Attributes: + openapi_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. +{{/compatibleWithPythonLegacy}} + """ # noqa: E501 +{{#vars}} + {{name}}: {{{vendorExtensions.x-py-typing}}} +{{/vars}} +{{#isAdditionalPropertiesTrue}} + additional_properties: Dict[str, Any] = {} +{{/isAdditionalPropertiesTrue}} +{{#compatibleWithPythonLegacy}} + openapi_types: ClassVar[Dict[str, str]] = { +{{#allVars}} + {{#vendorExtensions.x-py-public-name-literal}}{{{vendorExtensions.x-py-public-name-literal}}}{{/vendorExtensions.x-py-public-name-literal}}{{^vendorExtensions.x-py-public-name-literal}}{{#lambda.pythonStringLiteral}}{{{name}}}{{/lambda.pythonStringLiteral}}{{/vendorExtensions.x-py-public-name-literal}}: {{#lambda.pythonStringLiteral}}{{{dataType}}}{{/lambda.pythonStringLiteral}}{{^-last}},{{/-last}} +{{/allVars}} + } + + attribute_map: ClassVar[Dict[str, str]] = { +{{#allVars}} + {{#vendorExtensions.x-py-public-name-literal}}{{{vendorExtensions.x-py-public-name-literal}}}{{/vendorExtensions.x-py-public-name-literal}}{{^vendorExtensions.x-py-public-name-literal}}{{#lambda.pythonStringLiteral}}{{{name}}}{{/lambda.pythonStringLiteral}}{{/vendorExtensions.x-py-public-name-literal}}: {{{vendorExtensions.x-py-wire-name-literal}}}{{^-last}},{{/-last}} +{{/allVars}} + } +{{/compatibleWithPythonLegacy}} + __properties: ClassVar[List[str]] = [{{#allVars}}{{{vendorExtensions.x-py-wire-name-literal}}}{{^-last}}, {{/-last}}{{/allVars}}] +{{#vars}} + {{#vendorExtensions.x-regex}} + + @field_validator('{{{name}}}', mode="before") + def {{{name}}}_validate_regular_expression(cls, value): + """Validates the regular expression""" + {{^required}} + if value is None: + return value + + {{/required}} + {{#required}} + {{#isNullable}} + if value is None: + return value + + {{/isNullable}} + {{/required}} + if isinstance(value, str) and not re.match(r"{{{.}}}", value{{#vendorExtensions.x-modifiers}} ,re.{{{.}}}{{/vendorExtensions.x-modifiers}}): + raise ValueError(r"must validate the regular expression {{{vendorExtensions.x-pattern}}}") + return value + {{/vendorExtensions.x-regex}} + {{#isEnum}} + + @field_validator('{{{name}}}') + def {{{name}}}_validate_enum(cls, value): + """Validates the enum""" + {{^required}} + if value is None: + return value + + {{/required}} + {{#required}} + {{#isNullable}} + if value is None: + return value + + {{/isNullable}} + {{/required}} + {{#isContainer}} + {{#isArray}} + for i in value: + if i not in set([{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}]): + raise ValueError("each list item must be one of ({{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}})") + {{/isArray}} + {{#isMap}} + for i in value.values(): + if i not in set([{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}]): + raise ValueError("dict values must be one of enum values ({{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}})") + {{/isMap}} + {{/isContainer}} + {{^isContainer}} + if value not in set([{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}]): + raise ValueError("must be one of enum values ({{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}})") + {{/isContainer}} + return value + {{/isEnum}} + {{#vendorExtensions.x-python-not-string-enum-values.size}} + @field_validator('{{{name}}}') + def {{{name}}}_validate_not_enum(cls, value): + """Validates values excluded by not""" + {{^required}} + if value is None: + return value + + {{/required}} + {{#required}} + {{#isNullable}} + if value is None: + return value + + {{/isNullable}} + {{/required}} + if value in set([{{#vendorExtensions.x-python-not-string-enum-values}}{{#lambda.pythonStringLiteral}}{{{.}}}{{/lambda.pythonStringLiteral}}{{^-last}}, {{/-last}}{{/vendorExtensions.x-python-not-string-enum-values}}]): + raise ValueError("must not be one of excluded enum values") + return value + {{/vendorExtensions.x-python-not-string-enum-values.size}} +{{/vars}} + +{{#vendorExtensions.x-py-preprocesses-input-names}} + @classmethod + def __preprocess_input_names( + cls, + obj: Any, + remove_hidden_storage_names: bool = True, + ) -> Any: + if not isinstance(obj, _Mapping): + return obj + obj = dict(obj) +{{#vendorExtensions.x-py-input-name-properties}} +{{#vendorExtensions.x-py-public-name-differs-from-wire}} +{{#vendorExtensions.x-py-explicit-public-name}} + if ( + {{{vendorExtensions.x-py-wire-name-literal}}} in obj + and {{{vendorExtensions.x-py-public-name-literal}}} in obj + ): + raise ValueError( + "%s received both %r and %r" + % ( + cls.__name__, + {{{vendorExtensions.x-py-wire-name-literal}}}, + {{{vendorExtensions.x-py-public-name-literal}}}, + ) + ) +{{/vendorExtensions.x-py-explicit-public-name}} + if {{{vendorExtensions.x-py-wire-name-literal}}} not in obj and {{{vendorExtensions.x-py-public-name-literal}}} in obj: + obj[{{{vendorExtensions.x-py-wire-name-literal}}}] = obj[{{{vendorExtensions.x-py-public-name-literal}}}] + obj.pop({{{vendorExtensions.x-py-public-name-literal}}}, None) +{{/vendorExtensions.x-py-public-name-differs-from-wire}} +{{/vendorExtensions.x-py-input-name-properties}} +{{#vendorExtensions.x-py-hidden-storage-names.size}} + if remove_hidden_storage_names: +{{#vendorExtensions.x-py-hidden-storage-names}} + obj.pop({{#lambda.pythonStringLiteral}}{{{.}}}{{/lambda.pythonStringLiteral}}, None) +{{/vendorExtensions.x-py-hidden-storage-names}} +{{/vendorExtensions.x-py-hidden-storage-names.size}} + return obj + +{{/vendorExtensions.x-py-preprocesses-input-names}} +{{#vendorExtensions.x-py-validates-input-names}} + # Pydantic passes the model instance to wrap validators during assignment: + # https://docs.pydantic.dev/2.11/migration/#changes-to-validators + # Private names also keep inherited model validators distinct: + # https://docs.pydantic.dev/2.11/concepts/validators/#on-inheritance + @_model_validator(mode="wrap") + @classmethod + def __validate_input_names( + cls, + obj: Any, + handler: _ModelWrapValidatorHandler[Self], + ) -> Self: + if not isinstance(obj, cls): + obj = cls.__preprocess_input_names(obj) + return handler(obj) + +{{/vendorExtensions.x-py-validates-input-names}} + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + validate_assignment=True, +{{#compatibleWithPythonLegacy}} +{{! +python-legacy generated explicit constructor parameters, so unknown kwargs failed: +https://github.com/OpenAPITools/openapi-generator/blob/c84b949df1a9ec04ba75989cb49b45c940c2f694/modules/openapi-generator/src/main/resources/python-legacy/model.mustache#L64-L100 +}} + extra="forbid", +{{/compatibleWithPythonLegacy}} + protected_namespaces=(), + ) + + +{{#hasChildren}} +{{#discriminator}} + # JSON field name that stores the object type + __discriminator_property_name: ClassVar[str] = {{#lambda.pythonSingleQuotedStringLiteral}}{{{discriminator.propertyBaseName}}}{{/lambda.pythonSingleQuotedStringLiteral}} + + # discriminator mappings + __discriminator_value_class_map: ClassVar[Dict[str, str]] = { + {{#mappedModels}}{{#lambda.pythonSingleQuotedStringLiteral}}{{{mappingName}}}{{/lambda.pythonSingleQuotedStringLiteral}}: '{{{modelName}}}'{{^-last}},{{/-last}}{{/mappedModels}} + } + + @classmethod + def get_discriminator_value(cls, obj: Dict[str, Any]) -> Optional[str]: + """Returns the discriminator value (object type) of the data""" + discriminator_value = obj.get(cls.__discriminator_property_name) + if discriminator_value: + return cls.__discriminator_value_class_map.get(discriminator_value) + else: + return None + +{{/discriminator}} +{{/hasChildren}} + def to_str(self) -> str: +{{#compatibleWithPythonLegacy}} + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) +{{/compatibleWithPythonLegacy}} +{{^compatibleWithPythonLegacy}} + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) +{{/compatibleWithPythonLegacy}} +{{#compatibleWithPythonLegacy}} + + def __repr__(self) -> str: + """For print and pprint""" + return self.to_str() + + def __eq__(self, other: object) -> bool: + """Returns true if both objects are equal""" + if not isinstance(other, {{classname}}): + return False + +{{#isAdditionalPropertiesTrue}} + return ( + self.to_dict() == other.to_dict() + and self.additional_properties == other.additional_properties + ) +{{/isAdditionalPropertiesTrue}} +{{^isAdditionalPropertiesTrue}} + return self.to_dict() == other.to_dict() +{{/isAdditionalPropertiesTrue}} + + def __ne__(self, other: object) -> bool: + """Returns true if both objects are not equal""" + if not isinstance(other, {{classname}}): + return True + + return not (self == other) + +{{/compatibleWithPythonLegacy}} + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" +{{#compatibleWithPythonLegacy}} + to_openapi_dict = _get_openapi_to_dict(self) + if to_openapi_dict is not None: + return json.dumps(to_jsonable_python(to_openapi_dict(self))) + return json.dumps(to_jsonable_python(self.to_dict())) +{{/compatibleWithPythonLegacy}} +{{^compatibleWithPythonLegacy}} + return json.dumps(to_jsonable_python(self.to_dict())) +{{/compatibleWithPythonLegacy}} + + @classmethod + def from_json(cls, json_str: str) -> Optional[{{^hasChildren}}Self{{/hasChildren}}{{#hasChildren}}{{#discriminator}}Union[{{#mappedModels}}{{{modelName}}}{{^-last}}, {{/-last}}{{/mappedModels}}]{{/discriminator}}{{^discriminator}}Self{{/discriminator}}{{/hasChildren}}]: + """Create an instance of {{{classname}}} from a JSON string""" + return cls.from_dict(json.loads(json_str)) + +{{#compatibleWithPythonLegacy}} + def to_dict(self, serialize: bool = False) -> Dict[str, Any]: + """Return all declared model fields using public or wire names.""" + return { +{{#allVars}} + ({{{vendorExtensions.x-py-wire-name-literal}}} if serialize else {{#vendorExtensions.x-py-public-name-literal}}{{{vendorExtensions.x-py-public-name-literal}}}{{/vendorExtensions.x-py-public-name-literal}}{{^vendorExtensions.x-py-public-name-literal}}{{#lambda.pythonStringLiteral}}{{{name}}}{{/lambda.pythonStringLiteral}}{{/vendorExtensions.x-py-public-name-literal}}): _to_legacy_value(getattr(self, {{#lambda.pythonStringLiteral}}{{{name}}}{{/lambda.pythonStringLiteral}}, None), serialize), +{{/allVars}} + } + + def __openapi_generator_modern_projection(self) -> Dict[str, Any]: +{{/compatibleWithPythonLegacy}} +{{^compatibleWithPythonLegacy}} + def to_dict(self) -> Dict[str, Any]: +{{/compatibleWithPythonLegacy}} + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + {{#vendorExtensions.x-py-readonly}} + * OpenAPI `readOnly` fields are excluded. + {{/vendorExtensions.x-py-readonly}} + {{#isAdditionalPropertiesTrue}} + * Fields in `self.additional_properties` are added to the output dict. + {{/isAdditionalPropertiesTrue}} + """ + excluded_fields: Set[str] = set([ + {{#vendorExtensions.x-py-readonly}} + "{{{.}}}", + {{/vendorExtensions.x-py-readonly}} + {{#isAdditionalPropertiesTrue}} + "additional_properties", + {{/isAdditionalPropertiesTrue}} + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + {{#allVars}} + {{#isContainer}} + {{#isArray}} + {{#items.isArray}} + {{^items.items.isPrimitiveType}} + # override the default output from pydantic by calling `to_dict()` of each item in {{{name}}} (list of list) + _items = [] + if self.{{{name}}}: + for _item_{{{name}}} in self.{{{name}}}: + _items.append( + [{{#compatibleWithPythonLegacy}}_to_openapi_value(_inner_item){{/compatibleWithPythonLegacy}}{{^compatibleWithPythonLegacy}}_inner_item.to_dict(){{/compatibleWithPythonLegacy}} if _inner_item is not None else None for _inner_item in _item_{{{name}}}] if _item_{{{name}}} is not None else None + ) + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _items + {{/items.items.isPrimitiveType}} + {{/items.isArray}} + {{#items.isMap}} + {{^items.items.isPrimitiveType}} + # override the default output from pydantic by calling `to_dict()` of each item in {{{name}}} (list of dict) + _items = [] + if self.{{{name}}}: + for _item_{{{name}}} in self.{{{name}}}: + _items.append( + {_inner_key: {{#compatibleWithPythonLegacy}}_to_openapi_value(_inner_value){{/compatibleWithPythonLegacy}}{{^compatibleWithPythonLegacy}}_inner_value.to_dict(){{/compatibleWithPythonLegacy}} if _inner_value is not None else None for _inner_key, _inner_value in _item_{{{name}}}.items()} if _item_{{{name}}} is not None else None + ) + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _items + {{/items.items.isPrimitiveType}} + {{/items.isMap}} + {{^items.isArray}} + {{^items.isMap}} + {{^items.isPrimitiveType}} + {{^items.isEnumOrRef}} + # override the default output from pydantic by calling `to_dict()` of each item in {{{name}}} (list) + _items = [] + if self.{{{name}}}: + for _item_{{{name}}} in self.{{{name}}}: + _items.append({{#compatibleWithPythonLegacy}}_to_openapi_value(_item_{{{name}}}){{/compatibleWithPythonLegacy}}{{^compatibleWithPythonLegacy}}_item_{{{name}}}.to_dict(){{/compatibleWithPythonLegacy}} if _item_{{{name}}} is not None else None) + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _items + {{/items.isEnumOrRef}} + {{/items.isPrimitiveType}} + {{/items.isMap}} + {{/items.isArray}} + {{/isArray}} + {{#isMap}} + {{#items.isArray}} + {{^items.items.isPrimitiveType}} + # override the default output from pydantic by calling `to_dict()` of each value in {{{name}}} (dict of array) + _field_dict_of_array = {} + if self.{{{name}}}: + for _key_{{{name}}} in self.{{{name}}}: + _field_dict_of_array[_key_{{{name}}}] = [ + {{#compatibleWithPythonLegacy}}_to_openapi_value(_item){{/compatibleWithPythonLegacy}}{{^compatibleWithPythonLegacy}}_item.to_dict(){{/compatibleWithPythonLegacy}} if _item is not None else None for _item in self.{{{name}}}[_key_{{{name}}}] + ] if self.{{{name}}}[_key_{{{name}}}] is not None else None + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _field_dict_of_array + {{/items.items.isPrimitiveType}} + {{/items.isArray}} + {{#items.isMap}} + {{^items.items.isPrimitiveType}} + # override the default output from pydantic by calling `to_dict()` of each value in {{{name}}} (dict of dict) + _field_dict_of_dict = {} + if self.{{{name}}}: + for _key_{{{name}}}, _value_{{{name}}} in self.{{{name}}}.items(): + _field_dict_of_dict[_key_{{{name}}}] = { + _key: {{#compatibleWithPythonLegacy}}_to_openapi_value(_value){{/compatibleWithPythonLegacy}}{{^compatibleWithPythonLegacy}}_value.to_dict(){{/compatibleWithPythonLegacy}} if _value is not None else None for _key, _value in _value_{{{name}}}.items() + } if _value_{{{name}}} is not None else None + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _field_dict_of_dict + {{/items.items.isPrimitiveType}} + {{/items.isMap}} + {{^items.isMap}} + {{^items.isArray}} + {{^items.isPrimitiveType}} + {{^items.isEnumOrRef}} + # override the default output from pydantic by calling `to_dict()` of each value in {{{name}}} (dict) + _field_dict = {} + if self.{{{name}}}: + for _key_{{{name}}} in self.{{{name}}}: + _field_dict[_key_{{{name}}}] = {{#compatibleWithPythonLegacy}}_to_openapi_value(self.{{{name}}}[_key_{{{name}}}]){{/compatibleWithPythonLegacy}}{{^compatibleWithPythonLegacy}}self.{{{name}}}[_key_{{{name}}}].to_dict(){{/compatibleWithPythonLegacy}} if self.{{{name}}}[_key_{{{name}}}] is not None else None + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = _field_dict + {{/items.isEnumOrRef}} + {{/items.isPrimitiveType}} + {{/items.isArray}} + {{/items.isMap}} + {{/isMap}} + {{/isContainer}} + {{^isContainer}} + {{^isPrimitiveType}} + {{^isEnumOrRef}} + # override the default output from pydantic by calling `to_dict()` of {{{name}}} + if self.{{{name}}}: + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = {{#compatibleWithPythonLegacy}}_to_openapi_value(self.{{{name}}}){{/compatibleWithPythonLegacy}}{{^compatibleWithPythonLegacy}}self.{{{name}}}.to_dict(){{/compatibleWithPythonLegacy}} + {{/isEnumOrRef}} + {{/isPrimitiveType}} + {{/isContainer}} + {{/allVars}} + {{#isAdditionalPropertiesTrue}} + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + {{/isAdditionalPropertiesTrue}} + {{#allVars}} + {{#isNullable}} + # set to None if {{{name}}} (nullable) is None + # and model_fields_set contains the field + if self.{{name}} is None and "{{{name}}}" in self.model_fields_set: + _dict[{{#lambda.pythonSingleQuotedStringLiteral}}{{{baseName}}}{{/lambda.pythonSingleQuotedStringLiteral}}] = None + + {{/isNullable}} + {{/allVars}} + return _dict + +{{#compatibleWithPythonLegacy}} +{{>_legacy_model_dict_registration}} + +{{/compatibleWithPythonLegacy}} + {{#hasChildren}} + @classmethod + def from_dict(cls, obj: Dict[str, Any]) -> Optional[{{#discriminator}}Union[{{#mappedModels}}{{{modelName}}}{{^-last}}, {{/-last}}{{/mappedModels}}]{{/discriminator}}{{^discriminator}}Self{{/discriminator}}]: + """Create an instance of {{{classname}}} from a dict""" + {{/hasChildren}} + {{^hasChildren}} + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of {{{classname}}} from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + {{/hasChildren}} +{{#vendorExtensions.x-py-preprocesses-input-names}} + + obj = _cast( + Dict[str, Any], + cls.__preprocess_input_names( + obj, + remove_hidden_storage_names={{#hasChildren}}{{#discriminator}}False{{/discriminator}}{{^discriminator}}True{{/discriminator}}{{/hasChildren}}{{^hasChildren}}True{{/hasChildren}}, + ), + ) + +{{/vendorExtensions.x-py-preprocesses-input-names}} + {{#hasChildren}} + {{#discriminator}} + # look up the object type based on discriminator mapping + object_type = cls.get_discriminator_value(obj) + {{#mappedModels}} + if object_type == '{{{modelName}}}': + return import_module("{{packageName}}.models.{{model.classFilename}}").{{modelName}}.from_dict(obj) + {{/mappedModels}} + + raise ValueError("{{{classname}}} failed to lookup discriminator value from " + + json.dumps(obj) + ". Discriminator property name: " + cls.__discriminator_property_name + + ", mapping: " + json.dumps(cls.__discriminator_value_class_map)) + {{/discriminator}} + {{/hasChildren}} + {{^hasChildren}} +{{^vendorExtensions.x-py-preprocesses-input-names}} + +{{/vendorExtensions.x-py-preprocesses-input-names}} + {{#disallowAdditionalPropertiesIfNotPresent}} + {{^isAdditionalPropertiesTrue}} + # raise errors for additional fields in the input + for _key in obj.keys(): + if _key not in cls.__properties: + raise ValueError("Error due to additional fields (not defined in {{classname}}) in the input: " + _key) + + {{/isAdditionalPropertiesTrue}} + {{/disallowAdditionalPropertiesIfNotPresent}} + _obj = cls.model_validate({k: v for k, v in { + {{#allVars}} + {{#isContainer}} + {{#isArray}} + {{#items.isContainer}} + {{#items.isArray}} + {{#items.items.isPrimitiveType}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} + {{/items.items.isPrimitiveType}} + {{^items.items.isPrimitiveType}} + {{{vendorExtensions.x-py-wire-name-literal}}}: [ + [{{{items.items.dataType}}}.from_dict(_inner_item) for _inner_item in _item] if _item is not None else None + for _item in obj[{{{vendorExtensions.x-py-wire-name-literal}}}] + ] if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} + {{/items.items.isPrimitiveType}} + {{/items.isArray}} + {{#items.isMap}} + {{#items.items.isPrimitiveType}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} + {{/items.items.isPrimitiveType}} + {{^items.items.isPrimitiveType}} + {{{vendorExtensions.x-py-wire-name-literal}}}: [ + {_inner_key: {{{items.items.dataType}}}.from_dict(_inner_value) for _inner_key, _inner_value in _item.items()} if _item is not None else None + for _item in obj[{{{vendorExtensions.x-py-wire-name-literal}}}] + ] if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} + {{/items.items.isPrimitiveType}} + {{/items.isMap}} + {{/items.isContainer}} + {{^items.isContainer}} + {{^items.isPrimitiveType}} + {{#items.isEnumOrRef}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} + {{/items.isEnumOrRef}} + {{^items.isEnumOrRef}} + {{{vendorExtensions.x-py-wire-name-literal}}}: [{{{items.dataType}}}.from_dict(_item) for _item in obj[{{{vendorExtensions.x-py-wire-name-literal}}}]] if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} + {{/items.isEnumOrRef}} + {{/items.isPrimitiveType}} + {{#items.isPrimitiveType}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} + {{/items.isPrimitiveType}} + {{/items.isContainer}} + {{/isArray}} + {{#isMap}} + {{^items.isPrimitiveType}} + {{^items.isEnumOrRef}} + {{#items.isContainer}} + {{#items.isMap}} + {{{vendorExtensions.x-py-wire-name-literal}}}: dict( + (_k, dict( + (_ik, {{{items.items.dataType}}}.from_dict(_iv)) + for _ik, _iv in _v.items() + ) + if _v is not None + else None + ) + for _k, _v in obj[{{{vendorExtensions.x-py-wire-name-literal}}}].items() + ) + if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None + else None{{^-last}},{{/-last}} + {{/items.isMap}} + {{#items.isArray}} + {{{vendorExtensions.x-py-wire-name-literal}}}: { + _k: [{{{items.items.dataType}}}.from_dict(_item) for _item in _v] if _v is not None else None + for _k, _v in obj[{{{vendorExtensions.x-py-wire-name-literal}}}].items() + } + if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None + else None{{^-last}},{{/-last}} + {{/items.isArray}} + {{/items.isContainer}} + {{^items.isContainer}} + {{{vendorExtensions.x-py-wire-name-literal}}}: dict( + (_k, {{{items.dataType}}}.from_dict(_v)) + for _k, _v in obj[{{{vendorExtensions.x-py-wire-name-literal}}}].items() + ) + if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None + else None{{^-last}},{{/-last}} + {{/items.isContainer}} + {{/items.isEnumOrRef}} + {{#items.isEnumOrRef}} + {{{vendorExtensions.x-py-wire-name-literal}}}: dict((_k, _v) for _k, _v in obj.get({{{vendorExtensions.x-py-wire-name-literal}}}).items()) if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} + {{/items.isEnumOrRef}} + {{/items.isPrimitiveType}} + {{#items.isPrimitiveType}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} + {{/items.isPrimitiveType}} + {{/isMap}} + {{/isContainer}} + {{^isContainer}} + {{^isPrimitiveType}} + {{^isEnumOrRef}} + {{{vendorExtensions.x-py-wire-name-literal}}}: {{{dataType}}}.from_dict(obj[{{{vendorExtensions.x-py-wire-name-literal}}}]) if obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None else None{{^-last}},{{/-last}} + {{/isEnumOrRef}} + {{#isEnumOrRef}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{#defaultValue}} if {{#isNullable}}{{{vendorExtensions.x-py-wire-name-literal}}} in obj{{/isNullable}}{{^isNullable}}obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None{{/isNullable}} else {{{defaultValue}}}{{/defaultValue}}{{^-last}},{{/-last}} + {{/isEnumOrRef}} + {{/isPrimitiveType}} + {{#isPrimitiveType}} + {{#defaultValue}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) if {{#isNullable}}{{{vendorExtensions.x-py-wire-name-literal}}} in obj{{/isNullable}}{{^isNullable}}obj.get({{{vendorExtensions.x-py-wire-name-literal}}}) is not None{{/isNullable}} else {{{defaultValue}}}{{^-last}},{{/-last}} + {{/defaultValue}} + {{^defaultValue}} + {{{vendorExtensions.x-py-wire-name-literal}}}: obj.get({{{vendorExtensions.x-py-wire-name-literal}}}){{^-last}},{{/-last}} + {{/defaultValue}} + {{/isPrimitiveType}} + {{/isContainer}} + {{/allVars}} + }.items() if k in obj}) + {{#isAdditionalPropertiesTrue}} + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + {{/isAdditionalPropertiesTrue}} + return _obj + {{/hasChildren}} +{{#vendorExtensions.x-py-has-public-name-properties}} + + if TYPE_CHECKING: +{{#vars}} + {{#vendorExtensions.x-py-public-name-differs-from-storage}} + + @property{{#vendorExtensions.x-py-public-name-overrides-base-model}} # type: ignore[override]{{/vendorExtensions.x-py-public-name-overrides-base-model}} + def {{{vendorExtensions.x-py-public-name}}}(self) -> _{{classname}}_{{name}}_public_type: + return self.{{{name}}} + + @{{{vendorExtensions.x-py-public-name}}}.setter + def {{{vendorExtensions.x-py-public-name}}}(self, value: _{{classname}}_{{name}}_public_type) -> None:{{#vendorExtensions.x-py-public-name-overrides-base-model}} # pyright: ignore[reportIncompatibleMethodOverride]{{/vendorExtensions.x-py-public-name-overrides-base-model}} + self.{{{name}}} = value + {{/vendorExtensions.x-py-public-name-differs-from-storage}} +{{/vars}} +{{/vendorExtensions.x-py-has-public-name-properties}} + +{{#vendorExtensions.x-py-postponed-model-imports.size}} +{{#vendorExtensions.x-py-postponed-model-imports}} +{{{.}}} +{{/vendorExtensions.x-py-postponed-model-imports}} +# TODO: Rewrite to not use raise_errors +{{classname}}.model_rebuild(raise_errors=False) +{{/vendorExtensions.x-py-postponed-model-imports.size}} +{{#vendorExtensions.x-py-has-public-name-properties}} + +if TYPE_CHECKING: +{{#vars}} +{{#vendorExtensions.x-py-public-name-differs-from-storage}} + _{{classname}}_{{name}}_public_type = {{{vendorExtensions.x-py-public-name-typing}}} +{{/vendorExtensions.x-py-public-name-differs-from-storage}} +{{/vars}} + +# Install forwarding properties after Pydantic has consumed the class +# namespace and resolved any postponed model annotations. +{{#vars}} +{{#vendorExtensions.x-py-public-name-differs-from-storage}} +setattr( + {{classname}}, + {{{vendorExtensions.x-py-public-name-literal}}}, + property( + lambda self: self.{{{name}}}, + lambda self, value: setattr( + self, + {{#lambda.pythonStringLiteral}}{{{name}}}{{/lambda.pythonStringLiteral}}, + value, + ), + ), +) +{{/vendorExtensions.x-py-public-name-differs-from-storage}} +{{/vars}} +{{/vendorExtensions.x-py-has-public-name-properties}} diff --git a/tests/test_request_serialize.py b/tests/test_request_serialize.py new file mode 100644 index 0000000..8535204 --- /dev/null +++ b/tests/test_request_serialize.py @@ -0,0 +1,13 @@ +from ynab.models.existing_transaction import ExistingTransaction + + +def test_from_dict_omits_missing_nullable_fields(): + transaction = ExistingTransaction.from_dict({"amount": -5000}) + + assert transaction.to_dict() == {"amount": -5000} + + +def test_from_dict_keeps_explicit_null(): + transaction = ExistingTransaction.from_dict({"amount": -5000, "memo": None}) + + assert transaction.to_dict() == {"amount": -5000, "memo": None} diff --git a/ynab/models/account.py b/ynab/models/account.py index 7dd9a1d..f659f8d 100644 --- a/ynab/models/account.py +++ b/ynab/models/account.py @@ -141,7 +141,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "name": obj.get("name"), "type": obj.get("type"), @@ -166,7 +166,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "cleared_balance_currency": obj.get("cleared_balance_currency"), "uncleared_balance_formatted": obj.get("uncleared_balance_formatted"), "uncleared_balance_currency": obj.get("uncleared_balance_currency") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/account_base.py b/ynab/models/account_base.py index 96cfbc3..9c2a6be 100644 --- a/ynab/models/account_base.py +++ b/ynab/models/account_base.py @@ -135,7 +135,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "name": obj.get("name"), "type": obj.get("type"), @@ -154,7 +154,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "debt_minimum_payments": obj.get("debt_minimum_payments"), "debt_escrow_amounts": obj.get("debt_escrow_amounts"), "deleted": obj.get("deleted") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/account_response.py b/ynab/models/account_response.py index fa3ec0c..90fdadc 100644 --- a/ynab/models/account_response.py +++ b/ynab/models/account_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": AccountResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/account_response_data.py b/ynab/models/account_response_data.py index 8d5f8a1..9337f3d 100644 --- a/ynab/models/account_response_data.py +++ b/ynab/models/account_response_data.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "account": Account.from_dict(obj["account"]) if obj.get("account") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/accounts_response.py b/ynab/models/accounts_response.py index 7f38466..eda8b4d 100644 --- a/ynab/models/accounts_response.py +++ b/ynab/models/accounts_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": AccountsResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/accounts_response_data.py b/ynab/models/accounts_response_data.py index c9ece93..2a41c85 100644 --- a/ynab/models/accounts_response_data.py +++ b/ynab/models/accounts_response_data.py @@ -88,10 +88,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "accounts": [Account.from_dict(_item) for _item in obj["accounts"]] if obj.get("accounts") is not None else None, "server_knowledge": obj.get("server_knowledge") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/bulk_response.py b/ynab/models/bulk_response.py index a7438f0..1b1d417 100644 --- a/ynab/models/bulk_response.py +++ b/ynab/models/bulk_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": BulkResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/bulk_response_data.py b/ynab/models/bulk_response_data.py index ac9ab35..5e915ff 100644 --- a/ynab/models/bulk_response_data.py +++ b/ynab/models/bulk_response_data.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "bulk": BulkResponseDataBulk.from_dict(obj["bulk"]) if obj.get("bulk") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/bulk_response_data_bulk.py b/ynab/models/bulk_response_data_bulk.py index a1b7871..c3f253a 100644 --- a/ynab/models/bulk_response_data_bulk.py +++ b/ynab/models/bulk_response_data_bulk.py @@ -81,10 +81,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "transaction_ids": obj.get("transaction_ids"), "duplicate_import_ids": obj.get("duplicate_import_ids") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/bulk_transactions.py b/ynab/models/bulk_transactions.py index 571f268..ebeaea7 100644 --- a/ynab/models/bulk_transactions.py +++ b/ynab/models/bulk_transactions.py @@ -87,9 +87,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "transactions": [SaveTransactionWithOptionalFields.from_dict(_item) for _item in obj["transactions"]] if obj.get("transactions") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/categories_response.py b/ynab/models/categories_response.py index c952aea..7dfa18e 100644 --- a/ynab/models/categories_response.py +++ b/ynab/models/categories_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": CategoriesResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/categories_response_data.py b/ynab/models/categories_response_data.py index 749f6c8..fd82f83 100644 --- a/ynab/models/categories_response_data.py +++ b/ynab/models/categories_response_data.py @@ -88,10 +88,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "category_groups": [CategoryGroupWithCategories.from_dict(_item) for _item in obj["category_groups"]] if obj.get("category_groups") is not None else None, "server_knowledge": obj.get("server_knowledge") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/category.py b/ynab/models/category.py index 1b0b4a7..e46cdaa 100644 --- a/ynab/models/category.py +++ b/ynab/models/category.py @@ -257,7 +257,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "category_group_id": obj.get("category_group_id"), "category_group_name": obj.get("category_group_name"), @@ -299,7 +299,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "goal_overall_funded_currency": obj.get("goal_overall_funded_currency"), "goal_overall_left_formatted": obj.get("goal_overall_left_formatted"), "goal_overall_left_currency": obj.get("goal_overall_left_currency") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/category_base.py b/ynab/models/category_base.py index c4239b8..e5adba0 100644 --- a/ynab/models/category_base.py +++ b/ynab/models/category_base.py @@ -203,7 +203,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "category_group_id": obj.get("category_group_id"), "category_group_name": obj.get("category_group_name"), @@ -231,7 +231,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "goal_overall_left": obj.get("goal_overall_left"), "goal_snoozed_at": obj.get("goal_snoozed_at"), "deleted": obj.get("deleted") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/category_group.py b/ynab/models/category_group.py index 85a8e34..3c71268 100644 --- a/ynab/models/category_group.py +++ b/ynab/models/category_group.py @@ -85,13 +85,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "name": obj.get("name"), "hidden": obj.get("hidden"), "internal": obj.get("internal"), "deleted": obj.get("deleted") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/category_group_with_categories.py b/ynab/models/category_group_with_categories.py index c73dba1..78ae52d 100644 --- a/ynab/models/category_group_with_categories.py +++ b/ynab/models/category_group_with_categories.py @@ -93,14 +93,14 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "name": obj.get("name"), "hidden": obj.get("hidden"), "internal": obj.get("internal"), "deleted": obj.get("deleted"), "categories": [Category.from_dict(_item) for _item in obj["categories"]] if obj.get("categories") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/category_response.py b/ynab/models/category_response.py index 44cf0c9..47152c3 100644 --- a/ynab/models/category_response.py +++ b/ynab/models/category_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": CategoryResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/category_response_data.py b/ynab/models/category_response_data.py index e5a43df..20b104c 100644 --- a/ynab/models/category_response_data.py +++ b/ynab/models/category_response_data.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "category": Category.from_dict(obj["category"]) if obj.get("category") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/currency_format.py b/ynab/models/currency_format.py index fa8c405..8029877 100644 --- a/ynab/models/currency_format.py +++ b/ynab/models/currency_format.py @@ -87,7 +87,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "iso_code": obj.get("iso_code"), "example_format": obj.get("example_format"), "decimal_digits": obj.get("decimal_digits"), @@ -96,7 +96,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "group_separator": obj.get("group_separator"), "currency_symbol": obj.get("currency_symbol"), "display_symbol": obj.get("display_symbol") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/date_format.py b/ynab/models/date_format.py index 227b10b..8ed6cd3 100644 --- a/ynab/models/date_format.py +++ b/ynab/models/date_format.py @@ -80,9 +80,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "format": obj.get("format") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/error_detail.py b/ynab/models/error_detail.py index b72a614..57d0c07 100644 --- a/ynab/models/error_detail.py +++ b/ynab/models/error_detail.py @@ -82,11 +82,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "name": obj.get("name"), "detail": obj.get("detail") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/error_response.py b/ynab/models/error_response.py index 251075a..b280c9b 100644 --- a/ynab/models/error_response.py +++ b/ynab/models/error_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "error": ErrorDetail.from_dict(obj["error"]) if obj.get("error") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/existing_category.py b/ynab/models/existing_category.py index e96b994..d73eb32 100644 --- a/ynab/models/existing_category.py +++ b/ynab/models/existing_category.py @@ -123,7 +123,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "name": obj.get("name"), "note": obj.get("note"), "category_group_id": obj.get("category_group_id"), @@ -131,7 +131,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "goal_target_date": obj.get("goal_target_date"), "goal_needs_whole_amount": obj.get("goal_needs_whole_amount"), "goal_frequency": obj.get("goal_frequency") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/existing_transaction.py b/ynab/models/existing_transaction.py index 3671e29..11ac949 100644 --- a/ynab/models/existing_transaction.py +++ b/ynab/models/existing_transaction.py @@ -127,7 +127,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "account_id": obj.get("account_id"), "date": obj.get("date"), "amount": obj.get("amount"), @@ -139,7 +139,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "approved": obj.get("approved"), "flag_color": obj.get("flag_color"), "subtransactions": [SaveSubTransaction.from_dict(_item) for _item in obj["subtransactions"]] if obj.get("subtransactions") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/hybrid_transaction.py b/ynab/models/hybrid_transaction.py index 6964d10..abe5f97 100644 --- a/ynab/models/hybrid_transaction.py +++ b/ynab/models/hybrid_transaction.py @@ -196,7 +196,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "date": obj.get("date"), "amount": obj.get("amount"), @@ -223,7 +223,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "account_name": obj.get("account_name"), "payee_name": obj.get("payee_name"), "category_name": obj.get("category_name") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/hybrid_transactions_response.py b/ynab/models/hybrid_transactions_response.py index c661ced..793af75 100644 --- a/ynab/models/hybrid_transactions_response.py +++ b/ynab/models/hybrid_transactions_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": HybridTransactionsResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/hybrid_transactions_response_data.py b/ynab/models/hybrid_transactions_response_data.py index 27de96e..37cd1db 100644 --- a/ynab/models/hybrid_transactions_response_data.py +++ b/ynab/models/hybrid_transactions_response_data.py @@ -88,10 +88,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "transactions": [HybridTransaction.from_dict(_item) for _item in obj["transactions"]] if obj.get("transactions") is not None else None, "server_knowledge": obj.get("server_knowledge") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/money_movement.py b/ynab/models/money_movement.py index 5c282c4..f45133e 100644 --- a/ynab/models/money_movement.py +++ b/ynab/models/money_movement.py @@ -127,7 +127,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "month": obj.get("month"), "moved_at": obj.get("moved_at"), @@ -139,7 +139,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "amount": obj.get("amount"), "amount_formatted": obj.get("amount_formatted"), "amount_currency": obj.get("amount_currency") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/money_movement_base.py b/ynab/models/money_movement_base.py index ac08084..80136df 100644 --- a/ynab/models/money_movement_base.py +++ b/ynab/models/money_movement_base.py @@ -125,7 +125,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "month": obj.get("month"), "moved_at": obj.get("moved_at"), @@ -135,7 +135,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "from_category_id": obj.get("from_category_id"), "to_category_id": obj.get("to_category_id"), "amount": obj.get("amount") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/money_movement_group.py b/ynab/models/money_movement_group.py index 568b1fd..87c666e 100644 --- a/ynab/models/money_movement_group.py +++ b/ynab/models/money_movement_group.py @@ -96,13 +96,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "group_created_at": obj.get("group_created_at"), "month": obj.get("month"), "note": obj.get("note"), "performed_by_user_id": obj.get("performed_by_user_id") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/money_movement_groups_response.py b/ynab/models/money_movement_groups_response.py index 4c05d00..a6a8364 100644 --- a/ynab/models/money_movement_groups_response.py +++ b/ynab/models/money_movement_groups_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": MoneyMovementGroupsResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/money_movement_groups_response_data.py b/ynab/models/money_movement_groups_response_data.py index 03904da..258663c 100644 --- a/ynab/models/money_movement_groups_response_data.py +++ b/ynab/models/money_movement_groups_response_data.py @@ -88,10 +88,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "money_movement_groups": [MoneyMovementGroup.from_dict(_item) for _item in obj["money_movement_groups"]] if obj.get("money_movement_groups") is not None else None, "server_knowledge": obj.get("server_knowledge") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/money_movements_response.py b/ynab/models/money_movements_response.py index d94bc00..6a5473f 100644 --- a/ynab/models/money_movements_response.py +++ b/ynab/models/money_movements_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": MoneyMovementsResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/money_movements_response_data.py b/ynab/models/money_movements_response_data.py index dd099e5..abc89be 100644 --- a/ynab/models/money_movements_response_data.py +++ b/ynab/models/money_movements_response_data.py @@ -88,10 +88,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "money_movements": [MoneyMovement.from_dict(_item) for _item in obj["money_movements"]] if obj.get("money_movements") is not None else None, "server_knowledge": obj.get("server_knowledge") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/month_detail.py b/ynab/models/month_detail.py index e667bce..dd7603b 100644 --- a/ynab/models/month_detail.py +++ b/ynab/models/month_detail.py @@ -114,7 +114,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "month": obj.get("month"), "note": obj.get("note"), "income": obj.get("income"), @@ -132,7 +132,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "to_be_budgeted_formatted": obj.get("to_be_budgeted_formatted"), "to_be_budgeted_currency": obj.get("to_be_budgeted_currency"), "categories": [Category.from_dict(_item) for _item in obj["categories"]] if obj.get("categories") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/month_detail_base.py b/ynab/models/month_detail_base.py index 4943ddc..39134e7 100644 --- a/ynab/models/month_detail_base.py +++ b/ynab/models/month_detail_base.py @@ -106,7 +106,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "month": obj.get("month"), "note": obj.get("note"), "income": obj.get("income"), @@ -116,7 +116,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "age_of_money": obj.get("age_of_money"), "deleted": obj.get("deleted"), "categories": [CategoryBase.from_dict(_item) for _item in obj["categories"]] if obj.get("categories") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/month_detail_response.py b/ynab/models/month_detail_response.py index ad0a60e..39f396b 100644 --- a/ynab/models/month_detail_response.py +++ b/ynab/models/month_detail_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": MonthDetailResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/month_detail_response_data.py b/ynab/models/month_detail_response_data.py index 74fb8cc..d84510b 100644 --- a/ynab/models/month_detail_response_data.py +++ b/ynab/models/month_detail_response_data.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "month": MonthDetail.from_dict(obj["month"]) if obj.get("month") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/month_summaries_response.py b/ynab/models/month_summaries_response.py index 51e2268..8283ad3 100644 --- a/ynab/models/month_summaries_response.py +++ b/ynab/models/month_summaries_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": MonthSummariesResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/month_summaries_response_data.py b/ynab/models/month_summaries_response_data.py index 5ffc6c0..4c44dc9 100644 --- a/ynab/models/month_summaries_response_data.py +++ b/ynab/models/month_summaries_response_data.py @@ -88,10 +88,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "months": [MonthSummary.from_dict(_item) for _item in obj["months"]] if obj.get("months") is not None else None, "server_knowledge": obj.get("server_knowledge") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/month_summary.py b/ynab/models/month_summary.py index 952775f..7e3f088 100644 --- a/ynab/models/month_summary.py +++ b/ynab/models/month_summary.py @@ -106,7 +106,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "month": obj.get("month"), "note": obj.get("note"), "income": obj.get("income"), @@ -123,7 +123,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "activity_currency": obj.get("activity_currency"), "to_be_budgeted_formatted": obj.get("to_be_budgeted_formatted"), "to_be_budgeted_currency": obj.get("to_be_budgeted_currency") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/month_summary_base.py b/ynab/models/month_summary_base.py index e0a5547..0109d32 100644 --- a/ynab/models/month_summary_base.py +++ b/ynab/models/month_summary_base.py @@ -98,7 +98,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "month": obj.get("month"), "note": obj.get("note"), "income": obj.get("income"), @@ -107,7 +107,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "to_be_budgeted": obj.get("to_be_budgeted"), "age_of_money": obj.get("age_of_money"), "deleted": obj.get("deleted") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/new_category.py b/ynab/models/new_category.py index 5995252..ef7a034 100644 --- a/ynab/models/new_category.py +++ b/ynab/models/new_category.py @@ -123,7 +123,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "name": obj.get("name"), "note": obj.get("note"), "category_group_id": obj.get("category_group_id"), @@ -131,7 +131,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "goal_target_date": obj.get("goal_target_date"), "goal_needs_whole_amount": obj.get("goal_needs_whole_amount"), "goal_frequency": obj.get("goal_frequency") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/new_transaction.py b/ynab/models/new_transaction.py index 38f8f43..b572b03 100644 --- a/ynab/models/new_transaction.py +++ b/ynab/models/new_transaction.py @@ -133,7 +133,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "account_id": obj.get("account_id"), "date": obj.get("date"), "amount": obj.get("amount"), @@ -146,7 +146,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "flag_color": obj.get("flag_color"), "subtransactions": [SaveSubTransaction.from_dict(_item) for _item in obj["subtransactions"]] if obj.get("subtransactions") is not None else None, "import_id": obj.get("import_id") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/patch_category_group_wrapper.py b/ynab/models/patch_category_group_wrapper.py index 12db8e6..8494d46 100644 --- a/ynab/models/patch_category_group_wrapper.py +++ b/ynab/models/patch_category_group_wrapper.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "category_group": SaveCategoryGroup.from_dict(obj["category_group"]) if obj.get("category_group") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/patch_category_wrapper.py b/ynab/models/patch_category_wrapper.py index bc6701a..b36c6d5 100644 --- a/ynab/models/patch_category_wrapper.py +++ b/ynab/models/patch_category_wrapper.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "category": ExistingCategory.from_dict(obj["category"]) if obj.get("category") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/patch_month_category_wrapper.py b/ynab/models/patch_month_category_wrapper.py index d0d267b..b7545b4 100644 --- a/ynab/models/patch_month_category_wrapper.py +++ b/ynab/models/patch_month_category_wrapper.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "category": SaveMonthCategory.from_dict(obj["category"]) if obj.get("category") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/patch_payee_wrapper.py b/ynab/models/patch_payee_wrapper.py index d76915f..002e0d9 100644 --- a/ynab/models/patch_payee_wrapper.py +++ b/ynab/models/patch_payee_wrapper.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "payee": SavePayee.from_dict(obj["payee"]) if obj.get("payee") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/patch_transactions_wrapper.py b/ynab/models/patch_transactions_wrapper.py index ccab975..cecce33 100644 --- a/ynab/models/patch_transactions_wrapper.py +++ b/ynab/models/patch_transactions_wrapper.py @@ -87,9 +87,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "transactions": [SaveTransactionWithIdOrImportId.from_dict(_item) for _item in obj["transactions"]] if obj.get("transactions") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/payee.py b/ynab/models/payee.py index c376a0b..428c7b5 100644 --- a/ynab/models/payee.py +++ b/ynab/models/payee.py @@ -89,12 +89,12 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "name": obj.get("name"), "transfer_account_id": obj.get("transfer_account_id"), "deleted": obj.get("deleted") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/payee_location.py b/ynab/models/payee_location.py index a3174fb..bbb5dfe 100644 --- a/ynab/models/payee_location.py +++ b/ynab/models/payee_location.py @@ -85,13 +85,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "payee_id": obj.get("payee_id"), "latitude": obj.get("latitude"), "longitude": obj.get("longitude"), "deleted": obj.get("deleted") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/payee_location_response.py b/ynab/models/payee_location_response.py index ad5b2f1..b05e7c1 100644 --- a/ynab/models/payee_location_response.py +++ b/ynab/models/payee_location_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": PayeeLocationResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/payee_location_response_data.py b/ynab/models/payee_location_response_data.py index b054748..2febeb9 100644 --- a/ynab/models/payee_location_response_data.py +++ b/ynab/models/payee_location_response_data.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "payee_location": PayeeLocation.from_dict(obj["payee_location"]) if obj.get("payee_location") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/payee_locations_response.py b/ynab/models/payee_locations_response.py index e7b5a61..7fb6b6d 100644 --- a/ynab/models/payee_locations_response.py +++ b/ynab/models/payee_locations_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": PayeeLocationsResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/payee_locations_response_data.py b/ynab/models/payee_locations_response_data.py index 15c0db9..93e0059 100644 --- a/ynab/models/payee_locations_response_data.py +++ b/ynab/models/payee_locations_response_data.py @@ -87,9 +87,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "payee_locations": [PayeeLocation.from_dict(_item) for _item in obj["payee_locations"]] if obj.get("payee_locations") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/payee_response.py b/ynab/models/payee_response.py index e16847d..2f23926 100644 --- a/ynab/models/payee_response.py +++ b/ynab/models/payee_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": PayeeResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/payee_response_data.py b/ynab/models/payee_response_data.py index 95350c6..6e7d2ef 100644 --- a/ynab/models/payee_response_data.py +++ b/ynab/models/payee_response_data.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "payee": Payee.from_dict(obj["payee"]) if obj.get("payee") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/payees_response.py b/ynab/models/payees_response.py index 940e7bd..5e14f3e 100644 --- a/ynab/models/payees_response.py +++ b/ynab/models/payees_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": PayeesResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/payees_response_data.py b/ynab/models/payees_response_data.py index 1b31256..cb8dea9 100644 --- a/ynab/models/payees_response_data.py +++ b/ynab/models/payees_response_data.py @@ -88,10 +88,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "payees": [Payee.from_dict(_item) for _item in obj["payees"]] if obj.get("payees") is not None else None, "server_knowledge": obj.get("server_knowledge") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/plan_detail.py b/ynab/models/plan_detail.py index 54ec5f5..a10fec6 100644 --- a/ynab/models/plan_detail.py +++ b/ynab/models/plan_detail.py @@ -186,7 +186,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "name": obj.get("name"), "last_modified_on": obj.get("last_modified_on"), @@ -204,7 +204,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "subtransactions": [SubTransactionBase.from_dict(_item) for _item in obj["subtransactions"]] if obj.get("subtransactions") is not None else None, "scheduled_transactions": [ScheduledTransactionSummaryBase.from_dict(_item) for _item in obj["scheduled_transactions"]] if obj.get("scheduled_transactions") is not None else None, "scheduled_subtransactions": [ScheduledSubTransactionBase.from_dict(_item) for _item in obj["scheduled_subtransactions"]] if obj.get("scheduled_subtransactions") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/plan_detail_response.py b/ynab/models/plan_detail_response.py index 406b22b..7c42418 100644 --- a/ynab/models/plan_detail_response.py +++ b/ynab/models/plan_detail_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": PlanDetailResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/plan_detail_response_data.py b/ynab/models/plan_detail_response_data.py index cc14a2a..f3c8c3e 100644 --- a/ynab/models/plan_detail_response_data.py +++ b/ynab/models/plan_detail_response_data.py @@ -85,10 +85,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "plan": PlanDetail.from_dict(obj["plan"]) if obj.get("plan") is not None else None, "server_knowledge": obj.get("server_knowledge") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/plan_settings.py b/ynab/models/plan_settings.py index 1df3016..b02fba4 100644 --- a/ynab/models/plan_settings.py +++ b/ynab/models/plan_settings.py @@ -99,10 +99,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "date_format": DateFormat.from_dict(obj["date_format"]) if obj.get("date_format") is not None else None, "currency_format": CurrencyFormat.from_dict(obj["currency_format"]) if obj.get("currency_format") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/plan_settings_response.py b/ynab/models/plan_settings_response.py index 18d3a07..e64dbcb 100644 --- a/ynab/models/plan_settings_response.py +++ b/ynab/models/plan_settings_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": PlanSettingsResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/plan_settings_response_data.py b/ynab/models/plan_settings_response_data.py index a961104..dccc8ba 100644 --- a/ynab/models/plan_settings_response_data.py +++ b/ynab/models/plan_settings_response_data.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "settings": PlanSettings.from_dict(obj["settings"]) if obj.get("settings") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/plan_summary.py b/ynab/models/plan_summary.py index 4f77a40..fda8a44 100644 --- a/ynab/models/plan_summary.py +++ b/ynab/models/plan_summary.py @@ -114,7 +114,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "name": obj.get("name"), "last_modified_on": obj.get("last_modified_on"), @@ -123,7 +123,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "date_format": DateFormat.from_dict(obj["date_format"]) if obj.get("date_format") is not None else None, "currency_format": CurrencyFormat.from_dict(obj["currency_format"]) if obj.get("currency_format") is not None else None, "accounts": [Account.from_dict(_item) for _item in obj["accounts"]] if obj.get("accounts") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/plan_summary_response.py b/ynab/models/plan_summary_response.py index 37c7e38..6f32055 100644 --- a/ynab/models/plan_summary_response.py +++ b/ynab/models/plan_summary_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": PlanSummaryResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/plan_summary_response_data.py b/ynab/models/plan_summary_response_data.py index 4e21f5d..a10860d 100644 --- a/ynab/models/plan_summary_response_data.py +++ b/ynab/models/plan_summary_response_data.py @@ -91,10 +91,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "plans": [PlanSummary.from_dict(_item) for _item in obj["plans"]] if obj.get("plans") is not None else None, "default_plan": PlanSummary.from_dict(obj["default_plan"]) if obj.get("default_plan") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/post_account_wrapper.py b/ynab/models/post_account_wrapper.py index b6121d4..88653f1 100644 --- a/ynab/models/post_account_wrapper.py +++ b/ynab/models/post_account_wrapper.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "account": SaveAccount.from_dict(obj["account"]) if obj.get("account") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/post_category_group_wrapper.py b/ynab/models/post_category_group_wrapper.py index f307b0e..141a5f7 100644 --- a/ynab/models/post_category_group_wrapper.py +++ b/ynab/models/post_category_group_wrapper.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "category_group": SaveCategoryGroup.from_dict(obj["category_group"]) if obj.get("category_group") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/post_category_wrapper.py b/ynab/models/post_category_wrapper.py index f00c6c9..28c6eab 100644 --- a/ynab/models/post_category_wrapper.py +++ b/ynab/models/post_category_wrapper.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "category": NewCategory.from_dict(obj["category"]) if obj.get("category") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/post_payee.py b/ynab/models/post_payee.py index da3c9ac..248c6f0 100644 --- a/ynab/models/post_payee.py +++ b/ynab/models/post_payee.py @@ -81,9 +81,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "name": obj.get("name") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/post_payee_wrapper.py b/ynab/models/post_payee_wrapper.py index 5005d03..a1520f5 100644 --- a/ynab/models/post_payee_wrapper.py +++ b/ynab/models/post_payee_wrapper.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "payee": PostPayee.from_dict(obj["payee"]) if obj.get("payee") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/post_scheduled_transaction_wrapper.py b/ynab/models/post_scheduled_transaction_wrapper.py index 0b82f28..e485256 100644 --- a/ynab/models/post_scheduled_transaction_wrapper.py +++ b/ynab/models/post_scheduled_transaction_wrapper.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "scheduled_transaction": SaveScheduledTransaction.from_dict(obj["scheduled_transaction"]) if obj.get("scheduled_transaction") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/post_transactions_wrapper.py b/ynab/models/post_transactions_wrapper.py index e3977c3..4cb5b7d 100644 --- a/ynab/models/post_transactions_wrapper.py +++ b/ynab/models/post_transactions_wrapper.py @@ -91,10 +91,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "transaction": NewTransaction.from_dict(obj["transaction"]) if obj.get("transaction") is not None else None, "transactions": [NewTransaction.from_dict(_item) for _item in obj["transactions"]] if obj.get("transactions") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/put_scheduled_transaction_wrapper.py b/ynab/models/put_scheduled_transaction_wrapper.py index aa9b878..de18b8b 100644 --- a/ynab/models/put_scheduled_transaction_wrapper.py +++ b/ynab/models/put_scheduled_transaction_wrapper.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "scheduled_transaction": SaveScheduledTransaction.from_dict(obj["scheduled_transaction"]) if obj.get("scheduled_transaction") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/put_transaction_wrapper.py b/ynab/models/put_transaction_wrapper.py index d382946..2960821 100644 --- a/ynab/models/put_transaction_wrapper.py +++ b/ynab/models/put_transaction_wrapper.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "transaction": ExistingTransaction.from_dict(obj["transaction"]) if obj.get("transaction") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_account.py b/ynab/models/save_account.py index 06b3e4c..a3c782e 100644 --- a/ynab/models/save_account.py +++ b/ynab/models/save_account.py @@ -83,11 +83,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "name": obj.get("name"), "type": obj.get("type"), "balance": obj.get("balance") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_category.py b/ynab/models/save_category.py index f539f82..4220090 100644 --- a/ynab/models/save_category.py +++ b/ynab/models/save_category.py @@ -123,7 +123,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "name": obj.get("name"), "note": obj.get("note"), "category_group_id": obj.get("category_group_id"), @@ -131,7 +131,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "goal_target_date": obj.get("goal_target_date"), "goal_needs_whole_amount": obj.get("goal_needs_whole_amount"), "goal_frequency": obj.get("goal_frequency") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_category_group.py b/ynab/models/save_category_group.py index 0924912..d997197 100644 --- a/ynab/models/save_category_group.py +++ b/ynab/models/save_category_group.py @@ -81,9 +81,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "name": obj.get("name") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_category_group_response.py b/ynab/models/save_category_group_response.py index 42b720e..450272c 100644 --- a/ynab/models/save_category_group_response.py +++ b/ynab/models/save_category_group_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": SaveCategoryGroupResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_category_group_response_data.py b/ynab/models/save_category_group_response_data.py index 992fd39..3202630 100644 --- a/ynab/models/save_category_group_response_data.py +++ b/ynab/models/save_category_group_response_data.py @@ -85,10 +85,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "category_group": CategoryGroup.from_dict(obj["category_group"]) if obj.get("category_group") is not None else None, "server_knowledge": obj.get("server_knowledge") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_category_response.py b/ynab/models/save_category_response.py index 6168b23..e759734 100644 --- a/ynab/models/save_category_response.py +++ b/ynab/models/save_category_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": SaveCategoryResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_category_response_data.py b/ynab/models/save_category_response_data.py index 5256a58..54b9dc7 100644 --- a/ynab/models/save_category_response_data.py +++ b/ynab/models/save_category_response_data.py @@ -85,10 +85,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "category": Category.from_dict(obj["category"]) if obj.get("category") is not None else None, "server_knowledge": obj.get("server_knowledge") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_month_category.py b/ynab/models/save_month_category.py index 2cb954a..8c643ff 100644 --- a/ynab/models/save_month_category.py +++ b/ynab/models/save_month_category.py @@ -80,9 +80,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "budgeted": obj.get("budgeted") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_payee.py b/ynab/models/save_payee.py index 342d71a..57bbeb4 100644 --- a/ynab/models/save_payee.py +++ b/ynab/models/save_payee.py @@ -81,9 +81,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "name": obj.get("name") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_payee_response.py b/ynab/models/save_payee_response.py index 5bc7c7f..5114189 100644 --- a/ynab/models/save_payee_response.py +++ b/ynab/models/save_payee_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": SavePayeeResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_payee_response_data.py b/ynab/models/save_payee_response_data.py index acc6462..4ae7932 100644 --- a/ynab/models/save_payee_response_data.py +++ b/ynab/models/save_payee_response_data.py @@ -85,10 +85,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "payee": Payee.from_dict(obj["payee"]) if obj.get("payee") is not None else None, "server_knowledge": obj.get("server_knowledge") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_scheduled_transaction.py b/ynab/models/save_scheduled_transaction.py index f3ed798..a24440b 100644 --- a/ynab/models/save_scheduled_transaction.py +++ b/ynab/models/save_scheduled_transaction.py @@ -118,7 +118,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "account_id": obj.get("account_id"), "date": obj.get("date"), "amount": obj.get("amount"), @@ -128,7 +128,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "memo": obj.get("memo"), "flag_color": obj.get("flag_color"), "frequency": obj.get("frequency") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_sub_transaction.py b/ynab/models/save_sub_transaction.py index e9528dd..63336ca 100644 --- a/ynab/models/save_sub_transaction.py +++ b/ynab/models/save_sub_transaction.py @@ -106,13 +106,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "amount": obj.get("amount"), "payee_id": obj.get("payee_id"), "payee_name": obj.get("payee_name"), "category_id": obj.get("category_id"), "memo": obj.get("memo") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_transaction_with_id_or_import_id.py b/ynab/models/save_transaction_with_id_or_import_id.py index f84274a..0c997ad 100644 --- a/ynab/models/save_transaction_with_id_or_import_id.py +++ b/ynab/models/save_transaction_with_id_or_import_id.py @@ -139,7 +139,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "account_id": obj.get("account_id"), "date": obj.get("date"), "amount": obj.get("amount"), @@ -153,7 +153,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "subtransactions": [SaveSubTransaction.from_dict(_item) for _item in obj["subtransactions"]] if obj.get("subtransactions") is not None else None, "id": obj.get("id"), "import_id": obj.get("import_id") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_transaction_with_optional_fields.py b/ynab/models/save_transaction_with_optional_fields.py index 0e6e3e0..d6fda3d 100644 --- a/ynab/models/save_transaction_with_optional_fields.py +++ b/ynab/models/save_transaction_with_optional_fields.py @@ -127,7 +127,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "account_id": obj.get("account_id"), "date": obj.get("date"), "amount": obj.get("amount"), @@ -139,7 +139,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "approved": obj.get("approved"), "flag_color": obj.get("flag_color"), "subtransactions": [SaveSubTransaction.from_dict(_item) for _item in obj["subtransactions"]] if obj.get("subtransactions") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_transactions_response.py b/ynab/models/save_transactions_response.py index fb3eb04..cd0d487 100644 --- a/ynab/models/save_transactions_response.py +++ b/ynab/models/save_transactions_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": SaveTransactionsResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/save_transactions_response_data.py b/ynab/models/save_transactions_response_data.py index 08e2dd6..b15331e 100644 --- a/ynab/models/save_transactions_response_data.py +++ b/ynab/models/save_transactions_response_data.py @@ -94,13 +94,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "transaction_ids": obj.get("transaction_ids"), "transaction": TransactionDetail.from_dict(obj["transaction"]) if obj.get("transaction") is not None else None, "transactions": [TransactionDetail.from_dict(_item) for _item in obj["transactions"]] if obj.get("transactions") is not None else None, "duplicate_import_ids": obj.get("duplicate_import_ids"), "server_knowledge": obj.get("server_knowledge") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/scheduled_sub_transaction.py b/ynab/models/scheduled_sub_transaction.py index 01957ea..6b5169e 100644 --- a/ynab/models/scheduled_sub_transaction.py +++ b/ynab/models/scheduled_sub_transaction.py @@ -122,7 +122,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "scheduled_transaction_id": obj.get("scheduled_transaction_id"), "amount": obj.get("amount"), @@ -135,7 +135,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "deleted": obj.get("deleted"), "amount_formatted": obj.get("amount_formatted"), "amount_currency": obj.get("amount_currency") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/scheduled_sub_transaction_base.py b/ynab/models/scheduled_sub_transaction_base.py index abc79c5..8923059 100644 --- a/ynab/models/scheduled_sub_transaction_base.py +++ b/ynab/models/scheduled_sub_transaction_base.py @@ -120,7 +120,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "scheduled_transaction_id": obj.get("scheduled_transaction_id"), "amount": obj.get("amount"), @@ -131,7 +131,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "category_name": obj.get("category_name"), "transfer_account_id": obj.get("transfer_account_id"), "deleted": obj.get("deleted") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/scheduled_transaction_detail.py b/ynab/models/scheduled_transaction_detail.py index 714c26b..4f4cf21 100644 --- a/ynab/models/scheduled_transaction_detail.py +++ b/ynab/models/scheduled_transaction_detail.py @@ -155,7 +155,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "date_first": obj.get("date_first"), "date_next": obj.get("date_next"), @@ -175,7 +175,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "payee_name": obj.get("payee_name"), "category_name": obj.get("category_name"), "subtransactions": [ScheduledSubTransaction.from_dict(_item) for _item in obj["subtransactions"]] if obj.get("subtransactions") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/scheduled_transaction_response.py b/ynab/models/scheduled_transaction_response.py index 84fc68a..7748365 100644 --- a/ynab/models/scheduled_transaction_response.py +++ b/ynab/models/scheduled_transaction_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": ScheduledTransactionResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/scheduled_transaction_response_data.py b/ynab/models/scheduled_transaction_response_data.py index 340aa8d..29907cb 100644 --- a/ynab/models/scheduled_transaction_response_data.py +++ b/ynab/models/scheduled_transaction_response_data.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "scheduled_transaction": ScheduledTransactionDetail.from_dict(obj["scheduled_transaction"]) if obj.get("scheduled_transaction") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/scheduled_transaction_summary.py b/ynab/models/scheduled_transaction_summary.py index 302494d..5450522 100644 --- a/ynab/models/scheduled_transaction_summary.py +++ b/ynab/models/scheduled_transaction_summary.py @@ -134,7 +134,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "date_first": obj.get("date_first"), "date_next": obj.get("date_next"), @@ -150,7 +150,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "deleted": obj.get("deleted"), "amount_formatted": obj.get("amount_formatted"), "amount_currency": obj.get("amount_currency") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/scheduled_transaction_summary_base.py b/ynab/models/scheduled_transaction_summary_base.py index 4572f44..b232e95 100644 --- a/ynab/models/scheduled_transaction_summary_base.py +++ b/ynab/models/scheduled_transaction_summary_base.py @@ -132,7 +132,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "date_first": obj.get("date_first"), "date_next": obj.get("date_next"), @@ -146,7 +146,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "category_id": obj.get("category_id"), "transfer_account_id": obj.get("transfer_account_id"), "deleted": obj.get("deleted") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/scheduled_transactions_response.py b/ynab/models/scheduled_transactions_response.py index 872f960..ea2ec49 100644 --- a/ynab/models/scheduled_transactions_response.py +++ b/ynab/models/scheduled_transactions_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": ScheduledTransactionsResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/scheduled_transactions_response_data.py b/ynab/models/scheduled_transactions_response_data.py index 2c540f9..4c0b1f9 100644 --- a/ynab/models/scheduled_transactions_response_data.py +++ b/ynab/models/scheduled_transactions_response_data.py @@ -88,10 +88,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "scheduled_transactions": [ScheduledTransactionDetail.from_dict(_item) for _item in obj["scheduled_transactions"]] if obj.get("scheduled_transactions") is not None else None, "server_knowledge": obj.get("server_knowledge") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/sub_transaction.py b/ynab/models/sub_transaction.py index 4174acb..6ba931c 100644 --- a/ynab/models/sub_transaction.py +++ b/ynab/models/sub_transaction.py @@ -128,7 +128,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "transaction_id": obj.get("transaction_id"), "amount": obj.get("amount"), @@ -142,7 +142,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "deleted": obj.get("deleted"), "amount_formatted": obj.get("amount_formatted"), "amount_currency": obj.get("amount_currency") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/sub_transaction_base.py b/ynab/models/sub_transaction_base.py index 6213fcb..57424ce 100644 --- a/ynab/models/sub_transaction_base.py +++ b/ynab/models/sub_transaction_base.py @@ -126,7 +126,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "transaction_id": obj.get("transaction_id"), "amount": obj.get("amount"), @@ -138,7 +138,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "transfer_account_id": obj.get("transfer_account_id"), "transfer_transaction_id": obj.get("transfer_transaction_id"), "deleted": obj.get("deleted") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/transaction_detail.py b/ynab/models/transaction_detail.py index a9a408e..be2085a 100644 --- a/ynab/models/transaction_detail.py +++ b/ynab/models/transaction_detail.py @@ -195,7 +195,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "date": obj.get("date"), "amount": obj.get("amount"), @@ -221,7 +221,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "payee_name": obj.get("payee_name"), "category_name": obj.get("category_name"), "subtransactions": [SubTransaction.from_dict(_item) for _item in obj["subtransactions"]] if obj.get("subtransactions") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/transaction_response.py b/ynab/models/transaction_response.py index 2f787d1..0f119d1 100644 --- a/ynab/models/transaction_response.py +++ b/ynab/models/transaction_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": TransactionResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/transaction_response_data.py b/ynab/models/transaction_response_data.py index 620671f..f1161ac 100644 --- a/ynab/models/transaction_response_data.py +++ b/ynab/models/transaction_response_data.py @@ -85,10 +85,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "transaction": TransactionDetail.from_dict(obj["transaction"]) if obj.get("transaction") is not None else None, "server_knowledge": obj.get("server_knowledge") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/transaction_summary.py b/ynab/models/transaction_summary.py index 314ef1e..f3852d0 100644 --- a/ynab/models/transaction_summary.py +++ b/ynab/models/transaction_summary.py @@ -174,7 +174,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "date": obj.get("date"), "amount": obj.get("amount"), @@ -196,7 +196,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "deleted": obj.get("deleted"), "amount_formatted": obj.get("amount_formatted"), "amount_currency": obj.get("amount_currency") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/transaction_summary_base.py b/ynab/models/transaction_summary_base.py index 303ff8e..20981b6 100644 --- a/ynab/models/transaction_summary_base.py +++ b/ynab/models/transaction_summary_base.py @@ -172,7 +172,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id"), "date": obj.get("date"), "amount": obj.get("amount"), @@ -192,7 +192,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "import_payee_name_original": obj.get("import_payee_name_original"), "debt_transaction_type": obj.get("debt_transaction_type"), "deleted": obj.get("deleted") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/transactions_import_response.py b/ynab/models/transactions_import_response.py index ab1265a..24e5007 100644 --- a/ynab/models/transactions_import_response.py +++ b/ynab/models/transactions_import_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": TransactionsImportResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/transactions_import_response_data.py b/ynab/models/transactions_import_response_data.py index 594e73e..20f02b9 100644 --- a/ynab/models/transactions_import_response_data.py +++ b/ynab/models/transactions_import_response_data.py @@ -80,9 +80,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "transaction_ids": obj.get("transaction_ids") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/transactions_response.py b/ynab/models/transactions_response.py index dd20126..8c13a46 100644 --- a/ynab/models/transactions_response.py +++ b/ynab/models/transactions_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": TransactionsResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/transactions_response_data.py b/ynab/models/transactions_response_data.py index 2e18717..8ef4962 100644 --- a/ynab/models/transactions_response_data.py +++ b/ynab/models/transactions_response_data.py @@ -88,10 +88,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "transactions": [TransactionDetail.from_dict(_item) for _item in obj["transactions"]] if obj.get("transactions") is not None else None, "server_knowledge": obj.get("server_knowledge") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/user.py b/ynab/models/user.py index d4f9cb1..5a3bed2 100644 --- a/ynab/models/user.py +++ b/ynab/models/user.py @@ -81,9 +81,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "id": obj.get("id") - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/user_response.py b/ynab/models/user_response.py index 1b65231..903e083 100644 --- a/ynab/models/user_response.py +++ b/ynab/models/user_response.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "data": UserResponseData.from_dict(obj["data"]) if obj.get("data") is not None else None - }) + }.items() if k in obj}) return _obj diff --git a/ynab/models/user_response_data.py b/ynab/models/user_response_data.py index e85f618..14a2f7a 100644 --- a/ynab/models/user_response_data.py +++ b/ynab/models/user_response_data.py @@ -84,9 +84,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ + _obj = cls.model_validate({k: v for k, v in { "user": User.from_dict(obj["user"]) if obj.get("user") is not None else None - }) + }.items() if k in obj}) return _obj From d8af999643913a99c02e30cf422a10c14ce1d6e3 Mon Sep 17 00:00:00 2001 From: Brady Holt Date: Mon, 2 Nov 2026 12:48:35 -0600 Subject: [PATCH 3/3] Bump version to 5.0.0 Passing None explicitly on an update request now sends null and clears the value, where 4.4.1 left it unchanged. That breaks existing callers silently, so it needs a major version. --- openapi-generator-config.yaml | 2 +- pyproject.toml | 2 +- ynab/__init__.py | 2 +- ynab/api_client.py | 2 +- ynab/configuration.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/openapi-generator-config.yaml b/openapi-generator-config.yaml index b1bd7d5..2799b75 100644 --- a/openapi-generator-config.yaml +++ b/openapi-generator-config.yaml @@ -1,5 +1,5 @@ packageName: ynab -packageVersion: 4.5.0 +packageVersion: 5.0.0 packageDescription: Official Python client for the YNAB API. API documentation available at https://api.ynab.com. licenseInfo: name: Apache-2.0 diff --git a/pyproject.toml b/pyproject.toml index e9a62f1..92c0603 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "ynab" -version = "4.5.0" +version = "5.0.0" description = "Official Python client for the YNAB API. API documentation available at https://api.ynab.com. Generated from server specification version 1.88.0" authors = ["YNAB"] license = "Apache-2.0" diff --git a/ynab/__init__.py b/ynab/__init__.py index 49d5fac..fa16546 100644 --- a/ynab/__init__.py +++ b/ynab/__init__.py @@ -14,7 +14,7 @@ """ # noqa: E501 -__version__ = "4.5.0" +__version__ = "5.0.0" # Define package exports __all__ = [ diff --git a/ynab/api_client.py b/ynab/api_client.py index 3d06d5f..d642d5c 100644 --- a/ynab/api_client.py +++ b/ynab/api_client.py @@ -91,7 +91,7 @@ def __init__( self.default_headers[header_name] = header_value self.cookie = cookie # Set default User-Agent. - self.user_agent = 'OpenAPI-Generator/4.5.0/python' + self.user_agent = 'OpenAPI-Generator/5.0.0/python' self.client_side_validation = configuration.client_side_validation def __enter__(self): diff --git a/ynab/configuration.py b/ynab/configuration.py index 1abf999..4b98aa2 100644 --- a/ynab/configuration.py +++ b/ynab/configuration.py @@ -505,7 +505,7 @@ def to_debug_report(self) -> str: "OS: {env}\n"\ "Python Version: {pyversion}\n"\ "Version of the API: 1.88.0\n"\ - "SDK Package Version: 4.5.0".\ + "SDK Package Version: 5.0.0".\ format(env=sys.platform, pyversion=sys.version) def get_host_settings(self) -> List[HostSetting]: