-
Notifications
You must be signed in to change notification settings - Fork 453
Description
Describe the bug
Many CreateParams
attributes on StripeObject
s are defined to be non-optional. This means that if that keyword argument is passed into the .create(
function, it must be a non-null value (that also adheres to the defined typing).
However, the API supports passing null values on many of these attributes and that seems to contextually make sense.
One example is the promotion_code attribute on the Subscription
CreateParams
class.
The following call succeeds without issue:
import stripe
api_key = "***" # loaded from env
api_version = "2023-10-16" # At the time of writing this ticket, I am using this API version
customer_id = "cus_xxx" # use any customer_id with a payment source in your own env
price_id = "price_xxx". # use an existing active price on a product in your stripe env
promotion_code = None
subscription = stripe.Subscription.create(
customer=customer_id,
items=[{"price": price_id}],
payment_behavior="error_if_incomplete",
promotion_code=promotion_code,
)
however, mypy will find issues with the fact that promotion_code
is None
and prefers it not to be passed at all.
The workaround at this current moment (other than ignoring the type issue) would be to add a conditional
if promotion_code:
subscription = stripe.Subscription.create(
customer=customer_id,
items=[{"price": price_id}],
payment_behavior="error_if_incomplete",
promotion_code=promotion_code,
)
else:
subscription = stripe.Subscription.create(
customer=customer_id,
items=[{"price": price_id}],
payment_behavior="error_if_incomplete",
)
however, this is quite tedious and becomes unruly if you have more than one attribute you need to check (a permutation of checks will occur)
To Reproduce
- Write the follow or similar code
import stripe
api_key = "***" # loaded from env
api_version = "2023-10-16" # At the time of writing this ticket, I am using this API version
customer_id = "cus_xxx" # use any customer_id with a payment source in your own env
price_id = "price_xxx". # use an existing active price on a product in your stripe env
promotion_code = None
subscription = stripe.Subscription.create(
customer=customer_id,
items=[{"price": price_id}],
payment_behavior="error_if_incomplete",
promotion_code=promotion_code,
)
- Run mypy checker
- You will see the following error:
error: Argument "promotion_code" to "create" of "Subscription" has incompatible type "str | None"; expected "str" [arg-type]
Expected behavior
Using this line as an example, any nullable CreateParams
attribute should be noted as Optional
Suggested Solution
promotion_code: NotRequired["str|None"]
^This solution most similarly reflects the way that Optional is implemented on the base RequestOptions
class
Code snippets
Sample attribute to modify: https://github.com/stripe/stripe-python/blob/1657f036266412b7ef38d46c77f1b30f5455d83b/stripe/_subscription.py#L594
Existing way Optional is implemented: https://github.com/stripe/stripe-python/blob/1657f036266412b7ef38d46c77f1b30f5455d83b/stripe/_request_options.py#L7
OS
macOS
Language version
Python 3.11.3
Library version
stripe-python v8.9.0
API version
2023-10-16
Additional context
No response
Activity
helenye-stripe commentedon Apr 3, 2024
Hi @tetsujiono! Thanks for pointing this out, we'll investigate whether or not to add this for QoL improvement. In the meantime, this is a small improvement:
aahung commentedon Apr 8, 2024
BTW, somehow it only complaints when running in ghaction, but not on my Mac with latest mypy and same
stripe
version (8.10.0)tetsujiono commentedon Apr 8, 2024
Interesting, for me it's affecting both my local mypy run and the remote mypy workflow step.
twavv commentedon Oct 20, 2024
+1 to this.
We have a situation where we're using Stripe Connect as well as our own Stripe account for various things. There are places where we specify (eg)
application_fee_amount
which can either be an actual amount (for Stripe Connect payment intents) orNone
for payment intents using our own Stripe account.