Prisma Client Python is an auto-generated and fully type-safe database client

Overview

Prisma Client Python

Type-safe database access for Python


What is Prisma Client Python?

Prisma Client Python is an unofficial implementation of Prisma which is a next-generation ORM that comes bundled with tools, such as Prisma Migrate, which make working with databases as easy as possible.

Prisma Client Python can be used in any Python backend application. This can be a REST API, a GraphQL API or anything else that needs a database.

Why should you use Prisma Client Python?

Unlike other Python ORMs, Prisma Client Python is fully type safe and offers native support for usage with and without async. All you have to do is specify the type of client you would like to use for your project in the Prisma schema file.

Core features:

Supported database providers:

  • PostgreSQL
  • MySQL
  • SQLite
  • MongoDB (experimental)
  • SQL Server (experimental)

How does Prisma work?

This section provides a high-level overview of how Prisma works and its most important technical components. For a more thorough introduction, visit the documentation.

The Prisma schema

Every project that uses a tool from the Prisma toolkit starts with a Prisma schema file. The Prisma schema allows developers to define their application models in an intuitive data modeling language. It also contains the connection to a database and defines a generator:

// database
datasource db {
  provider = "sqlite"
  url      = "file:database.db"
}

// generator
generator client {
  provider = "prisma-client-py"
}

// data models
model Post {
  id        Int     @id @default(autoincrement())
  title     String
  content   String?
  views     Int     @default(0)
  published Boolean @default(false)
  author    User?   @relation(fields: [author_id], references: [id])
  author_id Int?
}

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
  posts Post[]
}

In this schema, you configure three things:

  • Data source: Specifies your database connection. In this case we use a local SQLite database however you can also use an environment variable.
  • Generator: Indicates that you want to generate Prisma Client Python.
  • Data models: Defines your application models.

On this page, the focus is on the generator as this is the only part of the schema that is specific to Prisma Client Python. You can learn more about Data sources and Data models on their respective documentation pages.

Prisma generator

A prisma schema can define one or more generators, defined by the generator block.

A generator determines what assets are created when you run the prisma generate command. The provider value defines which Prisma Client will be created. In this case, as we want to generate Prisma Client Python, we use the prisma-client-py value.

You can also define where the client will be generated to with the output option. By default Prisma Client Python will be generated to the same location it was installed to, whether thats inside a virtual environment, the global python installation or anywhere else that python packages can be imported from.

For more options see configuring Prisma Client Python.


Accessing your database with Prisma Client Python

Just want to play around with Prisma Client Python and not worry about any setup? You can try it out online on gitpod.

Installing Prisma Client Python

The first step with any python project should be to setup a virtual environment to isolate installed packages from your other python projects, however that is out of the scope for this page.

In this example we'll use an asynchronous client, if you would like to use a synchronous client see setting up a synchronous client.

pip install -U prisma

Generating Prisma Client Python

Now that we have Prisma Client Python installed we need to actually generate the client to be able to access the database.

Copy the Prisma schema file shown above to a schema.prisma file in the root directory of your project and run:

prisma db push

This command will add the data models to your database and generate the client, you should see something like this:

Prisma schema loaded from schema.prisma
Datasource "db": SQLite database "database.db" at "file:database.db"

SQLite database database.db created at file:database.db


πŸš€  Your database is now in sync with your schema. Done in 26ms

βœ” Generated Prisma Client Python to ./.venv/lib/python3.9/site-packages/prisma in 265ms

It should be noted that whenever you make changes to your schema.prisma file you will have to re-generate the client, you can do this automatically by running prisma generate --watch.

The simplest asynchronous Prisma Client Python application looks something like this:

import asyncio
from prisma import Client

async def main() -> None:
    client = Client()
    await client.connect()

    # write your queries here

    await client.disconnect()

if __name__ == '__main__':
    asyncio.get_event_loop().run_until_complete(main())

Query examples

For a more complete list of queries you can perform with Prisma Client Python see the documentation.

All query methods return pydantic models.

Retrieve all User records from the database

users = await client.user.find_many()

Include the posts relation on each returned User object

users = await client.user.find_many(
    include={
        'posts': True,
    },
)

Retrieve all Post records that contain "prisma"

posts = await client.post.find_many(
    where={
        'OR': [
            {'title': {'contains': 'prisma'}},
            {'content': {'contains': 'prisma'}},
        ]
    }
)

Create a new User and a new Post record in the same query

user = await client.user.create(
    data={
        'name': 'Robert',
        'email': '[email protected]',
        'posts': {
            'create': {
                'title': 'My first post from Prisma!',
            },
        },
    },
)

Update an existing Post record

post = await client.post.update(
    where={
        'id': 42,
    },
    data={
        'views': {
            'increment': 1,
        },
    },
)

Usage with static type checkers

All Prisma Client Python methods are fully statically typed, this means you can easily catch bugs in your code without having to run it!

For more details see the documentation.

Room for improvement

Prisma Client Python is a new project and as such there are some features that are missing or incomplete.

Auto completion for query arguments

Prisma Client Python query arguments make use of TypedDict types. While there is very limited support for completion of these types within the Python ecosystem some editors do support it.

Supported editors / extensions:

user = await client.user.find_first(
    where={
        '|'
    }
)

Given the cursor is where the | is, an IDE should suggest the following completions:

  • id
  • email
  • name
  • posts

Performance

There has currently not been any work done on improving the performance of Prisma Client Python queries, this is something that will be worked on in the future and there is room for massive improvements.

Supported platforms

Only MacOS and Linux are officially supported.

Windows is unofficially supported as tests are not currently ran on windows.

Version guarantees

Prisma Client Python is not stable.

Breaking changes will be documented and released under a new MINOR version following this format.

MAJOR.MINOR.PATCH

Contributing

We use conventional commits (also known as semantic commits) to ensure consistent and descriptive commit messages.

See the contributing documentation for more information.

Attributions

This project would not be possible without the work of the amazing folks over at prisma.

Massive h/t to @steebchen for his work on prisma-client-go which was incredibly helpful in the creation of this project.

This README is also heavily inspired by the README in the prisma/prisma repository.

