Skip to content

Commit

Permalink
passing db tests with jsongit
Browse files Browse the repository at this point in the history
  • Loading branch information
talos committed Mar 11, 2012
1 parent d12fb7a commit e503ce9
Show file tree
Hide file tree
Showing 3 changed files with 317 additions and 83 deletions.
164 changes: 164 additions & 0 deletions caustic/database.py
@@ -0,0 +1,164 @@
# -*- coding: utf-8 -*-

"""
caustic.database
"""

import pymongo
from pymongo.errors import DuplicateKeyError
from jsongit import signature
from caustic.models import User, InstructionDocument
from dictshield.base import ShieldException

def get_db(server, port, name):
db = pymongo.Connection(server, port)[name]
db.safe = True
return db


class Users(object):
"""Collection of users. Ensures uniqueness of non-deleted
names.
"""

def __init__(self, db):
self.coll = db.users
self.coll.ensure_index('name', unique=True)
self.deleted = db.deleted_users

def create(self, name):
"""Create a new user.
Returns the User, or None if the user has a duplicate name.
"""
try:
id = self.coll.insert(User(name=name).to_python())
return self.get(id)
except DuplicateKeyError:
return None

def get(self, id):
"""Get a user by id.
Returns the User or None.
"""
u = self.coll.find_one(id)
return User(**u) if u else None

def find(self, name):
"""Get a user by name.
Returns the User or None.
"""
u = self.coll.find_one({'name': name})
return User(**u) if u else None

def delete(self, user):
"""Delete a user.
"""
self.coll.remove(user.id)
self.deleted.save(user.to_python())


class Instructions(object):
"""Collection of instructions. Ensures uniquenss of
creator_id and name. Keeps git repo fresh.
"""

def __init__(self, users, repo, db):
self.repo = repo
self.users = users
self.coll = db.instructions
self.coll.ensure_index([('creator_id', pymongo.ASCENDING),
('name', pymongo.ASCENDING)],
unique=True)

def _repo_key(self, creator, instruction):
"""The key for the repo.
"""
return '/'.join([str(creator.id), str(instruction.id)])

def for_creator(self, creator_name):
"""Find all instructions by a creator.
Returns an array of InstructionDocuments, or None if
the creator_name does not exist.
"""
u = self.users.find(creator_name)
if u:
cursor = self.coll.find({'creator_id': u.id})
return [InstructionDocument(**i) for i in cursor]
else:
return None

def find(self, creator_name, name):
"""Find an instruction by creator name and its own name.
Returns the InstructionDocument or None.
"""
u = self.users.find(creator_name)
if u:
i = self.coll.find_one({'creator_id': u.id, 'name': name})
return InstructionDocument(**i) if i else None
else:
return None

def tagged(self, creator_name, tag):
"""Find instructions by creator name and tag.
Returns a list of InstructionDocuments, or None if
the creator doesn't exist.
"""
u = self.users.find(creator_name)
if u:
cursor = self.coll.find({'creator_id': u.id, 'tags': tag})
return [InstructionDocument(**i) for i in cursor]
else:
return None

def create(self, creator, name, instruction):
"""Create an instruction for a creator.
Returns the Instruction if it's created, or None if it
is a duplicate or invalid.
"""
try:
doc = InstructionDocument(
creator_id=creator.id,
name=name,
instruction=instruction)
doc.validate()
except ShieldException:
return None

try:
id = self.coll.insert(doc.to_python())
doc = InstructionDocument(**self.coll.find_one(id)) # grab ID
self.repo.create(self._repo_key(creator, doc), doc.instruction,
author=signature(creator.name, creator.name))
return doc
except DuplicateKeyError:
return None

def save(self, doc):
"""Save an instruction.
Returns None if the save was successful, a message explaining why it
failed otherwise.
"""
try:
doc.validate()
self.coll.save(doc.to_python())
except ShieldException as e:
return str(e)

creator = self.users.get(doc.creator_id)
self.repo.commit(self._repo_key(creator, doc), doc.instruction,
author=signature(creator.name, creator.name))

def delete(self, doc):
"""Delete an instruction.
Returns True if the deletion was successful.
"""
return self.coll.remove(doc.id)['n'] == 1
1 change: 1 addition & 0 deletions caustic/models.py
Expand Up @@ -42,6 +42,7 @@ class InstructionDocument(Document):
An Instruction Document has not just the instruction, but also a name, tags,
and a creator ID.
"""
id = ObjectIdField(id_field=True)
creator_id = ObjectIdField(required=True)
name = StringField(required=True)
tags = ListField(StringField())
Expand Down

0 comments on commit e503ce9

Please sign in to comment.