Declarative Interface

The acid.meta module provides an ORM-like metaclass that simplifies definition of database models using Python code.

Warning

This is a work in progress! The examples here do not yet work perfectly, and the most interesting aspect is missing. A future version will use the model definitions to automatically maintain a compact encoding. For now this module is mainly a curiosity.

import acid
import acid.meta


class Base(acid.meta.Model):
    """Base for models belonging to this program. Can be used to add common
    fields, and to bind all subclasses to a particular acid.Store with a
    single call."""


class User(Base):
    email = acid.meta.String()
    first = acid.meta.String()
    last = acid.meta.String()
    age = acid.meta.Integer()

    @acid.meta.constraint
    def sane_age(self):
        """Ensure the user's age is 1..149 if they provided it."""
        return self.age is None or (0 < self.age < 150)


class Item(Base):
    user_id = acid.meta.Integer()
    data = acid.meta.String()

    @acid.meta.constraint
    def sane_user_id(self):
        """Ensure a User model exists for user_id."""
        return User.get(self.user_id) is not None


def main():
    Base.bind_store(acid.open('ListEngine'))

    user = User(email='john@example.com', first='John')
    user.save()

    user = User.get(1)
    print 'Saved user:', user

if __name__ == '__main__':
    main()

Model class

class acid.meta.Model(**kwargs)

Inherit from this class to add fields to the basic model.

classmethod bind_store(store)

Bind this class and all subclasses to a acid.Store, clearing any cached references to the previous store, if any.

store = acid.open('ListEngine')
MyModel.bind_store(store)
classmethod collection()

Return the acid.Collection used to store instances of this model. The collection handles objects understood by the underlying encoder, not Model instances.

bind_store() must be called before accessing this property.

delete()

Delete the model if it has been saved.

classmethod find(key=None, lo=None, hi=None, prefix=None, reverse=None, include=False, raw=False)

Fetch the first matching instance; see acid.Collection.find().

classmethod get(key)

Fetch an instance given its key; see acid.Collection.get().

classmethod iter(key=None, lo=None, hi=None, prefix=None, reverse=None, max=None, include=False, raw=False)

Yield matching models in key order; see acid.Store.values().

save()

Create or update the model in the database.

is_saved

True if the model has been saved already.

class acid.meta.BaseModel(**kwargs)

Basic model class implementation. This exists separately from Model to allow clean subclassing of the ModelMeta metaclass.

Field Types

class acid.meta.Bool

A boolean field.

class acid.meta.Double

A double field.

class acid.meta.Integer

An integer field.

class acid.meta.String

A string field.

Specifying an index

acid.meta.index()

Mark a function as an index for the model. The function will be called during update to produce secondary indices for each item.

See acid.Index for more information on the function’s return value.

Once the model class has been constructed, accessing Model.func_name will return a acid.Index instance representing the index. The original function can still be accessed via acid.Index.func.

class Person(meta.Model):
    age = meta.Integer()

    @meta.index
    def by_age(self):
        return self.age


# Count all people 22 or older.
print('Total people older than 22:', Person.by_age.count(lo=22))

# Fetch youngest and oldest people.
youngest = Person.by_age.find()
oldest = Person.by_age.find(reverse=True)

Specifying a key function

acid.meta.key()

Mark a function as the model’s primary key function. If the function returns a stable result given the same input model, then derived_key() should be used instead.

@meta.key
def key_func(self):
    return int(time.time() * 1000)
acid.meta.derived_key()

Mark a function as the model’s primary key function. If the function does not return a stable result given the same input model, then use key() instead.

@meta.derived_key
def key_func(self):
    return self.name, self.email