Minimalist Couchbase object wrapper for python.
- uses couchbase official driver
- tested
- fast
- could be modified to work with other data persistence layers as needed with minimal effort
You will need to install libcouchbase and python couchbase external to this library. They are not set as dependencies but will be considered to be satisfied externally if you intend to use the CouchbaseConnection.
Connect to a persistence layer, then work through your models.
This favors convenience.
from cushion.persist import set_connection
from cushion.persist.cb import CouchbaseConnection
from cushion.model import Model, DocTypeMismatch, DocTypeNotFound
from cushion.field import Field
# do this one time, before any db related work
set_connection(CouchbaseConnection('lvlrtest', 'localhost', 'gogogogo'))
class SomeModel(Model):
myfield = Field(default="shoes")
This model has one generic field with a default value that can be overwritten as needed.
Models can be instantiated blankly:
some_one = SomeModel()
Or, models can be instantiated with values as needed:
some_one = SomeModel(myfield="other value")
Once you have a model, you can assign directly to the members.
some_one.myfield = "cool stuff"
Persisting is easy.
some_one.save()
Saves return the instance they have saved, so it's simple to chain instantiation and creation.
some_one = SomeModel(myfield="other value").save()
Deleting is easy also.
some_one.delete()
After a document is saved, it has an id
field defined.
some_one = SomeModel().save()
my_doc_id = some_one.id
If you have the id
you can retrieve that document directly.
original_one = SomeModel.load(my_doc_id)
There are many field types that provide some validation and ease. Some
examples are TextField
, FloatField
, etc.
from cushion.field import DateTimeField, IntegerField, TextField
class Pants(Model):
size = IntegerField(default=32)
color = TextField(default="blue")
inspected_date = DateTimeField(default=datetime.now)
Notice the default
parameter above for the inspected_date
is not a scalar
but a callable. The function will be executed when the value is accessed the
first time.
_asdf
It's often useful to limit the input on a field to a certain subset.
class Shoe(Model):
color = OptionField(choices=['red', 'blue', 'black'], null_ok=False)
lacetype = OptionField(choices=['leather', 'rope'])
Notice the null_ok
above. By default this is True and allows the choice
field to have nothing assigned to it.
You can also reference another Model
using a RefField
.
from cushion.field import RefField
class Outfit(Model):
last_worn = DateTimeField()
pants = RefField(Pants)
blue_pants = Pants().save()
monday_attire = Outfit(last_worn=datetime.now(), pants=blue_pants).save()
You can then access the referenced model simply:
print "My pants were {}".format( monday_attire.pants.color )
Collection fields are limited to basic python types only right now.
from cushion.field import ListField, DictField
class AnotherThing(Model):
my_stuff = ListField()
my_dict = DictField()
tt = AnotherThing()
tt.my_stuff.append('this one time')
tt.my_dict['mykey'] = 'bigfoot'
todo add more documentation on field types
By defining a view, and then adding a helper method to your Model
, you can
simplify accessing the docs by params.
from cushion.view import View, sync_all
class Shoe(Model):
size = IntegerField()
by_size = View(
'shoes', 'by_size',
'''
function(doc, meta) {
if (doc.type=='shoe') {
emit(doc.size, null)
}
}
''' )
@classmethod
def all_for_size(cls, sz):
res = cls.by_size(startkey=sz, endkey=sz, include_docs=True)
return res
# be sure to sync your views before using them
sync_all(Shoe.viewlist())
# now have a list of Shoe objects that are size 11
size_11_shoes = Shoe.all_for_size(11)
There is a mock connection type, called a MemConnection
, that allows you to
test your models w/o needing a live couchbase instance.
To use it instead of the couchbase connection, just set your active connection to a MemConnection instance.
from cushion.persist.mem import MemConnection
set_connection(MemConnection())
To run tests, do the following:
- chdir to the cushion base directory:
cd cushion
- initiate a virtualenv:
mkdir .venv && virtualenv .venv
- activate the virtualenv:
source .venv/bin/activate
- install runtime requirements:
pip install -r requirements.txt
- install dev requirements:
pip install -r requirements_test.txt
- finally, run the tests:
nosetests
cushion$ nosetests
............
----------------------------------------------------------------------
Ran 12 tests in 0.770s
OK
- Unit tests - all functional for now, sorry.
Cushion is heavily inspired by mogo.
We also learned a few lessons from couchbase-mapping.