ext/rest.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Mon, 08 Feb 2010 12:05:56 +0100
changeset 4494 ccb7fce7297b
parent 4483 918fd9931cb7
child 4719 aaed3f813ef8
permissions -rw-r--r--
AdaptedList -> SameETypeList *NO BW COMPAT*, benefit from cw 3.6 releasing of folder,file and blog which use it to get update at the same time. CMHN and PEGASE will need update (but won't go to 3.6 without update, so seem fine).
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     1
"""rest publishing functions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     2
996
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
     3
contains some functions and setup of docutils for cubicweb. Provides the
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
     4
following ReST directives:
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
     5
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
     6
* `eid`, create link to entity in the repository by their eid
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
     7
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
     8
* `card`, create link to card entity in the repository by their wikiid
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
     9
  (proposing to create it when the refered card doesn't exist yet)
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
    10
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
    11
* `winclude`, reference to a web documentation file (in wdoc/ directories)
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
    12
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
    13
* `sourcecode` (if pygments is installed), source code colorization
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    14
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    15
:organization: Logilab
4212
ab6573088b4a update copyright: welcome 2010
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4118
diff changeset
    16
:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    17
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1643
diff changeset
    18
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    19
"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    20
__docformat__ = "restructuredtext en"
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    21
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    22
from cStringIO import StringIO
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    23
from itertools import chain
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    24
from logging import getLogger
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    25
from os.path import join
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    26
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    27
from docutils import statemachine, nodes, utils, io
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    28
from docutils.core import publish_string
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    29
from docutils.parsers.rst import Parser, states, directives
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    30
from docutils.parsers.rst.roles import register_canonical_role, set_classes
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    31
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2311
diff changeset
    32
from logilab.mtconverter import ESC_UCAR_TABLE, ESC_CAR_TABLE, xml_escape
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    33
2467
6983631f5d0d don't fail on unknown eid, simply issue a warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2312
diff changeset
    34
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
    35
from cubicweb.ext.html4zope import Writer
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    36
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    37
# We provide our own parser as an attempt to get rid of
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    38
# state machine reinstanciation
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    39
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    40
import re
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    41
# compile states.Body patterns
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    42
for k, v in states.Body.patterns.items():
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    43
    if isinstance(v, str):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    44
        states.Body.patterns[k] = re.compile(v)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    45
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    46
# register ReStructured Text mimetype / extensions
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    47
import mimetypes
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
mimetypes.add_type('text/rest', '.rest')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    49
mimetypes.add_type('text/rest', '.rst')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    50
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    51
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    52
LOGGER = getLogger('cubicweb.rest')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    53
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    54
def eid_reference_role(role, rawtext, text, lineno, inliner,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    55
                       options={}, content=[]):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    56
    try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    57
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    58
            eid_num, rest = text.split(u':', 1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    59
        except:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    60
            eid_num, rest = text, '#'+text
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    61
        eid_num = int(eid_num)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    62
        if eid_num < 0:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    63
            raise ValueError
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    64
    except ValueError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    65
        msg = inliner.reporter.error(
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    66
            'EID number must be a positive number; "%s" is invalid.'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    67
            % text, line=lineno)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    68
        prb = inliner.problematic(rawtext, rawtext, msg)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    69
        return [prb], [msg]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    70
    # Base URL mainly used by inliner.pep_reference; so this is correct:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    71
    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
    72
    try:
3418
7b49fa7e942d [api] use _cw, cw_row, cw_col, cw_rset etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2680
diff changeset
    73
        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
    74
    except UnknownEid:
6983631f5d0d don't fail on unknown eid, simply issue a warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2312
diff changeset
    75
        ref = '#'
3418
7b49fa7e942d [api] use _cw, cw_row, cw_col, cw_rset etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2680
diff changeset
    76
        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
    77
    else:
6983631f5d0d don't fail on unknown eid, simply issue a warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2312
diff changeset
    78
        ref = refedentity.absolute_url()
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    79
    set_classes(options)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    80
    return [nodes.reference(rawtext, utils.unescape(rest), refuri=ref,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    81
                            **options)], []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    82
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    83
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    84
def winclude_directive(name, arguments, options, content, lineno,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    85
                       content_offset, block_text, state, state_machine):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    86
    """Include a reST file as part of the content of this reST file.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    87
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    88
    same as standard include directive but using config.locate_doc_resource to
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    89
    get actual file to include.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    90
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    91
    Most part of this implementation is copied from `include` directive defined
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    92
    in `docutils.parsers.rst.directives.misc`
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    93
    """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    94
    context = state.document.settings.context
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    95
    source = state_machine.input_lines.source(
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    96
        lineno - state_machine.input_offset - 1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    97
    #source_dir = os.path.dirname(os.path.abspath(source))
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    98
    fid = arguments[0]
4334
dda74c345b06 3.6 api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    99
    for lang in chain((context._cw.lang, context.vreg.property_value('ui.language')),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   100
                      context.config.available_languages()):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   101
        rid = '%s_%s.rst' % (fid, lang)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   102
        resourcedir = context.config.locate_doc_file(rid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   103
        if resourcedir:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   104
            break
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   105
    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   106
        severe = state_machine.reporter.severe(
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   107
              'Problems with "%s" directive path:\nno resource matching %s.'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   108
              % (name, fid),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   109
              nodes.literal_block(block_text, block_text), line=lineno)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   110
        return [severe]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   111
    path = join(resourcedir, rid)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   112
    encoding = options.get('encoding', state.document.settings.input_encoding)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   113
    try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   114
        state.document.settings.record_dependencies.add(path)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   115
        include_file = io.FileInput(
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   116
            source_path=path, encoding=encoding,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   117
            error_handler=state.document.settings.input_encoding_error_handler,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   118
            handle_io_errors=None)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   119
    except IOError, error:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   120
        severe = state_machine.reporter.severe(
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   121
              'Problems with "%s" directive path:\n%s: %s.'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   122
              % (name, error.__class__.__name__, error),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   123
              nodes.literal_block(block_text, block_text), line=lineno)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   124
        return [severe]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   125
    try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   126
        include_text = include_file.read()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   127
    except UnicodeError, error:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   128
        severe = state_machine.reporter.severe(
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   129
              'Problem with "%s" directive:\n%s: %s'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   130
              % (name, error.__class__.__name__, error),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   131
              nodes.literal_block(block_text, block_text), line=lineno)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   132
        return [severe]
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   133
    if options.has_key('literal'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   134
        literal_block = nodes.literal_block(include_text, include_text,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   135
                                            source=path)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   136
        literal_block.line = 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   137
        return literal_block
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   138
    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   139
        include_lines = statemachine.string2lines(include_text,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   140
                                                  convert_whitespace=1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   141
        state_machine.insert_input(include_lines, path)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   142
        return []
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   143
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   144
winclude_directive.arguments = (1, 0, 1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   145
winclude_directive.options = {'literal': directives.flag,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   146
                              'encoding': directives.encoding}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   147
996
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   148
try:
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   149
    from pygments import highlight
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   150
    from pygments.lexers import get_lexer_by_name, LEXERS
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   151
    from pygments.formatters import HtmlFormatter
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   152
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
   153
    pygments_directive = None
996
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   154
else:
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   155
    _PYGMENTS_FORMATTER = HtmlFormatter()
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   156
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   157
    def pygments_directive(name, arguments, options, content, lineno,
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   158
                           content_offset, block_text, state, state_machine):
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   159
        try:
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   160
            lexer = get_lexer_by_name(arguments[0])
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   161
        except ValueError:
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   162
            # no lexer found
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   163
            lexer = get_lexer_by_name('text')
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   164
        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
   165
        # 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
   166
        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
   167
            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
   168
            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
   169
        except AttributeError:
918fd9931cb7 cleanup, don't fail if no context set on the sourcecode directive
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4334
diff changeset
   170
            # used outside cubicweb
918fd9931cb7 cleanup, don't fail if no context set on the sourcecode directive
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4334
diff changeset
   171
            pass
996
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   172
        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
   173
996
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   174
    pygments_directive.arguments = (1, 0, 1)
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   175
    pygments_directive.content = 1
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   176
9495a0594b95 sourcecode directive
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   177
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   178
class CubicWebReSTParser(Parser):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   179
    """The (customized) reStructuredText parser."""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   180
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
    def __init__(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   182
        self.initial_state = 'Body'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
        self.state_classes = states.state_classes
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
        self.inliner = states.Inliner()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
        self.statemachine = states.RSTStateMachine(
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
              state_classes=self.state_classes,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
              initial_state=self.initial_state,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   188
              debug=0)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   190
    def parse(self, inputstring, document):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   191
        """Parse `inputstring` and populate `document`, a document tree."""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   192
        self.setup_parse(inputstring, document)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   193
        inputlines = statemachine.string2lines(inputstring,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   194
                                               convert_whitespace=1)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   195
        self.statemachine.run(inputlines, document, inliner=self.inliner)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   196
        self.finish_parse()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   197
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   198
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   199
def rest_publish(context, data):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   200
    """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
   201
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   202
    :type context: a cubicweb application object
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   203
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   204
    :type data: str
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   205
    :param data: some ReST text
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   206
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   207
    :rtype: unicode
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   208
    :return:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   209
      the data formatted as HTML or the original data if an error occured
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   210
    """
3418
7b49fa7e942d [api] use _cw, cw_row, cw_col, cw_rset etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 2680
diff changeset
   211
    req = context._cw
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   212
    if isinstance(data, unicode):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   213
        encoding = 'unicode'
2311
f178182b1305 actually close #344401 by removing unprintable characters
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   214
        # 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
   215
        data = data.translate(ESC_UCAR_TABLE)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   216
    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   217
        encoding = req.encoding
2311
f178182b1305 actually close #344401 by removing unprintable characters
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   218
        # 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
   219
        data = data.translate(ESC_CAR_TABLE)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   220
    settings = {'input_encoding': encoding, 'output_encoding': 'unicode',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   221
                'warning_stream': StringIO(), 'context': context,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   222
                # dunno what's the max, severe is 4, and we never want a crash
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   223
                # (though try/except may be a better option...)
1447
a1ca676294f0 don't use a singleton rest parser which may leads to concurrency bugs
sylvain.thenault@logilab.fr
parents: 1323
diff changeset
   224
                'halt_level': 10,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   225
                }
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   226
    if context:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   227
        if hasattr(req, 'url'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   228
            base_url = req.url()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   229
        elif hasattr(context, 'absolute_url'):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   230
            base_url = context.absolute_url()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   231
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   232
            base_url = req.base_url()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   233
    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   234
        base_url = None
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   235
    try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   236
        return publish_string(writer=Writer(base_url=base_url),
1447
a1ca676294f0 don't use a singleton rest parser which may leads to concurrency bugs
sylvain.thenault@logilab.fr
parents: 1323
diff changeset
   237
                              parser=CubicWebReSTParser(), source=data,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   238
                              settings_overrides=settings)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   239
    except Exception:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   240
        LOGGER.exception('error while publishing ReST text')
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   241
        if not isinstance(data, unicode):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   242
            data = unicode(data, encoding, 'replace')
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2311
diff changeset
   243
        return xml_escape(req._('error while publishing ReST text')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   244
                           + '\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
   245
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
   246
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
   247
_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
   248
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
   249
    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
   250
    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
   251
        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
   252
    _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
   253
    register_canonical_role('eid', eid_reference_role)
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
   254
    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
   255
    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
   256
        directives.register_directive('sourcecode', pygments_directive)