diff --git a/stripe/util.py b/stripe/util.py index d4c55392f..b5ad1ab84 100644 --- a/stripe/util.py +++ b/stripe/util.py @@ -174,8 +174,13 @@ def convert_to_stripe_object( last_response=stripe_response, ) - if hasattr(obj, "object") and ( - (obj.object == "list") or (obj.object == "search_result") + # We only need to update _retrieve_params when special params were + # actually passed. Otherwise, leave it as is as the list / search result + # constructors will instantiate their own params. + if ( + params is not None + and hasattr(obj, "object") + and ((obj.object == "list") or (obj.object == "search_result")) ): obj._retrieve_params = params diff --git a/tests/api_resources/test_invoice.py b/tests/api_resources/test_invoice.py index 23a2fd294..4a53e9b98 100644 --- a/tests/api_resources/test_invoice.py +++ b/tests/api_resources/test_invoice.py @@ -136,3 +136,11 @@ def test_can_void_invoice_classmethod(self, request_mock): "post", "/v1/invoices/%s/void" % TEST_RESOURCE_ID ) assert isinstance(resource, stripe.Invoice) + + def test_can_iterate_lines(self, request_mock): + resource = stripe.Invoice.retrieve(TEST_RESOURCE_ID) + assert isinstance(resource.lines.data, list) + assert isinstance(resource.lines.data[0], stripe.InvoiceLineItem) + seen = [item["id"] for item in resource.lines.auto_paging_iter()] + + assert seen.__len__() > 0 diff --git a/tests/test_stripe_object.py b/tests/test_stripe_object.py index 5a4d7bdaa..15c26b670 100644 --- a/tests/test_stripe_object.py +++ b/tests/test_stripe_object.py @@ -34,28 +34,60 @@ "subtotal": 10000, "total": 10000, "lines": { - "invoiceitems": [], - "prorations": [], - "subscriptions": [ + "object": "list", + "data": [ { - "plan": { - "interval": "month", - "object": "plan", - "identifier": "expensive", + "id": "il_1LSiex2eZvKYlo2CZ5IspTNx", + "object": "line_item", + "amount": 2499, + "amount_excluding_tax": 2499, + "currency": "usd", + "description": "My First Invoice Item (created for API docs)", + "discount_amounts": [], + "discountable": true, + "discounts": [], + "invoice_item": "ii_1LSiex2eZvKYlo2C0X4adTLR", + "livemode": false, + "metadata": {}, + "period": { + "end": 1659537295, + "start": 1659537295 + }, + "price": { + "id": "price_1LSicu2eZvKYlo2C4WSIaXEp", + "object": "price", + "active": true, + "billing_scheme": "per_unit", + "created": 1659537168, "currency": "usd", + "custom_unit_amount": null, "livemode": false, - "amount": 10000, - "name": "Expensive Plan", - "trial_period_days": null, - "id": "expensive" + "lookup_key": null, + "metadata": {}, + "nickname": null, + "product": "prod_MB4mvosUV5tObf", + "recurring": null, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "one_time", + "unit_amount": 2499, + "unit_amount_decimal": "2499" }, - "period": { - "end": 1340917128, - "start": 1338238728 + "proration": false, + "proration_details": { + "credited_items": null }, - "amount": 10000 + "quantity": 1, + "subscription": null, + "tax_amounts": [], + "tax_rates": [], + "type": "invoiceitem", + "unit_amount_excluding_tax": "2499" } - ] + ], + "has_more": false, + "url": "/v1/invoices/in_t9mHb2hpK7mml1/lines" } } """ @@ -157,11 +189,32 @@ def test_refresh_from_nested_object(self): SAMPLE_INVOICE, "key" ) - assert len(obj.lines.subscriptions) == 1 + assert len(obj.lines) == 1 + assert isinstance(obj.lines, stripe.ListObject) + assert isinstance(obj.lines.data[0], stripe.InvoiceLineItem) assert isinstance( - obj.lines.subscriptions[0], stripe.stripe_object.StripeObject + obj.lines.data[0].price, stripe.stripe_object.StripeObject + ) + assert isinstance(obj.lines.data[0].price, stripe.Price) + assert obj.lines.data[0].price.billing_scheme == "per_unit" + + def test_refresh_from_nested_object_can_be_paged(self): + obj = stripe.stripe_object.StripeObject.construct_from( + SAMPLE_INVOICE, "key" ) - assert obj.lines.subscriptions[0].plan.interval == "month" + + assert len(obj.lines) == 1 + assert isinstance(obj.lines, stripe.ListObject) + seen = [item["id"] for item in obj.lines.auto_paging_iter()] + + assert seen == ["il_1LSiex2eZvKYlo2CZ5IspTNx"] + + assert isinstance(obj.lines.data[0], stripe.InvoiceLineItem) + assert isinstance( + obj.lines.data[0].price, stripe.stripe_object.StripeObject + ) + assert isinstance(obj.lines.data[0].price, stripe.Price) + assert obj.lines.data[0].price.billing_scheme == "per_unit" def test_to_json(self): obj = stripe.stripe_object.StripeObject.construct_from( @@ -173,15 +226,16 @@ def test_to_json(self): def check_invoice_data(self, data): # Check rough structure assert len(list(data.keys())) == 20 - assert len(list(data["lines"].keys())) == 3 - assert len(data["lines"]["invoiceitems"]) == 0 - assert len(data["lines"]["subscriptions"]) == 1 + assert len(list(data["lines"]["data"][0].keys())) == 22 + assert len(data["lines"]["data"]) == 1 # Check various data types assert data["date"] == 1338238728 assert data["next_payment_attempt"] is None assert data["livemode"] is False - assert data["lines"]["subscriptions"][0]["plan"]["interval"] == "month" + assert ( + data["lines"]["data"][0]["price"]["billing_scheme"] == "per_unit" + ) def test_repr(self): obj = stripe.stripe_object.StripeObject("foo", "bar", myparam=5)