mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
separate sqlalchemystorage from __init__
This commit is contained in:
parent
1f2a52f45c
commit
dc2f45208f
47
doc/web/searchadapters.rst
Normal file
47
doc/web/searchadapters.rst
Normal file
@ -0,0 +1,47 @@
|
||||
.. _searchadapters:
|
||||
|
||||
.. currentmodule:: sphinx.websupport.search
|
||||
|
||||
Search Adapters
|
||||
===============
|
||||
|
||||
To create a custom search adapter you will need to subclass the
|
||||
:class:`~BaseSearch` class. Then create an instance of the new class
|
||||
and pass that as the `search` keyword argument when you create the
|
||||
:class:`~sphinx.websupport.WebSupport` object::
|
||||
|
||||
support = Websupport(srcdir=srcdir,
|
||||
outdir=outdir,
|
||||
search=MySearch())
|
||||
|
||||
For more information about creating a custom search adapter, please see
|
||||
the documentation of the :class:`BaseSearch` class below.
|
||||
|
||||
.. class:: BaseSearch
|
||||
|
||||
Defines an interface for search adapters.
|
||||
|
||||
BaseSearch Methods
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following methods are defined in the BaseSearch class. Some methods
|
||||
do not need to be overridden, but some (
|
||||
:meth:`~sphinx.websupport.search.BaseSearch.add_document` and
|
||||
:meth:`~sphinx.websupport.search.BaseSearch.handle_query`) must be
|
||||
overridden in your subclass. For a working example, look at the
|
||||
built-in adapter for whoosh.
|
||||
|
||||
.. automethod:: sphinx.websupport.search.BaseSearch.init_indexing
|
||||
|
||||
.. automethod:: sphinx.websupport.search.BaseSearch.finish_indexing
|
||||
|
||||
.. automethod:: sphinx.websupport.search.BaseSearch.feed
|
||||
|
||||
.. automethod:: sphinx.websupport.search.BaseSearch.add_document
|
||||
|
||||
.. automethod:: sphinx.websupport.search.BaseSearch.query
|
||||
|
||||
.. automethod:: sphinx.websupport.search.BaseSearch.handle_query
|
||||
|
||||
.. automethod:: sphinx.websupport.search.BaseSearch.extract_context
|
||||
|
47
doc/web/storagebackends.rst
Normal file
47
doc/web/storagebackends.rst
Normal file
@ -0,0 +1,47 @@
|
||||
.. _searchadapters:
|
||||
|
||||
.. currentmodule:: sphinx.websupport.search
|
||||
|
||||
Search Adapters
|
||||
===============
|
||||
|
||||
To create a custom search adapter you will need to subclass the
|
||||
:class:`~BaseSearch` class. Then create an instance of the new class
|
||||
and pass that as the `search` keyword argument when you create the
|
||||
:class:`~sphinx.websupport.WebSupport` object::
|
||||
|
||||
support = Websupport(srcdir=srcdir,
|
||||
outdir=outdir,
|
||||
search=MySearch())
|
||||
|
||||
For more information about creating a custom search adapter, please see
|
||||
the documentation of the :class:`BaseSearch` class below.
|
||||
|
||||
.. class:: BaseSearch
|
||||
|
||||
Defines an interface for search adapters.
|
||||
|
||||
BaseSearch Methods
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following methods are defined in the BaseSearch class. Some methods
|
||||
do not need to be overridden, but some (
|
||||
:meth:`~sphinx.websupport.search.BaseSearch.add_document` and
|
||||
:meth:`~sphinx.websupport.search.BaseSearch.handle_query`) must be
|
||||
overridden in your subclass. For a working example, look at the
|
||||
built-in adapter for whoosh.
|
||||
|
||||
.. automethod:: sphinx.websupport.search.BaseSearch.init_indexing
|
||||
|
||||
.. automethod:: sphinx.websupport.search.BaseSearch.finish_indexing
|
||||
|
||||
.. automethod:: sphinx.websupport.search.BaseSearch.feed
|
||||
|
||||
.. automethod:: sphinx.websupport.search.BaseSearch.add_document
|
||||
|
||||
.. automethod:: sphinx.websupport.search.BaseSearch.query
|
||||
|
||||
.. automethod:: sphinx.websupport.search.BaseSearch.handle_query
|
||||
|
||||
.. automethod:: sphinx.websupport.search.BaseSearch.extract_context
|
||||
|
@ -12,4 +12,5 @@ into your web application. To learn more read the
|
||||
web/quickstart
|
||||
web/api
|
||||
web/frontend
|
||||
web/searchadapters
|
||||
web/searchadapters
|
||||
web/storagebackends
|
@ -18,7 +18,7 @@ from jinja2 import Environment, FileSystemLoader
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.util.osutil import ensuredir
|
||||
from sphinx.websupport.search import BaseSearch, search_adapters
|
||||
from sphinx.websupport import comments as sphinxcomments
|
||||
from sphinx.websupport.comments import StorageBackend
|
||||
|
||||
class WebSupportApp(Sphinx):
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -46,17 +46,18 @@ class WebSupport(object):
|
||||
self._init_comments(comments)
|
||||
|
||||
def _init_comments(self, comments):
|
||||
if isinstance(comments, sphinxcomments.CommentBackend):
|
||||
if isinstance(comments, StorageBackend):
|
||||
self.comments = comments
|
||||
else:
|
||||
# If a CommentBackend isn't provided, use the default
|
||||
# If a StorageBackend isn't provided, use the default
|
||||
# SQLAlchemy backend with an SQLite db.
|
||||
from sphinx.websupport.comments import SQLAlchemyComments
|
||||
from sphinx.websupport.comments.sqlalchemystorage \
|
||||
import SQLAlchemyStorage
|
||||
from sqlalchemy import create_engine
|
||||
db_path = path.join(self.outdir, 'comments', 'comments.db')
|
||||
ensuredir(path.dirname(db_path))
|
||||
engine = create_engine('sqlite:///%s' % db_path)
|
||||
self.comments = SQLAlchemyComments(engine)
|
||||
self.comments = SQLAlchemyStorage(engine)
|
||||
|
||||
def _init_templating(self):
|
||||
import sphinx
|
||||
@ -93,8 +94,7 @@ class WebSupport(object):
|
||||
self.outdir, doctreedir, 'websupport',
|
||||
search=self.search,
|
||||
comments=self.comments)
|
||||
# TODO:
|
||||
# Hook comments into Sphinx signals.
|
||||
|
||||
self.comments.pre_build()
|
||||
app.build()
|
||||
self.comments.post_build()
|
||||
|
@ -1,12 +1,5 @@
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from sphinx.websupport.comments.db import Base, Node, Comment, Vote
|
||||
|
||||
Session = sessionmaker()
|
||||
|
||||
class CommentBackend(object):
|
||||
class StorageBackend(object):
|
||||
def pre_build(self):
|
||||
pass
|
||||
|
||||
@ -22,117 +15,3 @@ class CommentBackend(object):
|
||||
|
||||
def get_comments(self, parent_id):
|
||||
raise NotImplemented
|
||||
|
||||
|
||||
class SQLAlchemyComments(CommentBackend):
|
||||
def __init__(self, engine):
|
||||
self.engine = engine
|
||||
Base.metadata.bind = engine
|
||||
Base.metadata.create_all()
|
||||
Session.configure(bind=engine)
|
||||
self.session = Session()
|
||||
|
||||
def pre_build(self):
|
||||
self.current_pk = None
|
||||
|
||||
def add_node(self, document, line, source, treeloc):
|
||||
node = Node(document, line, source, treeloc)
|
||||
self.session.add(node)
|
||||
if self.current_pk is None:
|
||||
self.session.commit()
|
||||
self.current_pk = node.id
|
||||
else:
|
||||
self.current_pk += 1
|
||||
return self.current_pk
|
||||
|
||||
def post_build(self):
|
||||
self.session.commit()
|
||||
|
||||
def add_comment(self, parent_id, text, displayed,
|
||||
username, rating, time):
|
||||
time = time or datetime.now()
|
||||
|
||||
id = parent_id[1:]
|
||||
if parent_id[0] == 's':
|
||||
node = self.session.query(Node).filter(Node.id == id).first()
|
||||
comment = Comment(text, displayed, username, rating,
|
||||
time, node=node)
|
||||
elif parent_id[0] == 'c':
|
||||
parent = self.session.query(Comment).filter(Comment.id == id).first()
|
||||
comment = Comment(text, displayed, username, rating,
|
||||
time, parent=parent)
|
||||
|
||||
self.session.add(comment)
|
||||
self.session.commit()
|
||||
return self.serializable(comment)
|
||||
|
||||
def get_comments(self, parent_id, user_id):
|
||||
parent_id = parent_id[1:]
|
||||
node = self.session.query(Node).filter(Node.id == parent_id).first()
|
||||
comments = []
|
||||
for comment in node.comments:
|
||||
comments.append(self.serializable(comment, user_id))
|
||||
|
||||
return comments
|
||||
|
||||
def process_vote(self, comment_id, user_id, value):
|
||||
vote = self.session.query(Vote).filter(
|
||||
Vote.comment_id == comment_id).filter(
|
||||
Vote.user_id == user_id).first()
|
||||
|
||||
comment = self.session.query(Comment).filter(
|
||||
Comment.id == comment_id).first()
|
||||
|
||||
if vote is None:
|
||||
vote = Vote(comment_id, user_id, value)
|
||||
comment.rating += value
|
||||
else:
|
||||
comment.rating += value - vote.value
|
||||
vote.value = value
|
||||
self.session.add(vote)
|
||||
self.session.commit()
|
||||
|
||||
def serializable(self, comment, user_id=None):
|
||||
delta = datetime.now() - comment.time
|
||||
|
||||
time = {'year': comment.time.year,
|
||||
'month': comment.time.month,
|
||||
'day': comment.time.day,
|
||||
'hour': comment.time.hour,
|
||||
'minute': comment.time.minute,
|
||||
'second': comment.time.second,
|
||||
'iso': comment.time.isoformat(),
|
||||
'delta': self.pretty_delta(delta)}
|
||||
|
||||
vote = ''
|
||||
if user_id is not None:
|
||||
vote = self.session.query(Vote).filter(
|
||||
Vote.comment_id == comment.id).filter(
|
||||
Vote.user_id == user_id).first()
|
||||
if vote is not None:
|
||||
vote = vote.value
|
||||
|
||||
return {'text': comment.text,
|
||||
'username': comment.username or 'Anonymous',
|
||||
'id': comment.id,
|
||||
'rating': comment.rating,
|
||||
'age': delta.seconds,
|
||||
'time': time,
|
||||
'vote': vote or 0,
|
||||
'node': comment.node.id if comment.node else None,
|
||||
'parent': comment.parent.id if comment.parent else None,
|
||||
'children': [self.serializable(child, user_id)
|
||||
for child in comment.children]}
|
||||
|
||||
def pretty_delta(self, delta):
|
||||
days = delta.days
|
||||
seconds = delta.seconds
|
||||
hours = seconds / 3600
|
||||
minutes = seconds / 60
|
||||
|
||||
if days == 0:
|
||||
dt = (minutes, 'minute') if hours == 0 else (hours, 'hour')
|
||||
else:
|
||||
dt = (days, 'day')
|
||||
|
||||
return '%s %s ago' % dt if dt[0] == 1 else '%s %ss ago' % dt
|
||||
|
125
sphinx/websupport/comments/sqlalchemystorage.py
Normal file
125
sphinx/websupport/comments/sqlalchemystorage.py
Normal file
@ -0,0 +1,125 @@
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from sphinx.websupport.comments import StorageBackend
|
||||
from sphinx.websupport.comments.db import Base, Node, Comment, Vote
|
||||
|
||||
Session = sessionmaker()
|
||||
|
||||
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, parent_id, text, displayed,
|
||||
username, rating, time):
|
||||
time = time or datetime.now()
|
||||
|
||||
session = Session()
|
||||
|
||||
id = parent_id[1:]
|
||||
if parent_id[0] == 's':
|
||||
node = session.query(Node).filter(Node.id == id).first()
|
||||
comment = Comment(text, displayed, username, rating,
|
||||
time, node=node)
|
||||
elif parent_id[0] == 'c':
|
||||
parent = session.query(Comment).filter(Comment.id == id).first()
|
||||
comment = Comment(text, displayed, username, rating,
|
||||
time, parent=parent)
|
||||
|
||||
session.add(comment)
|
||||
session.commit()
|
||||
comment = self.serializable(session, comment)
|
||||
session.close()
|
||||
return comment
|
||||
|
||||
def get_comments(self, parent_id, user_id):
|
||||
parent_id = parent_id[1:]
|
||||
session = Session()
|
||||
node = session.query(Node).filter(Node.id == parent_id).first()
|
||||
comments = []
|
||||
for comment in node.comments:
|
||||
comments.append(self.serializable(session, comment, user_id))
|
||||
|
||||
session.close()
|
||||
return comments
|
||||
|
||||
def process_vote(self, comment_id, user_id, value):
|
||||
session = Session()
|
||||
vote = session.query(Vote).filter(
|
||||
Vote.comment_id == comment_id).filter(
|
||||
Vote.user_id == user_id).first()
|
||||
|
||||
comment = session.query(Comment).filter(
|
||||
Comment.id == comment_id).first()
|
||||
|
||||
if vote is None:
|
||||
vote = Vote(comment_id, user_id, value)
|
||||
comment.rating += value
|
||||
else:
|
||||
comment.rating += value - vote.value
|
||||
vote.value = value
|
||||
session.add(vote)
|
||||
session.commit()
|
||||
session.close()
|
||||
|
||||
def serializable(self, session, comment, user_id=None):
|
||||
delta = datetime.now() - comment.time
|
||||
|
||||
time = {'year': comment.time.year,
|
||||
'month': comment.time.month,
|
||||
'day': comment.time.day,
|
||||
'hour': comment.time.hour,
|
||||
'minute': comment.time.minute,
|
||||
'second': comment.time.second,
|
||||
'iso': comment.time.isoformat(),
|
||||
'delta': self.pretty_delta(delta)}
|
||||
|
||||
vote = ''
|
||||
if user_id is not None:
|
||||
vote = session.query(Vote).filter(
|
||||
Vote.comment_id == comment.id).filter(
|
||||
Vote.user_id == user_id).first()
|
||||
if vote is not None:
|
||||
vote = vote.value
|
||||
|
||||
return {'text': comment.text,
|
||||
'username': comment.username or 'Anonymous',
|
||||
'id': comment.id,
|
||||
'rating': comment.rating,
|
||||
'age': delta.seconds,
|
||||
'time': time,
|
||||
'vote': vote or 0,
|
||||
'node': comment.node.id if comment.node else None,
|
||||
'parent': comment.parent.id if comment.parent else None,
|
||||
'children': [self.serializable(session, child, user_id)
|
||||
for child in comment.children]}
|
||||
|
||||
def pretty_delta(self, delta):
|
||||
days = delta.days
|
||||
seconds = delta.seconds
|
||||
hours = seconds / 3600
|
||||
minutes = seconds / 60
|
||||
|
||||
if days == 0:
|
||||
dt = (minutes, 'minute') if hours == 0 else (hours, 'hour')
|
||||
else:
|
||||
dt = (days, 'day')
|
||||
|
||||
return '%s %s ago' % dt if dt[0] == 1 else '%s %ss ago' % dt
|
Loading…
Reference in New Issue
Block a user