# Custom Code Regions in Python

To enable custom code regions for Python SDKs, update the project's
`.speakeasy/gen.yaml` file as follows:

```diff filename=".speakeasy/gen.yaml"
configVersion: 2.0.0
generation:
  # ...
python:
  # ...
+ enableCustomCodeRegions: true
```

## Full example

The Speakeasy examples repository includes a [full Python SDK](https://github.com/speakeasy-api/examples/tree/main/customcode-sdkclasses-python) that uses custom code regions.

## Regions

Below are the available code regions in Python SDKs.

### SDK classes

Python SDK classes can have two code regions:

- `# region imports`: The imports region allows you to add imports to an SDK file needed for
  custom methods and properties. It must be located at the top of the
  file alongside generated imports.
- `# region sdk-class-body`: The class-body region allows you to add custom methods and
  properties to an SDK class. It must be located in the body of a Python
  SDK class alongside generated methods and properties.

## Managing dependencies

When adding custom code that requires external packages, configure these dependencies in the `.speakeasy/gen.yaml` file to prevent them from being removed during SDK regeneration. Use the `additionalDependencies` configuration to specify package dependencies:

```yaml filename=".speakeasy/gen.yaml"
python:
  additionalDependencies:
    main:
      markdown: "^3.4.0"
      beautifulsoup4: "^4.12.0"
    dev:
      pytest: "^7.0.0"
      black: "^23.0.0"
```

This ensures that dependencies persist across SDK regenerations and are properly included in the generated `pyproject.toml`.

```python filename="src/todos_sdk/todos.py"
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""

from .basesdk import BaseSDK
from todos_sdk import models, utils
from todos_sdk._hooks import HookContext
from todos_sdk.types import OptionalNullable, UNSET
from typing import Mapping, Optional

# region imports
import markdown
# endregion imports

class Todos(BaseSDK):
    # region sdk-class-body
    def render_todo(self, id: str) -> str:
        todo = self.get_one(id=id)

        return markdown.markdown(f"# {todo.title}\n\n{todo.description}")

    # endregion sdk-class-body

    def get_one(
        self,
        *,
        id: int,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.Todo:
        ...

    async def get_one_async(
        self,
        *,
        id: int,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.Todo:
        ...
```