Comments
  • Add full support for filtering by relations

    Add full support for filtering by relations

    Problem

    Currently only support nested filtering (through the include argument), this means that even if nothing matches the nested filter the base filter still passes, which could be confusing.

    Suggested solution

    Add relational fields to WhereInput, e.g.

    model Post {
      ...
      categories Category[] @relation(references: [id])
    }
    
    model Category {
      id    Int    @id @default(autoincrement())
      posts Post[] @relation(references: [id])
      name  String
    }
    
    class PostWhereInput(TypedDict, total=False):
    	...
    	categories: Optional['CategoryListRelationalFilter']
    
    class CategoryListRelationalFilter(TypedDict, total=False):
    	every: Optional['CategoryWhereInput']
    	some: Optional['CategoryWhereInput']
    	none: Optional['CategoryWhereInput']
    

    Additional context

    Playground schema screenshot

    kind/feature 
    opened by RobertCraigie 32
  • Where clause with multiple values

    Where clause with multiple values

    Hey,

    Is there any way to use IN and NOT IN for normal kind of columns in the where clause?

    Ex: Get the objects from the db from a list of IDs.

    Sorry for opening an issue, I searched the docs but couldn't find it.

    kind/question 
    opened by danielweil 16
  • Temporary tables

    Temporary tables

    Hello Robert,

    I am trying to create temporary tables using query_raw, and when I try to access it in the next query command, it can't be found.

    If I put it into the same string, and execute all of it in one query_raw command, it works. But I would like to do it the other way.

    Is there any solution?

    image

    This doesn't work!

    kind/question 
    opened by danielweil 14
  • refactor(cli): remove pkg in favour of automatically downloading Node

    refactor(cli): remove pkg in favour of automatically downloading Node

    Change Summary

    This PR completely refactors how the Prisma CLI is downloaded / installed / called. We now download Node itself at runtime and use that to install the Prisma CLI and then run it directly with Node as well.

    This has some significant advantages:

    • We are now no longer tied to releases of the packaged CLI
      • These were being released by Luca, who created the Go Client and is no longer at Prisma, on his own free time.
      • Only major versions were released which means the CLI couldn't be easily tested with the latest changes on the https://github.com/prisma/prisma repository
    • Prisma Studio can now be launched from the CLI
    • The TypeScript Client can now be generated from our CLI wrapper
    • We now longer have to manually download the engine binaries ourselves, that's handled transparently for us
    • A packaged version of Node no longer has to be installed for each new Prisma version
    • We now have support for ARM

    However, this does not come without some concerns:

    • Size increase
      • We use https://github.com/ekalinin/nodeenv to download Node at runtime if it isn't already installed. This downloads and creates extra files that are not strictly necessary for our use case. This results in an increase from ~140MB -> ~300MB. -
      • However this size increase can be reduced by installing nodejs-bin which you can do by providing the node extra, e.g. pip install prisma[node]. This brings the total download size to be very similar to the packaged CLI.
      • This concern also doesn't apply in cases where Node is already present. It actually will greatly improve the experience in this case.

    How does it work?

    We now resolve a Node binary using this flow:

    • Check if nodejs-bin is installed
    • Check if Node is installed globally
    • Downloads Node using https://github.com/ekalinin/nodeenv to a configurable location which defaults to ~/.cache/prisma-nodeenv

    The first two steps in this flow can be skipped if you so desire through your pyproject.toml file or using environment variables. For example:

    [tool.prisma]
    # skip global node check
    use_global_node = false
    
    # skip nodejs-bin check
    use_nodejs_bin = false
    
    # change nodeenv installation directory
    nodeenv_cache_dir = '~/.foo/nodeenv'
    

    Or using the environment variables, PRISMA_USE_GLOBAL_NODE, PRISMA_USE_NODEJS_BIN and PRISMA_NODEENV_CACHE_DIR respectively.

    The Prisma CLI is then installed directly from npm and ran directly using the resolved Node binary.

    closes #22 closes #236 closes #370 closes #413 closes #461 closes #621

    Checklist

    • [ ] Unit tests for the changes exist
    • [ ] Tests pass without significant drop in coverage
    • [ ] Documentation reflects changes where applicable
    • [ ] Test snapshots have been updated if applicable

    TODO:

    • [x] Write node tests
    • [x] Ensure we don't use an out of date global node installation
    • [x] Fix windows
    • [x] Documentation
      • [x] Document config
    • [x] Fix TODOs in _node.py
    • [x] Fix incorrect caching location in tests
    • [x] Fix prisma_version not reading from environment variables
    • [x] Audit subprocess calls
    • [x] Test refactored fetch command
    • [x] Check binaryTargets warning.

    Agreement

    By submitting this pull request, I confirm that you can use, modify, copy and redistribute this contribution, under the terms of your choice.

    opened by RobertCraigie 13
  • feat(types): improve order by type safety

    feat(types): improve order by type safety

    Change Summary

    Improves the order type to signify that only one field can be present at any given time.

    Checklist

    • [x] Unit tests for the changes exist
    • [x] Tests pass without significant drop in coverage
    • [ ] Documentation reflects changes where applicable
    • [ ] Test snapshots have been updated if applicable

    Agreement

    By submitting this pull request, I confirm that you can use, modify, copy and redistribute this contribution, under the terms of your choice.

    opened by RobertCraigie 13
  • feat(http): add support for httpx

    feat(http): add support for httpx

    HTTPX is a requests-API compatible library providing high performance sync and async http clients.

    This PR adds both sync and async clients backed by HTTPX.

    Given that this client is brand new, maybe consider going with just httpx so that you can offer support for both sync and async clients w/o the complexity or having 2 dependencies w/ vastly different interfaces?

    opened by adriangb 13
  • ImportError with custom output

    ImportError with custom output

    Hey, hello again!

    It is giving me the error message:

    Unable to match input value to any allowed input type for the field. Parse errors: [Query parsing/validation error at Mutation.upsertOneUser.create.UserCreateInput.name: Field does not exist on enclosing type., Query parsing/validation error at Mutation.upsertOneUser.create.UserUncheckedCreateInput.name: Field does not exist on enclosing type.]atMutation.upsertOneUser.create

    when I added the field "name" into my object.

    How can I fix it?

    kind/question 
    opened by danielweil 12
  • Experimental support  for the Decimal type

    Experimental support for the Decimal type

    Why is this experimental?

    Currently Prisma Client Python does not have access to the field metadata containing the precision of Decimal fields at the database level. This means that we cannot:

    • Raise an error if you attempt to pass a Decimal value with a greater precision than the database supports, leading to implicit truncation which may cause confusing errors
    • Set the precision level on the returned decimal.Decimal objects to match the database level, potentially leading to even more confusing errors.

    To try and mitigate the effects of these errors you must be explicit that you understand that the support for the Decimal type is not up to the standard of the other types. You do this by setting the enable_experimental_decimal config flag, e.g.

    generator py {
      provider                    = "prisma-client-py"
      enable_experimental_decimal = true
    }
    
    topic: types kind/feature level/advanced priority/medium 
    opened by RobertCraigie 12
  • DateTime comparisons behaving unexpectedly

    DateTime comparisons behaving unexpectedly

    Bug description

    A find_many query based on a datetime field returns unexpected results. gt/gte/lt/lte should be able to be used to specify ranges of availability (either in isolation or in combination), but diverge from what I was expecting.

    How to reproduce

    1. Clone https://github.com/iiian/prisma_python_datefailure_demo
    2. prisma generate && prisma db push to produce cli and db files the demo model:
    model Demo {
      id         Int      @id
      created_at DateTime @default(now())
    }
    
    1. open db, sqlite3 database.db
    2. INSERT INTO Demo (id) VALUES (1); to create a record with the present moment in the created_at field
    3. SELECT * FROM Demo; to confirm its existence
    sqlite> SELECT * FROM Demo;
    1|2022-01-08 08:01:58
    
    1. run python3 demo.py, and observe test results:

    TESTS

    today = datetime.utcnow()
    # 1. does a record exist who was created before the present moment? (Expecting true)
    print(await client.demo.find_many(where={
        'created_at': {
            'lt': today
        }
    }))
    # 2. " " " before or at present (Expecting true)
    print(await client.demo.find_many(where={
        'created_at': {
            'lte': today
        }
    }))
    # 3. does a record exist who was created after the present moment? (Expecting false)
    print(await client.demo.find_many(where={
        'created_at': {
            'gt': today
        }
    }))
    # 4. " " " after or at present moment (Expecting false)
    print(await client.demo.find_many(where={
        'created_at': {
            'gte': today
        }
    }))
    # 5. " " " after this morning, and before this time tomorrow (Expecting true)
    print(await client.demo.find_many(where={
        # (I think syntax is correct? doesn't complain)
        'created_at': {
            'gt': datetime(year=today.year, month=today.month, day=today.day),
            'lt': today + relativedelta(day=1),
        }
    }))
    # 6. " " " after this time tomorrow, and before this morning (impossible, so false)
    print(await client.demo.find_many(where={
        'created_at': {
            'gt': today + relativedelta(day=1),
            'lt': datetime(year=today.year, month=today.month, day=today.day)
        }
    }))
    # 7. after this morning, before tomorrow with and syntax (I think this is correct?, Expecting true)
    print(await client.demo.find_many(where={
        'AND': [
            {
                'created_at': {
                    'lt': today + relativedelta(day=1),
                }
            },
            {
                'created_at': {
                    'gt': datetime(year=today.year, month=today.month, day=today.day)
                }
            }
        ]
    }))
    
    # 8. same as sixth test case, should be impossible, just with and syntax
    print(await client.demo.find_many(where={
        'AND': [
            {
                'created_at': {
                    'gt': today + relativedelta(day=1),
                }
            },
            {
                'created_at': {
                    'lt': datetime(year=today.year, month=today.month, day=today.day)
                }
            }
        ]
    }))
    

    TEST RESULTS

    # Test 1
    []
    # Test 2
    []
    # Test 3
    [Demo(id=1, created_at=datetime.datetime(2022, 1, 8, 8, 1, 58, tzinfo=datetime.timezone.utc))]
    # Test 4
    [Demo(id=1, created_at=datetime.datetime(2022, 1, 8, 8, 1, 58, tzinfo=datetime.timezone.utc))]
    # Test 5
    []
    # Test 6
    []
    # Test 7
    []
    # Test 8
    []
    

    Prisma python, therefore, currently claiming record I created before running demo was created after I ran the demo. Also, seems that including lt(e) in the query may result in immediate loss? I haven't tried specifying a time in the future.

    Expected behavior

    Test Result Expectations

    # Test 1
    [Demo(id=1, created_at=datetime.datetime(2022, 1, 8, 8, 1, 58, tzinfo=datetime.timezone.utc))]
    # Test 2
    [Demo(id=1, created_at=datetime.datetime(2022, 1, 8, 8, 1, 58, tzinfo=datetime.timezone.utc))]
    # Test 3
    []
    # Test 4
    []
    # Test 5
    [Demo(id=1, created_at=datetime.datetime(2022, 1, 8, 8, 1, 58, tzinfo=datetime.timezone.utc))]
    # Test 6
    []
    # Test 7
    [Demo(id=1, created_at=datetime.datetime(2022, 1, 8, 8, 1, 58, tzinfo=datetime.timezone.utc))]
    # Test 8
    []
    

    Prisma information

    // database
    datasource db {
      provider = "sqlite"
      url      = "file:database.db"
    }
    
    // generator
    generator client {
      provider = "prisma-client-py"
    }
    
    model Demo {
      id         Int      @id
      created_at DateTime @default(now())
    }
    
    

    Environment & setup

    • OS: Tested on Windows 10, and macOS Big Sur
    • Database: Sqlite3
    • Python version: 3.10 Windows, 3.9 macOS
    • Prisma version: 3.7.0, 0.4.3
    bug/2-confirmed kind/bug topic: external priority/low level/unknown 
    opened by iiian 11
  • Running any command will lead to an error

    Running any command will lead to an error

    Bug description

    Running any command with prisma-client-py (will be abbreviated as prisma to make sense in this report) will not work, even using a virtual environment to install prisma & then running the command from there will not work either. It always leads to the output being an assertion error, where the 'bin' directory does not exist.

    How to reproduce

    Steps to reproduce the behavior:

    1. Make a python virtual environment
    2. Enter the virtual environment & install the latest version of prisma client.
    3. Run any prisma command while in the virtual environment
    4. See error

    Expected behavior

    Should be able to show the output of the command being used. For example, being able to migrate my schema to my database & being able to show the usable commands when running prisma.

    Prisma information

    No information required.

    Environment & setup

    • OS: Windows
    • Database: Postgres
    • Python version: 3.10
    • Prisma version: 0.80
    
    
    bug/0-needs-info kind/bug 
    opened by De-y 10
  • Singleton Class

    Singleton Class

    Hey, in the original Prisma Library, I used a singleton class to instantiate the client only once and then use it in my code. I did not need to connect and disconnect it everytime as well.

    I tried doing something similar here but I am having a rough time to import the singleton class from another module.

    Do you think it can be done?

    Thanks!

    kind/question 
    opened by danielweil 10
  • Deserialize raw query types into richer python types

    Deserialize raw query types into richer python types

    Problem

    We currently deserialize raw query fields into types that are different than what the core ORM uses, e.g. Decimal becomes float instead of decimal.Decimal, this was implemented this way for backwards compatibility reasons.

    Suggested solution

    We should use types that are nicer to work with:

    • [ ] datetime.datetime for DateTime fields
    • [ ] decimal.Decimal for Decimal fields
    • [ ] prisma.Base64 for Bytes fields
    kind/improvement topic: client level/intermediate priority/low topic: raw queries 
    opened by RobertCraigie 0
  • Add support for `@db.Date` fields

    Add support for `@db.Date` fields

    Problem

    We don't currently support DateTime fields that represent Dates at the database level because we generate a datetime.datetime type instead of datetime.date which results in failed Pydantic validation.

    date DateTime @default(dbgenerated("CURRENT_DATE")) @db.Date
    

    Suggested solution

    This is essentially blocked on https://github.com/prisma/prisma/issues/3998 unfortunately...

    topic: types kind/feature topic: client level/advanced priority/low 
    opened by RobertCraigie 0
  • Add missing tests for native database types

    Add missing tests for native database types

    We currently do not have tests for every possible native database type.

    Status (not yet exhaustive):

    • [ ] db.Date
    • [x] db.Date in raw queries
    • [ ] db.Time
    • [ ] db.Time in raw queries
    • [ ] db.Timetz
    • [ ] db.Timetz in raw queries
    • [ ] db.Timestamp
    • [ ] db.Timestamp in raw queries
    • [ ] db.Timestamptz
    • [ ] db.Timestamptz in raw queries
    kind/improvement topic: internal priority/medium level/unknown 
    opened by RobertCraigie 0
  • feat(client): add support for selecting fields

    feat(client): add support for selecting fields

    Change Summary

    This PR adds support for querying from partial models and only selects the fields that are present on the partial model.

    closes #90 closes #19 (as one implementation - we should provide alternative solutions as well)

    TODO:

    • [ ] Write tests for the generated SQL
    • [ ] Define base classes that don't have any fields defined for easier non-partials usage

    Checklist

    • [ ] Unit tests for the changes exist
    • [ ] Tests pass without significant drop in coverage
    • [ ] Documentation reflects changes where applicable
    • [ ] Test snapshots have been updated if applicable

    Agreement

    By submitting this pull request, I confirm that you can use, modify, copy and redistribute this contribution, under the terms of your choice.

    opened by RobertCraigie 0
  • Add comparison tables against other ORMs

    Add comparison tables against other ORMs

    Problem

    When evaluating what ORM to use for your project it is not clear what tradeoffs / advantages you would get from choosing Prisma over another ORM. We should make this easy to figure out.

    Suggested solution

    Add a comparison table to the README / docs stating what features are / are not supported.

    topic: docs kind/docs level/intermediate priority/high 
    opened by RobertCraigie 0
  • chore(deps): update dev (major)

    chore(deps): update dev (major)

    Mend Renovate

    This PR contains the following updates:

    | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | coverage | ==6.5.0 -> ==7.0.4 | age | adoption | passing | confidence | | mkdocs-material | ==8.5.11 -> ==9.0.3 | age | adoption | passing | confidence | | mock (source) | ==4.0.3 -> ==5.0.0 | age | adoption | passing | confidence |


    Release Notes

    nedbat/coveragepy

    v7.0.4

    Compare Source

    • Performance: an internal cache of file names was accidentally disabled, resulting in sometimes drastic reductions in performance. This is now fixed, closing issue 1527_. Thanks to Ivan Ciuvalschii for the reproducible test case.

    .. _issue 1527:https://github.com/nedbat/coveragepy/issues/15277

    .. _changes_7-0-3:

    v7.0.3

    Compare Source

    • Fix: when using pytest-cov or pytest-xdist, or perhaps both, the combining step could fail with assert row is not None using 7.0.2. This was due to a race condition that has always been possible and is still possible. In 7.0.1 and before, the error was silently swallowed by the combining code. Now it will produce a message "Couldn't combine data file" and ignore the data file as it used to do before 7.0.2. Closes issue 1522_.

    .. _issue 1522:https://github.com/nedbat/coveragepy/issues/15222

    .. _changes_7-0-2:

    v7.0.2

    Compare Source

    • Fix: when using the [run] relative_files = True setting, a relative [paths] pattern was still being made absolute. This is now fixed, closing issue 1519_.

    • Fix: if Python doesn't provide tomllib, then TOML configuration files can only be read if coverage.py is installed with the [toml] extra. Coverage.py will raise an error if TOML support is not installed when it sees your settings are in a .toml file. But it didn't understand that [tools.coverage] was a valid section header, so the error wasn't reported if you used that header, and settings were silently ignored. This is now fixed, closing issue 1516_.

    • Fix: adjusted how decorators are traced on PyPy 7.3.10, fixing issue 1515_.

    • Fix: the coverage lcov report did not properly implement the --fail-under=MIN option. This has been fixed.

    • Refactor: added many type annotations, including a number of refactorings. This should not affect outward behavior, but they were a bit invasive in some places, so keep your eyes peeled for oddities.

    • Refactor: removed the vestigial and long untested support for Jython and IronPython.

    .. _issue 1515:https://github.com/nedbat/coveragepy/issues/15155 .. _issue 1516https://github.com/nedbat/coveragepy/issues/151616 .. _issue 151https://github.com/nedbat/coveragepy/issues/1519519

    .. _changes_7-0-1:

    v7.0.1

    Compare Source

    • When checking if a file mapping resolved to a file that exists, we weren't considering files in .whl files. This is now fixed, closing issue 1511_.

    • File pattern rules were too strict, forbidding plus signs and curly braces in directory and file names. This is now fixed, closing issue 1513_.

    • Unusual Unicode or control characters in source files could prevent reporting. This is now fixed, closing issue 1512_.

    • The PyPy wheel now installs on PyPy 3.7, 3.8, and 3.9, closing issue 1510_.

    .. _issue 1510:https://github.com/nedbat/coveragepy/issues/15100 .. _issue 1511https://github.com/nedbat/coveragepy/issues/151111 .. _issue 151https://github.com/nedbat/coveragepy/issues/1512512 .. _issue 15https://github.com/nedbat/coveragepy/issues/15131513

    .. _changes_7-0-0:

    v7.0.0

    Compare Source

    Nothing new beyond 7.0.0b1.

    .. _changes_7-0-0b1:

    squidfunk/mkdocs-material

    v9.0.3: mkdocs-material-9.0.3

    Compare Source

    • Improved discernability of section index pages in navigation
    • Improved collapsing of adjacent whitespace in search plugin
    • Updated Indonesian translations
    • Fixed view source of this page button when edit URL points to blob
    • Fixed #​4829: Search overlay does not close for active anchor result
    • Fixed #​4824: Search plugin crashes for h[1-6] contained in other elements
    • Fixed #​4804: Nested navigation items not expandable with keyboard
    • Fixed #​4689: anchor tracking not working for anchors in tables
    • Upgraded to Mermaid 9.3.0

    v9.0.2: mkdocs-material-9.0.2

    Compare Source

    • Fixed #​4823: Improved contrast ratio in footer to meet WCAG guidelines
    • Fixed #​4819: Social plugin crashes when card generation is disabled
    • Fixed #​4817: Search plugin crashes on numeric page titles in nav

    v9.0.1: mkdocs-material-9.0.1

    Compare Source

    • Removed pipdeptree dependency for built-in info plugin
    • Fixed appearance of linked tags when hovered (9.0.0 regression)
    • Fixed #​4810: Abbreviations run out of screen on touch devices
    • Fixed #​4813: View source and edit button links are the same

    v9.0.0: mkdocs-material-9.0.0

    Compare Source

    Additions and improvements

    • Added support for rich search previews
    • Added support for tokenizer lookahead
    • Added support for better search highlighting
    • Added support for excluding content from search
    • Added support for configurable search pipeline
    • Added support for offline search via offline plugin
    • Added support for multiple instances of built-in tags plugin
    • Added support for removing copy-to-clipboard button
    • Added support for removing footer navigation
    • Added support for button to view the source of a page
    • Improved readability of query string for search sharing
    • Improved stability of search plugin when using --dirtyreload
    • Improved search result group button, now sticky and stable
    • Updated Norwegian translations
    • Updated MkDocs to 1.4.2

    Removals

    • Removed deprecated alternative admonition qualifiers
    • Removed :is() selectors (in output) for easier overriding
    • Removed .title suffix on translations
    • Removed legacy method for providing page title in feedback URL
    • Removed support for indexing only titles in search
    • Removed support for custom search transforms
    • Removed support for custom search workers
    • Removed temporary snow feature (easter egg)

    Fixes

    • Fixed Norwegian and Korean language code
    • Fixed detection of composition events in search interface
    • Fixed search plugin not using title set via front matter
    • Fixed search highlighting of tags
    • Fixed search sharing URL using post transformed string
    • Fixed theme-color meta tag getting out-of-sync with palette toggle
    • Fixed prev/next page keyboard navigation when footer is not present
    • Fixed overflowing navigation tabs not being scrollable
    • Fixed inclusion of code block line numbers from search
    testing-cabal/mock

    v5.0.0

    Compare Source

    • gh-98624: Add a mutex to unittest.mock.NonCallableMock to protect concurrent access to mock attributes.

    • bpo-43478: Mocks can no longer be used as the specs for other Mocks. As a result, an already-mocked object cannot have an attribute mocked using autospec=True or be the subject of a create_autospec(...) call. This can uncover bugs in tests since these Mock-derived Mocks will always pass certain tests (e.g. isinstance) and builtin assert functions (e.g. assert_called_once_with) will unconditionally pass.

    • bpo-45156: Fixes infinite loop on :func:unittest.mock.seal of mocks created by :func:~unittest.create_autospec.

    • bpo-41403: Make :meth:mock.patch raise a :exc:TypeError with a relevant error message on invalid arg. Previously it allowed a cryptic :exc:AttributeError to escape.

    • gh-91803: Fix an error when using a method of objects mocked with :func:unittest.mock.create_autospec after it was sealed with :func:unittest.mock.seal function.

    • bpo-41877: AttributeError for suspected misspellings of assertions on mocks are now pointing out that the cause are misspelled assertions and also what to do if the misspelling is actually an intended attribute name. The unittest.mock document is also updated to reflect the current set of recognised misspellings.

    • bpo-43478: Mocks can no longer be provided as the specs for other Mocks. As a result, an already-mocked object cannot be passed to mock.Mock(). This can uncover bugs in tests since these Mock-derived Mocks will always pass certain tests (e.g. isinstance) and builtin assert functions (e.g. assert_called_once_with) will unconditionally pass.

    • bpo-45010: Remove support of special method __div__ in :mod:unittest.mock. It is not used in Python 3.

    • gh-84753: :func:inspect.iscoroutinefunction now properly returns True when an instance of :class:unittest.mock.AsyncMock is passed to it. This makes it consistent with behavior of :func:asyncio.iscoroutinefunction. Patch by Mehdi ABAAKOUK.

    • bpo-46852: Remove the undocumented private float.__set_format__() method, previously known as float.__setformat__() in Python 3.7. Its docstring said: "You probably don't want to use this function. It exists mainly to be used in Python's test suite." Patch by Victor Stinner.

    • gh-98086: Make sure patch.dict() can be applied on async functions.

    • gh-100287: Fix the interaction of :func:unittest.mock.seal with :class:unittest.mock.AsyncMock.

    • gh-83076: Instantiation of Mock() and AsyncMock() is now 3.8x faster.

    • bpo-41877: A check is added against misspellings of autospect, auto_spec and set_spec being passed as arguments to patch, patch.object and create_autospec.


    Configuration

    πŸ“… Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    β™» Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    πŸ‘» Immortal: This PR will be recreated if closed unmerged. Get config help if that's undesired.


    • [ ] If you want to rebase/retry this PR, check this box

    This PR has been generated by Mend Renovate. View repository job log here.

    opened by renovate[bot] 0
