gminick / sphinx-gsoc2009
fork of sphinx
A support for per-paragraph comments and user/developer interface for submitting/committing fixes.
Clone this repository (size: 8.4 MB): HTTPS / SSH
$ hg clone http://bitbucket.org/gminick/sphinx-gsoc2009/
| commit 1569: | ae72a8b254e8 |
| parent 1568: | 413f8c6b53f2 |
| branch: | default |
Add basics for theming on webapp level
Changed (Δ2.0 KB):
raw changeset »
sphinx/builders/webapp/webapp.py (6 lines added, 4 lines removed)
sphinx/web/middleware/appserver.py (96 lines added, 44 lines removed)
Up to file-list sphinx/builders/webapp/webapp.py:
| … | … | @@ -101,10 +101,12 @@ class WebAppBuilder(SerializingHTMLBuild |
101 |
101 |
except Exception, err: |
102 |
102 |
raise SphinxError(err) |
103 |
103 |
|
104 |
src_dir = path.join(path.dirname(__file__), '../../themes/basic/static') |
|
105 |
dst_dir = path.join(self.outdir, 'public/_static') |
|
106 |
shutil.copytree(src_dir, dst_dir) |
|
107 |
||
104 |
sphinx_dirs = (('../../themes/basic/static', 'public/_static'), |
|
105 |
('../../themes', 'themes')) |
|
106 |
for sdir in sphinx_dirs: |
|
107 |
src_dir = path.join(path.dirname(__file__), sdir[0]) |
|
108 |
dst_dir = path.join(self.outdir, sdir[1]) |
|
109 |
shutil.copytree(src_dir, dst_dir) |
|
108 |
110 |
|
109 |
111 |
### |
110 |
112 |
### Xapian search engine |
Up to file-list sphinx/web/middleware/appserver.py:
10 |
10 |
:license: BSD, see LICENSE for details. |
11 |
11 |
""" |
12 |
12 |
|
13 |
import json |
|
13 |
try: |
|
14 |
import json |
|
15 |
except ImportError: |
|
16 |
try: |
|
17 |
import simplejson as json |
|
18 |
except ImportError: |
|
19 |
raise ImportError('json module not found') |
|
20 |
||
21 |
import os |
|
14 |
22 |
import time |
15 |
23 |
import locale |
16 |
24 |
import cPickle |
17 |
25 |
from os import path |
18 |
from hashlib import md5 |
|
19 |
26 |
from difflib import Differ |
20 |
27 |
|
21 |
28 |
from jinja2 import Environment, FileSystemLoader, Template |
22 |
29 |
from webob import Request, Response |
23 |
30 |
|
24 |
from sphinx.application import TemplateBridge |
|
31 |
from sphinx.application import TemplateBridge, Sphinx |
|
32 |
from sphinx.environment import BuildEnvironment |
|
25 |
33 |
from sphinx.errors import SphinxError |
34 |
from sphinx.highlighting import PygmentsBridge |
|
35 |
from sphinx.jinja2glue import BuiltinTemplateLoader |
|
26 |
36 |
from sphinx.theming import Theme |
37 |
from sphinx.builders.html import StandaloneHTMLBuilder |
|
38 |
from sphinx.util import relative_uri |
|
39 |
from sphinx.writers.html import HTMLTranslator |
|
27 |
40 |
|
28 |
# it's here only temporarily, until I get all the theming problems resolved |
|
41 |
||
29 |
42 |
tmp_template = """ |
30 |
<html> |
|
31 |
<head> |
|
32 |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
|
33 |
<link rel="stylesheet" href="_static/basic.css" type="text/css" /> |
|
34 |
<link rel="stylesheet" href="_static/pygments.css" type="text/css" /> |
|
35 |
<script type="text/javascript"> |
|
36 |
var DOCUMENTATION_OPTIONS = { |
|
37 |
URL_ROOT: '', |
|
38 |
VERSION: '0.5.2', |
|
39 |
COLLAPSE_MODINDEX: false, |
|
40 |
FILE_SUFFIX: '.html', |
|
41 |
HAS_SOURCE: true |
|
42 |
}; |
|
43 |
</script> |
|
44 |
<script type="text/javascript" src="_static/jquery.js"></script> |
|
45 |
<script type="text/javascript" src="_static/jquery.form.js"></script> |
|
46 |
<script type="text/javascript" src="_static/comments.js"></script> |
|
47 |
<script type="text/javascript" src="_static/doctools.js"></script> |
|
48 |
</head> |
|
49 |
<body> |
|
50 |
{{ body }} |
|
51 |
</body> |
|
52 |
</html> |
|
43 |
{%% extends "basic/layout.html" %%} |
|
44 |
{%% block body %%} %(body)s {%% endblock %%} |
|
53 |
45 |
""" |
54 |
46 |
|
47 |
||
55 |
48 |
def load_comments(db_path): |
56 |
49 |
"""Open a 'db_path' file, dejsonify the loaded data and return it. |
57 |
50 |
On error return empty list.""" |
| … | … | @@ -154,6 +147,63 @@ def get_sorted_by_thread(data): |
154 |
147 |
return comments_sorted |
155 |
148 |
|
156 |
149 |
|
150 |
class SinglefileHTMLBuilder(StandaloneHTMLBuilder, Sphinx): |
|
151 |
"""Render a file when requested using data from a pickled archive. |
|
152 |
Handle theming.""" |
|
153 |
def __init__(self, www_dir): |
|
154 |
self.outdir = www_dir |
|
155 |
||
156 |
try: |
|
157 |
w = open(path.join(self.outdir, 'globalcontext.pickle')) |
|
158 |
self.globalcontext = cPickle.load(w) |
|
159 |
w.close() |
|
160 |
except Exception, err: |
|
161 |
raise SphinxError(err) |
|
162 |
||
163 |
self.cwd = os.getcwd() |
|
164 |
self.srcdir = self.cwd |
|
165 |
self.confdir = self.cwd |
|
166 |
self.doctreedir = path.join(self.cwd, www_dir) |
|
167 |
||
168 |
self.env = None |
|
169 |
self.freshenv = None |
|
170 |
||
171 |
# self.config = {} |
|
172 |
# self.env = BuildEnvironment.frompickle(self.config, self.envdir) |
|
173 |
# self.config = self.env.config |
|
174 |
||
175 |
confdir = path.join(self.cwd, '../../') |
|
176 |
self.app = Sphinx(self.srcdir, confdir, '.', 'public', 'html', {}, None) |
|
177 |
self.info = self.app.info |
|
178 |
self.warn = self.app.warn |
|
179 |
self.config = self.app.config |
|
180 |
self.config.html_theme_path = 'themes/' + self.config.html_theme |
|
181 |
||
182 |
self.load_i18n() |
|
183 |
self.load_env() |
|
184 |
||
185 |
StandaloneHTMLBuilder.init(self) |
|
186 |
self.style = self.theme.get_confstr('theme', 'stylesheet') |
|
187 |
||
188 |
def render_file(self, filename, ctx): |
|
189 |
ctx.update(self.globalcontext.copy()) |
|
190 |
# current_page_name is backwards compatibility |
|
191 |
ctx['pagename'] = ctx['current_page_name'] = filename |
|
192 |
def pathto(otheruri, resource=False, |
|
193 |
baseuri=self.get_target_uri(filename)): |
|
194 |
if not resource: |
|
195 |
otheruri = self.get_target_uri(otheruri) |
|
196 |
return relative_uri(baseuri, otheruri) |
|
197 |
ctx['pathto'] = pathto |
|
198 |
ctx['hasdoc'] = lambda name: name in self.env.all_docs |
|
199 |
pgname = path.basename(filename).split('.')[0] |
|
200 |
ctx['customsidebar'] = self.config.html_sidebars.get(pgname) |
|
201 |
ctx['encoding'] = encoding = self.config.html_output_encoding |
|
202 |
ctx['toctree'] = lambda **kw: self._get_local_toctree(filename, **kw) |
|
203 |
ctx['style'] = self.style |
|
204 |
||
205 |
return self.templates.render_string(tmp_template % (ctx), ctx) |
|
206 |
||
157 |
207 |
class AppServer(object): |
158 |
208 |
"""This middleware is responsible for serving the docs (the docs are |
159 |
209 |
pickled files, so it has to load a file from a pickle) and for handling |
| … | … | @@ -165,6 +215,7 @@ class AppServer(object): |
165 |
215 |
self.www_dir = www_dir |
166 |
216 |
self.template_vals = {} |
167 |
217 |
|
218 |
self.htmlbuilder = SinglefileHTMLBuilder(self.www_dir) |
|
168 |
219 |
self.init_templates() |
169 |
220 |
|
170 |
221 |
# an argument for 'reverse' option of sorted function: |
| … | … | @@ -197,21 +248,7 @@ class AppServer(object): |
197 |
248 |
elif SW('/fixes/'): |
198 |
249 |
resp = self.doReadFixes(req, resp) |
199 |
250 |
elif req.path.endswith('.html'): |
200 |
file_path = self.constructPath(req) |
|
201 |
try: |
|
202 |
if file_path.endswith('.pkl'): |
|
203 |
file_contents = cPickle.loads(open(file_path).read())['body'] |
|
204 |
else: |
|
205 |
file_contents = open(file_path, 'rb').read() |
|
206 |
except: |
|
207 |
file_contents = '<html><body>doHTMLFile(): 404!</body></html>' |
|
208 |
||
209 |
resp.status = 200 |
|
210 |
resp.body = file_contents.encode('utf8') |
|
211 |
||
212 |
# Regular HTML file |
|
213 |
if req.path.endswith('.html'): |
|
214 |
|
|
251 |
resp = self.doHTMLFile(req, resp) |
|
215 |
252 |
else: |
216 |
253 |
return self.app(environ, start_response) |
217 |
254 |
|
| … | … | @@ -380,7 +417,21 @@ class AppServer(object): |
380 |
417 |
resp.content_type = 'text/html' |
381 |
418 |
resp.charset = 'utf8' |
382 |
419 |
|
383 |
|
|
420 |
file_path = self.constructPath(req) |
|
421 |
try: |
|
422 |
if file_path.endswith('.pkl'): |
|
423 |
file_contents = cPickle.loads(open(file_path).read()) |
|
424 |
else: |
|
425 |
file_contents = open(file_path, 'rb').read() |
|
426 |
resp.body = file_contents.encode('utf8') |
|
427 |
resp.status = 200 |
|
428 |
return resp |
|
429 |
except: |
|
430 |
file_contents = '<html><body>doHTMLFile(): 404!</body></html>' |
|
431 |
return resp |
|
432 |
||
433 |
resp.body = self.htmlbuilder.render_file(file_path, |
|
434 |
file_contents).encode('utf8') |
|
384 |
435 |
|
385 |
436 |
# html_code = unicode(file_contents, |
386 |
437 |
# locale.getpreferredencoding(), 'replace') |
| … | … | @@ -388,7 +439,8 @@ class AppServer(object): |
388 |
439 |
|
389 |
440 |
# self.render_openid(environ) |
390 |
441 |
# rendered = self.env.from_string(html_code).render(self.template_vals) |
391 |
|
|
442 |
#resp.body = rendered.encode('utf8') |
|
443 |
resp.status = 200 |
|
392 |
444 |
return resp |
393 |
445 |
|
394 |
446 |
