8000 Add classmethod to stripe.PaymentIntent.confirm. by PIG208 · Pull Request #8498 · python/typeshed · GitHub
[go: up one dir, main page]

Skip to content

Add classmethod to stripe.PaymentIntent.confirm. #8498

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 8, 2022

Conversation

PIG208
Copy link
Contributor
@PIG208 PIG208 commented Aug 6, 2022

Similar to #7230, stripe.PaymentIntent.confirm can be called as an
instance method or a classmethod.

@PIG208 PIG208 force-pushed the stripe branch 2 times, most recently from cba8c22 to ca68934 Compare August 6, 2022 01:54
@github-actions

This comment has been minimized.

2 similar comments
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@PIG208 PIG208 force-pushed the stripe branch 2 times, most recently from de9cb99 to c7508e9 Compare August 7, 2022 02:20
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

1 similar comment
@github-actions

This comment has been minimized.

Comment on lines +14 to +21
@overload
@classmethod
def confirm(
cls, intent: str, api_key: str | None = ..., stripe_version: str | None = ..., stripe_account: str | None = ..., **params
): ...
@overload
@classmethod
def confirm(cls, idempotency_key: str | None = ..., **params): ...
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the second overload not be decorated with @classmethod? If I understand the @class_method_variant decorator correctly, this can be called in two versions:

PaymentIntent().confirm("key", ...)
PaymentIntent.confirm("payment intent", "key", ...)

Copy link
Contributor Author
@PIG208 PIG208 Aug 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mainly for avoiding mypy complaining about one of the methods not being decorated consistently with @classmethod; another reason is that mypy does not correctly remove the first argument of the second variant for the caller without them both having @classmethod. The first error can be silenced with a # type: ignore directive, but the second error is likely a bug.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it works, I'm fine with this. I think it would be a good idea to add a test case for a complicated case like this, though. Maybe @AlexWaygood can help with this.

We could also try to annotate class_method_variant() correctly and use the decorator here. Descriptor protocol support in type checkers is decent. But that's probably out of scope for this PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be a good idea to add a test case for a complicated case like this, though. Maybe @AlexWaygood can help with this.

We don't (yet) have the infrastructure set up to add test cases for our third-party stub -- only our stdlib stubs. This has come up a few times now, though, so I can work on setting something up. But we probably shouldn't wait on merging this PR before then.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I filed #8505 as a reminder to myself.

Copy link
Contributor Author
@PIG208 PIG208 Aug 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also try to annotate class_method_variant() correctly and use the decorator here. Descriptor protocol support in type checkers is decent. But that's probably out of scope for this PR.

Yes. That's helpful for sweeping up other similar use cases of the decorator in the stubs, but I am not sure how that will be possible with type annotation alone. We can figure this out later.

@PIG208 PIG208 force-pushed the stripe branch 2 times, most recently from 4dd5204 to 73ec5c0 Compare August 8, 2022 12:19
@github-actions

This comment has been minimized.

Similar to python#7230, stripe.PaymentIntent.confirm can be called as an
instance method or a classmethod.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
@github-actions

This comment has been minimized.

1 similar comment
@github-actions
Copy link
Contributor
github-actions bot commented Aug 8, 2022

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

@PIG208
Copy link
Contributor Author
PIG208 commented Aug 8, 2022

It would be great if @andersk can review this as well.

@srittau srittau merged commit 28fde2e into python:master Aug 8, 2022
@andersk
Copy link
Contributor
andersk commented Aug 9, 2022

Note that stripe-python doesn’t have 1 or 2 methods like this, but 86.

