Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion codegen/pkg/builder/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func deprecationNotice(operation *v3.Operation) *string {
}

// methodDoc creates godoc comment for an operation.
func methodDoc(operation *v3.Operation) string {
func methodDoc(operation *v3.Operation, responses []Response) string {
out := new(strings.Builder)

if operation.Summary != "" {
Expand All @@ -44,9 +44,50 @@ func methodDoc(operation *v3.Operation) string {
fmt.Fprintf(out, "\n%s: %s\n", extDescription, operation.ExternalDocs.URL)
}

if raisesDoc := methodRaisesDoc(responses); raisesDoc != "" {
fmt.Fprintf(out, "\n\n%s", raisesDoc)
}

return formatDoc(out.String())
}

func methodRaisesDoc(responses []Response) string {
errorDescriptions := make([]string, 0, len(responses))

for _, response := range responses {
if !response.IsErr {
continue
}

description := response.ErrDescription
if description == "" {
description = "the API returns an error response"
}

if response.IsDefault {
errorDescriptions = append(errorDescriptions, description)
continue
}

errorDescriptions = append(errorDescriptions, fmt.Sprintf("%d: %s", response.Code, description))
}

out := new(strings.Builder)
out.WriteString("Raises:\n")
if len(errorDescriptions) == 0 {
out.WriteString(" APIError: Raised when the API returns an unexpected response.")
return out.String()
}

out.WriteString(" APIError: Raised when the API returns one of the documented error responses:\n")
for _, description := range errorDescriptions {
fmt.Fprintf(out, " %s\n", description)
}
out.WriteString(" Unexpected response statuses also raise this exception.")

return out.String()
}

// schemaDoc creates godoc for a schema.
func schemaDoc(name string, schema *base.Schema) string {
out := new(strings.Builder)
Expand Down
52 changes: 52 additions & 0 deletions codegen/pkg/builder/doc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package builder

import (
"strings"
"testing"

v3 "github.com/pb33f/libopenapi/datamodel/high/v3"
)

func TestMethodDocIncludesRaisesForDocumentedErrors(t *testing.T) {
t.Parallel()

doc := methodDoc(&v3.Operation{
Summary: "Create a checkout",
Description: "Creates a new checkout.",
}, []Response{
{Code: 201},
{Code: 400, IsErr: true, ErrDescription: "The request body is invalid."},
{Code: 401, IsErr: true, ErrDescription: "The request is not authorized."},
})

if !strings.Contains(doc, "Raises:\n APIError:") {
t.Fatalf("expected Raises section in docstring, got %q", doc)
}

if !strings.Contains(doc, "400: The request body is invalid.") {
t.Fatalf("expected 400 response in Raises section, got %q", doc)
}

if !strings.Contains(doc, "401: The request is not authorized.") {
t.Fatalf("expected 401 response in Raises section, got %q", doc)
}

if !strings.Contains(doc, "Unexpected response statuses also raise this exception.") {
t.Fatalf("expected unexpected response note in Raises section, got %q", doc)
}
}

func TestMethodDocIncludesRaisesForUnexpectedResponsesOnly(t *testing.T) {
t.Parallel()

doc := methodDoc(&v3.Operation{
Summary: "Ping",
Description: "Checks service health.",
}, []Response{
{Code: 204},
})

if !strings.Contains(doc, "Raises:\n APIError: Raised when the API returns an unexpected response.") {
t.Fatalf("expected fallback Raises section in docstring, got %q", doc)
}
}
2 changes: 1 addition & 1 deletion codegen/pkg/builder/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func (b *Builder) operationToMethod(method, path string, o *v3.Operation) (*Meth
)

return &Method{
Description: methodDoc(o),
Description: methodDoc(o, responses),
DeprecationNotice: deprecationNotice(o),
Method: strings.ToLower(method),
FunctionName: methodName,
Expand Down
106 changes: 106 additions & 0 deletions sumup/checkouts/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,12 @@ def list_available_payment_methods(
Get available payment methods

Get payment methods available for the given merchant to use with a checkout.


Raises:
APIError: Raised when the API returns one of the documented error responses:
400: The request is invalid for the submitted query parameters.
Unexpected response statuses also raise this exception.
"""
query_data: dict[str, typing.Any] = {}
if not isinstance(amount, NotGivenType) and amount is not None:
Expand Down Expand Up @@ -377,6 +383,15 @@ def create(
To use the [Hosted Checkout](https://developer.sumup.com/online-payments/checkouts/hosted-checkout/) page, setthe `hosted_checkout.enabled` to `true`.

Follow by processing a checkout to charge the provided payment instrument.


Raises:
APIError: Raised when the API returns one of the documented error responses:
400: The request body is invalid.
401: The request is not authorized.
403: The request isn't sufficiently authorized to create a checkout.
409: A checkout already exists for the provided unique parameters.
Unexpected response statuses also raise this exception.
"""
body_data: dict[str, typing.Any] = {}
body_data["checkout_reference"] = checkout_reference
Expand Down Expand Up @@ -436,6 +451,12 @@ def list(
List checkouts

Lists created checkout resources according to the applied `checkout_reference`.


Raises:
APIError: Raised when the API returns one of the documented error responses:
401: The request is not authorized.
Unexpected response statuses also raise this exception.
"""
query_data: dict[str, typing.Any] = {}
if not isinstance(checkout_reference, NotGivenType) and checkout_reference is not None:
Expand All @@ -460,6 +481,13 @@ def get(self, id: str, headers: typing.Optional[HeaderTypes] = None) -> Checkout
Retrieve a checkout

Retrieves an identified checkout resource. Use this request after processing a checkout to confirm its status and informthe end user respectively.


Raises:
APIError: Raised when the API returns one of the documented error responses:
401: The request is not authorized.
404: The requested resource does not exist.
Unexpected response statuses also raise this exception.
"""
resp = self._client.get(
f"/v0.1/checkouts/{id}",
Expand Down Expand Up @@ -499,6 +527,15 @@ def process(
Processing a checkout will attempt to charge the provided payment instrument for the amount of the specified checkout resourceinitiated in the `Create a checkout` endpoint.

Follow this request with `Retrieve a checkout` to confirm its status.


Raises:
APIError: Raised when the API returns one of the documented error responses:
400: The request body is invalid for processing the checkout.
401: The request is not authorized.
404: The requested resource does not exist.
409: The request conflicts with the current state of the resource.
Unexpected response statuses also raise this exception.
"""
body_data: dict[str, typing.Any] = {}
body_data["payment_type"] = payment_type
Expand Down Expand Up @@ -556,6 +593,14 @@ def deactivate(self, id: str, headers: typing.Optional[HeaderTypes] = None) -> C
Deactivate a checkout

Deactivates an identified checkout resource. If the checkout has already been processed it can not be deactivated.


Raises:
APIError: Raised when the API returns one of the documented error responses:
401: The request is not authorized.
404: The requested resource does not exist.
409: The request conflicts with the current state of the resource.
Unexpected response statuses also raise this exception.
"""
resp = self._client.delete(
f"/v0.1/checkouts/{id}",
Expand Down Expand Up @@ -592,6 +637,14 @@ def create_apple_pay_session(
`ApplePaySession.completeMerchantValidation(...)` in the browser.
SumUp validates the merchant session request and returns the Apple Pay
session object that your frontend should pass to Apple's JavaScript API.



Raises:
APIError: Raised when the API returns one of the documented error responses:
400: Bad Request
404: The requested resource does not exist.
Unexpected response statuses also raise this exception.
"""
body_data: dict[str, typing.Any] = {}
body_data["context"] = context
Expand Down Expand Up @@ -634,6 +687,12 @@ async def list_available_payment_methods(
Get available payment methods

Get payment methods available for the given merchant to use with a checkout.


Raises:
APIError: Raised when the API returns one of the documented error responses:
400: The request is invalid for the submitted query parameters.
Unexpected response statuses also raise this exception.
"""
query_data: dict[str, typing.Any] = {}
if not isinstance(amount, NotGivenType) and amount is not None:
Expand Down Expand Up @@ -682,6 +741,15 @@ async def create(
To use the [Hosted Checkout](https://developer.sumup.com/online-payments/checkouts/hosted-checkout/) page, setthe `hosted_checkout.enabled` to `true`.

Follow by processing a checkout to charge the provided payment instrument.


Raises:
APIError: Raised when the API returns one of the documented error responses:
400: The request body is invalid.
401: The request is not authorized.
403: The request isn't sufficiently authorized to create a checkout.
409: A checkout already exists for the provided unique parameters.
Unexpected response statuses also raise this exception.
"""
body_data: dict[str, typing.Any] = {}
body_data["checkout_reference"] = checkout_reference
Expand Down Expand Up @@ -741,6 +809,12 @@ async def list(
List checkouts

Lists created checkout resources according to the applied `checkout_reference`.


Raises:
APIError: Raised when the API returns one of the documented error responses:
401: The request is not authorized.
Unexpected response statuses also raise this exception.
"""
query_data: dict[str, typing.Any] = {}
if not isinstance(checkout_reference, NotGivenType) and checkout_reference is not None:
Expand All @@ -765,6 +839,13 @@ async def get(self, id: str, headers: typing.Optional[HeaderTypes] = None) -> Ch
Retrieve a checkout

Retrieves an identified checkout resource. Use this request after processing a checkout to confirm its status and informthe end user respectively.


Raises:
APIError: Raised when the API returns one of the documented error responses:
401: The request is not authorized.
404: The requested resource does not exist.
Unexpected response statuses also raise this exception.
"""
resp = await self._client.get(
f"/v0.1/checkouts/{id}",
Expand Down Expand Up @@ -804,6 +885,15 @@ async def process(
Processing a checkout will attempt to charge the provided payment instrument for the amount of the specified checkout resourceinitiated in the `Create a checkout` endpoint.

Follow this request with `Retrieve a checkout` to confirm its status.


Raises:
APIError: Raised when the API returns one of the documented error responses:
400: The request body is invalid for processing the checkout.
401: The request is not authorized.
404: The requested resource does not exist.
409: The request conflicts with the current state of the resource.
Unexpected response statuses also raise this exception.
"""
body_data: dict[str, typing.Any] = {}
body_data["payment_type"] = payment_type
Expand Down Expand Up @@ -861,6 +951,14 @@ async def deactivate(self, id: str, headers: typing.Optional[HeaderTypes] = None
Deactivate a checkout

Deactivates an identified checkout resource. If the checkout has already been processed it can not be deactivated.


Raises:
APIError: Raised when the API returns one of the documented error responses:
401: The request is not authorized.
404: The requested resource does not exist.
409: The request conflicts with the current state of the resource.
Unexpected response statuses also raise this exception.
"""
resp = await self._client.delete(
f"/v0.1/checkouts/{id}",
Expand Down Expand Up @@ -897,6 +995,14 @@ async def create_apple_pay_session(
`ApplePaySession.completeMerchantValidation(...)` in the browser.
SumUp validates the merchant session request and returns the Apple Pay
session object that your frontend should pass to Apple's JavaScript API.



Raises:
APIError: Raised when the API returns one of the documented error responses:
400: Bad Request
404: The requested resource does not exist.
Unexpected response statuses also raise this exception.
"""
body_data: dict[str, typing.Any] = {}
body_data["context"] = context
Expand Down
Loading
Loading