rembrembdocs

Generating Python Types

How to generate Python types for your API and Supabase libraries.


Supabase APIs are generated from your database, which means that we can use database introspection to generate type-safe API definitions.

Generating types using Supabase CLI#

The Supabase CLI is a single binary Go application that provides everything you need to setup a local development environment.

You can install the CLI via npm or other supported package managers. The minimum required version of the CLI is v2.66.0.

1npm i supabase --save-dev

Login with your Personal Access Token:

1npx supabase login

Before generating types, ensure you initialize your Supabase project:

1npx supabase init

Generate types for your project to produce the database_types.py file:

1npx supabase gen types --lang=python --project-id "$PROJECT_REF" --schema public > database.types.py

or in case of local development:

1npx supabase gen types --lang=python --local > database_types.py

These types are generated from your database schema. Given a table public.movies, the generated types will look like:

1create table public.movies (2  id bigint generated always as identity primary key,3  name text not null,4  data jsonb null5);
1class PublicMovies(BaseModel):2    data: Optional[Json[Any]] = Field(alias="data")3    id: int = Field(alias="id")4    name: str = Field(alias="name")56class PublicMoviesInsert(TypedDict):7    data: NotRequired[Annotated[Json[Any], Field(alias="data")]]8    id: NotRequired[Annotated[int, Field(alias="id")]]9    name: Annotated[str, Field(alias="name")]1011class PublicMoviesUpdate(TypedDict):12    data: NotRequired[Annotated[Json[Any], Field(alias="data")]]13    id: NotRequired[Annotated[int, Field(alias="id")]]14    name: NotRequired[Annotated[str, Field(alias="name")]]

Types for select, insert and update#

The PublicMovies class is used to parse SELECT results from the movies table, while PublicMoviesInsert and PublicMoviesUpdate are used to format and provide completion for arguments for insert and update respectively.

1from .database_types import PublicMovies, PublicMoviesInsert, PublicMoviesUpdate2from supabase import create_client34client = create_client("YOUR_SUPABASE_URL", "YOUR_SUPABASE_KEY")5movies = client.table("movies")67# Select8selected = [PublicMovies(m) for m in movies.select("*").execute().data]910# Insert11inserted = [PublicMovies(m) for m in movies.insert(PublicMoviesInsert(name="foo", data="bar")) \12                                          .execute().data]1314# Update15updated  = [PublicMovies(m) for m in movies.update(PublicMoviesUpdate(name="bar")) \16                                        .eq("id", 5) \17                                        .execute().data]

Update types automatically with GitHub Actions#

One way to keep your type definitions in sync with your database is to set up a GitHub action that runs on a schedule.

Add the following script to your package.json to run it using npm run update-types

1"update-types": "npx supabase gen types --lang=python --project-id \"$PROJECT_REF\" > database_types.py"

Create a file .github/workflows/update-types.yml with the following snippet to define the action along with the environment variables. This script will commit new type changes to your repo every night.

1name: Update database types23on:4  schedule:5    # sets the action to run daily. You can modify this to run the action more or less frequently6    - cron: '0 0 * * *'78jobs:9  update:10    runs-on: ubuntu-latest11    permissions:12      contents: write13    env:14      SUPABASE_ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}15      PROJECT_REF: <your-project-id>16    steps:17      - uses: actions/checkout@v418        with:19          persist-credentials: false20          fetch-depth: 021      - uses: actions/setup-node@v422        with:23          node-version: 2224      - run: npm run update-types25      - name: check for file changes26        id: git_status27        run: |28          echo "status=$(git status -s)" >> $GITHUB_OUTPUT29      - name: Commit files30        if: ${{contains(steps.git_status.outputs.status, ' ')}}31        run: |32          git add database_types.py33          git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"34          git config --local user.name "github-actions[bot]"35          git commit -m "Update database types" -a36      - name: Push changes37        if: ${{contains(steps.git_status.outputs.status, ' ')}}38        uses: ad-m/github-push-action@master39        with:40          github_token: ${{ secrets.GITHUB_TOKEN }}41          branch: ${{ github.ref }}

Resources#