diff options
author | Jacob Mason <jacoblmason@gmail.com> | 2010-08-05 19:29:24 -0500 |
---|---|---|
committer | Jacob Mason <jacoblmason@gmail.com> | 2010-08-05 19:29:24 -0500 |
commit | d29f65112e327054dde4501a61d3c7d4fa16bcbf (patch) | |
tree | 48b635b1cfc2e57daece7d49e7839e3fcf7429e2 /sphinx/websupport/storage/sqlalchemystorage.py | |
parent | fbd047b8f593a439d0a8ca9eec02ad2491d2bd78 (diff) | |
download | sphinx-git-d29f65112e327054dde4501a61d3c7d4fa16bcbf.tar.gz |
added storage package
Diffstat (limited to 'sphinx/websupport/storage/sqlalchemystorage.py')
-rw-r--r-- | sphinx/websupport/storage/sqlalchemystorage.py | 178 |
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() |