Skip to content

Limitations

There are two forms of limitations imposed on Prisma Client Python, the first is due to missing features / performance issues with mypy and can be re-enabled by switching to use pyright instead. The second is due to scenarios that cannot be accurately represented within Python's type system.

Default Type Limitations

Note

It is highly recommended to use pyright as your type checker of choice for Prisma Client Python applications.

Due to mypy limtations, some types are not as explicit as they should be and as such cannot be considered fully type safe, however all of the limitations imposed by mypy can be removed by switching to pyright and configuring prisma to use recursive types.

Removing Limitations

You can catch all errors while type checking by using pyright and configuring prisma to use recursive types.

Filtering by Relational Fields

Prisma supports searching for records based off of relational record values. However, type checking this feature with mypy caused mypy to hang and eventually crash.

As such these types have been broadened, this means that mypy will not catch errors when filtering by a relational field, for example, the following will not raise any mypy errors, however an error will be raised at runtime.

from prisma import Prisma

async def main(db: Prisma) -> None:
    user = await db.user.find_first(
        where={
            'profile': {
                'is': {
                    'an_invalid_value': 'foo',
                },
            },
        }
    )

Complex Grouping Arguments

Mypy does not support Literal TypeVars which means the following invalid code will not produce an error when type checking:

results = await Profile.prisma().group_by(
    by=['country'],
    order={
        # city has to be included in the `by` argument to be valid
        'city': True,
    }
)

This error can be revealed by switching to pyright and configuring prisma to use recursive types.

Python Limitations

There are some limitations to type safety due to Python's inability to expressively work with input types. While it would be possible to work around this as Prisma Client Python code is auto-generated, we need to strike a balance between performance and correctness.

These limitations only effect 2 arguments in one query method in the entire client API.

Grouping records

Explanation

Some filters can only be performed on fields that are being grouped (i.e. in the by argument), this is not possible to type in Python with any accuracy. It is possible to limit dictionary keys but it is not possible to match the dictionary keys to specific types like you can with a standard TypedDict.

For example, the order argument can correctly limit the available keys as all the values have the same type

results = await Profile.prisma().group_by(
    by=['city'],
    order={
        'city': 'asc',
        # this will error as 'country' is not present in the `by` argument
        'country': 'desc',
    },
)

However this is not possible with the having argument as all the dictionary values have different types.

# this error will NOT be caught by static type checkers!
# but it will raise an error at runtime
results = await Profile.prisma().group_by(
    by=['city'],
    having={
        'views': {
            'gt': 50,
        },
    },
)

Limitations

Order Argument

The order argument can only take one field at a time.

The following example will pass type checks but will raise an error at runtime.

results = await Profile.prisma().group_by(
    by=['city', 'country'],
    order={
        'city': 'asc',
        'country': 'desc',
    },
)
Having Argument

The having argument only takes fields that are present in the by argument or aggregation filters.

For example:

# this will pass type checks but will raise an error at runtime
# as 'views' is not present in the `by` argument
await Profile.prisma().group_by(
    by=['country'],
    count=True,
    having={
        'views': {
            'gt': 50,
        },
    },
)

# however this will pass both type checks and at runtime!
await Profile.prisma().group_by(
    by=['country'],
    count=True,
    having={
        'views': {
            '_avg': {
                'gt': 50,
            },
        },
    },
)