[Python-modules-commits] [sphinxcontrib-websupport] 01/01: Upstream version 1.0.1

Dmitry Shachnev mitya57 at moszumanska.debian.org
Sun Jul 9 15:00:44 UTC 2017


This is an automated email from the git hooks/post-receive script.

mitya57 pushed a commit to branch debian/master
in repository sphinxcontrib-websupport.

commit 5d53f4a598582a306984f67de7a04c8cec955dd4
Author: Dmitry Shachnev <mitya57 at gmail.com>
Date:   Sun Jul 9 17:59:14 2017 +0300

    Upstream version 1.0.1
---
 CHANGES                                            |   9 +
 LICENSE                                            |  29 ++
 MANIFEST.in                                        |   7 +
 PKG-INFO                                           |  30 ++
 README.rst                                         |  38 ++
 setup.cfg                                          |  21 +
 setup.py                                           |  65 +++
 sphinxcontrib/__init__.py                          |   2 +
 sphinxcontrib/websupport/__init__.py               |  16 +
 sphinxcontrib/websupport/builder.py                | 196 +++++++++
 sphinxcontrib/websupport/core.py                   | 456 +++++++++++++++++++++
 sphinxcontrib/websupport/errors.py                 |  26 ++
 sphinxcontrib/websupport/search/__init__.py        | 134 ++++++
 sphinxcontrib/websupport/search/nullsearch.py      |  24 ++
 sphinxcontrib/websupport/search/whooshsearch.py    |  61 +++
 sphinxcontrib/websupport/search/xapiansearch.py    |  86 ++++
 sphinxcontrib/websupport/storage/__init__.py       | 116 ++++++
 sphinxcontrib/websupport/storage/differ.py         |  86 ++++
 sphinxcontrib/websupport/storage/sqlalchemy_db.py  | 226 ++++++++++
 .../websupport/storage/sqlalchemystorage.py        | 177 ++++++++
 sphinxcontrib/websupport/utils.py                  |  18 +
 sphinxcontrib/websupport/version.py                |  11 +
 sphinxcontrib/websupport/writer.py                 |  46 +++
 sphinxcontrib_websupport.egg-info/PKG-INFO         |  30 ++
 sphinxcontrib_websupport.egg-info/SOURCES.txt      |  93 +++++
 .../dependency_links.txt                           |   1 +
 .../namespace_packages.txt                         |   1 +
 sphinxcontrib_websupport.egg-info/not-zip-safe     |   1 +
 sphinxcontrib_websupport.egg-info/requires.txt     |   4 +
 sphinxcontrib_websupport.egg-info/top_level.txt    |   1 +
 tests/path.py                                      | 207 ++++++++++
 tests/root/Makefile                                |  67 +++
 tests/root/_static/README                          |   1 +
 tests/root/_static/excluded.css                    |   1 +
 tests/root/_static/subdir/foo.css                  |   1 +
 tests/root/_templates/contentssb.html              |   2 +
 tests/root/_templates/customsb.html                |   4 +
 tests/root/_templates/layout.html                  |  15 +
 tests/root/autodoc.txt                             |  49 +++
 tests/root/autodoc_fodder.py                       |   7 +
 tests/root/autodoc_missing_imports.py              |  18 +
 tests/root/bom.po                                  |  12 +
 tests/root/bom.txt                                 |   5 +
 tests/root/conf.py                                 | 117 ++++++
 tests/root/contents.txt                            |  70 ++++
 tests/root/en.lproj/localized.txt                  |   2 +
 tests/root/ext.py                                  |   4 +
 tests/root/extapi.txt                              |  10 +
 tests/root/extensions.txt                          |  28 ++
 tests/root/footnote.txt                            |  57 +++
 tests/root/images.txt                              |  28 ++
 tests/root/img.foo.png                             | Bin 0 -> 66247 bytes
 tests/root/img.gif                                 | Bin 0 -> 24976 bytes
 tests/root/img.pdf                                 | Bin 0 -> 141783 bytes
 tests/root/img.png                                 | Bin 0 -> 66247 bytes
 tests/root/includes.txt                            | 102 +++++
 tests/root/lists.txt                               |  63 +++
 tests/root/literal.inc                             |  13 +
 tests/root/literal_orig.inc                        |  13 +
 tests/root/markup.txt                              | 432 +++++++++++++++++++
 tests/root/math.txt                                |  31 ++
 tests/root/metadata.add                            |  57 +++
 tests/root/objects.txt                             | 213 ++++++++++
 tests/root/otherext.foo                            |   2 +
 tests/root/parsermod.py                            |  12 +
 tests/root/quotes.inc                              |   1 +
 tests/root/rimg.png                                | Bin 0 -> 120 bytes
 tests/root/robots.txt                              |   2 +
 tests/root/special/api.h                           |   1 +
 tests/root/special/code.py                         |   2 +
 tests/root/subdir.po                               |   9 +
 tests/root/subdir/excluded.txt                     |   2 +
 tests/root/subdir/images.txt                       |   6 +
 tests/root/subdir/img.png                          | Bin 0 -> 66247 bytes
 tests/root/subdir/include.inc                      |   5 +
 tests/root/subdir/includes.txt                     |  18 +
 tests/root/subdir/simg.png                         | Bin 0 -> 66247 bytes
 tests/root/svgimg.pdf                              | Bin 0 -> 141783 bytes
 tests/root/svgimg.svg                              | 158 +++++++
 tests/root/tabs.inc                                |   5 +
 tests/root/templated.css_t                         |   2 +
 tests/root/test.inc                                |   3 +
 tests/root/testtheme/layout.html                   |   5 +
 tests/root/testtheme/static/staticimg.png          | Bin 0 -> 120 bytes
 tests/root/testtheme/static/statictmpl.html_t      |   2 +
 tests/root/testtheme/theme.conf                    |   7 +
 tests/root/wrongenc.inc                            |   3 +
 tests/root/ziptheme.zip                            | Bin 0 -> 1039 bytes
 tests/roots/test-searchadapters/conf.py            |   4 +
 tests/roots/test-searchadapters/markup.txt         | 447 ++++++++++++++++++++
 tests/test_searchadapters.py                       |  69 ++++
 tests/test_websupport.py                           | 274 +++++++++++++
 tests/util.py                                      | 364 ++++++++++++++++
 tox.ini                                            |  26 ++
 94 files changed, 5069 insertions(+)

