#teddy-pythonobject-mocktests

1 messages ยท Page 1 of 1 (latest)

spice mesaBOT
tame lantern
#

Hello! What's up?

inland locust
#

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?

tame lantern
#

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?

inland locust
#

yeah yeah, I know

#

It is only for more context

#

Well, I am getting this error

#

"StripeObject" has no attribute "object"

#

With mypy

tame lantern
#

Which line of code is throwing that error?

inland locust
#
event = convert_to_stripe_object(
    deepcopy(WEBHOOK_EVENT_CUSTOMER_CREATED),
    "test-api-key",
    "test-stripe-account",
)
event.object.id = "test_123"
#

This, for example

tame lantern
#

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?

inland locust
#

sorry

#

I have updated the code

#

well, it's the same jaja

tame lantern
#

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?

inland locust
#

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'
#

๐Ÿ˜…

tame lantern
#

Okay, I guess I don't understand.

inland locust
#

I am getting the error only when I execute mypy

#

a type checker for Python

tame lantern
#

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?

inland locust
#

The code works

#

It is an error with mypy

#

for the types

#

This code works:

event.object.id = "test_123"
tame lantern
#

Okay, let's back up.

inland locust
#

Okay

tame lantern
#

Are you getting the error "StripeObject" has no attribute "object"?

inland locust
#

Yes

tame lantern
#

Okay, what line of code is throwing that error?

inland locust
#

All lines in my code that are typed as StripeObject

tame lantern
#

Okay, can you share the first line of code which throws the error?

inland locust
#
event = convert_to_stripe_object(
    deepcopy(WEBHOOK_EVENT_CUSTOMER_CREATED),
    "test-api-key",
    "test-stripe-account",
)
event.object.id = "test_123"
tame lantern
#

That is more than one line. Can you confirm the line event.object.id = "test_123" is the one throwing the error?

inland locust
#

Yes

#

I confirm

tame lantern
#

Okay, if you change that line to event.id = "test_123" do you still get the same error?

inland locust
#

let me check

#

"StripeObject" has no attribute "id" [attr-defined]

#

I have this one also:
from stripe import convert_to_stripe_object # type: ignore

tame lantern
#

Okay, interesting. Let talk with someone with more Python experience, hang on...

inland locust
#

Perfect

tame lantern
#

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.

inland locust
#

It is a test

#

I am generating a StripeObject in a test

#

So, I need a different id i each pytest session

spice mesaBOT
inland locust
#

Hi!

rugged burrow
#

Hi ๐Ÿ‘‹

The event doesn't have an object property. It's event.data.object

#

event.data.object.id = 'test_123' should work

inland locust
#

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"
rugged burrow
#

What is the class that is returned for customer_created_object? Is it an Event object?

inland locust
#
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
  }
}
rugged burrow
#

That isn't what I asked for. What is the type?

inland locust
#

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

rugged burrow
#

I'm reviewing this with some colleagues

inland locust
#

Perfect

rugged burrow
#

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",
    ))
inland locust
#

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"

rugged burrow
#

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

inland locust
#

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

rugged burrow
#

Okay so let's back up. You want to get the Invoice object and assing a fake ID, correct?

inland locust
#

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

rugged burrow
#

The ID of the event? or the data object associated with it?

inland locust
#

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

rugged burrow
#

There is only one Event class

inland locust
#

Okay

#

I will build a event directly

#

and not a StripeObject

rugged burrow
#

The different is in the type and what is in the data.object properties

inland locust
#

Okay

rugged burrow
#

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.

inland locust
#

I know it