#teddy-pythonobject-mocktests
1 messages ยท Page 1 of 1 (latest)
Hello! What's up?
Hi!
I have an integration with Stripe and I am using the webhooks
The integration is in Python
def stripe_webhook() -> Response:
try:
client = StripeClient(
STRIPE_API_KEY,
stripe_version="2023-10-16",
)
event = client.construct_event(
request.data,
request.headers["stripe-signature"],
STRIPE_WEBHOOK_SECRET,
)
except SignatureVerificationError as e:
pass
if event.type == "customer.created":
pass
this is the basic structure, with the new client, all right?
We can't provide code reviews here. I can't tell you if this code will run correctly or not. I'm happy to answer specific questions though. What happens when you run this?
yeah yeah, I know
It is only for more context
Well, I am getting this error
"StripeObject" has no attribute "object"
With mypy
Which line of code is throwing that error?
event = convert_to_stripe_object(
deepcopy(WEBHOOK_EVENT_CUSTOMER_CREATED),
"test-api-key",
"test-stripe-account",
)
event.object.id = "test_123"
This, for example
Oh, so the error is about customer_created_object not having an object property? That seems expected. customer_created_object should be a Customer, so it should have an id at the top level. Does customer_created_object.id work instead?
Same exact error?
Wait...
The code change didn't do what I recommended.
You're still trying to access .object.id instead of just .id
Can you try removing the .object part?
wait
ipdb> customer_created_object
<StripeObject at 0x7ffff1cd4c70> JSON: {
"object": {
"address": {
"city": null,
"country": "ES",
"line1": null,
"line2": null,
"postal_code": null,
"state": null
},
"balance": 0,
"created": 1706101387,
"currency": null,
"default_source": null,
"delinquent": false,
"description": null,
"discount": null,
"email": "xxxx@xxxx.com",
"id": "cus_xxxxxx",
"invoice_prefix": "Fxxx",
"invoice_settings": {
"custom_fields": null,
"default_payment_method": null,
"footer": null,
"rendering_options": null
},
"livemode": false,
"metadata": {},
"name": "xxxx",
"next_invoice_sequence": 2,
"object": "customer",
"phone": "+34XXXXXXXXX",
"preferred_locales": [
"en-GB"
],
"shipping": null,
"tax_exempt": "none",
"test_clock": null
}
}
ipdb> customer_created_object.object
<Customer customer id=cus_xxxxxx at 0x7ffff1cb6f40> JSON: {
"address": {
"city": null,
"country": "ES",
"line1": null,
"line2": null,
"postal_code": null,
"state": null
},
"balance": 0,
"created": 1706101387,
"currency": null,
"default_source": null,
"delinquent": false,
"description": null,
"discount": null,
"email": "xxxx@xxxx.com",
"id": "cus_xxxxxx",
"invoice_prefix": "Fxxxx",
"invoice_settings": {
"custom_fields": null,
"default_payment_method": null,
"footer": null,
"rendering_options": null
},
"livemode": false,
"metadata": {},
"name": "xxxx",
"next_invoice_sequence": 2,
"object": "customer",
"phone": "+34XXXXXXXXX",
"preferred_locales": [
"en-GB"
],
"shipping": null,
"tax_exempt": "none",
"test_clock": null
}
ipdb> customer_created_object.object.id
'cus_xxxxxx'
๐
Okay, I guess I don't understand.
To clarify, when your code above runs, this line:
event.object.id = "test_123"
Causes this error:
"StripeObject" has no attribute "object"
Is that correct or incorrect?
The code works
It is an error with mypy
for the types
This code works:
event.object.id = "test_123"
Okay, let's back up.
Okay
Are you getting the error "StripeObject" has no attribute "object"?
Yes
Okay, what line of code is throwing that error?
All lines in my code that are typed as StripeObject
Okay, can you share the first line of code which throws the error?
event = convert_to_stripe_object(
deepcopy(WEBHOOK_EVENT_CUSTOMER_CREATED),
"test-api-key",
"test-stripe-account",
)
event.object.id = "test_123"
That is more than one line. Can you confirm the line event.object.id = "test_123" is the one throwing the error?
Okay, if you change that line to event.id = "test_123" do you still get the same error?
let me check
"StripeObject" has no attribute "id" [attr-defined]
I have this one also:
from stripe import convert_to_stripe_object # type: ignore
Okay, interesting. Let talk with someone with more Python experience, hang on...
Perfect
We're checking regarding the new client, but aside from that why are you trying to set the id to something else? The id isn't designed to be changed.
It is a test
I am generating a StripeObject in a test
So, I need a different id i each pytest session
Hi!
Hi ๐
The event doesn't have an object property. It's event.data.object
event.data.object.id = 'test_123' should work
I have this version of stripe-python
stripe==8.0.0
And I am creating a test to simulate the Webhook process building a StripeObject
from stripe import convert_to_stripe_object
def test_invoice_paid_use_case_success() -> None:
customer_created_object = convert_to_stripe_object(
deepcopy(WEBHOOK_EVENT_CUSTOMER_CREATED),
"test-api-key",
"test-stripe-account",
)
# import ipdb; ipdb.set_trace()
customer_created_object.id = "in_1234"
But I am getting this error when I execute mypy:
tests/usecases/stripe/test_invoice_paid.py:21: error: "StripeObject" has no attribute "id" [attr-defined]
customer_created_object.id = "in_123"
What is the class that is returned for customer_created_object? Is it an Event object?
ipdb> customer_created_object
<StripeObject at 0x7ffff1cd4c70> JSON: {
"object": {
"address": {
"city": null,
"country": "ES",
"line1": null,
"line2": null,
"postal_code": null,
"state": null
},
"balance": 0,
"created": 1706101387,
"currency": null,
"default_source": null,
"delinquent": false,
"description": null,
"discount": null,
"email": "xxxx@xxxx.com",
"id": "cus_xxxxxx",
"invoice_prefix": "Fxxx",
"invoice_settings": {
"custom_fields": null,
"default_payment_method": null,
"footer": null,
"rendering_options": null
},
"livemode": false,
"metadata": {},
"name": "xxxx",
"next_invoice_sequence": 2,
"object": "customer",
"phone": "+34XXXXXXXXX",
"preferred_locales": [
"en-GB"
],
"shipping": null,
"tax_exempt": "none",
"test_clock": null
}
}
That isn't what I asked for. What is the type?
ipdb> type(customer_created_object) <class 'stripe._stripe_object.StripeObject'>
It is a problem with the typing, with mypy . The code works.
But you say that ou library include all the needed files for the type checking
I'm reviewing this with some colleagues
Perfect
Okay. So you are cloning a Webhook Event class but the function used returns a StripeObject, which doesn't have an id property. Can you try wrapping your function in a cast function to convert it to the property class? E.g.
customer_created_object = cast(stripe.Event, convert_to_stripe_object(
deepcopy(WEBHOOK_EVENT_CUSTOMER_CREATED),
"test-api-key",
"test-stripe-account",
))
Let me check
tests/usecases/stripe/test_invoice_paid.py:29: error: "Literal['event']" has no attribute "id" [attr-defined] customer_created_object.object.id = "in_1234"
Okay this syntax customer_created_object.object.id = "in_1234" is still wrong. That's what I mentioned in my earlier message. Try using event.data.object.id = 'test_123'
The customer_created_object.object property is a string with the value of event
tests/usecases/stripe/test_invoice_paid.py:29: error: "dict[str, Any]" has no attribute "id" [attr-defined] customer_created_object.data.object.id = "in_1234"
Well, probably there are other ways to do it
Okay so let's back up. You want to get the Invoice object and assing a fake ID, correct?
No
I have in the WEBHOOK_EVENT_CUSTOMER_CREATED. variable the static mock with the content of the customer.created event
And I am changing the ID to a fake ID
After that, I am doing something with the invoice yes
But anyway
The ID of the event? or the data object associated with it?
Do you know if it is possible to validate the payload send for the webhook for each different event?
customer.created-> create a CustomerEvent object or similar to validate it
invoice.paid-> create a InvoiceEvent object or similar to validate all the fields, etc
The different is in the type and what is in the data.object properties
Okay
For each event Type, our API ref doc states which kind of object is in the data.object property.
https://stripe.com/docs/api/events/types
E.g.
customer.created data.object is a customer
Occurs whenever a new customer is created.
I know it