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.

Features

  • Entity-based; perform CRUD operations using Python objects instead of hand-crafting SQL.
  • Validation; Entities validate before they get persisted to a database, also validate entities on-demand.
  • Transaction Contexts; enter and exit transaction scopes with language-level context management, avoid mismanaged transaction states.
  • DB Migrations; use Python code to apply (and undo) schema changes, data translation, etc using db-migrate CLI tool for use from CI/CD pipelines.
  • PEP 249 compatible abstractions; no need to refactor code just to switch DBMS.
  • Syntax normalization; parameterize SQL using %? instead of provider-specific syntaxes.
  • Raw SQL Access; execute raw SQL as-needed, including provider/DBMS-specific functions (primarily intended for advanced db-migrate cases.)
  • MongoDB support, with limited SQL translation support for PEP 249 interfaces.

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,   
            params=(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.
    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).

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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

deev-1.2.38.tar.gz (49.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

deev-1.2.38-py3-none-any.whl (63.3 kB view details)

Uploaded Python 3

File details

Details for the file deev-1.2.38.tar.gz.

File metadata

  • Download URL: deev-1.2.38.tar.gz
  • Upload date:
  • Size: 49.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.15+

File hashes

Hashes for deev-1.2.38.tar.gz
Algorithm Hash digest
SHA256 160fc788ffdafa3623e6be50f2bfc4d1a1e93e52ef928bb8249e178b61fa2003
MD5 6a6e4357257b7e47f773fa02b09089f1
BLAKE2b-256 7a9939b0369fd3d20bd96a32e925d80750e475038595aff85b3e591f0ff8ab36

See more details on using hashes here.

File details

Details for the file deev-1.2.38-py3-none-any.whl.

File metadata

  • Download URL: deev-1.2.38-py3-none-any.whl
  • Upload date:
  • Size: 63.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.15+

File hashes

Hashes for deev-1.2.38-py3-none-any.whl
Algorithm Hash digest
SHA256 962f01dd4fdb2056fc30fe42dc070789e232163b796d5fa7aecd1d873b346de4
MD5 062c049809fe2c459effb7f7c26b9440
BLAKE2b-256 7134892625fe6f56b8291b02a4b885e32901719032512db1a0010d6448073f18

See more details on using hashes here.

Release history Release notifications | RSS feed

1.6.11

2 files

1.6.9

2 files

1.6.8

2 files

1.6.7

2 files

1.5.4

2 files

1.5.3

2 files

1.5.1

2 files

1.5.0

2 files

1.4.5

2 files

1.4.4

2 files

1.4.2

2 files

1.4.1

2 files

1.4.0

2 files

1.3.4

2 files

1.3.3

2 files

This release

1.2.38 This release

2 files

1.2.37

2 files

1.2.35

2 files

1.2.34

2 files

1.2.33

2 files

1.2.32

2 files

1.2.30

2 files

1.2.29

2 files

1.2.26

2 files

1.2.25

2 files

1.2.23

2 files

1.2.16

2 files

1.2.10

2 files

1.2.9

2 files

1.2.8

2 files

1.2.6

2 files

1.2.4

2 files

1.2.3

2 files

1.2.2

2 files

1.2.1

2 files

1.2.0

2 files

1.1.6

2 files

1.1.5

2 files

1.1.4

2 files

1.1.2

2 files

1.1.0

2 files

1.0.1

2 files

1.0.0

2 files

0.1.14

2 files

0.1.13

2 files

0.1.10

2 files

0.1.9

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.1

2 files

0.1.0

2 files

0.0.5

2 files

0.0.2

2 files

0.0.1

2 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