diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2407e5b55..f59e56c82 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,7 @@ on: branches: - master - beta + - private-preview - sdk-release/** - feature/** tags: diff --git a/CODEGEN_VERSION b/CODEGEN_VERSION index 308945cbf..49f59e2e1 100644 --- a/CODEGEN_VERSION +++ b/CODEGEN_VERSION @@ -1 +1 @@ -baff58c9d515cdd5f5c3231d101989d588788c6f \ No newline at end of file +ea0f8e8d45ce01f448d4a4c4d336d1b491ce684f \ No newline at end of file diff --git a/OPENAPI_VERSION b/OPENAPI_VERSION index 28d67d2bf..c42c50657 100644 --- a/OPENAPI_VERSION +++ b/OPENAPI_VERSION @@ -1 +1 @@ -v2442 \ No newline at end of file +v2456 \ No newline at end of file diff --git a/README.md b/README.md index f6929e52c..8b40fd997 100644 --- a/README.md +++ b/README.md @@ -293,6 +293,17 @@ sends by default. If you are overriding `stripe.api_version` / `stripe_version` [webhook endpoint](https://stripe.com/docs/webhooks#api-versions) tied to an older version, be aware that the data you see at runtime may not match the types. +### Open and Closed Enums + +Many of Stripe API enums are open, meaning Stripe may add new values even on older API versions. +To reflect this, open enum fields are typed as `Union[Literal[...], str]` rather than a plain `Literal[...]`. +This ensures the field has the correct type for both values known at SDK release time and other values that may be added later. + +A small number of enums are closed, meaning Stripe guarantees no new values will be added without an API version change. + +Refer to the [API Reference](https://docs.stripe.com) for the latest set of allowed values. + + ### Public Preview SDKs Stripe has features in the [public preview phase](https://docs.stripe.com/release-phases) that can be accessed via versions of this package that have the `bX` suffix like `12.2.0b2`. diff --git a/justfile b/justfile index a56d62314..c9a7a6800 100644 --- a/justfile +++ b/justfile @@ -35,11 +35,11 @@ typecheck: install-test-deps install-dev-deps # ⭐ format all code format: install-dev-deps - ruff format . --quiet + ruff format . > /dev/null # verify formatting, but don't modify files format-check: install-dev-deps - ruff format . --check --quiet + ruff format . --check > /dev/null # remove venv & build artifacts clean: diff --git a/stripe/_discount.py b/stripe/_discount.py index d62b10208..3f034e979 100644 --- a/stripe/_discount.py +++ b/stripe/_discount.py @@ -2,7 +2,7 @@ # File generated from our OpenAPI spec from stripe._expandable_field import ExpandableField from stripe._stripe_object import StripeObject -from typing import ClassVar, Optional +from typing import ClassVar, Optional, Union from typing_extensions import Literal, TYPE_CHECKING if TYPE_CHECKING: @@ -26,7 +26,7 @@ class Source(StripeObject): """ The coupon that was redeemed to create this discount. """ - type: Literal["coupon"] + type: Union[Literal["coupon"], str] """ The source type of the discount. """ diff --git a/stripe/_order.py b/stripe/_order.py index c0f36bcc9..11a60bfb0 100644 --- a/stripe/_order.py +++ b/stripe/_order.py @@ -557,7 +557,7 @@ class WechatPay(StripeObject): """ The client type that the end customer will pay from """ - setup_future_usage: Optional[Literal["none"]] + setup_future_usage: Optional[Union[Literal["none"], str]] """ Indicates that you intend to make future payments with this PaymentIntent's payment method. diff --git a/stripe/_payment_attempt_record.py b/stripe/_payment_attempt_record.py index 4957deb3a..c05ccc110 100644 --- a/stripe/_payment_attempt_record.py +++ b/stripe/_payment_attempt_record.py @@ -280,7 +280,7 @@ class Card(StripeObject): """ card: Optional[Card] - type: Optional[Literal["card"]] + type: Optional[Union[Literal["card"], str]] """ funding type of the underlying payment method. """ @@ -1826,7 +1826,7 @@ class Card(StripeObject): """ card: Optional[Card] - type: Optional[Literal["card"]] + type: Optional[Union[Literal["card"], str]] """ Funding type of the underlying payment method. """ diff --git a/stripe/_payment_intent.py b/stripe/_payment_intent.py index 748c84714..a90fe4e24 100644 --- a/stripe/_payment_intent.py +++ b/stripe/_payment_intent.py @@ -4417,7 +4417,7 @@ class WechatPay(StripeObject): """ The client type that the end customer will pay from """ - setup_future_usage: Optional[Literal["none"]] + setup_future_usage: Optional[Union[Literal["none"], str]] """ Indicates that you intend to make future payments with this PaymentIntent's payment method. diff --git a/stripe/_payment_record.py b/stripe/_payment_record.py index 777f8970e..47988625b 100644 --- a/stripe/_payment_record.py +++ b/stripe/_payment_record.py @@ -300,7 +300,7 @@ class Card(StripeObject): """ card: Optional[Card] - type: Optional[Literal["card"]] + type: Optional[Union[Literal["card"], str]] """ funding type of the underlying payment method. """ @@ -1846,7 +1846,7 @@ class Card(StripeObject): """ card: Optional[Card] - type: Optional[Literal["card"]] + type: Optional[Union[Literal["card"], str]] """ Funding type of the underlying payment method. """ diff --git a/stripe/_stripe_object.py b/stripe/_stripe_object.py index f29bbce42..b37075ab1 100644 --- a/stripe/_stripe_object.py +++ b/stripe/_stripe_object.py @@ -413,7 +413,9 @@ def _refresh_from( for k, v in values.items(): # Apply field encoding coercion (e.g. int64_string: str → int) v = self._coerce_field_value(k, v) - inner_class = self._get_inner_class_type(k) + inner_class = self._get_union_variant_class( + k, v + ) or self._get_inner_class_type(k) is_dict = self._get_inner_class_is_beneath_dict(k) if is_dict: obj = { @@ -682,11 +684,41 @@ def __deepcopy__(self, memo: Dict[int, Any]) -> "StripeObject": _inner_class_dicts: ClassVar[List[str]] = [] _field_encodings: ClassVar[Dict[str, str]] = {} + # Maps a discriminated-union field to (discriminator, {value: class}). Generated + # subclasses override this; every other object keeps the empty default so the + # lookup in _update_attributes stays cheap. + _inner_class_union_variant_types: ClassVar[ + Dict[str, Tuple[str, Dict[str, Type["StripeObject"]]]] + ] = {} + def _get_inner_class_type( self, field_name: str ) -> Optional[Type["StripeObject"]]: return self._inner_class_types.get(field_name) + def _get_union_variant_class( + self, field_name: str, value: Any + ) -> Optional[Type["StripeObject"]]: + """ + Returns the variant class that a discriminated union field's value should + become, based on the discriminator carried in the value itself. + + Returns None rather than raising when the discriminator is absent, is not a + string, or names a variant this version of the SDK does not know about. The + caller then converts without a class, so a variant the API adds after this + release still deserializes instead of blowing up. + """ + union = self._inner_class_union_variant_types.get(field_name) + if union is None or not isinstance(value, dict): + return None + + discriminator, variants = union + discriminator_value = cast(Dict[str, Any], value).get(discriminator) + if not isinstance(discriminator_value, str): + return None + + return variants.get(discriminator_value) + def _get_inner_class_is_beneath_dict(self, field_name: str): return field_name in self._inner_class_dicts diff --git a/stripe/_subscription.py b/stripe/_subscription.py index 1ba407dc3..15c8d05e9 100644 --- a/stripe/_subscription.py +++ b/stripe/_subscription.py @@ -868,7 +868,7 @@ class Subscription(StripeObject): """ Unix timestamp in seconds of when the subscription status transitioned to `paused`. """ - type: Literal["subscription"] + type: Union[Literal["subscription"], str] """ The type of pause. """ diff --git a/stripe/checkout/_session.py b/stripe/checkout/_session.py index 317ceea07..6aa745f45 100644 --- a/stripe/checkout/_session.py +++ b/stripe/checkout/_session.py @@ -1019,7 +1019,7 @@ class AfterpayClearpay(StripeObject): """ class Alipay(StripeObject): - setup_future_usage: Optional[Literal["none"]] + setup_future_usage: Optional[Union[Literal["none"], str]] """ Indicates that you intend to make future payments with this PaymentIntent's payment method. @@ -1993,7 +1993,7 @@ class WechatPay(StripeObject): """ The client type that the end customer will pay from """ - setup_future_usage: Optional[Literal["none"]] + setup_future_usage: Optional[Union[Literal["none"], str]] """ Indicates that you intend to make future payments with this PaymentIntent's payment method. diff --git a/stripe/events/_v2_core_account_including_configuration_customer_capability_status_updated_event.py b/stripe/events/_v2_core_account_including_configuration_customer_capability_status_updated_event.py index e15b8704b..ebb479694 100644 --- a/stripe/events/_v2_core_account_including_configuration_customer_capability_status_updated_event.py +++ b/stripe/events/_v2_core_account_including_configuration_customer_capability_status_updated_event.py @@ -5,7 +5,7 @@ from stripe._stripe_response import StripeResponse from stripe._util import get_api_mode from stripe.v2.core._event import Event, EventNotification, RelatedObject -from typing import Any, Dict, Optional, cast +from typing import Any, Dict, Optional, Union, cast from typing_extensions import Literal, TYPE_CHECKING, override if TYPE_CHECKING: @@ -98,7 +98,7 @@ class V2CoreAccountIncludingConfigurationCustomerCapabilityStatusUpdatedEvent( class V2CoreAccountIncludingConfigurationCustomerCapabilityStatusUpdatedEventData( StripeObject, ): - updated_capability: Literal["automatic_indirect_tax"] + updated_capability: Union[Literal["automatic_indirect_tax"], str] """ Open Enum. The capability which had its status updated. """ diff --git a/stripe/params/_invoice_create_preview_params.py b/stripe/params/_invoice_create_preview_params.py index 0d0c69c32..2317f8014 100644 --- a/stripe/params/_invoice_create_preview_params.py +++ b/stripe/params/_invoice_create_preview_params.py @@ -2268,7 +2268,7 @@ class InvoiceCreatePreviewParamsSubscriptionDetailsPause(TypedDict): """ Determines how to handle debits and credits when pausing. Defaults to `pending_invoice_item`. """ - type: NotRequired[Literal["subscription"]] + type: NotRequired["Literal['subscription']|str"] """ The type of pause to apply. Defaults to `subscription`. """ diff --git a/stripe/params/_order_create_params.py b/stripe/params/_order_create_params.py index 39dbcf848..3197039e7 100644 --- a/stripe/params/_order_create_params.py +++ b/stripe/params/_order_create_params.py @@ -2081,7 +2081,7 @@ class OrderCreateParamsPaymentSettingsPaymentMethodOptionsWechatPay(TypedDict): """ The client type that the end customer will pay from """ - setup_future_usage: NotRequired[Literal["none"]] + setup_future_usage: NotRequired["Literal['none']|str"] """ Indicates that you intend to make future payments with this PaymentIntent's payment method. diff --git a/stripe/params/_order_modify_params.py b/stripe/params/_order_modify_params.py index 16f082804..db9e40be3 100644 --- a/stripe/params/_order_modify_params.py +++ b/stripe/params/_order_modify_params.py @@ -2091,7 +2091,7 @@ class OrderModifyParamsPaymentSettingsPaymentMethodOptionsWechatPay(TypedDict): """ The client type that the end customer will pay from """ - setup_future_usage: NotRequired[Literal["none"]] + setup_future_usage: NotRequired["Literal['none']|str"] """ Indicates that you intend to make future payments with this PaymentIntent's payment method. diff --git a/stripe/params/_order_update_params.py b/stripe/params/_order_update_params.py index f4583aedf..e9c574fea 100644 --- a/stripe/params/_order_update_params.py +++ b/stripe/params/_order_update_params.py @@ -2090,7 +2090,7 @@ class OrderUpdateParamsPaymentSettingsPaymentMethodOptionsWechatPay(TypedDict): """ The client type that the end customer will pay from """ - setup_future_usage: NotRequired[Literal["none"]] + setup_future_usage: NotRequired["Literal['none']|str"] """ Indicates that you intend to make future payments with this PaymentIntent's payment method. diff --git a/stripe/params/_payment_intent_confirm_params.py b/stripe/params/_payment_intent_confirm_params.py index a916e3e84..390608292 100644 --- a/stripe/params/_payment_intent_confirm_params.py +++ b/stripe/params/_payment_intent_confirm_params.py @@ -6590,7 +6590,7 @@ class PaymentIntentConfirmParamsPaymentMethodOptionsWechatPay(TypedDict): """ The client type that the end customer will pay from """ - setup_future_usage: NotRequired[Literal["none"]] + setup_future_usage: NotRequired["Literal['none']|str"] """ Indicates that you intend to make future payments with this PaymentIntent's payment method. diff --git a/stripe/params/_payment_intent_create_params.py b/stripe/params/_payment_intent_create_params.py index ba1c4df03..6315b9ee2 100644 --- a/stripe/params/_payment_intent_create_params.py +++ b/stripe/params/_payment_intent_create_params.py @@ -6710,7 +6710,7 @@ class PaymentIntentCreateParamsPaymentMethodOptionsWechatPay(TypedDict): """ The client type that the end customer will pay from """ - setup_future_usage: NotRequired[Literal["none"]] + setup_future_usage: NotRequired["Literal['none']|str"] """ Indicates that you intend to make future payments with this PaymentIntent's payment method. diff --git a/stripe/params/_payment_intent_modify_params.py b/stripe/params/_payment_intent_modify_params.py index fea6c40b0..ce4fe5325 100644 --- a/stripe/params/_payment_intent_modify_params.py +++ b/stripe/params/_payment_intent_modify_params.py @@ -6563,7 +6563,7 @@ class PaymentIntentModifyParamsPaymentMethodOptionsWechatPay(TypedDict): """ The client type that the end customer will pay from """ - setup_future_usage: NotRequired[Literal["none"]] + setup_future_usage: NotRequired["Literal['none']|str"] """ Indicates that you intend to make future payments with this PaymentIntent's payment method. diff --git a/stripe/params/_payment_intent_update_params.py b/stripe/params/_payment_intent_update_params.py index 9a0356742..4dd4609de 100644 --- a/stripe/params/_payment_intent_update_params.py +++ b/stripe/params/_payment_intent_update_params.py @@ -6562,7 +6562,7 @@ class PaymentIntentUpdateParamsPaymentMethodOptionsWechatPay(TypedDict): """ The client type that the end customer will pay from """ - setup_future_usage: NotRequired[Literal["none"]] + setup_future_usage: NotRequired["Literal['none']|str"] """ Indicates that you intend to make future payments with this PaymentIntent's payment method. diff --git a/stripe/params/_subscription_pause_params.py b/stripe/params/_subscription_pause_params.py index 8bd4a447e..41e9e5257 100644 --- a/stripe/params/_subscription_pause_params.py +++ b/stripe/params/_subscription_pause_params.py @@ -20,7 +20,7 @@ class SubscriptionPauseParams(RequestOptions): """ Determines how to handle debits and credits when pausing. Defaults to `pending_invoice_item`. """ - type: NotRequired[Literal["subscription"]] + type: NotRequired["Literal['subscription']|str"] """ The type of pause to apply. Defaults to `subscription`. """ diff --git a/stripe/params/checkout/_session_create_params.py b/stripe/params/checkout/_session_create_params.py index 71d083fbc..bd1004ef1 100644 --- a/stripe/params/checkout/_session_create_params.py +++ b/stripe/params/checkout/_session_create_params.py @@ -1541,7 +1541,7 @@ class SessionCreateParamsPaymentMethodOptionsAfterpayClearpay(TypedDict): class SessionCreateParamsPaymentMethodOptionsAlipay(TypedDict): - setup_future_usage: NotRequired[Literal["none"]] + setup_future_usage: NotRequired["Literal['none']|str"] """ Indicates that you intend to make future payments with this PaymentIntent's payment method. @@ -2615,7 +2615,7 @@ class SessionCreateParamsPaymentMethodOptionsWechatPay(TypedDict): """ The client type that the end customer will pay from """ - setup_future_usage: NotRequired[Literal["none"]] + setup_future_usage: NotRequired["Literal['none']|str"] """ Indicates that you intend to make future payments with this PaymentIntent's payment method. diff --git a/stripe/params/tax/_registration_create_params.py b/stripe/params/tax/_registration_create_params.py index dd0aa8138..93bc71f1d 100644 --- a/stripe/params/tax/_registration_create_params.py +++ b/stripe/params/tax/_registration_create_params.py @@ -2060,7 +2060,7 @@ class RegistrationCreateParamsCountryOptionsSrStandard(TypedDict): class RegistrationCreateParamsCountryOptionsTh(TypedDict): - type: Literal["simplified"] + type: Union[Literal["simplified"], str] """ Type of registration to be created in `country`. """ diff --git a/stripe/params/v2/billing/_cadence_list_params.py b/stripe/params/v2/billing/_cadence_list_params.py index ee791b64b..8b87cbb0f 100644 --- a/stripe/params/v2/billing/_cadence_list_params.py +++ b/stripe/params/v2/billing/_cadence_list_params.py @@ -1,11 +1,11 @@ # -*- coding: utf-8 -*- # File generated from our OpenAPI spec -from typing import List +from typing import List, Union from typing_extensions import Literal, NotRequired, TypedDict class CadenceListParams(TypedDict): - include: NotRequired[List[Literal["settings_data"]]] + include: NotRequired[List[Union[Literal["settings_data"], str]]] """ Additional resource to include in the response. """ @@ -35,7 +35,7 @@ class CadenceListParamsPayer(TypedDict): """ The ID of the Customer object. If provided, only cadences that specifically reference the provided customer ID will be returned. """ - type: Literal["customer"] + type: Union[Literal["customer"], str] """ A string identifying the type of the payer. Currently the only supported value is `customer`. """ diff --git a/stripe/params/v2/billing/_cadence_retrieve_params.py b/stripe/params/v2/billing/_cadence_retrieve_params.py index 8324c83d1..2629799cc 100644 --- a/stripe/params/v2/billing/_cadence_retrieve_params.py +++ b/stripe/params/v2/billing/_cadence_retrieve_params.py @@ -1,11 +1,11 @@ # -*- coding: utf-8 -*- # File generated from our OpenAPI spec -from typing import List +from typing import List, Union from typing_extensions import Literal, NotRequired, TypedDict class CadenceRetrieveParams(TypedDict): - include: NotRequired[List[Literal["settings_data"]]] + include: NotRequired[List[Union[Literal["settings_data"], str]]] """ Additional resource to include in the response. """ diff --git a/stripe/params/v2/billing/_collection_setting_create_params.py b/stripe/params/v2/billing/_collection_setting_create_params.py index 9d8c260af..7ef3011f0 100644 --- a/stripe/params/v2/billing/_collection_setting_create_params.py +++ b/stripe/params/v2/billing/_collection_setting_create_params.py @@ -180,7 +180,7 @@ class CollectionSettingCreateParamsPaymentMethodOptionsCustomerBalance( """ Configuration for the bank transfer funding type, if the `funding_type` is set to `bank_transfer`. """ - funding_type: NotRequired[Literal["bank_transfer"]] + funding_type: NotRequired["Literal['bank_transfer']|str"] """ The funding method type to be used when there are not enough funds in the customer balance. Currently the only supported value is `bank_transfer`. """ diff --git a/stripe/params/v2/billing/_collection_setting_update_params.py b/stripe/params/v2/billing/_collection_setting_update_params.py index f9878966d..89c19dc4a 100644 --- a/stripe/params/v2/billing/_collection_setting_update_params.py +++ b/stripe/params/v2/billing/_collection_setting_update_params.py @@ -186,7 +186,7 @@ class CollectionSettingUpdateParamsPaymentMethodOptionsCustomerBalance( """ Configuration for the bank transfer funding type, if the `funding_type` is set to `bank_transfer`. """ - funding_type: NotRequired[Literal["bank_transfer"]] + funding_type: NotRequired["Literal['bank_transfer']|str"] """ The funding method type to be used when there are not enough funds in the customer balance. Currently the only supported value is `bank_transfer`. """ diff --git a/stripe/params/v2/billing/_meter_event_adjustment_create_params.py b/stripe/params/v2/billing/_meter_event_adjustment_create_params.py index b39cc81f2..2de4e99d4 100644 --- a/stripe/params/v2/billing/_meter_event_adjustment_create_params.py +++ b/stripe/params/v2/billing/_meter_event_adjustment_create_params.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # File generated from our OpenAPI spec +from typing import Union from typing_extensions import Literal, TypedDict @@ -12,7 +13,7 @@ class MeterEventAdjustmentCreateParams(TypedDict): """ The name of the meter event. Corresponds with the `event_name` field on a meter. """ - type: Literal["cancel"] + type: Union[Literal["cancel"], str] """ Specifies the type of cancellation. Currently supports canceling a single event. """ diff --git a/stripe/params/v2/core/_account_create_params.py b/stripe/params/v2/core/_account_create_params.py index 8a52e2cc5..837b4f0e2 100644 --- a/stripe/params/v2/core/_account_create_params.py +++ b/stripe/params/v2/core/_account_create_params.py @@ -2210,7 +2210,7 @@ class AccountCreateParamsIdentityBusinessDetailsDocumentsBankAccountOwnershipVer """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2223,7 +2223,7 @@ class AccountCreateParamsIdentityBusinessDetailsDocumentsCompanyLicense( """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2236,7 +2236,7 @@ class AccountCreateParamsIdentityBusinessDetailsDocumentsCompanyMemorandumOfAsso """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2249,7 +2249,7 @@ class AccountCreateParamsIdentityBusinessDetailsDocumentsCompanyMinisterialDecre """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2262,7 +2262,7 @@ class AccountCreateParamsIdentityBusinessDetailsDocumentsCompanyRegistrationVeri """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2275,7 +2275,7 @@ class AccountCreateParamsIdentityBusinessDetailsDocumentsCompanyTaxIdVerificatio """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2288,7 +2288,7 @@ class AccountCreateParamsIdentityBusinessDetailsDocumentsPrimaryVerification( """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens referring to each side of the document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -2314,7 +2314,7 @@ class AccountCreateParamsIdentityBusinessDetailsDocumentsProofOfAddress( """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2333,7 +2333,7 @@ class AccountCreateParamsIdentityBusinessDetailsDocumentsProofOfRegistration( """ Person that is signing the document. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2361,7 +2361,7 @@ class AccountCreateParamsIdentityBusinessDetailsDocumentsProofOfUltimateBenefici """ Person that is signing the document. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2865,7 +2865,7 @@ class AccountCreateParamsIdentityIndividualDocumentsCompanyAuthorization( """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2876,7 +2876,7 @@ class AccountCreateParamsIdentityIndividualDocumentsPassport(TypedDict): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2889,7 +2889,7 @@ class AccountCreateParamsIdentityIndividualDocumentsPrimaryVerification( """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens referring to each side of the document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -2915,7 +2915,7 @@ class AccountCreateParamsIdentityIndividualDocumentsSecondaryVerification( """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens referring to each side of the document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -2939,7 +2939,7 @@ class AccountCreateParamsIdentityIndividualDocumentsVisa(TypedDict): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ diff --git a/stripe/params/v2/core/_account_token_create_params.py b/stripe/params/v2/core/_account_token_create_params.py index 9a7025f73..6cfc56b0d 100644 --- a/stripe/params/v2/core/_account_token_create_params.py +++ b/stripe/params/v2/core/_account_token_create_params.py @@ -392,7 +392,7 @@ class AccountTokenCreateParamsIdentityBusinessDetailsDocumentsBankAccountOwnersh """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -405,7 +405,7 @@ class AccountTokenCreateParamsIdentityBusinessDetailsDocumentsCompanyLicense( """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -418,7 +418,7 @@ class AccountTokenCreateParamsIdentityBusinessDetailsDocumentsCompanyMemorandumO """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -431,7 +431,7 @@ class AccountTokenCreateParamsIdentityBusinessDetailsDocumentsCompanyMinisterial """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -444,7 +444,7 @@ class AccountTokenCreateParamsIdentityBusinessDetailsDocumentsCompanyRegistratio """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -457,7 +457,7 @@ class AccountTokenCreateParamsIdentityBusinessDetailsDocumentsCompanyTaxIdVerifi """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -470,7 +470,7 @@ class AccountTokenCreateParamsIdentityBusinessDetailsDocumentsPrimaryVerificatio """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens referring to each side of the document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -496,7 +496,7 @@ class AccountTokenCreateParamsIdentityBusinessDetailsDocumentsProofOfAddress( """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -515,7 +515,7 @@ class AccountTokenCreateParamsIdentityBusinessDetailsDocumentsProofOfRegistratio """ Person that is signing the document. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -543,7 +543,7 @@ class AccountTokenCreateParamsIdentityBusinessDetailsDocumentsProofOfUltimateBen """ Person that is signing the document. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -1063,7 +1063,7 @@ class AccountTokenCreateParamsIdentityIndividualDocumentsCompanyAuthorization( """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -1074,7 +1074,7 @@ class AccountTokenCreateParamsIdentityIndividualDocumentsPassport(TypedDict): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -1087,7 +1087,7 @@ class AccountTokenCreateParamsIdentityIndividualDocumentsPrimaryVerification( """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens referring to each side of the document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -1113,7 +1113,7 @@ class AccountTokenCreateParamsIdentityIndividualDocumentsSecondaryVerification( """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens referring to each side of the document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -1137,7 +1137,7 @@ class AccountTokenCreateParamsIdentityIndividualDocumentsVisa(TypedDict): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ diff --git a/stripe/params/v2/core/_account_update_params.py b/stripe/params/v2/core/_account_update_params.py index 27098b211..360a700e2 100644 --- a/stripe/params/v2/core/_account_update_params.py +++ b/stripe/params/v2/core/_account_update_params.py @@ -2267,7 +2267,7 @@ class AccountUpdateParamsIdentityBusinessDetailsDocumentsBankAccountOwnershipVer """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2280,7 +2280,7 @@ class AccountUpdateParamsIdentityBusinessDetailsDocumentsCompanyLicense( """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2293,7 +2293,7 @@ class AccountUpdateParamsIdentityBusinessDetailsDocumentsCompanyMemorandumOfAsso """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2306,7 +2306,7 @@ class AccountUpdateParamsIdentityBusinessDetailsDocumentsCompanyMinisterialDecre """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2319,7 +2319,7 @@ class AccountUpdateParamsIdentityBusinessDetailsDocumentsCompanyRegistrationVeri """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2332,7 +2332,7 @@ class AccountUpdateParamsIdentityBusinessDetailsDocumentsCompanyTaxIdVerificatio """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2345,7 +2345,7 @@ class AccountUpdateParamsIdentityBusinessDetailsDocumentsPrimaryVerification( """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens referring to each side of the document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -2371,7 +2371,7 @@ class AccountUpdateParamsIdentityBusinessDetailsDocumentsProofOfAddress( """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2390,7 +2390,7 @@ class AccountUpdateParamsIdentityBusinessDetailsDocumentsProofOfRegistration( """ Person that is signing the document. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2418,7 +2418,7 @@ class AccountUpdateParamsIdentityBusinessDetailsDocumentsProofOfUltimateBenefici """ Person that is signing the document. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2924,7 +2924,7 @@ class AccountUpdateParamsIdentityIndividualDocumentsCompanyAuthorization( """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2935,7 +2935,7 @@ class AccountUpdateParamsIdentityIndividualDocumentsPassport(TypedDict): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -2948,7 +2948,7 @@ class AccountUpdateParamsIdentityIndividualDocumentsPrimaryVerification( """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens referring to each side of the document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -2974,7 +2974,7 @@ class AccountUpdateParamsIdentityIndividualDocumentsSecondaryVerification( """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens referring to each side of the document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -2998,7 +2998,7 @@ class AccountUpdateParamsIdentityIndividualDocumentsVisa(TypedDict): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ diff --git a/stripe/params/v2/core/_event_destination_list_params.py b/stripe/params/v2/core/_event_destination_list_params.py index c0320468a..d0cd324a3 100644 --- a/stripe/params/v2/core/_event_destination_list_params.py +++ b/stripe/params/v2/core/_event_destination_list_params.py @@ -1,11 +1,11 @@ # -*- coding: utf-8 -*- # File generated from our OpenAPI spec -from typing import List +from typing import List, Union from typing_extensions import Literal, NotRequired, TypedDict class EventDestinationListParams(TypedDict): - include: NotRequired[List[Literal["webhook_endpoint.url"]]] + include: NotRequired[List[Union[Literal["webhook_endpoint.url"], str]]] """ Additional fields to include in the response. Currently supports `webhook_endpoint.url`. """ diff --git a/stripe/params/v2/core/_event_destination_retrieve_params.py b/stripe/params/v2/core/_event_destination_retrieve_params.py index d43606b1d..ad0200416 100644 --- a/stripe/params/v2/core/_event_destination_retrieve_params.py +++ b/stripe/params/v2/core/_event_destination_retrieve_params.py @@ -1,11 +1,11 @@ # -*- coding: utf-8 -*- # File generated from our OpenAPI spec -from typing import List +from typing import List, Union from typing_extensions import Literal, NotRequired, TypedDict class EventDestinationRetrieveParams(TypedDict): - include: NotRequired[List[Literal["webhook_endpoint.url"]]] + include: NotRequired[List[Union[Literal["webhook_endpoint.url"], str]]] """ Additional fields to include in the response. """ diff --git a/stripe/params/v2/core/_event_destination_update_params.py b/stripe/params/v2/core/_event_destination_update_params.py index bc0feb0b8..b9b59ba83 100644 --- a/stripe/params/v2/core/_event_destination_update_params.py +++ b/stripe/params/v2/core/_event_destination_update_params.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # File generated from our OpenAPI spec from stripe._stripe_object import UntypedStripeObject -from typing import Dict, List, Optional +from typing import Dict, List, Optional, Union from typing_extensions import Literal, NotRequired, TypedDict @@ -14,7 +14,7 @@ class EventDestinationUpdateParams(TypedDict): """ The list of events to enable for this endpoint. """ - include: NotRequired[List[Literal["webhook_endpoint.url"]]] + include: NotRequired[List[Union[Literal["webhook_endpoint.url"], str]]] """ Additional fields to include in the response. Currently supports `webhook_endpoint.url`. """ diff --git a/stripe/params/v2/core/accounts/_person_create_params.py b/stripe/params/v2/core/accounts/_person_create_params.py index 4e7b02531..74e36cf35 100644 --- a/stripe/params/v2/core/accounts/_person_create_params.py +++ b/stripe/params/v2/core/accounts/_person_create_params.py @@ -245,7 +245,7 @@ class PersonCreateParamsDocumentsCompanyAuthorization(TypedDict): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -256,7 +256,7 @@ class PersonCreateParamsDocumentsPassport(TypedDict): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -267,7 +267,7 @@ class PersonCreateParamsDocumentsPrimaryVerification(TypedDict): """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens referring to each side of the document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -289,7 +289,7 @@ class PersonCreateParamsDocumentsSecondaryVerification(TypedDict): """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens referring to each side of the document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -311,7 +311,7 @@ class PersonCreateParamsDocumentsVisa(TypedDict): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ diff --git a/stripe/params/v2/core/accounts/_person_token_create_params.py b/stripe/params/v2/core/accounts/_person_token_create_params.py index 15a321f83..3b1b8fc23 100644 --- a/stripe/params/v2/core/accounts/_person_token_create_params.py +++ b/stripe/params/v2/core/accounts/_person_token_create_params.py @@ -239,7 +239,7 @@ class PersonTokenCreateParamsDocumentsCompanyAuthorization(TypedDict): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -250,7 +250,7 @@ class PersonTokenCreateParamsDocumentsPassport(TypedDict): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -261,7 +261,7 @@ class PersonTokenCreateParamsDocumentsPrimaryVerification(TypedDict): """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens referring to each side of the document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -285,7 +285,7 @@ class PersonTokenCreateParamsDocumentsSecondaryVerification(TypedDict): """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens referring to each side of the document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -309,7 +309,7 @@ class PersonTokenCreateParamsDocumentsVisa(TypedDict): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ diff --git a/stripe/params/v2/core/accounts/_person_update_params.py b/stripe/params/v2/core/accounts/_person_update_params.py index ed45a4816..2318e45f2 100644 --- a/stripe/params/v2/core/accounts/_person_update_params.py +++ b/stripe/params/v2/core/accounts/_person_update_params.py @@ -247,7 +247,7 @@ class PersonUpdateParamsDocumentsCompanyAuthorization(TypedDict): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -258,7 +258,7 @@ class PersonUpdateParamsDocumentsPassport(TypedDict): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -269,7 +269,7 @@ class PersonUpdateParamsDocumentsPrimaryVerification(TypedDict): """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens referring to each side of the document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -291,7 +291,7 @@ class PersonUpdateParamsDocumentsSecondaryVerification(TypedDict): """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens referring to each side of the document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -313,7 +313,7 @@ class PersonUpdateParamsDocumentsVisa(TypedDict): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ diff --git a/stripe/params/v2/money_management/_outbound_payment_create_params.py b/stripe/params/v2/money_management/_outbound_payment_create_params.py index 177953f7e..018963c5f 100644 --- a/stripe/params/v2/money_management/_outbound_payment_create_params.py +++ b/stripe/params/v2/money_management/_outbound_payment_create_params.py @@ -32,7 +32,7 @@ class OutboundPaymentCreateParams(_OutboundPaymentCreateParamsBase): """ The quote for this OutboundPayment. Only required for countries with regulatory mandates to display fee estimates before OutboundPayment creation. """ - purpose: NotRequired[Literal["payroll"]] + purpose: NotRequired["Literal['payroll']|str"] """ The purpose of the OutboundPayment. """ diff --git a/stripe/product_catalog/_trial_offer.py b/stripe/product_catalog/_trial_offer.py index d9e9fcf3e..1b740f53a 100644 --- a/stripe/product_catalog/_trial_offer.py +++ b/stripe/product_catalog/_trial_offer.py @@ -59,7 +59,7 @@ class Transition(StripeObject): """ transition: Transition - type: Literal["transition"] + type: Union[Literal["transition"], str] """ The type of behavior when the trial offer ends. """ diff --git a/stripe/tax/_registration.py b/stripe/tax/_registration.py index dd2d5d50c..cf72a920c 100644 --- a/stripe/tax/_registration.py +++ b/stripe/tax/_registration.py @@ -1166,7 +1166,7 @@ class Sr(StripeObject): """ class Th(StripeObject): - type: Literal["simplified"] + type: Union[Literal["simplified"], str] """ Type of registration in `country`. """ diff --git a/stripe/treasury/_outbound_payment.py b/stripe/treasury/_outbound_payment.py index 6cc41a812..4512897ec 100644 --- a/stripe/treasury/_outbound_payment.py +++ b/stripe/treasury/_outbound_payment.py @@ -300,7 +300,7 @@ class UsDomesticWire(StripeObject): """ String representing the object's type. Objects of the same type share the same value. """ - purpose: Optional[Literal["payroll"]] + purpose: Optional[Union[Literal["payroll"], str]] """ The purpose of the OutboundPayment, if applicable. """ diff --git a/stripe/v2/billing/_cadence.py b/stripe/v2/billing/_cadence.py index 5bf8081b9..87c25020a 100644 --- a/stripe/v2/billing/_cadence.py +++ b/stripe/v2/billing/_cadence.py @@ -179,7 +179,7 @@ class Payer(StripeObject): """ The ID of the Customer object. """ - type: Literal["customer"] + type: Union[Literal["customer"], str] """ A string identifying the type of the payer. Currently the only supported value is `customer`. """ @@ -391,7 +391,9 @@ class EuBankTransfer(StripeObject): """ Configuration for the bank transfer funding type, if the `funding_type` is set to `bank_transfer`. """ - funding_type: Optional[Literal["bank_transfer"]] + funding_type: Optional[ + Union[Literal["bank_transfer"], str] + ] """ The funding method type to be used when there are not enough funds in the customer balance. Currently the only supported value is `bank_transfer`. """ diff --git a/stripe/v2/billing/_collection_setting.py b/stripe/v2/billing/_collection_setting.py index 910efe646..61dc994d9 100644 --- a/stripe/v2/billing/_collection_setting.py +++ b/stripe/v2/billing/_collection_setting.py @@ -131,7 +131,7 @@ class EuBankTransfer(StripeObject): """ Configuration for the bank transfer funding type, if the `funding_type` is set to `bank_transfer`. """ - funding_type: Optional[Literal["bank_transfer"]] + funding_type: Optional[Union[Literal["bank_transfer"], str]] """ The funding method type to be used when there are not enough funds in the customer balance. Currently the only supported value is `bank_transfer`. """ diff --git a/stripe/v2/billing/_collection_setting_version.py b/stripe/v2/billing/_collection_setting_version.py index 9e7502b1c..85b248ebd 100644 --- a/stripe/v2/billing/_collection_setting_version.py +++ b/stripe/v2/billing/_collection_setting_version.py @@ -131,7 +131,7 @@ class EuBankTransfer(StripeObject): """ Configuration for the bank transfer funding type, if the `funding_type` is set to `bank_transfer`. """ - funding_type: Optional[Literal["bank_transfer"]] + funding_type: Optional[Union[Literal["bank_transfer"], str]] """ The funding method type to be used when there are not enough funds in the customer balance. Currently the only supported value is `bank_transfer`. """ diff --git a/stripe/v2/billing/_meter_event_adjustment.py b/stripe/v2/billing/_meter_event_adjustment.py index 741df9078..1a74d9bc3 100644 --- a/stripe/v2/billing/_meter_event_adjustment.py +++ b/stripe/v2/billing/_meter_event_adjustment.py @@ -48,7 +48,7 @@ class Cancel(StripeObject): """ Open Enum. The meter event adjustment's status. """ - type: Literal["cancel"] + type: Union[Literal["cancel"], str] """ Open Enum. Specifies the type of cancellation. Currently supports canceling a single event. """ diff --git a/stripe/v2/core/_account.py b/stripe/v2/core/_account.py index 04fd9c1bd..3709ed331 100644 --- a/stripe/v2/core/_account.py +++ b/stripe/v2/core/_account.py @@ -4183,7 +4183,7 @@ class BankAccountOwnershipVerification(StripeObject): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -4193,7 +4193,7 @@ class CompanyLicense(StripeObject): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -4203,7 +4203,7 @@ class CompanyMemorandumOfAssociation(StripeObject): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -4213,7 +4213,7 @@ class CompanyMinisterialDecree(StripeObject): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -4223,7 +4223,7 @@ class CompanyRegistrationVerification(StripeObject): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -4233,7 +4233,7 @@ class CompanyTaxIdVerification(StripeObject): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -4253,7 +4253,7 @@ class FrontBack(StripeObject): """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens for the front and back of the verification document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -4264,7 +4264,7 @@ class ProofOfAddress(StripeObject): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -4284,7 +4284,7 @@ class Signer(StripeObject): """ Person that is signing the document. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -4305,7 +4305,7 @@ class Signer(StripeObject): """ Person that is signing the document. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -4836,7 +4836,7 @@ class CompanyAuthorization(StripeObject): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -4846,7 +4846,7 @@ class Passport(StripeObject): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -4866,7 +4866,7 @@ class FrontBack(StripeObject): """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens for the front and back of the verification document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -4887,7 +4887,7 @@ class FrontBack(StripeObject): """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens for the front and back of the verification document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -4898,7 +4898,7 @@ class Visa(StripeObject): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ diff --git a/stripe/v2/core/_account_person.py b/stripe/v2/core/_account_person.py index f4f06045a..e1c4a1608 100644 --- a/stripe/v2/core/_account_person.py +++ b/stripe/v2/core/_account_person.py @@ -138,7 +138,7 @@ class CompanyAuthorization(StripeObject): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -148,7 +148,7 @@ class Passport(StripeObject): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ @@ -168,7 +168,7 @@ class FrontBack(StripeObject): """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens for the front and back of the verification document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -189,7 +189,7 @@ class FrontBack(StripeObject): """ The [file upload](https://docs.stripe.com/api/persons/update#create_file) tokens for the front and back of the verification document. """ - type: Literal["front_back"] + type: Union[Literal["front_back"], str] """ The format of the verification document. Currently supports `front_back` only. """ @@ -200,7 +200,7 @@ class Visa(StripeObject): """ One or more document IDs returned by a [file upload](https://docs.stripe.com/api/persons/update#create_file) with a purpose value of `account_requirement`. """ - type: Literal["files"] + type: Union[Literal["files"], str] """ The format of the document. Currently supports `files` only. """ diff --git a/stripe/v2/core/_event.py b/stripe/v2/core/_event.py index 7ad4eed88..2c0eb3886 100644 --- a/stripe/v2/core/_event.py +++ b/stripe/v2/core/_event.py @@ -42,7 +42,7 @@ class Request(StripeObject): """ Information on the API request that instigated the event. """ - type: Literal["request"] + type: Union[Literal["request"], str] """ Event reason type. """ diff --git a/stripe/v2/data/reporting/_query_run.py b/stripe/v2/data/reporting/_query_run.py index 2b217fa40..2fe5eee1d 100644 --- a/stripe/v2/data/reporting/_query_run.py +++ b/stripe/v2/data/reporting/_query_run.py @@ -47,7 +47,7 @@ class DownloadUrl(StripeObject): Contains metadata about the file produced by the `ReportRun` or `QueryRun`, including its content type, size, and a URL to download its contents. """ - type: Literal["file"] + type: Union[Literal["file"], str] """ The type of the `ReportRun` or `QueryRun` result. """ diff --git a/stripe/v2/iam/_activity_log.py b/stripe/v2/iam/_activity_log.py index f400b6d85..843dc981b 100644 --- a/stripe/v2/iam/_activity_log.py +++ b/stripe/v2/iam/_activity_log.py @@ -54,7 +54,7 @@ class Application(StripeObject): """ An application. """ - type: Literal["application"] + type: Union[Literal["application"], str] """ The type of entity. """ diff --git a/stripe/v2/money_management/_outbound_payment.py b/stripe/v2/money_management/_outbound_payment.py index afeae7178..0f7d9b7c9 100644 --- a/stripe/v2/money_management/_outbound_payment.py +++ b/stripe/v2/money_management/_outbound_payment.py @@ -61,7 +61,7 @@ class Failed(StripeObject): """ class Processing(StripeObject): - reason: Literal["under_review"] + reason: Union[Literal["under_review"], str] """ Open Enum. The `processing` status reason. """ @@ -204,7 +204,7 @@ class TraceId(StripeObject): """ The quote for this OutboundPayment. Only required for countries with regulatory mandates to display fee estimates before OutboundPayment creation. """ - purpose: Optional[Literal["payroll"]] + purpose: Optional[Union[Literal["payroll"], str]] """ The purpose of the OutboundPayment. """ diff --git a/stripe/v2/money_management/_outbound_transfer.py b/stripe/v2/money_management/_outbound_transfer.py index 461c5e5dd..81c7f34b7 100644 --- a/stripe/v2/money_management/_outbound_transfer.py +++ b/stripe/v2/money_management/_outbound_transfer.py @@ -54,7 +54,7 @@ class Failed(StripeObject): """ class Processing(StripeObject): - reason: Literal["under_review"] + reason: Union[Literal["under_review"], str] """ Open Enum. The `processing` status reason. """ diff --git a/stripe/v2/money_management/_received_credit.py b/stripe/v2/money_management/_received_credit.py index 7031faf79..5e21a021f 100644 --- a/stripe/v2/money_management/_received_credit.py +++ b/stripe/v2/money_management/_received_credit.py @@ -94,7 +94,7 @@ class SepaBankAccount(StripeObject): """ The IBAN that originated the transfer. """ - network: Literal["sepa_credit_transfer"] + network: Union[Literal["sepa_credit_transfer"], str] """ The money transmission network used to send funds for this ReceivedCredit. """ @@ -170,7 +170,7 @@ class Failed(StripeObject): """ class Returned(StripeObject): - reason: Literal["originator_initiated_reversal"] + reason: Union[Literal["originator_initiated_reversal"], str] """ Open Enum. The `returned` status reason. """ diff --git a/stripe/v2/money_management/_received_debit.py b/stripe/v2/money_management/_received_debit.py index 75ce02518..e875eb3e8 100644 --- a/stripe/v2/money_management/_received_debit.py +++ b/stripe/v2/money_management/_received_debit.py @@ -21,7 +21,7 @@ class UsBankAccount(StripeObject): """ The name of the bank the debit originated from. """ - network: Literal["ach"] + network: Union[Literal["ach"], str] """ Open Enum. The bank network the debit was originated on. """ @@ -34,7 +34,7 @@ class UsBankAccount(StripeObject): """ The Financial Address that was debited. """ - payment_method_type: Literal["us_bank_account"] + payment_method_type: Union[Literal["us_bank_account"], str] """ Open Enum. The type of the payment method used to originate the debit. """ diff --git a/tests/test_discriminated_unions.py b/tests/test_discriminated_unions.py new file mode 100644 index 000000000..ff20cc1a6 --- /dev/null +++ b/tests/test_discriminated_unions.py @@ -0,0 +1,309 @@ +""" +Tests for discriminated union runtime behavior. + +A discriminated union field arrives as a plain JSON object, and the SDK has to +pick the variant class out of the discriminator carried inside that object. The +fixtures below mirror what codegen emits for the fake spec's `test.llama` +resource, including the part that makes dispatch *observable*: the two color +variants declare different `_field_encodings`, so identical wire bytes hydrate +differently based only on the discriminator. Without dispatch the value becomes +a bare StripeObject carrying no encodings, and every coercion assertion here +fails. + +Static type narrowing (Literal discriminators, Union resolution) is checked by +pyright, not here. +""" + +from decimal import Decimal +from typing import Any, Dict, Optional, Union + +from typing_extensions import Literal + +from stripe._encode import _coerce_v2_params +from stripe._stripe_object import StripeObject + + +# --------------------------------------------------------------------------- +# Fixtures — shaped the way codegen emits them +# --------------------------------------------------------------------------- + + +class RgbColor(StripeObject): + luminance: Optional[int] + model: Literal["rgb"] + _field_encodings = {"luminance": "int64_string"} + + +class HsvColor(StripeObject): + model: Literal["hsv"] + saturation_precision: Optional[Decimal] + _field_encodings = {"saturation_precision": "decimal_string"} + + +class HslColor(StripeObject): + model: Literal["hsl"] + + +class MagicLlama(StripeObject): + mana_cost: Optional[int] + _field_encodings = {"mana_cost": "int64_string"} + + +class Llama(StripeObject): + """ + Carries both union shapes the generator produces: a standalone `color` + union whose variants are separate classes, and an inline `magic_llama` + union whose discriminator lives on the parent and whose payload is a + plain inner class. + """ + + color: Union[RgbColor, HsvColor, HslColor] + magic_llama: Optional[MagicLlama] + name: str + type: Literal["earth_llama", "magic_llama"] + _inner_class_types = {"magic_llama": MagicLlama} + _inner_class_union_variant_types = { + "color": ( + "model", + {"rgb": RgbColor, "hsv": HsvColor, "hsl": HslColor}, + ), + } + + +def _llama(**values: Any) -> Llama: + return Llama.construct_from( + {"name": "kuzco", **values}, key="sk_test", api_mode="V2" + ) + + +# Copied from the generated `LlamaService.create` call site. The generator +# flattens every variant's fields into one map keyed by field name, so this +# single schema covers both `luminance` (rgb) and `saturation_precision` (hsv). +_COLOR_REQUEST_SCHEMA: Dict[str, Any] = { + "color": { + "luminance": "int64_string", + "saturation_precision": "decimal_string", + }, +} + + +# --------------------------------------------------------------------------- +# Response side — variant dispatch +# --------------------------------------------------------------------------- + + +class TestVariantDispatch: + """The discriminator selects the variant class, not the base.""" + + def test_dispatches_to_the_rgb_variant(self): + llama = _llama(color={"model": "rgb", "luminance": "1500"}) + assert isinstance(llama.color, RgbColor) + + def test_dispatches_to_the_hsv_variant(self): + llama = _llama(color={"model": "hsv", "saturation_precision": "0.125"}) + assert isinstance(llama.color, HsvColor) + + def test_dispatches_to_a_variant_with_no_payload_fields(self): + llama = _llama(color={"model": "hsl"}) + assert isinstance(llama.color, HslColor) + assert llama.color.model == "hsl" + + def test_the_variants_int64_encoding_applies(self): + llama = _llama(color={"model": "rgb", "luminance": "1500"}) + assert llama.color.luminance == 1500 + assert isinstance(llama.color.luminance, int) + + def test_the_variants_decimal_encoding_applies(self): + llama = _llama(color={"model": "hsv", "saturation_precision": "0.125"}) + assert llama.color.saturation_precision == Decimal("0.125") + assert isinstance(llama.color.saturation_precision, Decimal) + + def test_only_the_discriminator_decides_which_field_coerces(self): + """ + The sharpest statement of what dispatch buys: two payloads differing + in nothing but the discriminator coerce different fields, because each + variant class knows only its own encodings. + """ + payload = {"luminance": "1500", "saturation_precision": "0.125"} + + as_rgb = _llama(color={"model": "rgb", **payload}).color + assert as_rgb.luminance == 1500 + assert as_rgb.saturation_precision == "0.125" + + as_hsv = _llama(color={"model": "hsv", **payload}).color + assert as_hsv.luminance == "1500" + assert as_hsv.saturation_precision == Decimal("0.125") + + def test_the_discriminator_itself_is_readable_on_the_variant(self): + llama = _llama(color={"model": "rgb", "luminance": "1"}) + assert llama.color.model == "rgb" + assert llama.color["model"] == "rgb" + + +# --------------------------------------------------------------------------- +# Response side — fallback +# --------------------------------------------------------------------------- + + +class TestUnknownVariantFallback: + """ + A variant the API adds after this release must still deserialize. The + fallback is a plain StripeObject: readable, but with no encodings, since + the SDK has no idea what the new variant's fields mean. + """ + + def test_an_unknown_discriminator_falls_back(self): + llama = _llama(color={"model": "cmyk", "cyan": "1"}) + assert type(llama.color) is StripeObject + assert llama.color.model == "cmyk" + assert llama.color.cyan == "1" + + def test_an_absent_discriminator_falls_back(self): + llama = _llama(color={"luminance": "1500"}) + assert type(llama.color) is StripeObject + assert llama.color.luminance == "1500" + + def test_a_non_string_discriminator_falls_back(self): + llama = _llama(color={"model": 7}) + assert type(llama.color) is StripeObject + + def test_a_null_union_value_stays_none(self): + assert _llama(color=None).color is None + + def test_a_non_object_union_value_passes_through(self): + """ + Not a shape the API produces, but the lookup must not raise on it — + the union field is read before anything has validated its type. + """ + assert _llama(color="rgb").color == "rgb" + + +# --------------------------------------------------------------------------- +# Response side — inline unions are unaffected +# --------------------------------------------------------------------------- + + +class TestInlineUnionsUseInnerClassTypes: + """ + Inline union variants are namespaced by field name, so they need no + discriminator lookup and keep going through `_inner_class_types`. These + pin that the union lookup did not displace it. + """ + + def test_the_inline_variant_gets_its_inner_class(self): + llama = _llama(type="magic_llama", magic_llama={"mana_cost": "42"}) + assert isinstance(llama.magic_llama, MagicLlama) + + def test_the_inline_variants_encoding_applies(self): + llama = _llama(type="magic_llama", magic_llama={"mana_cost": "42"}) + assert llama.magic_llama.mana_cost == 42 + assert isinstance(llama.magic_llama.mana_cost, int) + + def test_the_non_selected_variant_is_not_fabricated(self): + llama = _llama(type="earth_llama") + assert llama.type == "earth_llama" + # `__getattr__` raises for a key absent from `_data`, so this is a + # real statement that nothing was materialized for the other variant. + assert not hasattr(llama, "magic_llama") + + +# --------------------------------------------------------------------------- +# Response side — serialization back out +# --------------------------------------------------------------------------- + + +class TestUnionValueSerialization: + def test_to_dict_recurses_into_the_variant(self): + llama = _llama(color={"model": "rgb", "luminance": "1500"}) + assert llama.to_dict()["color"] == { + "model": "rgb", + "luminance": 1500, + } + + def test_to_dict_for_json_restringifies_the_decimal(self): + """ + The variant hydrates `saturation_precision` to a Decimal, which is not + JSON-serializable, so `for_json` has to put the string back. + """ + llama = _llama(color={"model": "hsv", "saturation_precision": "0.125"}) + + plain = llama.to_dict()["color"]["saturation_precision"] + assert isinstance(plain, Decimal) + + for_json = llama.to_dict(for_json=True)["color"] + assert for_json["saturation_precision"] == "0.125" + assert isinstance(for_json["saturation_precision"], str) + + def test_to_dict_preserves_an_unknown_variant_verbatim(self): + llama = _llama(color={"model": "cmyk", "cyan": "1"}) + assert llama.to_dict()["color"] == {"model": "cmyk", "cyan": "1"} + + +# --------------------------------------------------------------------------- +# Request side +# --------------------------------------------------------------------------- + + +class TestUnionRequestCoercion: + """ + Outbound coercion runs off the method-level schema, which is keyed by + field name only — there is no discriminator in it. + """ + + def test_the_rgb_variants_int64_field_is_stringified(self): + result = _coerce_v2_params( + {"color": {"model": "rgb", "luminance": 1500}}, + _COLOR_REQUEST_SCHEMA, + ) + assert result == {"color": {"model": "rgb", "luminance": "1500"}} + + def test_the_hsv_variants_decimal_field_is_stringified(self): + result = _coerce_v2_params( + { + "color": { + "model": "hsv", + "saturation_precision": Decimal("0.125"), + } + }, + _COLOR_REQUEST_SCHEMA, + ) + assert result == { + "color": {"model": "hsv", "saturation_precision": "0.125"} + } + + def test_a_payload_free_variant_passes_through_untouched(self): + result = _coerce_v2_params( + {"color": {"model": "hsl"}}, _COLOR_REQUEST_SCHEMA + ) + assert result == {"color": {"model": "hsl"}} + + def test_coercion_is_by_field_name_not_by_variant(self): + """ + Pins the generator's flattening decision: every variant's fields land + in one map, so a field is coerced whenever it appears, whatever the + discriminator says. Safe while variants do not share a field name with + conflicting encodings. + """ + result = _coerce_v2_params( + { + "color": { + "model": "rgb", + "saturation_precision": Decimal("0.5"), + } + }, + _COLOR_REQUEST_SCHEMA, + ) + assert result == { + "color": {"model": "rgb", "saturation_precision": "0.5"} + } + + def test_unknown_variant_fields_pass_through(self): + result = _coerce_v2_params( + {"color": {"model": "cmyk", "cyan": 1}}, + _COLOR_REQUEST_SCHEMA, + ) + assert result == {"color": {"model": "cmyk", "cyan": 1}} + + def test_a_null_union_is_not_coerced(self): + result = _coerce_v2_params({"color": None}, _COLOR_REQUEST_SCHEMA) + assert result == {"color": None}