summaryrefslogtreecommitdiff
path: root/sphinx/websupport/storage/sqlalchemystorage.py
diff options
context:
space:
mode:
authorJacob Mason <jacoblmason@gmail.com>2010-08-05 19:29:24 -0500
committerJacob Mason <jacoblmason@gmail.com>2010-08-05 19:29:24 -0500
commitd29f65112e327054dde4501a61d3c7d4fa16bcbf (patch)
tree48b635b1cfc2e57daece7d49e7839e3fcf7429e2 /sphinx/websupport/storage/sqlalchemystorage.py
parentfbd047b8f593a439d0a8ca9eec02ad2491d2bd78 (diff)
downloadsphinx-git-d29f65112e327054dde4501a61d3c7d4fa16bcbf.tar.gz
added storage package
Diffstat (limited to 'sphinx/websupport/storage/sqlalchemystorage.py')
-rw-r--r--sphinx/websupport/storage/sqlalchemystorage.py178
1 files changed, 178 insertions, 0 deletions
diff --git a/sphinx/websupport/storage/sqlalchemystorage.py b/sphinx/websupport/storage/sqlalchemystorage.py
new file mode 100644
index 000000000..e96f38cf0
--- /dev/null
+++ b/sphinx/websupport/storage/sqlalchemystorage.py
@@ -0,0 +1,178 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.websupport.storage.sqlalchemystorage
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ An SQLAlchemy storage backend.
+
+ :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+from datetime import datetime
+
+from sqlalchemy.orm import aliased
+from sphinx.websupport.errors import *
+from sphinx.websupport.storage import StorageBackend
+from sphinx.websupport.storage.db import Base, Node, Comment, CommentVote,\
+ Session
+from sphinx.websupport.storage.differ import CombinedHtmlDiff
+
+class SQLAlchemyStorage(StorageBackend):
+ def __init__(self, engine):
+ self.engine = engine
+ Base.metadata.bind = engine
+ Base.metadata.create_all()
+ Session.configure(bind=engine)
+
+ def pre_build(self):
+ self.build_session = Session()
+
+ def add_node(self, document, line, source, treeloc):
+ node = Node(document, line, source, treeloc)
+ self.build_session.add(node)
+ self.build_session.flush()
+ return node.id
+
+ def post_build(self):
+ self.build_session.commit()
+ self.build_session.close()
+
+ def add_comment(self, text, displayed, username, rating, time,
+ proposal, node_id, parent_id, moderator):
+ session = Session()
+
+ if node_id and proposal:
+ node = session.query(Node).filter(Node.id == node_id).one()
+ differ = CombinedHtmlDiff()
+ proposal_diff = differ.make_html(node.source, proposal)
+ elif parent_id:
+ parent = session.query(Comment.displayed).\
+ filter(Comment.id == parent_id).one()
+ if not parent.displayed:
+ raise CommentNotAllowedError(
+ "Can't add child to a parent that is not displayed")
+ proposal_diff = None
+ else:
+ proposal_diff = None
+
+ comment = Comment(text, displayed, username, rating,
+ time or datetime.now(), proposal, proposal_diff)
+ session.add(comment)
+ session.flush()
+ comment.set_path(node_id, parent_id)
+ session.commit()
+ comment = comment.serializable()
+ session.close()
+ return comment
+
+ def delete_comment(self, comment_id, username, moderator):
+ session = Session()
+ comment = session.query(Comment).\
+ filter(Comment.id == comment_id).one()
+ if moderator or comment.username == username:
+ comment.username = '[deleted]'
+ comment.text = '[deleted]'
+ session.commit()
+ session.close()
+ else:
+ session.close()
+ raise UserNotAuthorizedError()
+
+ def get_data(self, node_id, username, moderator):
+ session = Session()
+ node = session.query(Node).filter(Node.id == node_id).one()
+ session.close()
+ comments = self._serializable_list(node_id, username, moderator)
+ return {'source': node.source,
+ 'comments': comments}
+
+ def _serializable_list(self, node_id, username, moderator):
+ session = Session()
+
+ if username:
+ # If a username is provided, create a subquery to retrieve all
+ # votes by this user. We will outerjoin with the comment query
+ # with this subquery so we have a user's voting information.
+ sq = session.query(CommentVote).\
+ filter(CommentVote.username == username).subquery()
+ cvalias = aliased(CommentVote, sq)
+ q = session.query(Comment, cvalias.value).outerjoin(cvalias)
+ else:
+ q = session.query(Comment)
+
+ # Filter out all comments not descending from this node.
+ q = q.filter(Comment.path.like(str(node_id) + '.%'))
+ # Filter out non-displayed comments if this isn't a moderator.
+ if not moderator:
+ q = q.filter(Comment.displayed == True)
+ # Retrieve all results. Results must be ordered by Comment.path
+ # so that we can easily transform them from a flat list to a tree.
+ results = q.order_by(Comment.path).all()
+ session.close()
+
+ # We now need to convert the flat list of results to a nested
+ # lists to form the comment tree. Results will by ordered by
+ # the materialized path.
+ comments = []
+ list_stack = [comments]
+ for r in results:
+ comment, vote = r if username else (r, 0)
+
+ inheritance_chain = comment.path.split('.')[1:]
+
+ if len(inheritance_chain) == len(list_stack) + 1:
+ parent = list_stack[-1][-1]
+ list_stack.append(parent['children'])
+ elif len(inheritance_chain) < len(list_stack):
+ while len(inheritance_chain) < len(list_stack):
+ list_stack.pop()
+
+ list_stack[-1].append(comment.serializable(vote=vote))
+
+ return comments
+
+ def process_vote(self, comment_id, username, value):
+ session = Session()
+ vote = session.query(CommentVote).filter(
+ CommentVote.comment_id == comment_id).filter(
+ CommentVote.username == username).first()
+
+ comment = session.query(Comment).filter(
+ Comment.id == comment_id).first()
+
+ if vote is None:
+ vote = CommentVote(comment_id, username, value)
+ comment.rating += value
+ else:
+ comment.rating += value - vote.value
+ vote.value = value
+ session.add(vote)
+ session.commit()
+ session.close()
+
+ def update_username(self, old_username, new_username):
+ session = Session()
+ session.query(Comment).filter(Comment.username == old_username).\
+ update({Comment.username: new_username})
+ session.query(CommentVote).\
+ filter(CommentVote.username == old_username).\
+ update({CommentVote.username: new_username})
+ session.commit()
+ session.close()
+
+ def accept_comment(self, comment_id):
+ session = Session()
+ comment = session.query(Comment).\
+ filter(Comment.id == comment_id).one()
+ comment.displayed = True
+ session.commit()
+ session.close()
+
+ def reject_comment(self, comment_id):
+ session = Session()
+ comment = session.query(Comment).\
+ filter(Comment.id == comment_id).one()
+ session.delete(comment)
+ session.commit()
+ session.close()