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
34 changes: 14 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,19 @@ import os
import uuid

from sumup import Sumup
from sumup.checkouts import CreateCheckoutBody

client = Sumup(api_key="sup_sk_MvxmLOl0...")
merchant_code = os.environ["SUMUP_MERCHANT_CODE"]

# Create a checkout
checkout = client.checkouts.create(
body=CreateCheckoutBody(
amount=10.00,
currency="EUR",
checkout_reference=str(uuid.uuid4()),
merchant_code=merchant_code,
description="Test payment",
redirect_url="https://example.com/success",
return_url="https://example.com/webhook",
)
amount=10.00,
currency="EUR",
checkout_reference=str(uuid.uuid4()),
merchant_code=merchant_code,
description="Test payment",
redirect_url="https://example.com/success",
return_url="https://example.com/webhook",
)

print(f"Checkout ID: {checkout.id}")
Expand All @@ -91,23 +88,20 @@ print(f"Checkout Reference: {checkout.checkout_reference}")

```python
from sumup import Sumup
from sumup.readers import CreateReaderCheckoutBody, CreateReaderCheckoutBodyTotalAmount

client = Sumup(api_key="sup_sk_MvxmLOl0...")

# Create a reader checkout
reader_checkout = client.readers.create_checkout(
reader_id="your-reader-id",
merchant_code="your-merchant-code",
body=CreateReaderCheckoutBody(
total_amount=CreateReaderCheckoutBodyTotalAmount(
value=1000, # 10.00 EUR (amount in cents)
currency="EUR",
minor_unit=2,
),
description="Coffee purchase",
return_url="https://example.com/webhook",
),
total_amount={
"value": 1000, # 10.00 EUR (amount in cents)
"currency": "EUR",
"minor_unit": 2,
},
description="Coffee purchase",
return_url="https://example.com/webhook",
)

print(f"Reader checkout created: {reader_checkout}")
Expand Down
11 changes: 7 additions & 4 deletions codegen/pkg/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ type Builder struct {

// schemasByTag maps tags to respective schema references.
schemasByTag map[string][]*base.SchemaProxy
// requestSchemasByTag maps tags to schemas referenced from request bodies/query params.
requestSchemasByTag map[string][]*base.SchemaProxy

pathsByTag map[string]*v3.Paths

Expand Down Expand Up @@ -58,10 +60,11 @@ func New(cfg Config, opts ...Option) *Builder {
}

b := &Builder{
cfg: cfg,
schemasByTag: make(map[string][]*base.SchemaProxy),
pathsByTag: make(map[string]*v3.Paths),
templates: templates,
cfg: cfg,
schemasByTag: make(map[string][]*base.SchemaProxy),
requestSchemasByTag: make(map[string][]*base.SchemaProxy),
pathsByTag: make(map[string]*v3.Paths),
templates: templates,
}

for _, o := range opts {
Expand Down
66 changes: 38 additions & 28 deletions codegen/pkg/builder/collect.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,41 +51,51 @@ func (b *Builder) collectPaths() {
func (b *Builder) collectSchemas() {
// Map of schemas grouped by tag
schemasByTag := make(map[string][]*base.SchemaProxy)
requestSchemasByTag := make(map[string][]*base.SchemaProxy)

for path, pathItem := range b.spec.Paths.PathItems.FromOldest() {
for method, op := range pathItem.GetOperations().FromOldest() {
c := make(SchemaProxyCollection, 0, 100)
c.collectSchemasInResponse(op)
c.collectSchemasInParams(op)
c.collectSchemasInRequest(op)

for _, schema := range c {
if schema.GetReference() == "" {
continue
}

if len(op.Tags) == 0 {
slog.Error("no tags for schema under operation",
slog.String("path", path),
slog.String("method", method),
slog.String("ref", schema.GetReference()),
)
continue
}

for _, tag := range op.Tags {
tagLower := strings.ToLower(tag)
if !slices.ContainsFunc(schemasByTag[tagLower], func(sp *base.SchemaProxy) bool {
return sp.GetReference() == schema.GetReference()
}) {
schemasByTag[tagLower] = append(schemasByTag[tagLower], schema)
}
}
}
allSchemas := make(SchemaProxyCollection, 0, 100)
allSchemas.collectSchemasInResponse(op)
allSchemas.collectSchemasInParams(op)
allSchemas.collectSchemasInRequest(op)
b.collectSchemasByTag(schemasByTag, path, method, op, allSchemas)

requestSchemas := make(SchemaProxyCollection, 0, 100)
requestSchemas.collectSchemasInParams(op)
requestSchemas.collectSchemasInRequest(op)
b.collectSchemasByTag(requestSchemasByTag, path, method, op, requestSchemas)
}
}

b.schemasByTag = schemasByTag
b.requestSchemasByTag = requestSchemasByTag
}

func (b *Builder) collectSchemasByTag(dest map[string][]*base.SchemaProxy, path, method string, op *v3.Operation, schemas SchemaProxyCollection) {
for _, schema := range schemas {
if schema.GetReference() == "" {
continue
}

if len(op.Tags) == 0 {
slog.Error("no tags for schema under operation",
slog.String("path", path),
slog.String("method", method),
slog.String("ref", schema.GetReference()),
)
continue
}

for _, tag := range op.Tags {
tagLower := strings.ToLower(tag)
if !slices.ContainsFunc(dest[tagLower], func(sp *base.SchemaProxy) bool {
return sp.GetReference() == schema.GetReference()
}) {
dest[tagLower] = append(dest[tagLower], schema)
}
}
}
}

type SchemaProxyCollection []*base.SchemaProxy
Expand Down
13 changes: 6 additions & 7 deletions codegen/pkg/builder/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,6 @@ func methodDoc(operation *v3.Operation) string {
return formatDoc(out.String())
}

// operationParamsDoc creates godoc comment for a struct representing
// parameters of an operation.
func operationParamsDoc(name string, operation *v3.Operation) string {
return formatDoc(name + ": query parameters for " + operation.OperationId)
}

// schemaDoc creates godoc for a schema.
func schemaDoc(name string, schema *base.Schema) string {
out := new(strings.Builder)
Expand Down Expand Up @@ -191,5 +185,10 @@ func formatDoc(s string) string {
}
}

return strings.TrimSpace(out.String())
return escapePythonDocString(strings.TrimSpace(out.String()))
}

func escapePythonDocString(s string) string {
s = strings.ReplaceAll(s, "\\", "\\\\")
return s
}
26 changes: 24 additions & 2 deletions codegen/pkg/builder/intermediate_representation.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@ type ClassDeclaration struct {
Description string
// AdditionalPropertiesType holds the value type for additional properties if enabled.
AdditionalPropertiesType string
// RequestOnly marks request-only helper types that should not emit response models.
RequestOnly bool
// GenerateInput indicates this type needs an Input companion.
GenerateInput bool
}

type OneOfDeclaration struct {
Name string
Options []string
Name string
Options []string
RequestOnly bool
GenerateInput bool
}

// Property holds the information for Property of a type.
Expand All @@ -50,6 +56,9 @@ type EnumDeclaration[E cmp.Ordered] struct {
// Comment holds the description of the type
Comment string
Values []E
// RequestOnly marks request-only helper types that should only emit input aliases.
RequestOnly bool
GenerateInput bool
}

type Response struct {
Expand All @@ -68,11 +77,24 @@ type TypeAlias struct {
Type string
// Comment holds the description of the type
Comment string
// RequestOnly marks request-only helper types that should only emit input aliases.
RequestOnly bool
GenerateInput bool
}

func (ta *TypeAlias) String() string {
buf := new(strings.Builder)
if ta.RequestOnly {
fmt.Fprintf(buf, "%sInput = %s\n", ta.Name, inputTypeName(ta.Type))
if ta.Comment != "" {
fmt.Fprintf(buf, "'''\n%s\n'''\n", ta.Comment)
}
return buf.String()
}
fmt.Fprintf(buf, "%s = %s\n", ta.Name, ta.Type)
if ta.GenerateInput {
fmt.Fprintf(buf, "%sInput = %s\n", ta.Name, inputTypeName(ta.Type))
}
if ta.Comment != "" {
fmt.Fprintf(buf, "'''\n%s\n'''\n", ta.Comment)
}
Expand Down
Loading
Loading