|
1 # -*- coding: utf-8 -*- |
|
2 """ |
|
3 sphinx._jinja |
|
4 ~~~~~~~~~~~~~ |
|
5 |
|
6 Jinja glue. |
|
7 |
|
8 :copyright: 2007-2008 by Georg Brandl, Horst Gutmann. |
|
9 :license: BSD. |
|
10 """ |
|
11 |
|
12 import codecs |
|
13 from os import path |
|
14 |
|
15 from sphinx.util import mtimes_of_files |
|
16 from sphinx.application import TemplateBridge |
|
17 |
|
18 from jinja import Environment |
|
19 from jinja.loaders import BaseLoader |
|
20 from jinja.exceptions import TemplateNotFound |
|
21 |
|
22 |
|
23 def babel_extract(fileobj, keywords, comment_tags, options): |
|
24 """ |
|
25 Simple extractor to get some basic Babel support. |
|
26 """ |
|
27 env = Environment() |
|
28 for lineno, sg, pl in env.get_translations_for_string(fileobj.read()): |
|
29 yield lineno, None, (sg, pl), '' |
|
30 |
|
31 |
|
32 class SphinxFileSystemLoader(BaseLoader): |
|
33 """ |
|
34 A loader that loads templates either relative to one of a list of given |
|
35 paths, or from an absolute path. |
|
36 """ |
|
37 |
|
38 def __init__(self, basepath, extpaths): |
|
39 self.basepath = path.abspath(basepath) |
|
40 self.extpaths = map(path.abspath, extpaths) |
|
41 self.searchpaths = self.extpaths + [self.basepath] |
|
42 |
|
43 def get_source(self, environment, name, parent): |
|
44 name = name.replace('/', path.sep) |
|
45 if name.startswith('!'): |
|
46 name = name[1:] |
|
47 if not path.exists(path.join(self.basepath, name)): |
|
48 raise TemplateNotFound(name) |
|
49 filename = path.join(self.basepath, name) |
|
50 elif path.isabs(name): |
|
51 if not path.exists(name): |
|
52 raise TemplateNotFound(name) |
|
53 filename = name |
|
54 else: |
|
55 for searchpath in self.searchpaths: |
|
56 if path.exists(path.join(searchpath, name)): |
|
57 filename = path.join(searchpath, name) |
|
58 break |
|
59 else: |
|
60 raise TemplateNotFound(name) |
|
61 f = codecs.open(filename, 'r', environment.template_charset) |
|
62 try: |
|
63 return f.read() |
|
64 finally: |
|
65 f.close() |
|
66 |
|
67 |
|
68 class TranslatorEnvironment(Environment): |
|
69 class _Translator(object): |
|
70 def __init__(self, translator): |
|
71 self.trans = translator |
|
72 |
|
73 def gettext(self, string): |
|
74 return self.trans.ugettext(string) |
|
75 |
|
76 def ngettext(self, singular, plural, n): |
|
77 return self.trans.ungettext(singular, plural, n) |
|
78 |
|
79 def __init__(self, *args, **kwargs): |
|
80 self.translator = kwargs['translator'] |
|
81 del kwargs['translator'] |
|
82 super(TranslatorEnvironment, self).__init__(*args, **kwargs) |
|
83 |
|
84 def get_translator(self, context): |
|
85 return TranslatorEnvironment._Translator(self.translator) |
|
86 |
|
87 |
|
88 class BuiltinTemplates(TemplateBridge): |
|
89 def init(self, builder): |
|
90 self.templates = {} |
|
91 base_templates_path = path.join(path.dirname(__file__), 'templates') |
|
92 ext_templates_path = [path.join(builder.confdir, dir) |
|
93 for dir in builder.config.templates_path] |
|
94 self.templates_path = [base_templates_path] + ext_templates_path |
|
95 loader = SphinxFileSystemLoader(base_templates_path, ext_templates_path) |
|
96 if builder.translator is not None: |
|
97 self.jinja_env = TranslatorEnvironment(loader=loader, |
|
98 friendly_traceback=False, translator=builder.translator) |
|
99 else: |
|
100 self.jinja_env = Environment(loader=loader, |
|
101 # disable traceback, more likely that something |
|
102 # in the application is broken than in the templates |
|
103 friendly_traceback=False) |
|
104 |
|
105 def newest_template_mtime(self): |
|
106 return max(mtimes_of_files(self.templates_path, '.html')) |
|
107 |
|
108 def render(self, template, context): |
|
109 if template in self.templates: |
|
110 return self.templates[template].render(context) |
|
111 templateobj = self.templates[template] = \ |
|
112 self.jinja_env.get_template(template) |
|
113 return templateobj.render(context) |