$ git grep -p -A1 @util.class_method_variant
stripe/api_resources/abstract/deletable_api_resource.py=class DeletableAPIResource(APIResource):
--
stripe/api_resources/abstract/deletable_api_resource.py:    @util.class_method_variant("_cls_delete")
stripe/api_resources/abstract/deletable_api_resource.py-    def delete(self, **param
8000
s):
--
stripe/api_resources/account.py=class Account(
--
stripe/api_resources/account.py:    @util.class_method_variant("_cls_persons")
stripe/api_resources/account.py-    def persons(self, idempotency_key=None, **params):
--
stripe/api_resources/account.py:    @util.class_method_variant("_cls_reject")
stripe/api_resources/account.py-    def reject(self, idempotency_key=None, **params):
--
stripe/api_resources/application_fee.py=class ApplicationFee(ListableAPIResource):
--
stripe/api_resources/application_fee.py:    @util.class_method_variant("_cls_refund")
stripe/api_resources/application_fee.py-    def refund(self, idempotency_key=None, **params):
--
stripe/api_resources/charge.py=class Charge(
--
stripe/api_resources/charge.py:    @util.class_method_variant("_cls_capture")
stripe/api_resources/charge.py-    def capture(self, idempotency_key=None, **params):
--
stripe/api_resources/checkout/session.py=class Session(CreateableAPIResource, ListableAPIResource):
--
stripe/api_resources/checkout/session.py:    @util.class_method_variant("_cls_expire")
stripe/api_resources/checkout/session.py-    def expire(self, idempotency_key=None, **params):
--
stripe/api_resources/checkout/session.py:    @util.class_method_variant("_cls_list_line_items")
stripe/api_resources/checkout/session.py-    def list_line_items(self, idempotency_key=None, **params):
--
stripe/api_resources/credit_note.py=class CreditNote(
--
stripe/api_resources/credit_note.py:    @util.class_method_variant("_cls_void_credit_note")
stripe/api_resources/credit_note.py-    def void_credit_note(self, idempotency_key=None, **params):
--
stripe/api_resources/customer.py=class Customer(
--
stripe/api_resources/customer.py:    @util.class_method_variant("_cls_create_funding_instructions")
stripe/api_resources/customer.py-    def create_funding_instructions(self, idempotency_key=None, **params):
--
stripe/api_resources/customer.py:    @util.class_method_variant("_cls_delete_discount")
stripe/api_resources/customer.py-    def delete_discount(self, idempotency_key=None, **params):
--
stripe/api_resources/customer.py:    @util.class_method_variant("_cls_list_payment_methods")
stripe/api_resources/customer.py-    def list_payment_methods(self, idempotency_key=None, **params):
--
stripe/api_resources/customer.py:    @util.class_method_variant("_cls_retrieve_payment_method")
stripe/api_resources/customer.py-    def retrieve_payment_method(
--
stripe/api_resources/customer.py:        @util.class_method_variant("_cls_fund_cash_balance")
stripe/api_resources/customer.py-        def fund_cash_balance(self, idempotency_key=None, **params):
--
stripe/api_resources/dispute.py=class Dispute(ListableAPIResource, UpdateableAPIResource):
--
stripe/api_resources/dispute.py:    @util.class_method_variant("_cls_close")
stripe/api_resources/dispute.py-    def close(self, idempotency_key=None, **params):
--
stripe/api_resources/financial_connections/account.py=class Account(ListableAPIResource):
--
stripe/api_resources/financial_connections/account.py:    @util.class_method_variant("_cls_disconnect")
stripe/api_resources/financial_connections/account.py-    def disconnect(self, idempotency_key=None, **params):
--
stripe/api_resources/financial_connections/account.py:    @util.class_method_variant("_cls_list_owners")
stripe/api_resources/financial_connections/account.py-    def list_owners(self, idempotency_key=None, **params):
--
stripe/api_resources/financial_connections/account.py:    @util.class_method_variant("_cls_refresh_account")
stripe/api_resources/financial_connections/account.py-    def refresh_account(self, idempotency_key=None, **params):
--
stripe/api_resources/identity/verification_session.py=class VerificationSession(
--
stripe/api_resources/identity/verification_session.py:    @util.class_method_variant("_cls_cancel")
stripe/api_resources/identity/verification_session.py-    def cancel(self, idempotency_key=None, **params):
--
stripe/api_resources/identity/verification_session.py:    @util.class_method_variant("_cls_redact")
stripe/api_resources/identity/verification_session.py-    def redact(self, idempotency_key=None, **params):
--
stripe/api_resources/invoice.py=class Invoice(
--
stripe/api_resources/invoice.py:    @util.class_method_variant("_cls_finalize_invoice")
stripe/api_resources/invoice.py-    def finalize_invoice(self, idempotency_key=None, **params):
--
stripe/api_resources/invoice.py:    @util.class_method_variant("_cls_mark_uncollectible")
stripe/api_resources/invoice.py-    def mark_uncollectible(self, idempotency_key=None, **params):
--
stripe/api_resources/invoice.py:    @util.class_method_variant("_cls_pay")
stripe/api_resources/invoice.py-    def pay(self, idempotency_key=None, **params):
--
stripe/api_resources/invoice.py:    @util.class_method_variant("_cls_send_invoice")
stripe/api_resources/invoice.py-    def send_invoice(self, idempotency_key=None, **params):
--
stripe/api_resources/invoice.py:    @util.class_method_variant("_cls_void_invoice")
stripe/api_resources/invoice.py-    def void_invoice(self, idempotency_key=None, **params):
--
stripe/api_resources/issuing/authorization.py=class Authorization(ListableAPIResource, UpdateableAPIResource):
--
stripe/api_resources/issuing/authorization.py:    @util.class_method_variant("_cls_approve")
stripe/api_resources/issuing/authorization.py-    def approve(self, idempotency_key=None, **params):
--
stripe/api_resources/issuing/authorization.py:    @util.class_method_variant("_cls_decline")
stripe/api_resources/issuing/authorization.py-    def decline(self, idempotency_key=None, **params):
--
stripe/api_resources/issuing/card.py=class Card(CreateableAPIResource, ListableAPIResource, UpdateableAPIResource):
--
stripe/api_resources/issuing/card.py:        @util.class_method_variant("_cls_deliver_card")
stripe/api_resources/issuing/card.py-        def deliver_card(self, idempotency_key=None, **params):
--
stripe/api_resources/issuing/card.py:        @util.class_method_variant("_cls_fail_card")
stripe/api_resources/issuing/card.py-        def fail_card(self, idempotency_key=None, **params):
--
stripe/api_resources/issuing/card.py:        @util.class_method_variant("_cls_return_card")
stripe/api_resources/issuing/card.py-        def return_card(self, idempotency_key=None, **params):
--
stripe/api_resources/issuing/card.py:        @util.class_method_variant("_cls_ship_card")
stripe/api_resources/issuing/card.py-        def ship_card(self, idempotency_key=None, **params):
--
stripe/api_resources/issuing/dispute.py=class Dispute(
--
stripe/api_resources/issuing/dispute.py:    @util.class_method_variant("_cls_submit")
stripe/api_resources/issuing/dispute.py-    def submit(self, idempotency_key=None, **params):
--
stripe/api_resources/order.py=class Order(CreateableAPIResource, ListableAPIResource, UpdateableAPIResource):
--
stripe/api_resources/order.py:    @util.class_method_variant("_cls_cancel")
stripe/api_resources/order.py-    def cancel(self, idempotency_key=None, **params):
--
stripe/api_resources/order.py:    @util.class_method_variant("_cls_list_line_items")
stripe/api_resources/order.py-    def list_line_items(self, idempotency_key=None, **params):
--
stripe/api_resources/order.py:    @util.class_method_variant("_cls_reopen")
stripe/api_resources/order.py-    def reopen(self, idempotency_key=None, **params):
--
stripe/api_resources/order.py:    @util.class_method_variant("_cls_submit")
stripe/api_resources/order.py-    def submit(self, idempotency_key=None, **params):
--
stripe/api_resources/payment_intent.py=class PaymentIntent(
--
stripe/api_resources/payment_intent.py:    @util.class_method_variant("_cls_apply_customer_balance")
stripe/api_resources/payment_intent.py-    def apply_customer_balance(self, idempotency_key=None, **params):
--
stripe/api_resources/payment_intent.py:    @util.class_method_variant("_cls_cancel")
stripe/api_resources/payment_intent.py-    def cancel(self, idempotency_key=None, **params):
--
stripe/api_resources/payment_intent.py:    @util.class_method_variant("_cls_capture")
stripe/api_resources/payment_intent.py-    def capture(self, idempotency_key=None, **params):
--
stripe/api_resources/payment_intent.py:    @util.class_method_variant("_cls_confirm")
stripe/api_resources/payment_intent.py-    def confirm(self, idempotency_key=None, **params):
--
stripe/api_resources/payment_intent.py:    @util.class_method_variant("_cls_increment_authorization")
stripe/api_resources/payment_intent.py-    def increment_authorization(self, idempotency_key=None, **params):
--
stripe/api_resources/payment_intent.py:    @util.class_method_variant("_cls_verify_microdeposits")
stripe/api_resources/payment_intent.py-    def verify_microdeposits(self, idempotency_key=None, **params):
--
stripe/api_resources/payment_link.py=class PaymentLink(
--
stripe/api_resources/payment_link.py:    @util.class_method_variant("_cls_list_line_items")
stripe/api_resources/payment_link.py-    def list_line_items(self, idempotency_key=None, **params):
--
stripe/api_resources/payment_method.py=class PaymentMethod(
--
stripe/api_resources/payment_method.py:    @util.class_method_variant("_cls_attach")
stripe/api_resources/payment_method.py-    def attach(self, idempotency_key=None, **params):
--
stripe/api_resources/payment_method.py:    @util.class_method_variant("_cls_detach")
stripe/api_resources/payment_method.py-    def detach(self, idempotency_key=None, **params):
--
stripe/api_resources/payout.py=class Payout(
--
stripe/api_resources/payout.py:    @util.class_method_variant("_cls_cancel")
stripe/api_resources/payout.py-    def cancel(self, idempotency_key=None, **params):
--
stripe/api_resources/payout.py:    @util.class_method_variant("_cls_reverse")
stripe/api_resources/payout.py-    def reverse(self, idempotency_key=None, **params):
--
stripe/api_resources/quote.py=class Quote(CreateableAPIResource, ListableAPIResource, UpdateableAPIResource):
--
stripe/api_resources/quote.py:    @util.class_method_variant("_cls_accept")
stripe/api_resources/quote.py-    def accept(self, idempotency_key=None, **params):
--
stripe/api_resources/quote.py:    @util.class_method_variant("_cls_cancel")
stripe/api_resources/quote.py-    def cancel(self, idempotency_key=None, **params):
--
stripe/api_resources/quote.py:    @util.class_method_variant("_cls_finalize_quote")
stripe/api_resources/quote.py-    def finalize_quote(self, idempotency_key=None, **params):
--
stripe/api_resources/quote.py:    @util.class_method_variant("_cls_list_computed_upfront_line_items")
stripe/api_resources/quote.py-    def list_computed_upfront_line_items(self, idempotency_key=None, **params):
--
stripe/api_resources/quote.py:    @util.class_method_variant("_cls_list_line_items")
stripe/api_resources/quote.py-    def list_line_items(self, idempotency_key=None, **params):
--
stripe/api_resources/quote.py:    @util.class_method_variant("_cls_pdf")
stripe/api_resources/quote.py-    def pdf(
--
stripe/api_resources/refund.py=class Refund(
--
stripe/api_resources/refund.py:    @util.class_method_variant("_cls_cancel")
stripe/api_resources/refund.py-    def cancel(self, idempotency_key=None, **params):
--
stripe/api_resources/refund.py:        @util.class_method_variant("_cls_expire")
stripe/api_resources/refund.py-        def expire(self, idempotency_key=None, **params):
--
stripe/api_resources/review.py=class Review(ListableAPIResource):
--
stripe/api_resources/review.py:    @util.class_method_variant("_cls_approve")
stripe/api_resources/review.py-    def approve(self, idempotency_key=None, **params):
--
stripe/api_resources/setup_intent.py=class SetupIntent(
--
stripe/api_resources/setup_intent.py:    @util.class_method_variant("_cls_cancel")
stripe/api_resources/setup_intent.py-    def cancel(self, idempotency_key=None, **params):
--
stripe/api_resources/setup_intent.py:    @util.class_method_variant("_cls_confirm")
stripe/api_resources/setup_intent.py-    def confirm(self, idempotency_key=None, **params):
--
stripe/api_resources/setup_intent.py:    @util.class_method_variant("_cls_verify_microdeposits")
stripe/api_resources/setup_intent.py-    def verify_microdeposits(self, idempotency_key=None, **params):
--
stripe/api_resources/source.py=class Source(CreateableAPIResource, UpdateableAPIResource):
--
stripe/api_resources/source.py:    @util.class_method_variant("_cls_list_source_transactions")
stripe/api_resources/source.py-    def list_source_transactions(self, idempotency_key=None, **params):
--
stripe/api_resources/source.py:    @util.class_method_variant("_cls_verify")
stripe/api_resources/source.py-    def verify(self, idempotency_key=None, **params):
--
stripe/api_resources/subscription.py=class Subscription(
--
stripe/api_resources/subscription.py:    @util.class_method_variant("_cls_cancel")
stripe/api_resources/subscription.py-    def cancel(self, idempotency_key=None, **params):
--
stripe/api_resources/subscription.py:    @util.class_method_variant("_cls_delete_discount")
stripe/api_resources/subscription.py-    def delete_discount(self, idempotency_key=None, **params):
--
stripe/api_resources/subscription_schedule.py=class SubscriptionSchedule(
--
stripe/api_resources/subscription_schedule.py:    @util.class_method_variant("_cls_cancel")
stripe/api_resources/subscription_schedule.py-    def cancel(self, idempotency_key=None, **params):
--
stripe/api_resources/subscription_schedule.py:    @util.class_method_variant("_cls_release")
stripe/api_resources/subscription_schedule.py-    def release(self, idempotency_key=None, **params):
--
stripe/api_resources/terminal/reader.py=class Reader(
--
stripe/api_resources/terminal/reader.py:    @util.class_method_variant("_cls_cancel_action")
stripe/api_resources/terminal/reader.py-    def cancel_action(self, idempotency_key=None, **params):
--
stripe/api_resources/terminal/reader.py:    @util.class_method_variant("_cls_process_payment_intent")
stripe/api_resources/terminal/reader.py-    def process_payment_intent(self, idempotency_key=None, **params):
--
stripe/api_resources/terminal/reader.py:    @util.class_method_variant("_cls_process_setup_intent")
stripe/api_resources/terminal/reader.py-    def process_setup_intent(self, idempotency_key=None, **params):
--
stripe/api_resources/terminal/reader.py:    @util.class_method_variant("_cls_set_reader_display")
stripe/api_resources/terminal/reader.py-    def set_reader_display(self, idempotency_key=None, **params):
--
stripe/api_resources/terminal/reader.py:        @util.class_method_variant("_cls_present_payment_method")
stripe/api_resources/terminal/reader.py-        def present_payment_method(self, idempotency_key=None, **params):
--
stripe/api_resources/test_helpers/test_clock.py=class TestClock(
--
stripe/api_resources/test_helpers/test_clock.py:    @util.class_method_variant("_cls_advance")
stripe/api_resources/test_helpers/test_clock.py-    def advance(self, idempotency_key=None, **params):
--
stripe/api_resources/topup.py=class Topup(CreateableAPIResource, ListableAPIResource, UpdateableAPIResource):
--
stripe/api_resources/topup.py:    @util.class_method_variant("_cls_cancel")
stripe/api_resources/topup.py-    def cancel(self, idempotency_key=None, **params):
--
stripe/api_resources/treasury/financial_account.py=class FinancialAccount(
--
stripe/api_resources/treasury/financial_account.py:    @util.class_method_variant("_cls_retrieve_features")
stripe/api_resources/treasury/financial_account.py-    def retrieve_features(self, idempotency_key=None, **params):
--
stripe/api_resources/treasury/financial_account.py:    @util.class_method_variant("_cls_update_features")
stripe/api_resources/treasury/financial_account.py-    def update_features(self, idempotency_key=None, **params):
--
stripe/api_resources/treasury/inbound_transfer.py=class InboundTransfer(CreateableAPIResource, ListableAPIResource):
--
stripe/api_resources/treasury/inbound_transfer.py:    @util.class_method_variant("_cls_cancel")
stripe/api_resources/treasury/inbound_transfer.py-    def cancel(self, idempotency_key=None, **params):
--
stripe/api_resources/treasury/inbound_transfer.py:        @util.class_method_variant("_cls_fail")
stripe/api_resources/treasury/inbound_transfer.py-        def fail(self, idempotency_key=None, **params):
--
stripe/api_resources/treasury/inbound_transfer.py:        @util.class_method_variant("_cls_return_inbound_transfer")
stripe/api_resources/treasury/inbound_transfer.py-        def return_inbound_transfer(self, idempotency_key=None, **params):
--
stripe/api_resources/treasury/inbound_transfer.py:        @util.class_method_variant("_cls_succeed")
stripe/api_resources/treasury/inbound_transfer.py-        def succeed(self, idempotency_key=None, **params):
--
stripe/api_resources/treasury/outbound_payment.py=class OutboundPayment(CreateableAPIResource, ListableAPIResource):
--
stripe/api_resources/treasury/outbound_payment.py:    @util.class_method_variant("_cls_cancel")
stripe/api_resources/treasury/outbound_payment.py-    def cancel(self, idempotency_key=None, **params):
--
stripe/api_resources/treasury/outbound_payment.py:        @util.class_method_variant("_cls_fail")
stripe/api_resources/treasury/outbound_payment.py-        def fail(self, idempotency_key=None, **params):
--
stripe/api_resources/treasury/outbound_payment.py:        @util.class_method_variant("_cls_post")
stripe/api_resources/treasury/outbound_payment.py-        def post(self, idempotency_key=None, **params):
--
stripe/api_resources/treasury/outbound_payment.py:        @util.class_method_variant("_cls_return_outbound_payment")
stripe/api_resources/treasury/outbound_payment.py-        def return_outbound_payment(self, idempotency_key=None, **params):
--
stripe/api_resources/treasury/outbound_transfer.py=class OutboundTransfer(CreateableAPIResource, ListableAPIResource):
--
stripe/api_resources/treasury/outbound_transfer.py:    @util.class_method_variant("_cls_cancel")
stripe/api_resources/treasury/outbound_transfer.py-    def cancel(self, idempotency_key=None, **params):
--
stripe/api_resources/treasury/outbound_transfer.py:        @util.class_method_variant("_cls_fail")
stripe/api_resources/treasury/outbound_transfer.py-        def fail(self, idempotency_key=None, **params):
--
stripe/api_resources/treasury/outbound_transfer.py:        @util.class_method_variant("_cls_post")
stripe/api_resources/treasury/outbound_transfer.py-        def post(self, idempotency_key=None, **params):
--
stripe/api_resources/treasury/outbound_transfer.py:        @util.class_method_variant("_cls_return_outbound_transfer")
stripe/api_resources/treasury/outbound_transfer.py-        def return_outbound_transfer(self, idempotency_key=None, **params):
--
tests/api_resources/abstract/test_custom_method.py=class TestCustomMethod(object):
--
tests/api_resources/abstract/test_custom_method.py:        @util.class_method_variant("_cls_do_stuff_new_codegen")
tests/api_resources/abstract/test_custom_method.py-        def do_stuff_new_codegen(self, idempotency_key=None, **params):

It would kind of suck to go through this with all 86 of them, especially if the result is going to be inaccurate to work around mypy limitations. Maybe it’s worth reopening the conversation with upstream from #7230 about whether they really need this unusual pair of calling conventions. Even if they keep them both for backwards compatibility, it might make sense for them to mark one as deprecated, so we could remove it from the stubs and at least have an accurate type for the other.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
0