Skip to main content

deev on PyPI deev on readthedocs

deev (דיב) is an entity framework for Python.

This README is only a high-level introduction to deev. For more detailed documentation, please view the official docs at https://deev.readthedocs.io.

  • Entity-based CRUD — work with Python objects, not hand-crafted SQL.
  • Validation — entities are validated before persistence and on-demand.
  • Transaction Contexts — scope transactions with context managers, never leave a mismanaged state.
  • Migrations — version-controlled schema and data migrations via the db-migrate CLI or programmatically via the DbMigrate class.
  • Multi-provider — built-in providers for SQLite, MySQL, ClickHouse, and MongoDB.
  • PEP 249 compatibility — switch DBMS without refactoring data access code.
  • Parameterized queries — unified %? syntax across all providers.
  • Connection strings — DSN URIs (sqlite3:///, mysql://) and OLEDB-style strings.
  • Declarative indexes — define composite, unique, and directional indexes on entity fields.
  • Native Interface Access — drop down to provider-specific methods when the ORM layer isn't enough.

Installation

You can install deev from PyPI through usual means, such as pip:

    pip install deev

Usage

Let's have a look at the two popular use cases: using Python objects for CRUD operations, and using the db-migrate CLI tool to manage DB schema.

Entity CRUD

First, let's define a "SimpleEntity" class we will use as a database entity:

    from datetime import datetime, timezone
    from deev import entity, field
    from typing import Optional    

    # ./SimpleEntity.py
    @entity
    class SimpleEntity:
        column1: int
        column2: Optional[list[str]] = field(default=None)
        column3: Optional[datetime] = field(default=lambda: datetime.now(timezone.utc))
        id: int = field(autoincrement=True, default=None, primary_key=True)

Next, let's write some CRUD-based code:

    # imports
    from deev import entity, field

    # define a simple entity with an auto-increment PK, an int value column, and a list[str] column
    @entity
    class SimpleEntity:
        id: int = field(autoincrement=True, primary_key=True)
        column1: int
        column2: list[str]

    # create a database using familiar connection-string syntax
    from deev.utils import create_database

    connection_str = 'Server=./test_data/;Database=sqlite3/test.db;Provider=sqlite3'
    create_database(connection_str)

    # connect to your database, create a table for storage, and perform some CRUD operations
    from deev import connect
    from deev.sqlite import SQLiteTableAdapter
    with connect(connection_str) as db:
        table = SQLiteTableAdapter[SimpleEntity](db)
        table.create_table()
        # CREATE
        entity_key = table.create(SimpleEntity(
            column1=1,
            column2=[3, 2, 1]
        ))
        # READ
        entity = table.read(**entity_key)
        assert entity.id is not None
        assert entity.column1 == 1
        assert entity.column2[0] == 3
        assert entity.column2[1] == 2
        assert entity.column2[2] == 1
        # UPDATE
        entity.column2[1] = 4
        table.update(entity)
        # DELETE
        table.delete(**entity_key)

        # alternatives: upsert + query
        entity_key = table.upsert(SimpleEntity(
            column1=2,
            column2=[5]
        ))
        entity_key = table.upsert(SimpleEntity(
            column1=2,
            column2=[6]
        ))
        results = table.query(
            where='column1 = %?',
            orderby='column1 DESC',
            limit=2,   
            parameters=(2,)
        )
        count = 0
        for result in results:
            assert result.column2[0] in (5, 6)
            count += 1
        assert count == 2
        # query kwargs are optional, for example this creates a generator for all table records:
        results = table.query()

CLI db-migrate Tool

NOTE: For comprehensive migration documentation (provider-specific behavior, best practices, DDL auto-commit considerations), see the full Migration Guide.

The db-migrate tool can be used to apply a migration script or undo a previously applied migration script.

Basic syntax:

$ db-migrate -h
usage: db-migrate [-h] [--verbose] <COMMAND> ...

Utility for applying, undoing, or generating migrations.

positional arguments:
  <COMMAND>   Action to perform.
    apply     Apply migrations.
    generate  Generate DDL.
    undo      Undo migrations.

options:
  -h, --help  show this help message and exit
  --verbose   Enable verbose logging.

$ db-migrate apply -h
usage: db-migrate apply [-h] [--stop-at name] connectionstring [path]

positional arguments:
  connectionstring  Database connection string.
  path              Directory containing migration scripts (optional). If omitted, a path is calculated from the connectionstring argument, ie.
                    `./migrations/database_name/`.

options:
  -h, --help        show this help message and exit
  --stop-at name    Stop processing at the named migration (use "all" to process all).

NOTE: The generate subcommand is alpha-quality and subject to change without notice. Do not rely on its interface for production tooling.

A migration script is a Python file which defines two functions apply(...) and undo(...), each receiving a DbTransactionContext you can use to modify the database transactionally.

As an example, we will create two migration scripts "000_initial_schema.py" and "001_initial_seed.py", we name them so their sort order ensures the schema script runs before the seed script. (A practice used on internal projects is to use a datecode, issue number, or similar linearly progressing value.)

    # ./migrations/test_db/000_initial_schema.py
    from deev.common import DbTransactionContext
    from deev.utils import create_table_adapter
    from .SimpleEntity import SimpleEntity

    def apply(transaction: DbTransactionContext) -> None:
        table_adapter = create_table_adapter(SimpleEntity, transaction)
        table_adapter.create_table()
        transaction.commit()

    def undo(transaction: DbTransactionContext) -> None:
        transaction.execute_nonquery('DROP TABLE `SimpleEntities`;')
        transaction.commit()
    # ./migrations/test_db/001_initial_seed.py
    from deev.common import DbTransactionContext
    from deev.utils import create_table_adapter
    from .SimpleEntity import SimpleEntity

    def apply(transaction: DbTransactionContext) -> None:
        table_adapter = create_table_adapter(SimpleEntity, transaction)
        table_adapter.create(SimpleEntity(
            column1 = 345
        ))
        table_adapter.create(SimpleEntity(
            column1 = 456
        ))
        transaction.commit()

    def undo(transaction: DbTransactionContext) -> None:
        transaction.execute_nonquery('DELETE FROM `SimpleEntities` WHERE `column1` IN (345, 456)')
        transaction.commit()

Finally, we can apply the change to our existing database:

    # apply schema change
    db-migrate apply 'Server=./test_data/;Database=sqlite3/test.db;Provider=sqlite3' ./migrations/test_db/
    ..apply migration "000_initial_schema"
    ..apply migration "001_initial_seed"
    Migrations applied 2, skipped 0, available 2.

We can also undo the change after it has been applied:

    # undo schema change
    db-migrate undo 'Server=./test_data/;Database=sqlite3/test.db;Provider=sqlite3' ./migrations/test_db/
    ..undo migration "001_initial_seed"
    ..undo migration "000_initial_schema"
    Migrations undone 2, skipped 0, available 2.

Contact

You can reach me on Discord or open an Issue on Github.

Metadata

Release files for deev 2.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for deev 2.0.1
File Size Uploaded
deev-2.0.1.tar.gz 104.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for deev 2.0.1
File Interpreter ABI Platform
deev-2.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 250.7 kB

Release files / deev-2.0.1.tar.gz

Download URL deev-2.0.1.tar.gz
Size 104.8 kB
Tags Source
SHA-256 checksum
How to use checksums
9928ebfcbc06e08b2f625696a89a2a75b59b3c216cd67fc6ea8a5a1c5259cd50
BLAKE2b-256 checksum
How to use checksums
b10cde45bf53daf1e140694c4f8762c26f3a095f22a11a9c33ee4032a3c06b2c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Release files / deev-2.0.1-py3-none-any.whl

Download URL deev-2.0.1-py3-none-any.whl
Size 145.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
99a325c4c926adc26ee82c68651bea5f3f5c60d63a020e43944bceedf318b023
BLAKE2b-256 checksum
How to use checksums
31e24d7c6d884965f556666dea53ac6b00ed6b30c32dd4107807754db1e85e04
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Release history Release notifications | RSS feed

2.1.11

2 release files

2.1.10

2 release files

2.1.8

2 release files

2.1.7

2 release files

2.1.6

2 release files

2.1.5

2 release files

2.1.4

2 release files

2.1.3

2 release files

2.1.2

2 release files

2.1.1

2 release files

2.0.2

2 release files

This release

2.0.1 This release

2 release files

2.0.0

2 release files

1.6.23

2 release files

1.6.9

2 release files

1.6.8

2 release files

1.6.7

2 release files

1.5.4

2 release files

1.5.3

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.5

2 release files

1.4.4

2 release files

1.4.2

2 release files

1.4.1

2 release files

1.4.0

2 release files

1.3.4

2 release files

1.3.3

2 release files

1.2.35

2 release files

1.2.34

2 release files

1.2.33

2 release files

1.2.32

2 release files

1.2.30

2 release files

1.2.29

2 release files

1.2.26

2 release files

1.2.25

2 release files

1.2.23

2 release files

1.2.16

2 release files

1.2.10

2 release files

1.2.9

2 release files

1.2.8

2 release files

1.2.6

2 release files

1.2.4

2 release files

1.2.3

2 release files

1.2.2

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.6

2 release files

1.1.5

2 release files

1.1.4

2 release files

1.1.2

2 release files

1.1.0

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.1.13

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.5

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page