# Python configuration options

This section details the available configuration options for the Python SDK. All configuration is managed in the `gen.yaml` file under the `python` section.

## Identity and metadata

```yml
python:
  version: 1.2.3
  templateVersion: v2
  packageName: "openapi"
  moduleName: "openapi"
  authors: ["Author Name"]
  description: "Python Client SDK Generated by Speakeasy."
  homepage: "https://example.com"
  documentationUrl: "https://example.com/docs"
  license: "Apache-2.0"
```

### Different package and module names

Configure a different name for the PyPI package and the module to import from:

```yml
python:
  packageName: "my-package" # Install with: pip install my-package
  moduleName: "my_module" # Import with: from my_module import SDK
```

This can be useful when the package name follows PyPI conventions (using hyphens) but the module name follows Python conventions (using underscores).

## Build and tooling

```yml
python:
  packageManager: "uv"
  additionalDependencies:
    main:
      requests: "^2.25.1"
    dev:
      pytest: "^6.2.1"
  compileCommands:
    - ["uv", "lock"]
    - ["uv", "sync", "--dev"]
    - ["uv", "run", "python", "-m", "compileall", "-q", "."]
  pytestFilterWarnings:
    - error
    - "ignore::DeprecationWarning"
  pytestTimeout: 300
```

<Callout title="Default compilation pipeline" type="info">
When `compileCommands` is not set, the default pipeline runs based on the package manager (`uv` or `poetry`) and includes bytecode compilation (`compileall`), linting (`pylint -j=0`), and type checking (`mypy` and `pyright` in parallel). To reduce pylint parallelism and avoid OOM errors in CI, use `compileCommands` with `-j=1`.
</Callout>

### Optional dependencies

Use `optionalDependencies` to declare optional dependency groups, known as extras, in the generated `pyproject.toml` file. Extras let end users install packages that the SDK needs only for specific functionality, keeping the default installation lightweight.

Each top-level key under `optionalDependencies` is the name of an extra. Each extra holds a map of package names to [PEP 508](https://peps.python.org/pep-0508/) version specifiers:

```yml
python:
  optionalDependencies:
    http2:
      h2: ">=4.0.0"
    cli:
      click: ">=8.1.0"
      rich: ">=13.0.0"
```

This configuration generates the following `[project.optional-dependencies]` table:

```toml
[project.optional-dependencies]
cli = [
    "click >=8.1.0",
    "rich >=13.0.0",
]
http2 = [
    "h2 >=4.0.0",
]
```

End users then install an extra by name:

```bash
pip install my-package[http2]
```

Extras and their packages are sorted alphabetically in the output. An extra with no packages renders as an empty list, such as `http2 = []`. Both the `uv` and `poetry` package managers support `optionalDependencies`.

<Callout title="Optional vs. additional dependencies" type="info">
Use `additionalDependencies` for packages the SDK always needs, since they are installed with the base package. Use `optionalDependencies` for packages the SDK needs only for specific features, since they are installed only when an end user requests the matching extra.
</Callout>

## API surface shape

```yml
python:
  maxMethodParams: 999
  flattenRequests: true
  flatteningOrder: "parameters-first"
  methodArguments: "infer-optional-args"
  flattenGlobalSecurity: true
  envVarPrefix: "SPEAKEASY"
  responseFormat: "flat"
  multipartArrayFormat: "standard"
  imports:
    option: "openapi"
    paths:
      callbacks: "models/callbacks"
      errors: "models/errors"
      operations: "models/operations"
      shared: "models/shared"
      webhooks: "models/webhooks"
```

### Import paths

## Async and SSE

```yml
python:
  asyncMode: split
  useAsyncHooks: false
  sseFlatResponse: false
```

The `asyncMode` setting provides two patterns for handling async operations:

**Method-based (`both`, default)**: Every operation has two methods — a synchronous version and an asynchronous version with an `_async` suffix.

```python
sdk = MyAPI(api_key="...")

# Synchronous operations
result = sdk.list_users()

# Asynchronous operations
result = await sdk.list_users_async()
```

**Constructor-based (`split`)**: Separate constructors for synchronous and asynchronous clients. All method names are identical between sync and async versions.

```python
# Synchronous client
sync_sdk = MyAPI(api_key="...")
result = sync_sdk.list_users()

# Asynchronous client
async_sdk = AsyncMyAPI(api_key="...")
result = await async_sdk.list_users()
```

The constructor-based pattern eliminates method name duplication and provides clearer IDE suggestions.

<Callout title="Breaking change" type="warning">
Switching to `asyncMode: split` is a breaking change. Existing SDK consumers will need to update their code to use the new constructor pattern.
</Callout>

## Errors

```yml
python:
  clientServerStatusCodesAsErrors: true
  defaultErrorName: ""
  baseErrorName: "APIError"
```

## Enums and unions

```yml
python:
  enumFormat: "union"
  forwardCompatibleEnumsByDefault: true
  forwardCompatibleUnionsByDefault: "tagged-only"
  inferUnionDiscriminators: true
  preApplyUnionDiscriminators: true
```

## Models and miscellaneous

```yml
python:
  inputModelSuffix: "input"
  outputModelSuffix: "output"
  constFieldCasing: "normal"
  allowedRedefinedBuiltins:
    - id
    - object
    - input
    - dir
  enableCustomCodeRegions: false
```

## Fixes

Fixes to apply to the generated SDK. Generally `true` for new SDKs but may be `false` for backward compatibility with existing SDKs.

```yml
python:
  fixes:
    responseRequiredSep2024: true
    asyncPaginationSep2025: true
    conflictResistantModelImportsFeb2026: true
```
