Speakeasy Logo
Skip to Content

Generate Python SDKs from OpenAPI / Swagger

SDK Overview

Speakeasy-generated Python SDKs are designed to be best in class, providing a seamless developer experience and full type safety, alongside asynchronous support.

The core Python SDK features include:

  • Fully type-annotated classes and methods with full Pydantic models and associated TypedDicts.
  • Async and Sync methods for all endpoints.
  • Support for streaming uploads and downloads.
  • Support for Server-Sent Events (SSE) with automatic method overloads for enhanced type safety.
  • Authentication support for OAuth flows and support for standard security mechanisms (HTTP Basic, application tokens, etc.).
  • Optional pagination support for supported APIs.
  • Optional support for retries in every operation.
  • Complex number types including big integers and decimals.
  • Date and date/time types using RFC3339 date formats.
  • Custom type enums using strings and integers (including Open Enums).
  • Union types and combined types.

Python Package Structure

  • setup.py
  • ...

By default, uv handles Python dependencies and packaging, but users can configure poetry instead via the packageManager option.

Python Type Safety

Modern Python uses type hints to improve code readability and so do Speakeasy-generated Python SDKs! Speakeasy-generated Python SDKs expose type annotations for developers to perform type checks at runtime and increase type safety, we also employ Pydantic models to ensure that the data passed to and from the SDK is valid at runtime.

The generated models

Speakeasy uses pydantic for all generated models to correctly serialize and deserialize objects; whether the objects are passed as query parameters, path parameters, or request bodies. Metadata based on the definitions provided by the OpenAPI document are appended to fields.

For example, this is the generated class for the Drink  component from our SpeakeasyBar template repository :

class Drink(BaseModel): name: str r"""The name of the drink.""" price: float r"""The price of one unit of the drink in US cents.""" type: Optional[DrinkType] = None r"""The type of drink.""" stock: Optional[int] = None r"""The number of units of the drink in stock, only available when authenticated.""" product_code: Annotated[Optional[str], pydantic.Field(alias="productCode")] = None r"""The product code of the drink, only available when authenticated."""

Python also generates matching TypedDict classes for each model, which can be used to pass in dictionaries to the SDK methods without the need to import the model classes.

class DrinkTypedDict(TypedDict): name: str r"""The name of the drink.""" price: float r"""The price of one unit of the drink in US cents.""" type: NotRequired[DrinkType] r"""The type of drink.""" stock: NotRequired[int] r"""The number of units of the drink in stock, only available when authenticated.""" product_code: NotRequired[str] r"""The product code of the drink, only available when authenticated."""

which allows methods to be called one of two ways:

res = s.orders.create_order(drinks=[ { "type": bar.OrderType.INGREDIENT, "product_code": "AC-A2DF3", "quantity": 138554, }, ])

or

res = s.orders.create_order(drinks=[ Drink( type=bar.OrderType.INGREDIENT, product_code="AC-A2DF3", quantity=138554, ), ])

Server-Sent Events (SSE) with type safety

Python SDKs automatically generate method overloads for Server-Sent Events operations when the inferSSEOverload configuration is enabled (default: true). This feature provides enhanced type safety by creating separate method signatures for streaming and non-streaming responses.

When an operation meets the following criteria, Speakeasy will generate overloaded methods:

  • The operation has a required request body
  • The request body contains a stream field (boolean type)
  • The operation has exactly two responses: one text/event-stream and one application/json
# Non-streaming method - returns JSON response object response = s.chat.create(prompt="Hello world", stream=False) print(response.content) # Fully typed ChatResponse # Streaming method - returns SSE event iterator stream = s.chat.create(prompt="Hello world", stream=True) for event in stream: print(event.data) # Fully typed ChatEvent

This eliminates the need for runtime type checking and provides better IDE support with accurate type hints for both streaming and non-streaming use cases.

Async vs Sync Methods

Speakeasy-generated Python SDKs provide both synchronous and asynchronous methods for all endpoints. The SDK uses the httpx library for making HTTP requests, which supports both synchronous and asynchronous requests.

Synchronous:

res = s.orders.create_order(drinks=[ Drink( type=bar.OrderType.INGREDIENT, product_code="AC-A2DF3", quantity=138554, ), ])

Asynchronous:

res = await s.orders.create_order_async(drinks=[ Drink( type=bar.OrderType.INGREDIENT, product_code="AC-A2DF3", quantity=138554, ), ])

HTTP Client

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

Parameters

If configured, Speakeasy will generate methods with parameters for each parameter 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 is set to 0, a request object will be generated for the method to pass in all parameters as a single object.

Errors

The Python SDK will raise exceptions for any network or invalid request errors.

For unsuccessful responses, if a custom error response is specified in the spec file, the SDK will unmarshal the HTTP response details into the custom error response to be thrown as an exception. When no custom response is specified in the spec, the SDK will throw an SDKException with details of the failed response.

import sdk from sdk.models import errors s = sdk.SDK() res = None try: res = s.errors.status_get_x_speakeasy_errors(status_code=385913) except errors.StatusGetXSpeakeasyErrorsResponseBody as e: # handle exception except errors.SDKError as e: # handle exception if res is not None: # handle response pass

User Agent Strings

The Python SDK includes a user agent  string in all requests. This can be leveraged to track 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

SDK Memory footprint and Load time

Speakeasy-generated Python SDKs employ a lazy loading mechanism for their functional components (e.g., groups of operations like orders, users, etc.) and their associated models. This means these components are not loaded into memory when you initially import the SDK or create an SDK instance. Instead, a specific component is loaded only the first time you access it.

Example:

import sdk # Initial SDK instantiation: # Only the core SDK logic is loaded. # Modules for specific API features like 'orders' are NOT yet loaded. s = sdk.SDK() # First access to a component: # When s.orders is accessed here for the first time, # the 'orders' module is dynamically imported and initialized. # This is the point where the code for 'orders' functionality is loaded. orders_list = s.orders.list_orders() # Subsequent accesses: # The 'orders' component is now loaded and cached. # Further operations on s.orders use the already-loaded component directly. order_details = s.orders.get_details(id="some_id")

This design provides two key benefits:

  • Reduced Memory Footprint: Your application only loads the parts of the SDK it actually uses, conserving memory.
  • Faster Startup Times: The initial import of the SDK and its instantiation are quicker, as it avoids pre-emptively loading all possible components.

Collectively, these improvements contribute to a smoother and more efficient developer experience.

Last updated on