stripe-python
stripe-python copied to clipboard
For webhooks, `webhook.request` is both a method and a data attribute
Describe the bug
Incoming webhook events have a request
data attribute, but the event
instance already has a request
bound method, so we end up with a bit of a conflict. The data attribute can still be accessed with event["request"]
but it feels weird to need to do that for just that one data attribute and then use dot syntax for everything else.
>>> event = stripe.Webhook.construct_event(...)
>>> event.request
<bound method StripeObject.request of <Event event id=<id_omitted> at 0x1035bb450> JSON: { ...
>>> event["request"]
<StripeObject id=<id_omitted> at 0x102e95810> JSON: {
"id": "<id_omitted>",
"idempotency_key": "<idempotency_key_omitted>"
}
event.request
and event["request"]
both returning different things is rather confusing, and it took me quite a while to figure out what was going on.
To Reproduce
- Construct a webhook event.
- Access
event.request
. - Access
event["request"]
. - Notice that they are different.
I would probably consider this less of a "bug" and more of an oversight.
Expected behavior
The event.request
method should probably be something like event._request
so it doesn't conflict with the incoming data. That way I can call event.request
and actually get the attribute from the body of the webhook as expected.
Code snippets
No response
OS
macOS
Language version
Python 3.9.10
Library version
stripe-python v2.76.0
API version
2020-08-27
Additional context
No response
@AaronBeaudoin thanks for the detailed report! This feels similar to how items
on Subscription
can't be accessed by sub.items
because items
is a default method on dict
which all our API resources inherit from. We'll see if this is something we could fix in the future though.
Faced the same issue on the latest build stripe 3.5.0
. This is rather confusing and hopefully gets addressed in a future release.
☝️ Same issue trying to access Subscription.items
For now I'll use something like:
def get_subscription(subscription_id: str) -> stripe.Subscription:
try:
return stripe.Subscription.retrieve(subscription_id)
except StripeError as e:
print(e.error)
print(e.json_body)
print(e.user_message)
raise ValueError(f"Failed to retrieve subscription {subscription_id}")
subscription = get_subscription(subscription_id)
subscription.to_dict()["items"] # since subscription.items is dict's built-in method
Let me take a crack at this issue.