Generate Python SDKs from OpenAPI / Swagger

Info Icon

OSS Comparison

For a comparison between the Speakeasy Python SDK and some popular open-source generators, see this page.

SDK Overview

Speakeasy-generated Python SDKs are designed to be easy to use and easy to debug. Some of their core features include:

  • Fully type-annotated classes and methods
  • Docstrings generated from the OpenAPI document to enhance the developer experience
  • Optional Pagination available for supported APIs
  • Support for:
    • complex data types (Decimal, date, datetime)
    • Union types
    • string and integer based Enums
    • additionalProperties

Python Package Structure


├── src
| └── {SDK Class Name} # Root module for the SDK where {SDK Class Name} is the provided name of the SDK
| ├── {SDK Class Name}.py # The main SDK class
| ├── ... # Other SDK classes
| ├── models # Module for SDK's models
| | |── shared # Submodule providing the SDK's models generated from components in the OpenAPI document
| | |── operations # Submodule providing the SDK's operations models which generally house the request/response models for each API document
| | └── ...
| └── utils # Module for the SDK's utility classes
├── docs # Markdown files for the SDK's documentation
| └── ...
├── setup.py # Package setup
└── ...

Speakeasy Python SDKs are packaged using setuptools, which makes it easy to distribute them to your customers.

Python Type Safety

Modern Python makes use of type-hints to improve code readability and that's what Speakeasy-generated Python SDKs do! By exposing type annotations to developers we also allow them to perform type checking at runtime and increase type safety.

Dataclasses

Using dataclasses fields for all generated models allows Speakeasy to correctly serialize and deserialize objects – whether they are passed as query parameters, path parameters, or request bodies – by appending per-field metadata based on the definitions provided by the OpenAPI document.

For instance, here's the class that we generate for the Drink (opens in a new tab) component from our SpeakeasyBar template repository (opens in a new tab):


@dataclass_json(undefined=Undefined.EXCLUDE)
@dataclasses.dataclass
class Drink:
r"""A drink."""
name: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('name') }})
r"""The name of the drink."""
price: float = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('price') }})
r"""The price of one unit of the drink in US cents."""
product_code: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('productCode'), 'exclude': lambda f: f is None }})
r"""The product code of the drink, only available when authenticated."""
stock: Optional[int] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('stock'), 'exclude': lambda f: f is None }})
r"""The number of units of the drink in stock, only available when authenticated."""
type: Optional[shared_drinktype.DrinkType] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'lette

Union types

Speakeasy-generated Python SDKs now allow Union types! For instance, here's a typical Response class associated with the following schema:


Meal:
oneOf:
- $ref: "#/components/schemas/Lunch"
- $ref: "#/components/schemas/Dinner"


@dataclass_json(undefined=Undefined.EXCLUDE)
@dataclasses.dataclass
class MealPostRes:
r"""OK"""
json: Union[shared.lunch.Lunch, shared.dinner.Dinner] = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('json'), 'decoder': utils.decoder_with_discriminator('type') }})

Streamable Responses

If you create an endpoint with a top-level binary response body, you can treat that response as a streamable, and iterate over it without loading the entire response into memory. This is useful for large file downloads, long-running streaming responses and more.


/streamable:
get:
operationId: streamable
responses:
"200":
description: OK
content:
application/octet-stream:
schema:
title: bytes
type: string
format: binary

In this case, the Speakeasy Python SDK will generate a response object with a bytes attribute of type requests.Response. This low level response object allows you to iterate over the content using the iter_content function.

For example, you could use this code to write the stream to a file


s = SDK()
res = s.streamable()
with open(file_path, 'wb') as myfile:
for some_bytes in res.bytes.iter_content():
myfile.write(some_bytes)

HTTP Client

To make API calls the Python SDK instantiates its own HTTP client using the Session class from the Requests library. This allows authentication settings to persist across requests and reduce overhead.

Parameters

If configured we will generate methods with parameters for each of the parameters defined in the OpenAPI document, as long as the number of parameters is less than or equal to the configured maxMethodParams value in the gen.yaml file.

If the number of parameters exceeds the configured maxMethodParams value or this is set to 0 then a request object is generated for the method instead that allows for all parameters to be passed in a single object.

Errors

The Python SDK will raise Exceptions for any network or invalid request errors. For non-successful responses the SDK will return a response object that contains the status code and the response body, which can be checked for the status of the method call.

User Agent Strings

The Python SDK will include a user agent (opens in a new tab) string in all requests. This can be leveraged for tracking SDK usage amongst broader API usage. The format is as follows:


speakeasy-sdk/python {{SDKVersion}} {{GenVersion}} {{DocVersion}} {{PackageName}}

Where

  • SDKVersion is the version of the SDK, defined in gen.yaml and released
  • GenVersion is the version of the Speakeasy generator
  • DocVersion is the version of the OpenAPI document
  • PackageName is the name of the package defined in gen.yaml