mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
added more comments/docstrings
This commit is contained in:
parent
3f29ff6204
commit
3b3e001eb9
@ -34,6 +34,12 @@ class Node(Base):
|
||||
source = Column(Text, nullable=False)
|
||||
|
||||
def nested_comments(self, username, moderator):
|
||||
"""Create a tree of comments. First get all comments that are
|
||||
descendents of this node, then convert them to a tree form.
|
||||
|
||||
:param username: the name of the user to get comments for.
|
||||
:param moderator: whether the user is moderator.
|
||||
"""
|
||||
session = Session()
|
||||
|
||||
if username:
|
||||
@ -45,24 +51,30 @@ class Node(Base):
|
||||
cvalias = aliased(CommentVote, sq)
|
||||
q = session.query(Comment, cvalias.value).outerjoin(cvalias)
|
||||
else:
|
||||
# If a username is not provided, we don't need to join with
|
||||
# CommentVote.
|
||||
q = session.query(Comment)
|
||||
|
||||
# Filter out all comments not descending from this node.
|
||||
q = q.filter(Comment.path.like(str(self.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.
|
||||
return self._nest_comments(results, username)
|
||||
|
||||
def _nest_comments(self, results, username):
|
||||
"""Given the flat list of results, convert the list into a
|
||||
tree.
|
||||
|
||||
:param results: the flat list of comments
|
||||
:param username: the name of the user requesting the comments.
|
||||
"""
|
||||
comments = []
|
||||
list_stack = [comments]
|
||||
for r in results:
|
||||
@ -87,6 +99,7 @@ class Node(Base):
|
||||
self.source = source
|
||||
|
||||
class Comment(Base):
|
||||
"""An individual Comment being stored."""
|
||||
__tablename__ = db_prefix + 'comments'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
@ -110,6 +123,9 @@ class Comment(Base):
|
||||
self.proposal_diff = proposal_diff
|
||||
|
||||
def set_path(self, node_id, parent_id):
|
||||
"""Set the materialized path for this comment."""
|
||||
# This exists because the path can't be set until the session has
|
||||
# been flushed and this Comment has an id.
|
||||
if node_id:
|
||||
self.path = '%s.%s' % (node_id, self.id)
|
||||
else:
|
||||
@ -120,6 +136,9 @@ class Comment(Base):
|
||||
self.path = '%s.%s' % (parent_path, self.id)
|
||||
|
||||
def serializable(self, vote=0):
|
||||
"""Creates a serializable representation of the comment. This is
|
||||
converted to JSON, and used on the client side.
|
||||
"""
|
||||
delta = datetime.now() - self.time
|
||||
|
||||
time = {'year': self.time.year,
|
||||
@ -149,6 +168,9 @@ class Comment(Base):
|
||||
'children': []}
|
||||
|
||||
def pretty_delta(self, delta):
|
||||
"""Create a pretty representation of the Comment's age.
|
||||
(e.g. 2 minutes).
|
||||
"""
|
||||
days = delta.days
|
||||
seconds = delta.seconds
|
||||
hours = seconds / 3600
|
||||
@ -162,6 +184,7 @@ class Comment(Base):
|
||||
return '%s %s ago' % dt if dt[0] == 1 else '%s %ss ago' % dt
|
||||
|
||||
class CommentVote(Base):
|
||||
"""A vote a user has made on a Comment."""
|
||||
__tablename__ = db_prefix + 'commentvote'
|
||||
|
||||
username = Column(String(64), primary_key=True)
|
||||
|
@ -14,39 +14,18 @@ from cgi import escape
|
||||
from difflib import Differ
|
||||
|
||||
class CombinedHtmlDiff(object):
|
||||
|
||||
"""Create an HTML representation of the differences between two pieces
|
||||
of text.
|
||||
"""
|
||||
highlight_regex = re.compile(r'([\+\-\^]+)')
|
||||
|
||||
def _highlight_text(self, text, next, tag):
|
||||
next = next[2:]
|
||||
new_text = []
|
||||
start = 0
|
||||
for match in self.highlight_regex.finditer(next):
|
||||
new_text.append(text[start:match.start()])
|
||||
new_text.append('<%s>' % tag)
|
||||
new_text.append(text[match.start():match.end()])
|
||||
new_text.append('</%s>' % tag)
|
||||
start = match.end()
|
||||
new_text.append(text[start:])
|
||||
return ''.join(new_text)
|
||||
|
||||
def _handle_line(self, line, next=None):
|
||||
prefix = line[0]
|
||||
text = line[2:]
|
||||
|
||||
if prefix == ' ':
|
||||
return text
|
||||
elif prefix == '?':
|
||||
return ''
|
||||
|
||||
if next is not None and next[0] == '?':
|
||||
tag = 'ins' if prefix == '+' else 'del'
|
||||
text = self._highlight_text(text, next, tag)
|
||||
css_class = 'prop_added' if prefix == '+' else 'prop_removed'
|
||||
|
||||
return '<span class="%s">%s</span>\n' % (css_class, text.rstrip())
|
||||
|
||||
def make_html(self, source, proposal):
|
||||
"""Return the HTML representation of the differences between
|
||||
`source` and `proposal`.
|
||||
|
||||
:param source: the original text
|
||||
:param proposal: the proposed text
|
||||
"""
|
||||
proposal = escape(proposal)
|
||||
|
||||
differ = Differ()
|
||||
@ -64,3 +43,37 @@ class CombinedHtmlDiff(object):
|
||||
self._handle_line(line)
|
||||
break
|
||||
return ''.join(html)
|
||||
|
||||
def _handle_line(self, line, next=None):
|
||||
"""Handle an individual line in a diff."""
|
||||
prefix = line[0]
|
||||
text = line[2:]
|
||||
|
||||
if prefix == ' ':
|
||||
return text
|
||||
elif prefix == '?':
|
||||
return ''
|
||||
|
||||
if next is not None and next[0] == '?':
|
||||
tag = 'ins' if prefix == '+' else 'del'
|
||||
text = self._highlight_text(text, next, tag)
|
||||
css_class = 'prop_added' if prefix == '+' else 'prop_removed'
|
||||
|
||||
return '<span class="%s">%s</span>\n' % (css_class, text.rstrip())
|
||||
|
||||
def _highlight_text(self, text, next, tag):
|
||||
"""Highlight the specific changes made to a line by adding
|
||||
<ins> and <del> tags.
|
||||
"""
|
||||
next = next[2:]
|
||||
new_text = []
|
||||
start = 0
|
||||
for match in self.highlight_regex.finditer(next):
|
||||
new_text.append(text[start:match.start()])
|
||||
new_text.append('<%s>' % tag)
|
||||
new_text.append(text[match.start():match.end()])
|
||||
new_text.append('</%s>' % tag)
|
||||
start = match.end()
|
||||
new_text.append(text[start:])
|
||||
return ''.join(new_text)
|
||||
|
||||
|
@ -18,6 +18,9 @@ from sphinx.websupport.storage.db import Base, Node, Comment, CommentVote,\
|
||||
from sphinx.websupport.storage.differ import CombinedHtmlDiff
|
||||
|
||||
class SQLAlchemyStorage(StorageBackend):
|
||||
"""A :class:`~sphinx.websupport.storage.StorageBackend` using
|
||||
SQLAlchemy.
|
||||
"""
|
||||
def __init__(self, engine):
|
||||
self.engine = engine
|
||||
Base.metadata.bind = engine
|
||||
@ -40,7 +43,8 @@ class SQLAlchemyStorage(StorageBackend):
|
||||
def add_comment(self, text, displayed, username, time,
|
||||
proposal, node_id, parent_id, moderator):
|
||||
session = Session()
|
||||
|
||||
proposal_diff = None
|
||||
|
||||
if node_id and proposal:
|
||||
node = session.query(Node).filter(Node.id == node_id).one()
|
||||
differ = CombinedHtmlDiff()
|
||||
@ -51,19 +55,18 @@ class SQLAlchemyStorage(StorageBackend):
|
||||
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, 0,
|
||||
time or datetime.now(), proposal, proposal_diff)
|
||||
session.add(comment)
|
||||
session.flush()
|
||||
# We have to flush the session before setting the path so the
|
||||
# Comment has an id.
|
||||
comment.set_path(node_id, parent_id)
|
||||
session.commit()
|
||||
comment = comment.serializable()
|
||||
d = comment.serializable()
|
||||
session.close()
|
||||
return comment
|
||||
return d
|
||||
|
||||
def delete_comment(self, comment_id, username, moderator):
|
||||
session = Session()
|
||||
@ -72,6 +75,7 @@ class SQLAlchemyStorage(StorageBackend):
|
||||
if moderator or comment.username == username:
|
||||
comment.username = '[deleted]'
|
||||
comment.text = '[deleted]'
|
||||
comment.proposal = ''
|
||||
session.commit()
|
||||
session.close()
|
||||
else:
|
||||
|
Loading…
Reference in New Issue
Block a user