author | Sylvain Thénault <sylvain.thenault@logilab.fr> |
Tue, 17 Jan 2012 14:04:56 +0100 | |
branch | stable |
changeset 8167 | 41ec579e27c4 |
parent 7879 | 9aae456abab5 |
child 8695 | 358d8bed9626 |
child 8710 | becbbbc840b8 |
permissions | -rw-r--r-- |
7815
2a164a9cf81c
[exceptions] stop catching any exception in various places (closes #1942716)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7732
diff
changeset
|
1 |
# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
5421
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4771
diff
changeset
|
2 |
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4771
diff
changeset
|
3 |
# |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4771
diff
changeset
|
4 |
# This file is part of CubicWeb. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4771
diff
changeset
|
5 |
# |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4771
diff
changeset
|
6 |
# CubicWeb is free software: you can redistribute it and/or modify it under the |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4771
diff
changeset
|
7 |
# terms of the GNU Lesser General Public License as published by the Free |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4771
diff
changeset
|
8 |
# Software Foundation, either version 2.1 of the License, or (at your option) |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4771
diff
changeset
|
9 |
# any later version. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4771
diff
changeset
|
10 |
# |
5424
8ecbcbff9777
replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5421
diff
changeset
|
11 |
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT |
5421
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4771
diff
changeset
|
12 |
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4771
diff
changeset
|
13 |
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4771
diff
changeset
|
14 |
# details. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4771
diff
changeset
|
15 |
# |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4771
diff
changeset
|
16 |
# You should have received a copy of the GNU Lesser General Public License along |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4771
diff
changeset
|
17 |
# with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
0 | 18 |
"""rest publishing functions |
19 |
||
996 | 20 |
contains some functions and setup of docutils for cubicweb. Provides the |
21 |
following ReST directives: |
|
22 |
||
23 |
* `eid`, create link to entity in the repository by their eid |
|
24 |
||
25 |
* `card`, create link to card entity in the repository by their wikiid |
|
26 |
(proposing to create it when the refered card doesn't exist yet) |
|
27 |
||
28 |
* `winclude`, reference to a web documentation file (in wdoc/ directories) |
|
29 |
||
30 |
* `sourcecode` (if pygments is installed), source code colorization |
|
0 | 31 |
|
32 |
""" |
|
33 |
__docformat__ = "restructuredtext en" |
|
34 |
||
35 |
from cStringIO import StringIO |
|
36 |
from itertools import chain |
|
37 |
from logging import getLogger |
|
38 |
from os.path import join |
|
39 |
||
40 |
from docutils import statemachine, nodes, utils, io |
|
4771
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
41 |
from docutils.core import Publisher |
0 | 42 |
from docutils.parsers.rst import Parser, states, directives |
43 |
from docutils.parsers.rst.roles import register_canonical_role, set_classes |
|
44 |
||
2312
af4d8f75c5db
use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2311
diff
changeset
|
45 |
from logilab.mtconverter import ESC_UCAR_TABLE, ESC_CAR_TABLE, xml_escape |
0 | 46 |
|
2467
6983631f5d0d
don't fail on unknown eid, simply issue a warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2312
diff
changeset
|
47 |
from cubicweb import UnknownEid |
704
0c2c8f0a6ded
new ext package for modules depending on an option third party package
sylvain.thenault@logilab.fr
parents:
0
diff
changeset
|
48 |
from cubicweb.ext.html4zope import Writer |
0 | 49 |
|
6938
6c1a960735f5
add a rql directive to restructuredtext
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6275
diff
changeset
|
50 |
from cubicweb.web.views import vid_from_rset # XXX better not to import c.w.views here... |
6c1a960735f5
add a rql directive to restructuredtext
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6275
diff
changeset
|
51 |
|
0 | 52 |
# We provide our own parser as an attempt to get rid of |
53 |
# state machine reinstanciation |
|
54 |
||
55 |
import re |
|
56 |
# compile states.Body patterns |
|
57 |
for k, v in states.Body.patterns.items(): |
|
58 |
if isinstance(v, str): |
|
59 |
states.Body.patterns[k] = re.compile(v) |
|
60 |
||
61 |
# register ReStructured Text mimetype / extensions |
|
62 |
import mimetypes |
|
63 |
mimetypes.add_type('text/rest', '.rest') |
|
64 |
mimetypes.add_type('text/rest', '.rst') |
|
65 |
||
66 |
||
67 |
LOGGER = getLogger('cubicweb.rest') |
|
68 |
||
69 |
def eid_reference_role(role, rawtext, text, lineno, inliner, |
|
70 |
options={}, content=[]): |
|
71 |
try: |
|
72 |
try: |
|
73 |
eid_num, rest = text.split(u':', 1) |
|
7815
2a164a9cf81c
[exceptions] stop catching any exception in various places (closes #1942716)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7732
diff
changeset
|
74 |
except ValueError: |
0 | 75 |
eid_num, rest = text, '#'+text |
76 |
eid_num = int(eid_num) |
|
77 |
if eid_num < 0: |
|
78 |
raise ValueError |
|
79 |
except ValueError: |
|
80 |
msg = inliner.reporter.error( |
|
81 |
'EID number must be a positive number; "%s" is invalid.' |
|
82 |
% text, line=lineno) |
|
83 |
prb = inliner.problematic(rawtext, rawtext, msg) |
|
84 |
return [prb], [msg] |
|
85 |
# Base URL mainly used by inliner.pep_reference; so this is correct: |
|
86 |
context = inliner.document.settings.context |
|
2467
6983631f5d0d
don't fail on unknown eid, simply issue a warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2312
diff
changeset
|
87 |
try: |
3418
7b49fa7e942d
[api] use _cw, cw_row, cw_col, cw_rset etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2680
diff
changeset
|
88 |
refedentity = context._cw.entity_from_eid(eid_num) |
2467
6983631f5d0d
don't fail on unknown eid, simply issue a warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2312
diff
changeset
|
89 |
except UnknownEid: |
6983631f5d0d
don't fail on unknown eid, simply issue a warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2312
diff
changeset
|
90 |
ref = '#' |
3418
7b49fa7e942d
[api] use _cw, cw_row, cw_col, cw_rset etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2680
diff
changeset
|
91 |
rest += u' ' + context._cw._('(UNEXISTANT EID)') |
2467
6983631f5d0d
don't fail on unknown eid, simply issue a warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2312
diff
changeset
|
92 |
else: |
6983631f5d0d
don't fail on unknown eid, simply issue a warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2312
diff
changeset
|
93 |
ref = refedentity.absolute_url() |
0 | 94 |
set_classes(options) |
95 |
return [nodes.reference(rawtext, utils.unescape(rest), refuri=ref, |
|
96 |
**options)], [] |
|
97 |
||
6938
6c1a960735f5
add a rql directive to restructuredtext
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6275
diff
changeset
|
98 |
def rql_role(role, rawtext, text, lineno, inliner, options={}, content=[]): |
6c1a960735f5
add a rql directive to restructuredtext
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6275
diff
changeset
|
99 |
""":rql:`Any X,Y WHERE X is CWUser, X login Y:table`""" |
6c1a960735f5
add a rql directive to restructuredtext
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6275
diff
changeset
|
100 |
_cw = inliner.document.settings.context._cw |
6c1a960735f5
add a rql directive to restructuredtext
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6275
diff
changeset
|
101 |
text = text.strip() |
6c1a960735f5
add a rql directive to restructuredtext
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6275
diff
changeset
|
102 |
if ':' in text: |
6c1a960735f5
add a rql directive to restructuredtext
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6275
diff
changeset
|
103 |
rql, vid = text.rsplit(u':', 1) |
6c1a960735f5
add a rql directive to restructuredtext
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6275
diff
changeset
|
104 |
rql = rql.strip() |
6c1a960735f5
add a rql directive to restructuredtext
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6275
diff
changeset
|
105 |
else: |
6c1a960735f5
add a rql directive to restructuredtext
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6275
diff
changeset
|
106 |
rql, vid = text, None |
6c1a960735f5
add a rql directive to restructuredtext
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6275
diff
changeset
|
107 |
_cw.ensure_ro_rql(rql) |
7732
5430d0db52ab
[web] rql directive breaks if explicit vid and empty rset (closes #1893433)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
7577
diff
changeset
|
108 |
try: |
5430d0db52ab
[web] rql directive breaks if explicit vid and empty rset (closes #1893433)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
7577
diff
changeset
|
109 |
rset = _cw.execute(rql, {'userid': _cw.user.eid}) |
5430d0db52ab
[web] rql directive breaks if explicit vid and empty rset (closes #1893433)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
7577
diff
changeset
|
110 |
if rset: |
5430d0db52ab
[web] rql directive breaks if explicit vid and empty rset (closes #1893433)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
7577
diff
changeset
|
111 |
if vid is None: |
5430d0db52ab
[web] rql directive breaks if explicit vid and empty rset (closes #1893433)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
7577
diff
changeset
|
112 |
vid = vid_from_rset(_cw, rset, _cw.vreg.schema) |
5430d0db52ab
[web] rql directive breaks if explicit vid and empty rset (closes #1893433)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
7577
diff
changeset
|
113 |
else: |
5430d0db52ab
[web] rql directive breaks if explicit vid and empty rset (closes #1893433)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
7577
diff
changeset
|
114 |
vid = 'noresult' |
5430d0db52ab
[web] rql directive breaks if explicit vid and empty rset (closes #1893433)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
7577
diff
changeset
|
115 |
view = _cw.vreg['views'].select(vid, _cw, rset=rset) |
5430d0db52ab
[web] rql directive breaks if explicit vid and empty rset (closes #1893433)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
7577
diff
changeset
|
116 |
content = view.render() |
5430d0db52ab
[web] rql directive breaks if explicit vid and empty rset (closes #1893433)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
7577
diff
changeset
|
117 |
except Exception, exc: |
5430d0db52ab
[web] rql directive breaks if explicit vid and empty rset (closes #1893433)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
7577
diff
changeset
|
118 |
content = 'an error occured while interpreting this rql directive: %r' % exc |
6938
6c1a960735f5
add a rql directive to restructuredtext
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6275
diff
changeset
|
119 |
set_classes(options) |
6c1a960735f5
add a rql directive to restructuredtext
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6275
diff
changeset
|
120 |
return [nodes.raw('', content, format='html')], [] |
0 | 121 |
|
122 |
def winclude_directive(name, arguments, options, content, lineno, |
|
123 |
content_offset, block_text, state, state_machine): |
|
124 |
"""Include a reST file as part of the content of this reST file. |
|
125 |
||
126 |
same as standard include directive but using config.locate_doc_resource to |
|
127 |
get actual file to include. |
|
128 |
||
129 |
Most part of this implementation is copied from `include` directive defined |
|
130 |
in `docutils.parsers.rst.directives.misc` |
|
131 |
""" |
|
132 |
context = state.document.settings.context |
|
4769
5b878b02b67b
[rest] cleanup, avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4719
diff
changeset
|
133 |
cw = context._cw |
0 | 134 |
source = state_machine.input_lines.source( |
135 |
lineno - state_machine.input_offset - 1) |
|
136 |
#source_dir = os.path.dirname(os.path.abspath(source)) |
|
137 |
fid = arguments[0] |
|
4769
5b878b02b67b
[rest] cleanup, avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4719
diff
changeset
|
138 |
for lang in chain((cw.lang, cw.vreg.property_value('ui.language')), |
5b878b02b67b
[rest] cleanup, avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4719
diff
changeset
|
139 |
cw.vreg.config.available_languages()): |
0 | 140 |
rid = '%s_%s.rst' % (fid, lang) |
4769
5b878b02b67b
[rest] cleanup, avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4719
diff
changeset
|
141 |
resourcedir = cw.vreg.config.locate_doc_file(rid) |
0 | 142 |
if resourcedir: |
143 |
break |
|
144 |
else: |
|
145 |
severe = state_machine.reporter.severe( |
|
146 |
'Problems with "%s" directive path:\nno resource matching %s.' |
|
147 |
% (name, fid), |
|
148 |
nodes.literal_block(block_text, block_text), line=lineno) |
|
149 |
return [severe] |
|
150 |
path = join(resourcedir, rid) |
|
151 |
encoding = options.get('encoding', state.document.settings.input_encoding) |
|
152 |
try: |
|
153 |
state.document.settings.record_dependencies.add(path) |
|
154 |
include_file = io.FileInput( |
|
155 |
source_path=path, encoding=encoding, |
|
156 |
error_handler=state.document.settings.input_encoding_error_handler, |
|
157 |
handle_io_errors=None) |
|
158 |
except IOError, error: |
|
159 |
severe = state_machine.reporter.severe( |
|
160 |
'Problems with "%s" directive path:\n%s: %s.' |
|
161 |
% (name, error.__class__.__name__, error), |
|
162 |
nodes.literal_block(block_text, block_text), line=lineno) |
|
163 |
return [severe] |
|
164 |
try: |
|
165 |
include_text = include_file.read() |
|
166 |
except UnicodeError, error: |
|
167 |
severe = state_machine.reporter.severe( |
|
168 |
'Problem with "%s" directive:\n%s: %s' |
|
169 |
% (name, error.__class__.__name__, error), |
|
170 |
nodes.literal_block(block_text, block_text), line=lineno) |
|
171 |
return [severe] |
|
172 |
if options.has_key('literal'): |
|
173 |
literal_block = nodes.literal_block(include_text, include_text, |
|
174 |
source=path) |
|
175 |
literal_block.line = 1 |
|
176 |
return literal_block |
|
177 |
else: |
|
178 |
include_lines = statemachine.string2lines(include_text, |
|
179 |
convert_whitespace=1) |
|
180 |
state_machine.insert_input(include_lines, path) |
|
181 |
return [] |
|
182 |
||
183 |
winclude_directive.arguments = (1, 0, 1) |
|
184 |
winclude_directive.options = {'literal': directives.flag, |
|
185 |
'encoding': directives.encoding} |
|
186 |
||
996 | 187 |
try: |
188 |
from pygments import highlight |
|
4719
aaed3f813ef8
kill dead/useless code as suggested by pylint
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4483
diff
changeset
|
189 |
from pygments.lexers import get_lexer_by_name |
7879
9aae456abab5
[pylint] fix pylint detected errors and tweak it so that pylint -E will be much less verbose next time (+ update some copyrights on the way)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7815
diff
changeset
|
190 |
from pygments.formatters.html import HtmlFormatter |
996 | 191 |
except ImportError: |
4118
8a9a00a9405c
quick and dirty fix trying to avoid rest directive conflicts when using sphinx (which seems to import the code)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2680
diff
changeset
|
192 |
pygments_directive = None |
996 | 193 |
else: |
194 |
_PYGMENTS_FORMATTER = HtmlFormatter() |
|
195 |
||
196 |
def pygments_directive(name, arguments, options, content, lineno, |
|
197 |
content_offset, block_text, state, state_machine): |
|
198 |
try: |
|
199 |
lexer = get_lexer_by_name(arguments[0]) |
|
200 |
except ValueError: |
|
201 |
# no lexer found |
|
202 |
lexer = get_lexer_by_name('text') |
|
203 |
parsed = highlight(u'\n'.join(content), lexer, _PYGMENTS_FORMATTER) |
|
4483
918fd9931cb7
cleanup, don't fail if no context set on the sourcecode directive
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4334
diff
changeset
|
204 |
# don't fail if no context set on the sourcecode directive |
918fd9931cb7
cleanup, don't fail if no context set on the sourcecode directive
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4334
diff
changeset
|
205 |
try: |
918fd9931cb7
cleanup, don't fail if no context set on the sourcecode directive
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4334
diff
changeset
|
206 |
context = state.document.settings.context |
918fd9931cb7
cleanup, don't fail if no context set on the sourcecode directive
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4334
diff
changeset
|
207 |
context._cw.add_css('pygments.css') |
918fd9931cb7
cleanup, don't fail if no context set on the sourcecode directive
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4334
diff
changeset
|
208 |
except AttributeError: |
7577
9892937d9041
[all] remove pattern "try: function() except AttributeError: pass" (closes #1787966)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6938
diff
changeset
|
209 |
# used outside cubicweb XXX use hasattr instead |
4483
918fd9931cb7
cleanup, don't fail if no context set on the sourcecode directive
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4334
diff
changeset
|
210 |
pass |
996 | 211 |
return [nodes.raw('', parsed, format='html')] |
1447
a1ca676294f0
don't use a singleton rest parser which may leads to concurrency bugs
sylvain.thenault@logilab.fr
parents:
1323
diff
changeset
|
212 |
|
996 | 213 |
pygments_directive.arguments = (1, 0, 1) |
214 |
pygments_directive.content = 1 |
|
215 |
||
216 |
||
0 | 217 |
class CubicWebReSTParser(Parser): |
218 |
"""The (customized) reStructuredText parser.""" |
|
219 |
||
220 |
def __init__(self): |
|
221 |
self.initial_state = 'Body' |
|
222 |
self.state_classes = states.state_classes |
|
223 |
self.inliner = states.Inliner() |
|
224 |
self.statemachine = states.RSTStateMachine( |
|
225 |
state_classes=self.state_classes, |
|
226 |
initial_state=self.initial_state, |
|
227 |
debug=0) |
|
228 |
||
229 |
def parse(self, inputstring, document): |
|
230 |
"""Parse `inputstring` and populate `document`, a document tree.""" |
|
231 |
self.setup_parse(inputstring, document) |
|
232 |
inputlines = statemachine.string2lines(inputstring, |
|
233 |
convert_whitespace=1) |
|
234 |
self.statemachine.run(inputlines, document, inliner=self.inliner) |
|
235 |
self.finish_parse() |
|
236 |
||
237 |
||
4771
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
238 |
# XXX docutils keep a ref on context, can't find a correct way to remove it |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
239 |
class CWReSTPublisher(Publisher): |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
240 |
def __init__(self, context, settings, **kwargs): |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
241 |
Publisher.__init__(self, **kwargs) |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
242 |
self.set_components('standalone', 'restructuredtext', 'pseudoxml') |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
243 |
self.process_programmatic_settings(None, settings, None) |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
244 |
self.settings.context = context |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
245 |
|
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
246 |
|
0 | 247 |
def rest_publish(context, data): |
248 |
"""publish a string formatted as ReStructured Text to HTML |
|
1447
a1ca676294f0
don't use a singleton rest parser which may leads to concurrency bugs
sylvain.thenault@logilab.fr
parents:
1323
diff
changeset
|
249 |
|
0 | 250 |
:type context: a cubicweb application object |
251 |
||
252 |
:type data: str |
|
253 |
:param data: some ReST text |
|
254 |
||
255 |
:rtype: unicode |
|
256 |
:return: |
|
6109
47d9c0e0f7b7
integrate Celso's work on translation file: proper/complete spanish translation, fixed some typos in french translation, occured -> occurred fix in various places
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5424
diff
changeset
|
257 |
the data formatted as HTML or the original data if an error occurred |
0 | 258 |
""" |
3418
7b49fa7e942d
[api] use _cw, cw_row, cw_col, cw_rset etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2680
diff
changeset
|
259 |
req = context._cw |
0 | 260 |
if isinstance(data, unicode): |
261 |
encoding = 'unicode' |
|
2311
f178182b1305
actually close #344401 by removing unprintable characters
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
262 |
# remove unprintable characters unauthorized in xml |
f178182b1305
actually close #344401 by removing unprintable characters
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
263 |
data = data.translate(ESC_UCAR_TABLE) |
0 | 264 |
else: |
265 |
encoding = req.encoding |
|
2311
f178182b1305
actually close #344401 by removing unprintable characters
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
266 |
# remove unprintable characters unauthorized in xml |
f178182b1305
actually close #344401 by removing unprintable characters
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
267 |
data = data.translate(ESC_CAR_TABLE) |
0 | 268 |
settings = {'input_encoding': encoding, 'output_encoding': 'unicode', |
4771
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
269 |
'warning_stream': StringIO(), |
6275
20f30e01ae59
[ReST] settings update: add traceback=True to avoid sys.exit, and set stylesheet to None since we don't care about it and that may makes docutils stupidly fail according to the cwd at import time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6109
diff
changeset
|
270 |
'traceback': True, # don't sys.exit |
20f30e01ae59
[ReST] settings update: add traceback=True to avoid sys.exit, and set stylesheet to None since we don't care about it and that may makes docutils stupidly fail according to the cwd at import time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6109
diff
changeset
|
271 |
'stylesheet': None, # don't try to embed stylesheet (may cause |
20f30e01ae59
[ReST] settings update: add traceback=True to avoid sys.exit, and set stylesheet to None since we don't care about it and that may makes docutils stupidly fail according to the cwd at import time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6109
diff
changeset
|
272 |
# obscure bug due to docutils computing |
20f30e01ae59
[ReST] settings update: add traceback=True to avoid sys.exit, and set stylesheet to None since we don't care about it and that may makes docutils stupidly fail according to the cwd at import time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6109
diff
changeset
|
273 |
# relative path according to the directory |
20f30e01ae59
[ReST] settings update: add traceback=True to avoid sys.exit, and set stylesheet to None since we don't care about it and that may makes docutils stupidly fail according to the cwd at import time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6109
diff
changeset
|
274 |
# used *at import time* |
0 | 275 |
# dunno what's the max, severe is 4, and we never want a crash |
6275
20f30e01ae59
[ReST] settings update: add traceback=True to avoid sys.exit, and set stylesheet to None since we don't care about it and that may makes docutils stupidly fail according to the cwd at import time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6109
diff
changeset
|
276 |
# (though try/except may be a better option...). May be the |
20f30e01ae59
[ReST] settings update: add traceback=True to avoid sys.exit, and set stylesheet to None since we don't care about it and that may makes docutils stupidly fail according to the cwd at import time...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6109
diff
changeset
|
277 |
# above traceback option will avoid this? |
1447
a1ca676294f0
don't use a singleton rest parser which may leads to concurrency bugs
sylvain.thenault@logilab.fr
parents:
1323
diff
changeset
|
278 |
'halt_level': 10, |
0 | 279 |
} |
280 |
if context: |
|
281 |
if hasattr(req, 'url'): |
|
282 |
base_url = req.url() |
|
283 |
elif hasattr(context, 'absolute_url'): |
|
284 |
base_url = context.absolute_url() |
|
285 |
else: |
|
286 |
base_url = req.base_url() |
|
287 |
else: |
|
288 |
base_url = None |
|
289 |
try: |
|
4771
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
290 |
pub = CWReSTPublisher(context, settings, |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
291 |
parser=CubicWebReSTParser(), |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
292 |
writer=Writer(base_url=base_url), |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
293 |
source_class=io.StringInput, |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
294 |
destination_class=io.StringOutput) |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
295 |
pub.set_source(data) |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
296 |
pub.set_destination() |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
297 |
res = pub.publish(enable_exit_status=None) |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
298 |
# necessary for proper garbage collection, else a ref is kept somewhere in docutils... |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
299 |
del pub.settings.context |
e27d23f875c6
custom rest publisher instead of using rest_publish. Avoid to keep a ref on the latest context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4769
diff
changeset
|
300 |
return res |
0 | 301 |
except Exception: |
302 |
LOGGER.exception('error while publishing ReST text') |
|
303 |
if not isinstance(data, unicode): |
|
304 |
data = unicode(data, encoding, 'replace') |
|
2312
af4d8f75c5db
use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2311
diff
changeset
|
305 |
return xml_escape(req._('error while publishing ReST text') |
0 | 306 |
+ '\n\n' + data) |
4118
8a9a00a9405c
quick and dirty fix trying to avoid rest directive conflicts when using sphinx (which seems to import the code)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2680
diff
changeset
|
307 |
|
8a9a00a9405c
quick and dirty fix trying to avoid rest directive conflicts when using sphinx (which seems to import the code)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2680
diff
changeset
|
308 |
|
8a9a00a9405c
quick and dirty fix trying to avoid rest directive conflicts when using sphinx (which seems to import the code)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2680
diff
changeset
|
309 |
_INITIALIZED = False |
8a9a00a9405c
quick and dirty fix trying to avoid rest directive conflicts when using sphinx (which seems to import the code)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2680
diff
changeset
|
310 |
def cw_rest_init(): |
8a9a00a9405c
quick and dirty fix trying to avoid rest directive conflicts when using sphinx (which seems to import the code)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2680
diff
changeset
|
311 |
global _INITIALIZED |
8a9a00a9405c
quick and dirty fix trying to avoid rest directive conflicts when using sphinx (which seems to import the code)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2680
diff
changeset
|
312 |
if _INITIALIZED: |
8a9a00a9405c
quick and dirty fix trying to avoid rest directive conflicts when using sphinx (which seems to import the code)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2680
diff
changeset
|
313 |
return |
8a9a00a9405c
quick and dirty fix trying to avoid rest directive conflicts when using sphinx (which seems to import the code)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2680
diff
changeset
|
314 |
_INITIALIZED = True |
8a9a00a9405c
quick and dirty fix trying to avoid rest directive conflicts when using sphinx (which seems to import the code)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2680
diff
changeset
|
315 |
register_canonical_role('eid', eid_reference_role) |
6938
6c1a960735f5
add a rql directive to restructuredtext
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6275
diff
changeset
|
316 |
register_canonical_role('rql', rql_role) |
4118
8a9a00a9405c
quick and dirty fix trying to avoid rest directive conflicts when using sphinx (which seems to import the code)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2680
diff
changeset
|
317 |
directives.register_directive('winclude', winclude_directive) |
8a9a00a9405c
quick and dirty fix trying to avoid rest directive conflicts when using sphinx (which seems to import the code)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2680
diff
changeset
|
318 |
if pygments_directive is not None: |
8a9a00a9405c
quick and dirty fix trying to avoid rest directive conflicts when using sphinx (which seems to import the code)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2680
diff
changeset
|
319 |
directives.register_directive('sourcecode', pygments_directive) |