diff --git a/CHANGES b/CHANGES
new file mode 100644
index 0000000..93d87b2
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,9 @@
+Release 1.0.1 (2017-05-07)
+==========================
+
+* Make sqlalchemy and whoosh as optional dependency
+
+Release 1.0.0 (2017-04-23)
+==========================
+
+* Initial release (copied from sphinx package)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..3b8fd8e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,29 @@
+License for sphinxcontrib-websupport
+====================================
+
+Copyright (c) 2007-2017 by the Sphinx team
+(see https://github.com/sphinx-doc/sphinx/blob/master/AUTHORS).
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..4db06ab
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,7 @@
+include README.rst
+include LICENSE
+include CHANGES
+
+include tox.ini
+
+recursive-include tests *
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..15089b9
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,30 @@
+Metadata-Version: 1.1
+Name: sphinxcontrib-websupport
+Version: 1.0.1
+Summary: Sphinx API for Web Apps
+Home-page: http://sphinx-doc.org/
+Author: Georg Brandl
+Author-email: georg at python.org
+License: BSD
+Download-URL: https://pypi.python.org/pypi/sphinxcontrib-websupport
+Description: 
+        sphinxcontrib-webuspport provides a Python API to easily integrate Sphinx
+        documentation into your Web application.
+        
+Platform: any
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Console
+Classifier: Environment :: Web Environment
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Education
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
+Classifier: Framework :: Sphinx
+Classifier: Framework :: Sphinx :: Extension
+Classifier: Topic :: Documentation
+Classifier: Topic :: Documentation :: Sphinx
+Classifier: Topic :: Text Processing
+Classifier: Topic :: Utilities
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..c1ab116
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,38 @@
+===================================
+README for sphinxcontrib-websupport
+===================================
+
+This is the Sphinx documentation generator, see http://www.sphinx-doc.org/.
+
+
+Installing
+==========
+
+Install from PyPI::
+
+   pip install -U sphinxcontrib-websupport
+
+Release signatures
+==================
+
+Releases are signed with following keys:
+
+* `498D6B9E <https://pgp.mit.edu/pks/lookup?op=vindex&search=0x102C2C17498D6B9E>`_
+* `5EBA0E07 <https://pgp.mit.edu/pks/lookup?op=vindex&search=0x1425F8CE5EBA0E07>`_
+
+Testing
+=======
+
+To run the tests with the interpreter available as ``python``, use::
+
+    tox
+
+Continuous testing runs on travis: https://travis-ci.org/sphinx-doc/sphinxcontrib-websupport
+
+Contributing
+============
+
+See `CONTRIBUTING.rst`__
+
+.. __: https://github.com/sphinx-doc/sphinx/blob/master/CONTRIBUTING.rst
+
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..4f81bff
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,21 @@
+[egg_info]
+tag_build = 
+tag_date = 0
+
+[aliases]
+release = egg_info -Db ''
+upload = upload --sign --identity=36580288
+
+[extract_messages]
+mapping_file = babel.cfg
+output_file = sphinx/locale/sphinx.pot
+keywords = _ l_ lazy_gettext
+
+[wheel]
+universal = 1
+
+[flake8]
+max-line-length = 95
+ignore = E116,E241,E251
+exclude = .git,.tox,tests/*
+
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..c659309
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,65 @@
+# -*- coding: utf-8 -*-
+import os
+from setuptools import setup, find_packages
+
+long_desc = '''
+sphinxcontrib-webuspport provides a Python API to easily integrate Sphinx
+documentation into your Web application.
+'''
+
+extras_require = {
+    # Environment Marker works for wheel 0.24 or later
+    'test': [
+        'pytest',
+        'mock',  # it would be better for 'test:python_version in 2.7'
+    ],
+}
+
+
+def get_version():
+    """Get version number of the package from version.py without importing core module."""
+    package_dir = os.path.abspath(os.path.dirname(__file__))
+    version_file = os.path.join(package_dir, 'sphinxcontrib/websupport/version.py')
+
+    namespace = {}
+    with open(version_file, 'rt') as f:
+        exec(f.read(), namespace)
+
+    return namespace['__version__']
+
+
+setup(
+    name='sphinxcontrib-websupport',
+    version=get_version(),
+    url='http://sphinx-doc.org/',
+    download_url='https://pypi.python.org/pypi/sphinxcontrib-websupport',
+    license='BSD',
+    author='Georg Brandl',
+    author_email='georg at python.org',
+    description='Sphinx API for Web Apps',
+    long_description=long_desc,
+    zip_safe=False,
+    classifiers=[
+        'Development Status :: 5 - Production/Stable',
+        'Environment :: Console',
+        'Environment :: Web Environment',
+        'Intended Audience :: Developers',
+        'Intended Audience :: Education',
+        'License :: OSI Approved :: BSD License',
+        'Operating System :: OS Independent',
+        'Programming Language :: Python',
+        'Programming Language :: Python :: 2',
+        'Programming Language :: Python :: 3',
+        'Framework :: Sphinx',
+        'Framework :: Sphinx :: Extension',
+        'Topic :: Documentation',
+        'Topic :: Documentation :: Sphinx',
+        'Topic :: Text Processing',
+        'Topic :: Utilities',
+    ],
+    platforms='any',
+    packages=find_packages(exclude=['tests']),
+    include_package_data=True,
+    extras_require=extras_require,
+    namespace_packages=['sphinxcontrib'],
+)
diff --git a/sphinxcontrib/__init__.py b/sphinxcontrib/__init__.py
new file mode 100644
index 0000000..68c04af
--- /dev/null
+++ b/sphinxcontrib/__init__.py
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+__import__('pkg_resources').declare_namespace(__name__)
diff --git a/sphinxcontrib/websupport/__init__.py b/sphinxcontrib/websupport/__init__.py
new file mode 100644
index 0000000..643ff4a
--- /dev/null
+++ b/sphinxcontrib/websupport/__init__.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinxcontrib.websupport
+    ~~~~~~~~~~~~~~~~~~~~~~~~
+
+    A Python API to easily integrate Sphinx documentation into Web
+    applications.
+
+    :copyright: Copyright 2007-2017 by the Sphinx team, see README.
+    :license: BSD, see LICENSE for details.
+"""
+
+__import__('pkg_resources').declare_namespace(__name__)
+
+from sphinxcontrib.websupport.core import WebSupport  # NOQA
+from sphinxcontrib.websupport.version import __version__, __version_info__  # NOQA
diff --git a/sphinxcontrib/websupport/builder.py b/sphinxcontrib/websupport/builder.py
new file mode 100644
index 0000000..d38626e
--- /dev/null
+++ b/sphinxcontrib/websupport/builder.py
@@ -0,0 +1,196 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinx.builders.websupport
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Builder for the web support package.
+
+    :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+from os import path
+import posixpath
+import shutil
+
+from docutils.io import StringOutput
+
+from sphinx.jinja2glue import BuiltinTemplateLoader
+from sphinx.util.osutil import os_path, relative_uri, ensuredir, copyfile
+from sphinx.builders.html import PickleHTMLBuilder
+from sphinx.writers.websupport import WebSupportTranslator
+
+if False:
+    # For type annotation
+    from typing import Any, Dict, Iterable, Tuple  # NOQA
+    from docutils import nodes  # NOQA
+    from sphinx.application import Sphinx  # NOQA
+
+
+class WebSupportBuilder(PickleHTMLBuilder):
+    """
+    Builds documents for the web support package.
+    """
+    name = 'websupport'
+    versioning_method = 'commentable'
+    versioning_compare = True  # for commentable node's uuid stability.
+
+    def init(self):
+        # type: () -> None
+        PickleHTMLBuilder.init(self)
+        # templates are needed for this builder, but the serializing
+        # builder does not initialize them
+        self.init_templates()
+        if not isinstance(self.templates, BuiltinTemplateLoader):
+            raise RuntimeError('websupport builder must be used with '
+                               'the builtin templates')
+        # add our custom JS
+        self.script_files.append('_static/websupport.js')
+
+    def set_webinfo(self, staticdir, virtual_staticdir, search, storage):
+        # type: (unicode, unicode, Any, unicode) -> None
+        self.staticdir = staticdir
+        self.virtual_staticdir = virtual_staticdir
+        self.search = search
+        self.storage = storage
+
+    def init_translator_class(self):
+        # type: () -> None
+        if self.translator_class is None:
+            self.translator_class = WebSupportTranslator
+
+    def prepare_writing(self, docnames):
+        # type: (Iterable[unicode]) -> None
+        PickleHTMLBuilder.prepare_writing(self, docnames)
+        self.globalcontext['no_search_suffix'] = True
+
+    def write_doc(self, docname, doctree):
+        # type: (unicode, nodes.Node) -> None
+        destination = StringOutput(encoding='utf-8')
+        doctree.settings = self.docsettings
+
+        self.secnumbers = self.env.toc_secnumbers.get(docname, {})
+        self.fignumbers = self.env.toc_fignumbers.get(docname, {})
+        self.imgpath = '/' + posixpath.join(self.virtual_staticdir, self.imagedir)
+        self.dlpath = '/' + posixpath.join(self.virtual_staticdir, '_downloads')
+        self.current_docname = docname
+        self.docwriter.write(doctree, destination)
+        self.docwriter.assemble_parts()
+        body = self.docwriter.parts['fragment']
+        metatags = self.docwriter.clean_meta
+
+        ctx = self.get_doc_context(docname, body, metatags)
+        self.handle_page(docname, ctx, event_arg=doctree)
+
+    def write_doc_serialized(self, docname, doctree):
+        # type: (unicode, nodes.Node) -> None
+        self.imgpath = '/' + posixpath.join(self.virtual_staticdir, self.imagedir)
+        self.post_process_images(doctree)
+        title = self.env.longtitles.get(docname)
+        title = title and self.render_partial(title)['title'] or ''
+        self.index_page(docname, doctree, title)
+
+    def load_indexer(self, docnames):
+        # type: (Iterable[unicode]) -> None
+        self.indexer = self.search  # type: ignore
+        self.indexer.init_indexing(changed=docnames)  # type: ignore
+
+    def _render_page(self, pagename, addctx, templatename, event_arg=None):
+        # type: (unicode, Dict, unicode, unicode) -> Tuple[Dict, Dict]
+        # This is mostly copied from StandaloneHTMLBuilder. However, instead
+        # of rendering the template and saving the html, create a context
+        # dict and pickle it.
+        ctx = self.globalcontext.copy()
+        ctx['pagename'] = pagename
+
+        def pathto(otheruri, resource=False,
+                   baseuri=self.get_target_uri(pagename)):
+            # type: (unicode, bool, unicode) -> unicode
+            if resource and '://' in otheruri:
+                return otheruri
+            elif not resource:
+                otheruri = self.get_target_uri(otheruri)
+                return relative_uri(baseuri, otheruri) or '#'
+            else:
+                return '/' + posixpath.join(self.virtual_staticdir, otheruri)
+        ctx['pathto'] = pathto
+        ctx['hasdoc'] = lambda name: name in self.env.all_docs
+        ctx['encoding'] = self.config.html_output_encoding
+        ctx['toctree'] = lambda **kw: self._get_local_toctree(pagename, **kw)
+        self.add_sidebars(pagename, ctx)
+        ctx.update(addctx)
+
+        newtmpl = self.app.emit_firstresult('html-page-context', pagename,
+                                            templatename, ctx, event_arg)
+        if newtmpl:
+            templatename = newtmpl
+
+        # create a dict that will be pickled and used by webapps
+        doc_ctx = {
+            'body': ctx.get('body', ''),
+            'title': ctx.get('title', ''),
+            'css': ctx.get('css', ''),
+            'script': ctx.get('script', ''),
+        }
+        # partially render the html template to get at interesting macros
+        template = self.templates.environment.get_template(templatename)
+        template_module = template.make_module(ctx)
+        for item in ['sidebar', 'relbar', 'script', 'css']:
+            if hasattr(template_module, item):
+                doc_ctx[item] = getattr(template_module, item)()
+
+        return ctx, doc_ctx
+
+    def handle_page(self, pagename, addctx, templatename='page.html',
+                    outfilename=None, event_arg=None):
+        # type: (unicode, Dict, unicode, unicode, unicode) -> None
+        ctx, doc_ctx = self._render_page(pagename, addctx,
+                                         templatename, event_arg)
+
+        if not outfilename:
+            outfilename = path.join(self.outdir, 'pickles',
+                                    os_path(pagename) + self.out_suffix)
+        ensuredir(path.dirname(outfilename))
+        self.dump_context(doc_ctx, outfilename)
+
+        # if there is a source file, copy the source file for the
+        # "show source" link
+        if ctx.get('sourcename'):
+            source_name = path.join(self.staticdir,
+                                    '_sources', os_path(ctx['sourcename']))
+            ensuredir(path.dirname(source_name))
+            copyfile(self.env.doc2path(pagename), source_name)
+
+    def handle_finish(self):
+        # type: () -> None
+        # get global values for css and script files
+        _, doc_ctx = self._render_page('tmp', {}, 'page.html')
+        self.globalcontext['css'] = doc_ctx['css']
+        self.globalcontext['script'] = doc_ctx['script']
+
+        PickleHTMLBuilder.handle_finish(self)
+
+        # move static stuff over to separate directory
+        directories = [self.imagedir, '_static']
+        for directory in directories:
+            src = path.join(self.outdir, directory)
+            dst = path.join(self.staticdir, directory)
+            if path.isdir(src):
+                if path.isdir(dst):
+                    shutil.rmtree(dst)
+                shutil.move(src, dst)
+
+    def dump_search_index(self):
+        # type: () -> None
+        self.indexer.finish_indexing()  # type: ignore
+
+
+def setup(app):
+    # type: (Sphinx) -> Dict[unicode, Any]
+    app.add_builder(WebSupportBuilder)
+
+    return {
+        'version': 'builtin',
+        'parallel_read_safe': True,
+        'parallel_write_safe': True,
+    }
diff --git a/sphinxcontrib/websupport/core.py b/sphinxcontrib/websupport/core.py
new file mode 100644
index 0000000..062bf9f
--- /dev/null
+++ b/sphinxcontrib/websupport/core.py
@@ -0,0 +1,456 @@
+# -*- coding: utf-8 -*-
+"""
+    sphinxcontrib.websupport.core
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Base Module for web support functions.
+
+    :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+"""
+
+import sys
+import posixpath
+from os import path
+
+from six.moves import cPickle as pickle
+from jinja2 import Environment, FileSystemLoader
+from docutils.core import publish_parts
+
+from sphinx.locale import _
+from sphinx.util.osutil import ensuredir
+from sphinx.util.jsonimpl import dumps as dump_json
+from sphinx.util.pycompat import htmlescape
+from sphinxcontrib.websupport import errors
+from sphinxcontrib.websupport.search import BaseSearch, SEARCH_ADAPTERS
+from sphinxcontrib.websupport.storage import StorageBackend
+
+if False:
+    # For type annotation
+    from typing import Dict  # NOQA
+
+
+class WebSupport(object):
+    """The main API class for the web support package. All interactions
+    with the web support package should occur through this class.
+    """
+    def __init__(self,
+                 srcdir=None,      # only required for building
+                 builddir='',      # the dir with data/static/doctrees subdirs
+                 datadir=None,     # defaults to builddir/data
+                 staticdir=None,   # defaults to builddir/static
+                 doctreedir=None,  # defaults to builddir/doctrees
+                 search=None,      # defaults to no search
+                 storage=None,     # defaults to SQLite in datadir
+                 status=sys.stdout,
+                 warning=sys.stderr,
+                 moderation_callback=None,
+                 allow_anonymous_comments=True,
+                 docroot='',
+                 staticroot='static',
+                 ):
+        # directories
+        self.srcdir = srcdir
+        self.builddir = builddir
+        self.outdir = path.join(builddir, 'data')
+        self.datadir = datadir or self.outdir
+        self.staticdir = staticdir or path.join(self.builddir, 'static')
+        self.doctreedir = staticdir or path.join(self.builddir, 'doctrees')
+        # web server virtual paths
+        self.staticroot = staticroot.strip('/')
+        self.docroot = docroot.strip('/')
+
+        self.status = status
+        self.warning = warning
+        self.moderation_callback = moderation_callback
+        self.allow_anonymous_comments = allow_anonymous_comments
+
+        self._init_templating()
+        self._init_search(search)
+        self._init_storage(storage)
+
+        self._globalcontext = None  # type: ignore
+
+        self._make_base_comment_options()
+
+    def _init_storage(self, storage):
+        if isinstance(storage, StorageBackend):
+            self.storage = storage
+        else:
+            # If a StorageBackend isn't provided, use the default
+            # SQLAlchemy backend.
+            from sphinxcontrib.websupport.storage.sqlalchemystorage \
+                import SQLAlchemyStorage
+            if not storage:
+                # no explicit DB path given; create default sqlite database
+                db_path = path.join(self.datadir, 'db', 'websupport.db')
+                ensuredir(path.dirname(db_path))
+                storage = 'sqlite:///' + db_path
+            self.storage = SQLAlchemyStorage(storage)
+
+    def _init_templating(self):
+        import sphinx
+        template_path = path.join(sphinx.package_dir,
+                                  'themes', 'basic')
+        loader = FileSystemLoader(template_path)
+        self.template_env = Environment(loader=loader)
+
+    def _init_search(self, search):
+        if isinstance(search, BaseSearch):
+            self.search = search
+        else:
+            mod, cls = SEARCH_ADAPTERS[search or 'null']
+            mod = 'sphinxcontrib.websupport.search.' + mod
+            SearchClass = getattr(__import__(mod, None, None, [cls]), cls)
+            search_path = path.join(self.datadir, 'search')
+            self.search = SearchClass(search_path)
+        self.results_template = \
+            self.template_env.get_template('searchresults.html')
+
+    def build(self):
+        """Build the documentation. Places the data into the `outdir`
+        directory. Use it like this::
+
+            support = WebSupport(srcdir, builddir, search='xapian')
+            support.build()
+
+        This will read reStructured text files from `srcdir`. Then it will
+        build the pickles and search index, placing them into `builddir`.
+        It will also save node data to the database.
+        """
+        if not self.srcdir:
+            raise RuntimeError('No srcdir associated with WebSupport object')
+
+        from sphinx.application import Sphinx
+        app = Sphinx(self.srcdir, self.srcdir, self.outdir, self.doctreedir,
+                     'websupport', status=self.status, warning=self.warning)
+        app.builder.set_webinfo(self.staticdir, self.staticroot,  # type: ignore
+                                self.search, self.storage)
+
+        self.storage.pre_build()
+        app.build()
+        self.storage.post_build()
+
+    def get_globalcontext(self):
+        """Load and return the "global context" pickle."""
+        if not self._globalcontext:
+            infilename = path.join(self.datadir, 'globalcontext.pickle')
+            with open(infilename, 'rb') as f:
+                self._globalcontext = pickle.load(f)
+        return self._globalcontext
+
+    def get_document(self, docname, username='', moderator=False):
+        """Load and return a document from a pickle. The document will
+        be a dict object which can be used to render a template::
+
+            support = WebSupport(datadir=datadir)
+            support.get_document('index', username, moderator)
+
+        In most cases `docname` will be taken from the request path and
+        passed directly to this function. In Flask, that would be something
+        like this::
+
+            @app.route('/<path:docname>')
+            def index(docname):
+                username = g.user.name if g.user else ''
+                moderator = g.user.moderator if g.user else False
+                try:
+                    document = support.get_document(docname, username,
+                                                    moderator)
+                except DocumentNotFoundError:
+                    abort(404)
+                render_template('doc.html', document=document)
+
+        The document dict that is returned contains the following items
+        to be used during template rendering.
+
+        * **body**: The main body of the document as HTML
+        * **sidebar**: The sidebar of the document as HTML
+        * **relbar**: A div containing links to related documents
+        * **title**: The title of the document
+        * **css**: Links to css files used by Sphinx
+        * **script**: Javascript containing comment options
+
+        This raises :class:`~sphinxcontrib.websupport.errors.DocumentNotFoundError`
+        if a document matching `docname` is not found.
+
+        :param docname: the name of the document to load.
+        """
+        docpath = path.join(self.datadir, 'pickles', docname)
+        if path.isdir(docpath):
+            infilename = docpath + '/index.fpickle'
+            if not docname:
+                docname = 'index'
+            else:
+                docname += '/index'
+        else:
+            infilename = docpath + '.fpickle'
+
+        try:
+            with open(infilename, 'rb') as f:
+                document = pickle.load(f)
+        except IOError:
+            raise errors.DocumentNotFoundError(
+                'The document "%s" could not be found' % docname)
+
+        comment_opts = self._make_comment_options(username, moderator)
+        comment_meta = self._make_metadata(
+            self.storage.get_metadata(docname, moderator))
+
+        document['script'] = comment_opts + comment_meta + document['script']
+        return document
+
+    def get_search_results(self, q):
+        """Perform a search for the query `q`, and create a set
+        of search results. Then render the search results as html and
+        return a context dict like the one created by
+        :meth:`get_document`::
+
+            document = support.get_search_results(q)
+
+        :param q: the search query
+        """
+        results = self.search.query(q)
+        ctx = {
+            'q': q,
+            'search_performed': True,
+            'search_results': results,
+            'docroot': '../',  # XXX
+            '_': _,
+        }
+        document = {
+            'body': self.results_template.render(ctx),
+            'title': 'Search Results',
+            'sidebar': '',
+            'relbar': ''
+        }
+        return document
+
+    def get_data(self, node_id, username=None, moderator=False):
+        """Get the comments and source associated with `node_id`. If
+        `username` is given vote information will be included with the
+        returned comments. The default CommentBackend returns a dict with
+        two keys, *source*, and *comments*. *source* is raw source of the
+        node and is used as the starting point for proposals a user can
+        add. *comments* is a list of dicts that represent a comment, each
+        having the following items:
+
+        ============= ======================================================
+        Key           Contents
+        ============= ======================================================
+        text          The comment text.
+        username      The username that was stored with the comment.
+        id            The comment's unique identifier.
+        rating        The comment's current rating.
+        age           The time in seconds since the comment was added.
+        time          A dict containing time information. It contains the
+                      following keys: year, month, day, hour, minute, second,
+                      iso, and delta. `iso` is the time formatted in ISO
+                      8601 format. `delta` is a printable form of how old
+                      the comment is (e.g. "3 hours ago").
+        vote          If `user_id` was given, this will be an integer
+                      representing the vote. 1 for an upvote, -1 for a
+                      downvote, or 0 if unvoted.
+        node          The id of the node that the comment is attached to.
+                      If the comment's parent is another comment rather than
+                      a node, this will be null.
+        parent        The id of the comment that this comment is attached
+                      to if it is not attached to a node.
+        children      A list of all children, in this format.
+        proposal_diff An HTML representation of the differences between the
+                      the current source and the user's proposed source.
+        ============= ======================================================
+
+        :param node_id: the id of the node to get comments for.
+        :param username: the username of the user viewing the comments.
+        :param moderator: whether the user is a moderator.
+        """
+        return self.storage.get_data(node_id, username, moderator)
+
+    def delete_comment(self, comment_id, username='', moderator=False):
+        """Delete a comment.
+
+        If `moderator` is True, the comment and all descendants will be deleted
+        from the database, and the function returns ``True``.
+
+        If `moderator` is False, the comment will be marked as deleted (but not
+        removed from the database so as not to leave any comments orphaned), but
+        only if the `username` matches the `username` on the comment.  The
+        username and text files are replaced with "[deleted]" .  In this case,
+        the function returns ``False``.
+
+        This raises :class:`~sphinxcontrib.websupport.errors.UserNotAuthorizedError`
+        if moderator is False and `username` doesn't match username on the
+        comment.
+
+        :param comment_id: the id of the comment to delete.
+        :param username: the username requesting the deletion.
+        :param moderator: whether the requestor is a moderator.
+        """
+        return self.storage.delete_comment(comment_id, username, moderator)
+
+    def add_comment(self, text, node_id='', parent_id='', displayed=True,
+                    username=None, time=None, proposal=None,
+                    moderator=False):
+        """Add a comment to a node or another comment. Returns the comment
+        in the same format as :meth:`get_comments`. If the comment is being
+        attached to a node, pass in the node's id (as a string) with the
+        node keyword argument::
+
+            comment = support.add_comment(text, node_id=node_id)
+
+        If the comment is the child of another comment, provide the parent's
+        id (as a string) with the parent keyword argument::
+
+            comment = support.add_comment(text, parent_id=parent_id)
+
+        If you would like to store a username with the comment, pass
+        in the optional `username` keyword argument::
+
+            comment = support.add_comment(text, node=node_id,
+                                          username=username)
+
+        :param parent_id: the prefixed id of the comment's parent.
+        :param text: the text of the comment.
+        :param displayed: for moderation purposes
+        :param username: the username of the user making the comment.
+        :param time: the time the comment was created, defaults to now.
+        """
+        if username is None:
+            if self.allow_anonymous_comments:
+                username = 'Anonymous'
+            else:
+                raise errors.UserNotAuthorizedError()
+        parsed = self._parse_comment_text(text)
+        comment = self.storage.add_comment(parsed, displayed, username,
+                                           time, proposal, node_id,
+                                           parent_id, moderator)
+        comment['original_text'] = text
+        if not displayed and self.moderation_callback:
+            self.moderation_callback(comment)
+        return comment
+
+    def process_vote(self, comment_id, username, value):
+        """Process a user's vote. The web support package relies
+        on the API user to perform authentication. The API user will
+        typically receive a comment_id and value from a form, and then
+        make sure the user is authenticated. A unique username  must be
+        passed in, which will also be used to retrieve the user's past
+        voting data. An example, once again in Flask::
+
+            @app.route('/docs/process_vote', methods=['POST'])
+            def process_vote():
+                if g.user is None:
+                    abort(401)
+                comment_id = request.form.get('comment_id')
+                value = request.form.get('value')
+                if value is None or comment_id is None:
+                    abort(400)
+                support.process_vote(comment_id, g.user.name, value)
+                return "success"
+
+        :param comment_id: the comment being voted on
+        :param username: the unique username of the user voting
+        :param value: 1 for an upvote, -1 for a downvote, 0 for an unvote.
+        """
+        value = int(value)
+        if not -1 <= value <= 1:
+            raise ValueError('vote value %s out of range (-1, 1)' % value)
+        self.storage.process_vote(comment_id, username, value)
+
+    def update_username(self, old_username, new_username):
+        """To remain decoupled from a webapp's authentication system, the
+        web support package stores a user's username with each of their
+        comments and votes. If the authentication system allows a user to
+        change their username, this can lead to stagnate data in the web
+        support system. To avoid this, each time a username is changed, this
+        method should be called.
+
+        :param old_username: The original username.
+        :param new_username: The new username.
+        """
+        self.storage.update_username(old_username, new_username)
+
+    def accept_comment(self, comment_id, moderator=False):
+        """Accept a comment that is pending moderation.
+
+        This raises :class:`~sphinxcontrib.websupport.errors.UserNotAuthorizedError`
+        if moderator is False.
+
+        :param comment_id: The id of the comment that was accepted.
+        :param moderator: Whether the user making the request is a moderator.
+        """
+        if not moderator:
+            raise errors.UserNotAuthorizedError()
+        self.storage.accept_comment(comment_id)
+
+    def _make_base_comment_options(self):
+        """Helper method to create the part of the COMMENT_OPTIONS javascript
+        that remains the same throughout the lifetime of the
+        :class:`~sphinxcontrib.websupport.WebSupport` object.
+        """
+        self.base_comment_opts = {}  # type: Dict[unicode, unicode]
+
+        if self.docroot != '':
+            comment_urls = [
+                ('addCommentURL', '_add_comment'),
+                ('getCommentsURL', '_get_comments'),
+                ('processVoteURL', '_process_vote'),
+                ('acceptCommentURL', '_accept_comment'),
+                ('deleteCommentURL', '_delete_comment')
+            ]
+            for key, value in comment_urls:
+                self.base_comment_opts[key] = \
+                    '/' + posixpath.join(self.docroot, value)
+        if self.staticroot != 'static':
+            static_urls = [
+                ('commentImage', 'comment.png'),
+                ('closeCommentImage', 'comment-close.png'),
+                ('loadingImage', 'ajax-loader.gif'),
+                ('commentBrightImage', 'comment-bright.png'),
+                ('upArrow', 'up.png'),
+                ('upArrowPressed', 'up-pressed.png'),
+                ('downArrow', 'down.png'),
+                ('downArrowPressed', 'down-pressed.png')
+            ]
+            for key, value in static_urls:
+                self.base_comment_opts[key] = \
+                    '/' + posixpath.join(self.staticroot, '_static', value)
+
... 4716 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/sphinxcontrib-websupport.git



More information about the Python-modules-commits mailing list