Releases(v0.8.0)
  • v0.8.0(Jan 1, 2023)

    ⚠️ Prisma Schema Breaking Changes

    This release contains some changes to the format of the Prisma Schema.

    Most of these changes are due to a conceptual shift from allowing implicit behaviour to forcing verboseness to reduce the amount of under the hood magic that Prisma does, thankfully this means that a lot of the changes that you will be required to make should be pretty straightforward and easily fixable by running prisma format which will show you all the places that need changed in your schema.

    Changes:

    For more details see the Prisma v4.0.0 upgrade path.

    ⚠️ Internal Raw Query Changes

    This release includes an internal restructuring of how raw queries are deserialized. While all these changes should be completely backwards compatible, there may be edge cases that have changed. If you encounter one of these edge cases please open an issue and it will be fixed ASAP.

    For some additional context, this restructuring means that most fields will internally be returned as strings until Prisma Client Python deserializes them (previously this was done at the query engine level).

    CLI Improvements

    This release completely refactors how the Prisma CLI is downloaded and ran. The previous implementation relied on downloading a single pkg binary, this worked but had several limitations which means we now:

    • Support ARM architectures & certain Linux distributions
    • Support running Prisma Studio from the CLI
    • Support generating the JS Client
    • No longer have to maintain a separate implementation from Prisma for detecting the current platform & logic for downloading engines
      • As a user this means that more platforms & architectures will be supported faster!

    The new solution is involves directly downloading a Node.js binary (if you don't already have it installed) and directly installing the Prisma ClI through npm. Note that this does not pollute your userspace and does not make Node available to the rest of your system.

    This will result in a small size increase (~150MB) in the case where Node is not already installed on your machine, if this matters to you you can install Prisma Client Python with the node extra, e.g. pip install prisma[node], which will install a Node binary to your site-packages that results in the same storage requirements as the previous pkg solution. You can also directly install nodejs-bin yourself. It's also worth noting that this release includes significant (~50%) reduction in the size of the Prisma Engine binaries which makes the default Node binary size increase less impactful.

    Prisma Studio

    With this release you can now run Prisma Studio from the CLI which makes it incredibly easy to view & edit the data in your database. Simply run the following command

    $ prisma studio
    

    Or

    $ prisma studio --schema=backend/schema.prisma
    

    Screenshow showcasing Prisma Studio usage

    Note that there is also a dark mode available

    Support for CockroachDB

    This release adds official support for CockroachDB. You could've used CockroachDB previously by setting provider to postgresql but now you can explicitly specify CockroachDB in your Prisma Schema:

    datasource db {
      provider = "cockroachdb"
      url      = env("COCKROACHDB_URL")
    }
    

    It should be noted that there are a couple of edge cases:

    Prisma Updates

    TL;DR for improvements made by Prisma that will now be in Prisma Client Python

    Full list of changes:

    • https://github.com/prisma/prisma/releases/tag/3.14.0
    • https://github.com/prisma/prisma/releases/tag/3.15.0
    • https://github.com/prisma/prisma/releases/tag/3.15.1
    • https://github.com/prisma/prisma/releases/tag/3.15.2
    • https://github.com/prisma/prisma/releases/tag/4.0.0
    • https://github.com/prisma/prisma/releases/tag/4.1.0
    • https://github.com/prisma/prisma/releases/tag/4.1.1
    • https://github.com/prisma/prisma/releases/tag/4.2.0
    • https://github.com/prisma/prisma/releases/tag/4.2.1
    • https://github.com/prisma/prisma/releases/tag/4.3.0
    • https://github.com/prisma/prisma/releases/tag/4.3.1
    • https://github.com/prisma/prisma/releases/tag/4.4.0
    • https://github.com/prisma/prisma/releases/tag/4.5.0
    • https://github.com/prisma/prisma/releases/tag/4.6.0
    • https://github.com/prisma/prisma/releases/tag/4.7.0
    • https://github.com/prisma/prisma/releases/tag/4.7.1
    • https://github.com/prisma/prisma/releases/tag/4.8.0

    Miscellaneous Changes

    Public Roadmap

    Going forward we will now use a GitHub Project to track state and relative priority of certain issues. If you'd like to increase the priority of issues that would benefit you please add πŸ‘ reactions.

    This is less of a roadmap per se but will hopefully give you some insight into the priority of given issues / features.

    Attributions

    Thank you to @kfields for helping with raw query deserialization!

    Massive thank you to @prisma & @techied for their continued support and @exponential-sponsorship for becoming a sponsor!

    sponsors

    Source code(tar.gz)
    Source code(zip)
  • v0.7.1(Nov 12, 2022)

    What's Changed

    Bug Fixes

    Windows Support

    This release adds official support for the Windows platform!

    The main fix that comes with this release is a workaround for the missing error messages issue that has plagued so many.

    Internal Improvements

    A lot of the effort that went into this release was improving our internal testing strategies. This involved a major overhaul of our testing suite so that we can easily test multiple different database providers. This means we will be less likely to ship bugs and will be able to develop database specific features much faster!

    In addition to the refactored test suite we also have new docker-based tests for ensuring compatibility with multiple platforms and environments that were previously untested. @jacobdr deserves a massive thank you for this!

    Sponsors

    sponsors

    Source code(tar.gz)
    Source code(zip)
  • v0.7.0(Oct 1, 2022)

    Breaking Changes

    Path resolution for relative SQLite databases fixed

    Previously there was a mismatch between the resolution algorithm for relative SQLite paths which could cause the Client and the CLI to point to different databases.

    The mismatch is caused by the CLI using the path to the Prisma Schema file as the base path whereas the Client used the current working directory as the base path.

    The Client will now use the path to the Prisma Schema file as the base path for all relative SQLite paths, absolute paths are unchanged.

    What's Changed

    Add support for configuration through the pyproject.toml file

    You can now configure Prisma Client Python using an entry in your pyproject.toml file instead of having to set environment variables, e.g.

    [tool.prisma]
    binary_cache_dir = '.binaries'
    

    It should be noted that you can still use environment variables if you so desire, e.g.

    PRISMA_BINARY_CACHE_DIR=".binaries"
    

    This will also be useful as a workaround for #413 until the default behaviour is changed in the next release.

    See the documentation for more information.

    Fix .env files overriding environment variables

    Previously any environment variables present in the .env or prisma/.env file would take precedence over the environment variables set at the system level. This behaviour was not correct as it does not match what the Prisma CLI does. This has now been changed such that any environment variables in the .env file will only be set if there is not an environment variable already present.

    Add support for Python 3.11

    Python 3.11 is now officially supported and tested!

    It should be noted that you may encounter some deprecation warnings from the transitive dependencies we use.

    Add support for generating JSON Schema for Bytes types

    You can now generate JSON Schemas / OpenAPI Schemas for models that use the Bytes type.

    from prisma import Base64
    from pydantic import BaseModel
    
    class MyModel(BaseModel):
        image: Base64
    
    print(MyModel.schema_json(indent=2))
    
    {
      "title": "MyModel",
      "type": "object",
      "properties": {
        "image": {
          "title": "Image",
          "type": "string",
          "format": "byte"
        }
      },
      "required": [
        "image"
      ]
    }
    

    Add support for using the Base64 type in custom pydantic models

    You can now use the Base64 type in your own Pydantic models and benefit from all the advanced type coercion that Pydantic provides! Previously you would have to manually construct the Base64 instances yourself, now Pydantic will do that for you!

    from prisma import Base64
    from pydantic import BaseModel
    
    class MyModel(BaseModel):
        image: Base64
    
    # pass in a raw base64 encoded string and it will be transformed to a Base64 instance!
    model = MyModel.parse_obj({'image': 'SGV5IHRoZXJlIGN1cmlvdXMgbWluZCA6KQ=='})
    print(repr(model.image))  # Base64(b'SGV5IHRoZXJlIGN1cmlvdXMgbWluZCA6KQ==')
    

    It should be noted that this assumes that the data you pass is a valid base64 string, it does not do any conversion or validation for you.

    Add support for unregistering a client instance

    You can now unregister a client instance, this can be very useful for writing tests that interface with Prisma Client Python. However, you shouldn't ever have to use this outside of a testing context as you should only be creating a single Prisma instance for each Python process unless you are supporting multi-tenancy. Thanks @leejayhsu for this!

    from prisma.testing import unregister_client
    
    unregister_client()
    

    Access the location of the Prisma Schema file

    You can now access the location of the Prisma Schema file used to generate Prisma Client Python.

    from prisma import SCHEMA_PATH
    
    print(SCHEMA_PATH)  # Path('/absolute/path/prisma/schema.prisma')
    

    Other Changes

    Contributors

    Many thanks to @leejayhsu, @lewoudar, @tyteen4a03 and @nesb1 for contributing to this release!

    Sponsors

    A massive thank you to @prisma and @techied for their continued support! It is incredibly appreciated πŸ’œ

    I'd also like to thank GitHub themselves for sponsoring me as part of Maintainer Month!

    sponsors

    Source code(tar.gz)
    Source code(zip)
  • v0.6.6(May 21, 2022)

  • v0.6.5(May 9, 2022)

    What's Changed

    Raw queries are now typed with LiteralString

    This change is only applied when generating recursive types as mypy does not support LiteralString yet.

    PEP 675 introduces a new string type, LiteralString, this type is a supertype of literal string types that allows functions to accept any arbitrary literal string type such as 'foo' or 'bar' for example.

    All raw query methods, namely execute_raw, query_raw and query_first now take the LiteralString type as the query argument instead of str. This change means that any static type checker thats supports PEP 675 will report an error if you try and pass a string that cannot be defined statically, for example:

    await User.prisma().query_raw(f'SELECT * FROM User WHERE id = {user_id}')
    

    This change has been made to help prevent SQL injection attacks.

    Thank you to @leejayhsu for contributing this feature!

    Basic support for filtering by None values

    You can now filter records to remove or include occurrences where a field is None or not. For example, the following query will return all User records with an email that is not None:

    await client.user.find_many(
        where={
            'NOT': [{'email': None}]
        },
    )
    

    It should be noted that nested None checks are not supported yet, for example this is not valid:

    await client.user.find_many(
        where={
            'NOT': [{'email': {'equals': None}}]
        },
    )
    

    It should also be noted that this does not change the return type and you will still have to perform not None checks to appease type checkers. e.g.

    users = await client.user.find_many(
        where={
            'NOT': [{'email': None}]
        },
    )
    for user in users:
    	assert user.email is not None
    	print(user.email.split('@'))
    

    New exception classes

    There are two new exception classes, ForeignKeyViolationError and FieldNotFoundError.

    The ForeignKeyViolationError is raised when a foreign key field has been provided but is not valid, for example, trying to create a post and connecting it to a non existent user:

    await client.post.create(
        data={
            'title': 'My first post!',
            'published': True,
            'author_id': '<unknown user ID>',
        }
    )
    

    The FieldNotFoundError is raised when a field has been provided but is not valid in that context, for example, creating a record and setting a field that does not exist on that record:

    await client.post.create(
        data={
            'title': 'foo',
            'published': True,
            'non_existent_field': 'foo',
        }
    )
    

    Added scalar relational fields in create input

    The type definitions for creating records now contain the scalar relational fields as well as an alternative to the longer form for connecting relational fields, for example:

    model User {
      id         String   @id @default(cuid())
      name       String
      email      String @unique
      posts      Post[]
    }
    
    model Post {
      id         String     @id @default(cuid())
      author     User?      @relation(fields: [author_id], references: [id])
      author_id  String?
    }
    

    With the above schema and an already existent User record. You can now create a new Post record and connect it to the user by directly setting the author_id field:

    await Post.prisma().create(
      data={
          'author_id': '<existing user ID>',
          'title': 'My first post!',
      },
    )
    

    This is provided as an alternative to this query:

    await Post.prisma().create(
        data={
            'title': 'My first post!',
            'author': {
                'connect': {
                    'id': '<existing user ID>'
                }
            }
        },
    )
    

    Although the above query should be preferred as it also exposes other methods, such as creating the relational record inline or connecting based on other unique fields.

    Prisma Upgrade

    The internal Prisma binaries that Prisma Python makes use of have been upgraded from v3.11.1 to v3.13.0. For a full changelog see the v3.12.0 release notes and v3.13.0 release notes.

    Minor Changes

    • Fixed typos / outdated commands in the documentation
    • Fixed long standing style issue with dark mode in the documentation

    New Contributors

    Many thanks to @q0w and @leejayhsu for their first contributions!

    Sponsors

    sponsors

    Source code(tar.gz)
    Source code(zip)
  • v0.6.4(Apr 4, 2022)

    What's Changed

    Experimental support for the Decimal type

    Experimental support for the Decimal type has been added. The reason that support for this type is experimental is due to a missing internal feature in Prisma that means we cannot provide the same guarantees when working with the Decimal API as we can with the API for other types. For example, we cannot:

    • Raise an error if you attempt to pass a Decimal value with a greater precision than the database supports, leading to implicit truncation which may cause confusing errors
    • Set the precision level on the returned decimal.Decimal objects to match the database level, potentially leading to even more confusing errors.

    If you need to use Decimal and are happy to work around these potential footguns then you must explicitly specify that you are aware of the limitations by setting a flag in the Prisma Schema:

    generator py {
      provider                    = "prisma-client-py"
      enable_experimental_decimal = true
    }
    
    model User {
        id      String @id @default(cuid())
        balance Decimal
    }
    

    The Decimal type maps to the standard library's Decimal class. All available query operations can be found below:

    from decimal import Decimal
    from prisma import Prisma
    
    prisma = Prisma()
    user = await prisma.user.find_first(
        where={
            'balance': Decimal(1),
            # or
            'balance': {
                'equals': Decimal('1.23823923283'),
                'in': [Decimal('1.3'), Decimal('5.6')],
                'not_in': [Decimal(10), Decimal(20)],
                'gte': Decimal(5),
                'gt': Decimal(11),
                'lt': Decimal(4),
                'lte': Decimal(3),
                'not': Decimal('123456.28'),
            },
        },
    )
    

    Updates on the status of support for Decimal will be posted in #106.

    Add triple-slash comments to generated models

    You can now add comments to your Prisma Schema and have them appear in the docstring for models and fields! For example:

    /// The User model
    model User {
      /// The user's email address
      email String
    }
    

    Will generate a model that looks like this:

    class User(BaseModel):
        """The User model"""
    
        email: str
        """The user's email address"""
    

    Improved import error message if the client has not been generated

    If you try to import Prisma or Client before you've run prisma generate then instead of getting an opaque error message:

    >>> from prisma import Prisma
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ImportError: cannot import name 'Prisma' from 'prisma' (/prisma/__init__.py)
    

    you will now get an error like this:

    >>> from prisma import Prisma
    Traceback (most recent call last):
    ...
    RuntimeError: The Client hasn't been generated yet, you must run `prisma generate` before you can use the client.
    See https://prisma-client-py.readthedocs.io/en/stable/reference/troubleshooting/#client-has-not-been-generated-yet
    

    The query batcher is now publicly exposed

    You can now import the query batcher directly from the root package, making it much easier to type hint and providing support for an alternative API style:

    from prisma import Prisma, Batch
    
    prisma = Prisma()
    async with Batch(prisma) as batcher:
        ...
    
    def takes_batcher(batcher: Batch) -> None:
        ...
    

    Prisma upgrade

    The internal Prisma binaries that Prisma Python makes use of have been upgraded from v3.10.0 to v3.11.1. For a full changelog see the v3.11.0 release notes and v3.11.1 release notes.

    Sponsors

    This project is now being sponsored by @prisma and @techied. I am so incredibly grateful to both for supporting Prisma Client Python πŸ’œ

    Source code(tar.gz)
    Source code(zip)
  • v0.6.3(Mar 10, 2022)

    What's Changed

    This release is a patch release to fix incompatibilities between the documented MongoDB Prisma Schema and our version. In v3.10.0 Prisma made some breaking changes to MongoDB schemas, for example:

    • Replacing @default(dbgenerated()) with @default(auto())
    • Replacing @db.Array(ObjectId) with @db.ObjectId

    This caused some confusion as following an official Prisma guide in their documentation resulted in an error (#326).

    Bug Fixes

    • Disable raw queries for MongoDB as they are not officially supported yet (#324)
    Source code(tar.gz)
    Source code(zip)
  • v0.6.2(Mar 5, 2022)

    Bug Fixes

    In v0.6.0 we renamed Prisma to Client, in doing so we accidentally removed the export for the previous Client name which was kept for backwards compatibility. This release re-exports it so the following code will no longer raise an error:

    from prisma import Client
    

    What's Changed

    Support for filtering by in and not_in for Bytes fields

    For example the following query will find the first record where binary_data is either my binary data or my other binary data.

    from prisma import Base64
    from prisma.models import Data
    
    await Data.prisma().find_first(
        where={
            'binary_data': {
                'in': [
                    Base64.encode(b'my binary data'),
                    Base64.encode(b'my other binary data'),
                ],
            },
        },
    )
    

    And if you want to find a record that doesn't match any of the arguments you can use not_in

    from prisma import Base64
    from prisma.models import Data
    
    await Data.prisma().find_first(
        where={
            'binary_data': {
                'not_in': [
                    Base64.encode(b'my binary data'),
                    Base64.encode(b'my other binary data'),
                ],
            },
        },
    )
    

    Added __slots__ definitions

    All applicable classes now define the __slots__ attribute for improved performance and memory usage, for more information on what this means, see the Python documentation.

    New Contributors

    Thank you to @matyasrichter πŸ’œ

    Source code(tar.gz)
    Source code(zip)
  • v0.6.1(Mar 1, 2022)

    What's Changed

    Support for removing all auto-generated files

    Although very rare, it is sometimes possible to get your Prisma Client Python installation into a corrupted state when upgrading to a newer version. In this situation you could try uninstalling and reinstalling Prisma Client Python however doing so will not always fix the client state, in this case you have to remove all of the files that are auto-generated by Prisma Client Python. To achieve this you would either have to manually remove them or download and run a script that we use internally.

    With this release you can now automatically remove all auto-generated files by running the following command:

    python -m prisma_cleanup
    

    This will find your installed prisma package and remove the auto-generated files.

    If you're using a custom output location then all you need to do is pass the import path, the same way you do to use the client in your code, for example:

    python -m prisma_cleanup app.prisma
    

    Project name change

    The name change that occurred in the last release has been reverted, see #300 for reasoning.

    Source code(tar.gz)
    Source code(zip)
  • v0.6.0(Feb 22, 2022)

    Bug Fixes

    • Fix transformation of fields nested within a list (#264)

    What's Changed

    Client renamed to Prisma

    In order to improve readability, the recommended method to import the client has changed from Client to Prisma. However, for backwards compatibility you can still import Client.

    from prisma import Prisma
    
    prisma = Prisma()
    

    Removed redundant subclass warning when using FastAPI

    By default a warning is raised when you attempt to subclass a model while using pseudo-recursive types, see the documentation for more information.

    This warning was raised when using a Prisma model in a FastAPI response model as FastAPI implicitly subclasses the given model. This means that the warning was actually redundant and as such has been removed, the following code snippet will no longer raise a warning:

    from fastapi import FastAPI
    from prisma.models import User
    
    app = FastAPI()
    
    @app.get('/foo', response_model=User)
    async def get_foo() -> User:
        ...
    
    

    Prisma upgrade

    The internal Prisma binaries that Prisma Python makes use of have been upgraded from v3.8.1 to v3.9.1. For a full changelog see the v3.9.0 release notes and v3.9.1 release notes.

    Removing the HTTP timeout

    You can now completely remove the internal HTTP timeout

    from prisma import Prisma
    
    prisma = Prisma(
        http={
            'timeout': None,
        },
    )
    

    Project Name Change

    This project has been renamed from Prisma Client Python to Prisma Python

    Attributions

    Thanks to @ghandic for the bug report and thanks to @kivo360 for contributing!

    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(Jan 30, 2022)

    Bug Fixes

    • Removed relational fields from update_many mutation data, updating relational fields from update_many is not supported yet (https://github.com/prisma/prisma/issues/3143).
    • Fixed relational ordering typing, this was typed to order by the parent model, not the relational model (#234)
    • Fixed ordering typing to signify that only one field can be ordered by at once (pass a list if you need to order by multiple fields)

    What's Changed

    Dropped support for Python 3.6

    Python 3.6 reached its end of life on the 23rd of December 2021. You now need Python 3.7 or higher to use Prisma Client Python.

    Grouping records

    You can now group records by one or more field values and perform aggregations on each group!

    It should be noted that the structure of the returned data is different to most other action methods, returning a TypedDict instead of a BaseModel.

    For example:

    results = await Profile.prisma().group_by(
        by=['country'],
        sum={
            'views': True,
        },
    )
    # [
    #   {"country": "Canada", "_sum": {"views": 23}},
    #   {"country": "Scotland", "_sum": {"views": 143}},
    # ]
    

    For more examples see the documentation: https://prisma-client-py.readthedocs.io/en/stable/reference/operations/#grouping-records

    While the syntax is slightly different the official Prisma documentation is also a good reference: https://www.prisma.io/docs/concepts/components/prisma-client/aggregation-grouping-summarizing#group-by

    Improve support for custom generator options

    You can now easily (and with full type-safety) define custom options for your own Prisma Generators!

    from pydantic import BaseModel
    from prisma.generator import GenericGenerator, GenericData, Manifest
    
    
    # custom options must be defined using a pydantic BaseModel
    class Config(BaseModel):
        my_option: int
    
    
    # we don't technically need to define our own Data class
    # but it makes typing easier
    class Data(GenericData[Config]):
        pass
    
    
    # the GenericGenerator[Data] part is what tells Prisma Client Python to use our
    # custom Data class with our custom Config class
    class MyGenerator(GenericGenerator[Data]):
        def get_manifest(self) -> Manifest:
            return Manifest(
                name='My Custom Generator Options',
                default_output='schema.md',
            )
    
        def generate(self, data: Data) -> None:
            # generate some assets here
            pass
    
    
    if __name__ == '__main__':
        MyGenerator.invoke()
    

    Removal of deprecated arguments

    There are two arguments that were deprecated in previous releases that have now been removed:

    • The redundant encoding argument to Base64.decode()
    • The redundant order argument to actions.count()

    Support for updating unique fields

    You can now update fields that are marked as @unique or @id:

    user = await User.prisma().update(
        where={
            'email': '[email protected]',
        },
        data={
            'email': '[email protected]',
        },
    )
    

    Custom CLI binary

    You can now easily replace the Prisma CLI binary that Prisma Client Python makes use of by overriding the PRISMA_CLI_BINARY environment variable. This shouldn't be necessary for the vast majority of users however as some platforms are not officially supported yet, binaries must be built manually in these cases.

    Prisma upgrade

    The internal Prisma binaries that Prisma Client Python makes use of have been upgraded from v3.7.0 to v3.8.1. For a full changelog see the v3.8.0 release notes.

    Miscellaneous changes

    • The Prisma Studio CLI entrypoint is not supported, the error message for this has been improved and points out the two solutions.
    Source code(tar.gz)
    Source code(zip)
  • v0.4.3(Jan 5, 2022)

    Bug fixes

    • Correctly render Enum fields within compound keys (#190)

    What's Changed

    Subclassing pseudo-recursive models

    Subclassing pseudo-recursive models will now raise a warning instead of crashing, static types will still not respect the subclass, for example:

    from prisma.models import User
    
    class MyUser(User):
        @property
        def fullname(self) -> str:
            return f'{self.name} {self.surname}'
    
    # static type checkers will think that `user` is an instance of `User` when it is actually `MyUser` at runtime
    # you can fix this by following the steps here:
    # https://prisma-client-py.readthedocs.io/en/stable/reference/limitations/#removing-limitations
    user = MyUser.prisma().create(
        data={
            'name': 'Robert',
            'surname': 'Craigie',
        },
    )
    

    For more details, see the documentation

    Default HTTP timeout increased

    The default HTTP timeout used to communicate with the internal Query Engine has been increased from 5 seconds to 30 seconds, this means you should no longer encounter timeout errors when executing very large queries.

    Customise the internal HTTPX Client

    You can now customise the HTTPX Client used to communicate with the internal query engine, this could be useful if you need to increase the http timeout, for full reference see the documentation.

    client = Client(
        http={
            'timeout': 100,
        },
    )
    

    Prisma Upgrade

    The internal Prisma binaries that Prisma Client Python makes use of have been upgraded from v3.4.0 to v3.7.0 for a full changelog see:

    Create partial models without any relational fields

    Instead of having to manually update the list of excluded fields when creating partial models whenever a new relation is added you can now just use exclude_relational_fields=True!

    from prisma.models import User
    User.create_partial('UserWithoutRelations', exclude_relational_fields=True)
    
    class UserWithoutRelations:
      id: str
      name: str
      email: Optional[str]
    
    Source code(tar.gz)
    Source code(zip)
  • v0.4.2(Dec 17, 2021)

  • v0.4.1(Dec 13, 2021)

    What's Changed

    Custom Prisma Python Generators

    You can now easily write your own Prisma generators in Python!

    For example:

    generator.py

    from pathlib import Path
    from prisma.generator import BaseGenerator, Manifest, models
    
    
    class MyGenerator(BaseGenerator):
        def get_manifest(self) -> Manifest:
            return Manifest(
                name='My Prisma Generator',
                default_output=Path(__file__).parent / 'generated.md',
            )
    
        def generate(self, data: Data) -> None:
            lines = [
                '# My Prisma Models!\n',
            ]
            for model in data.dmmf.datamodel.models:
                lines.append(f'- {model.name}')
    
            output = Path(data.generator.output.value)
            output.write_text('\n'.join(lines))
    
    if __name__ == '__main__':
        MyGenerator.invoke()
    

    Then you can add the generator to your Prisma Schema file like so:

    generator custom {
      provider = "python generator.py"
    }
    

    Your custom generator will then be invoked whenever you run prisma generate

    $ prisma generate
    Prisma schema loaded from tests/data/schema.prisma
    
    βœ” Generated My Prisma Generator to ./generated.md in 497ms
    

    For more details see the documentation: https://prisma-client-py.readthedocs.io/en/latest/reference/custom-generators/

    Connect with a Context Manager

    You can now use the Client as a context manager to automatically connect and disconnect from the database, for example:

    from prisma import Client
    
    async with Client() as client:
        await client.user.create(
            data={
                'name': 'Robert',
            },
        )
    

    For more information see the documentation: https://prisma-client-py.readthedocs.io/en/stable/reference/client/#context-manager

    Automatically register the Client instance

    You can now automatically register the Client when it is created:

    from prisma import Client
    
    client = Client(auto_register=True)
    

    Which is equivalent to:

    from prisma import Client, register
    
    client = Client()
    register(client)
    

    Support for setting a default connection timeout

    The default timeout used for connecting to the database can now be set at the client level, for example:

    from prisma import Client
    
    client = Client(connect_timeout=5)
    

    You can still explicitly specify the timeout when connecting, for example:

    from prisma import Client
    
    client = Client(connect_timeout=5)
    client.connect()  # timeout: 5
    client.connect(timeout=10)  # timeout: 10
    

    Bug Fixes

    • Fixed unintentional blocking IO when decoding HTTP responses when using async (#169)
    • DateTime microsecond precision is now truncated to 3 places (#129)
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Nov 27, 2021)

    Breaking Changes

    The following field names are now restricted and attempting to generate the client with any of them will now raise an error:

    • startswith
    • endswith
    • order_by
    • not_in
    • is_not

    What's Changed

    Support for the Bytes type

    You can now create models that make use of binary data, this is stored in the underlying database as Base64 data, for example:

    model User {
      id     Int @id @default(autoincrement())
      name   String
      binary Bytes
    }
    
    from prisma import Base64
    from prisma.models import User
    
    user = await User.prisma().create(
        data={
            'name': 'Robert',
            'binary': Base64.encode(b'my binary data'),
        },
    )
    print(f'binary data: {user.binary.decode()}')
    

    Support for scalar list fields

    You can now query for and update scalar list fields, for example:

    model User {
      id     Int @id @default(autoincrement())
      emails String[]
    }
    
    user = await client.user.find_first(
        where={
            'emails': {
                'has': '[email protected]',
            },
        },
    )
    

    For more details, visit the documentation: https://prisma-client-py.readthedocs.io/en/latest/reference/operations/#lists-fields

    Argument deprecations

    The order argument to the count() method has been deprecated, this will be removed in the next release.

    Action Docstrings

    All query action methods now have auto-generated docstrings specific for each model, this means that additional documentation will be shown when you hover over the method call in your IDE, for example:

    Image showcasing docstring on hover

    Other Changes

    • typing-extensions is now a required dependency
    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Nov 9, 2021)

    Breaking Changes

    The prisma field name is now reserved, trying to generate a model that has a field called prisma will raise an error.

    You can, however, still create a model that uses the prisma field name at the database level.

    model User {
      id           String @id @default(cuid())
      prisma_field String @map("prisma")
    }
    

    What's Changed

    Querying from Model Classes

    You can now run prisma queries directly from model classes, for example:

    from prisma.models import User
    
    user = await User.prisma().create(
        data={
            'name': 'Robert',
        },
    )
    

    This API is exactly the same as the previous client-based API.

    To get starting running queries from model classes, you must first register the prisma client instance that will be used to communicate with the database.

    from prisma import Client, register
    
    client = Client()
    register(client)
    await client.connect()
    

    For more details, visit the documentation.

    Count non-null fields

    You can now select which fields are returned by count().

    This returns a dictionary matching the fields that are passed in the select argument.

    from prisma.models import Post
    
    results = await Post.prisma().count(
        select={
            '_all': True,
            'description': True,
        },
    )
    # {'_all': 3, 'description': 2}
    

    Support for Python 3.10

    Python 3.10 is now officially supported.

    Prisma Update

    The internal Prisma binaries that Prisma Client Python uses have been upgraded from 3.3.0 to 3.4.0.

    • Support for PostgreSQL 14
    • prisma db push support for MongoDB

    Improved Client Generation Message

    The current version of the client will now be displayed post-generation:

    Prisma schema loaded from schema.prisma
    
    βœ” Generated Prisma Client Python (v0.3.0) to ./.venv/lib/python3.9/site-packages/prisma in 765ms
    

    Improved Generation Error Message

    An explicit and helpful message is now shown when attempting to generate the Python Client using an unexpected version of Prisma.

    Environment variables loaded from .env
    Prisma schema loaded from tests/data/schema.prisma
    Error: 
      Prisma Client Python expected Prisma version: 1c9fdaa9e2319b814822d6dbfd0a69e1fcc13a85 but got: da6fafb57b24e0b61ca20960c64e2d41f9e8cff1
      If this is intentional, set the PRISMA_PY_DEBUG_GENERATOR environment variable to 1 and try again.
      Are you sure you are generating the client using the python CLI?
      e.g. python3 -m prisma generate (type=value_error)
    

    Other Changes

    • added --type-depth option to prisma py generate
    Source code(tar.gz)
    Source code(zip)
  • v0.2.4(Oct 28, 2021)

  • v0.2.3(Oct 28, 2021)

    🚨 DO NOT INSTALL FROM THIS VERSION 🚨

    This release has been yanked from PyPi as it contained auto-generated files, please install using 0.2.4 or greater.

    Bug Fixes

    • Partial types with enum fields are now correctly generated (#84)

    Prisma Update

    The internal Prisma binaries that Prisma Client Python uses have been upgraded from 3.1.1 to 3.3.0.

    • MongoDB introspection support is in preview

    For a full list of changes see https://github.com/prisma/prisma/releases/tag/3.2.0 and https://github.com/prisma/prisma/releases/tag/3.3.0

    Source code(tar.gz)
    Source code(zip)
  • v0.2.2(Oct 17, 2021)

    Package Rename

    The python package has been renamed from prisma-client to prisma!

    You can now install the client like so:

    pip install prisma
    

    You can still install using the old package name, however no new releases will be published.

    Datasource Overriding

    The datasource can be dynamically overriden when the client is instantiated:

    from prisma import Client
    
    client = Client(
        datasource={
            'url': 'file:./dev_qa.db',
        },
    )
    

    This is especially useful for testing purposes.

    Source code(tar.gz)
    Source code(zip)
  • v0.2.1(Oct 15, 2021)

    New features

    Support for case insensitive string filtering

    This feature is only supported when using PostgreSQL and MongoDB.

    user = await client.user.find_first(
        where={
            'name': {
                'contains': 'robert',
                'mode': 'insensitive',
            },
        },
    )
    

    Prisma Update

    The internal Prisma binaries that Prisma Client Python uses have been upgraded from 2.30.0 to 3.1.1.

    This brings with it a lot of new features and improvements:

    • Referential Actions
    • Named Constraints
    • Microsoft SQL Server and Azure SQL Connector

    For a full list of changes see https://github.com/prisma/prisma/releases/tag/3.1.1 and https://github.com/prisma/prisma/releases/tag/3.0.1

    Type Validator

    Prisma Client Python now comes bundled with a type validator, this makes it much easier to pass untrusted / untyped arguments to queries in a robust and type safe manner:

    import prisma
    from prisma.types import UserCreateInput
    
    def get_untrusted_input():
        return {'points': input('Enter how many points you have: ')}
    
    data = prisma.validate(UserCreateInput, get_untrusted_input())
    await client.user.create(data=data)
    

    Any invalid input would then raise an easy to understand error (note: edited for brevity):

    Enter how many points you have: a lot
    Traceback:
    pydantic.error_wrappers.ValidationError: 1 validation error for UserCreateInput
    points
      value is not a valid integer (type=type_error.integer)
    

    Minor Changes

    • Improved supported for the windows platform (not officially supported yet)
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Sep 28, 2021)

    🚨 This release contains breaking changes 🚨

    Filtering field types by NOT and IN has been renamed to not and in.

    For example:

    post = await client.post.find_first(
        where={
            'title': {
                'NOT': 'Exclude title',
            },
        },
    )
    

    Must now be written as:

    post = await client.post.find_first(
        where={
            'title': {
                'not': 'Exclude title',
            },
        },
    )
    

    Bug fixes

    • Fixes filtering records by NOT (#70)
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Sep 21, 2021)

    This release does not contain any new features and is simply to mark the start of new version guarantees.

    Breaking changes will now be released under a new MINOR version instead of the previous PATCH.

    MAJOR.MINOR.PATCH

    Source code(tar.gz)
    Source code(zip)
  • v0.0.4(Sep 8, 2021)

    🚨 This release contains breaking changes 🚨

    Removal of aiohttp and requests

    Support for aiohttp and requests has been removed in favour of httpx, as httpx supports both asynchronous and synchronous clients within the same library there is no reason to use aiohttp or requests anymore.

    This means that the way you install Prisma Client Python will change. You now no longer need to specify an extra, for example

    pip install prisma-client[aiohttp]
    

    turns into

    pip install prisma-client
    

    Config changes

    The http option has been replaced with the interface option. The new interface option is used to control whether or not the generated client is asynchronous.

    Migrating

    If you used aiohttp before you should use the following:

    generator client {
      provider  = "prisma-client-py"
      interface = "asyncio"
    }
    

    If you used requests before you should use the following:

    generator client {
      provider  = "prisma-client-py"
      interface = "sync"
    }
    

    Changes

    Support for Json types

    You can now make use of Prisma's Json type.

    model User {
      id   Int @default(autoincrement())
      meta Json
    }
    

    You can create and search for Json values like so:

    from prisma import Json
    
    user = await client.user.create(
        data={
             'meta': Json.keys(country='Scotland'),
        }
    )
    
    from prisma import Json
    
    user = await client.user.find_first(
        where={
            'meta': Json({'country': 'Scotland'})
            # or
            'meta': {
                'equals': Json.keys(country='Scotland'),
                'NOT': Json(['foo']),
            }
        }
    )
    

    Other changes

    • Adds support for BigInt types.
    • Improves error message for unsupported types.
    • Improves type safety for atomic updates.
    Source code(tar.gz)
    Source code(zip)
  • v0.0.3(Aug 26, 2021)

  • v0.0.2(Aug 26, 2021)

    This release fixes an issue with unresolvable dev dependencies.

    I added twine as a dev dependency to publish prisma-client-py to PyPi which ended up causing version conflicts. Twine has been removed as a dependency.

    Source code(tar.gz)
    Source code(zip)
  • v0.0.1(Aug 26, 2021)

A database migrations tool for TortoiseORM, ready to production.

Aerich Introduction Aerich is a database migrations tool for Tortoise-ORM, which is like alembic for SQLAlchemy, or like Django ORM with it's own migr

Tortoise 596 Jan 06, 2023
A Python Library for Simple Models and Containers Persisted in Redis

Redisco Python Containers and Simple Models for Redis Description Redisco allows you to store objects in Redis. It is inspired by the Ruby library Ohm

sebastien requiem 436 Nov 10, 2022
A single model for shaping, creating, accessing, storing data within a Database

'db' within pydantic - A single model for shaping, creating, accessing, storing data within a Database Key Features Integrated Redis Caching Support A

Joshua Jamison 178 Dec 16, 2022
A curated list of awesome tools for SQLAlchemy

Awesome SQLAlchemy A curated list of awesome extra libraries and resources for SQLAlchemy. Inspired by awesome-python. (See also other awesome lists!)

Hong Minhee (ζ΄ͺ 民憙) 2.5k Dec 31, 2022
Object mapper for Amazon's DynamoDB

Flywheel Build: Documentation: http://flywheel.readthedocs.org/ Downloads: http://pypi.python.org/pypi/flywheel Source: https://github.com/stevearc/fl

Steven Arcangeli 128 Dec 31, 2022
A very simple CRUD class for SQLModel! ✨

Base SQLModel A very simple CRUD class for SQLModel! ✨ Inspired on: Full Stack FastAPI and PostgreSQL - Base Project Generator FastAPI Microservices I

Marcelo Trylesinski 40 Dec 14, 2022
Redis OM Python makes it easy to model Redis data in your Python applications.

Object mapping, and more, for Redis and Python Redis OM Python makes it easy to model Redis data in your Python applications. Redis OM Python | Redis

Redis 568 Jan 02, 2023
Prisma Client Python is an auto-generated and fully type-safe database client

Prisma Client Python is an unofficial implementation of Prisma which is a next-generation ORM that comes bundled with tools, such as Prisma Migrate, which make working with databases as easy as possi

Robert Craigie 930 Jan 08, 2023
Sqlalchemy seeder that supports nested relationships.

sqlalchemyseed Sqlalchemy seeder that supports nested relationships. Supported file types json yaml csv Installation Default installation pip install

Jedy Matt Tabasco 10 Aug 13, 2022
SQLModel is a library for interacting with SQL databases from Python code, with Python objects.

SQLModel is a library for interacting with SQL databases from Python code, with Python objects. It is designed to be intuitive, easy to use, highly compatible, and robust.

SebastiΓ‘n RamΓ­rez 9.1k Dec 31, 2022
Bringing Async Capabilities to django ORM

Bringing Async Capabilities to django ORM

Skander BM 119 Dec 01, 2022
Tortoise ORM is an easy-to-use asyncio ORM inspired by Django.

Tortoise ORM was build with relations in mind and admiration for the excellent and popular Django ORM. It's engraved in it's design that you are working not with just tables, you work with relational

Tortoise 3.3k Jan 07, 2023
A simple project to explore the number of GCs when doing basic ORM work.

Question: Does Python do extremely too many GCs for ORMs? YES, OMG YES. Check this out Python Default GC Settings: SQLAlchemy - 20,000 records in one

Michael Kennedy 26 Jun 05, 2022
A Python Object-Document-Mapper for working with MongoDB

MongoEngine Info: MongoEngine is an ORM-like layer on top of PyMongo. Repository: https://github.com/MongoEngine/mongoengine Author: Harry Marr (http:

MongoEngine 3.9k Dec 30, 2022
The ormar package is an async mini ORM for Python, with support for Postgres, MySQL, and SQLite.

python async mini orm with fastapi in mind and pydantic validation

1.2k Jan 05, 2023
Sqlalchemy-databricks - SQLAlchemy dialect for Databricks

sqlalchemy-databricks A SQLAlchemy Dialect for Databricks using the officially s

Flynn 19 Nov 03, 2022
A pure Python Database Abstraction Layer

pyDAL pyDAL is a pure Python Database Abstraction Layer. It dynamically generates the SQL/noSQL in realtime using the specified dialect for the databa

440 Nov 13, 2022
A pythonic interface to Amazon's DynamoDB

PynamoDB A Pythonic interface for Amazon's DynamoDB. DynamoDB is a great NoSQL service provided by Amazon, but the API is verbose. PynamoDB presents y

2.1k Dec 30, 2022
A new ORM for Python specially for PostgreSQL

A new ORM for Python specially for PostgreSQL. Fully-typed for any query with Pydantic and auto-model generation, compatible with any sync or async driver

Yan Kurbatov 3 Apr 13, 2022
A PostgreSQL or SQLite orm for Python

Prom An opinionated lightweight orm for PostgreSQL or SQLite. Prom has been used in both single threaded and multi-threaded environments, including en

Jay Marcyes 18 Dec 01, 2022