# HG changeset patch # User Nicolas Chauvat # Date 1365090309 -7200 # Node ID 59a29405688c4f71fe5ecf19da7d5ab9ed672052 # Parent 0020aa12af07a45200041ac858a0becf8e2330c3 [ext/rest] add directive bookmark to rest (closes #2545595) diff -r 0020aa12af07 -r 59a29405688c doc/3.17.rst --- a/doc/3.17.rst Wed Apr 03 12:17:24 2013 +0200 +++ b/doc/3.17.rst Thu Apr 04 17:45:09 2013 +0200 @@ -10,6 +10,9 @@ * Add CubicWebRequestBase.content with the content of the HTTP request (see #2742453) (see `#2742453 `_) +* Add directive bookmark to ReST rendering + (see `#2545595 `_) + API changes ----------- diff -r 0020aa12af07 -r 59a29405688c doc/book/en/tutorials/index.rst --- a/doc/book/en/tutorials/index.rst Wed Apr 03 12:17:24 2013 +0200 +++ b/doc/book/en/tutorials/index.rst Thu Apr 04 17:45:09 2013 +0200 @@ -18,3 +18,4 @@ base/index advanced/index tools/windmill.rst + textreports/index diff -r 0020aa12af07 -r 59a29405688c doc/book/en/tutorials/textreports/index.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/tutorials/textreports/index.rst Thu Apr 04 17:45:09 2013 +0200 @@ -0,0 +1,13 @@ +.. -*- coding: utf-8 -*- + +Writing text reports with RestructuredText +========================================== + +|cubicweb| offers several text formats for the RichString type used in schemas, +including restructuredtext. + +Three additional restructuredtext roles are defined by |cubicweb|: + +.. autodocfunction:: cubicweb.ext.rest.eid_reference_role +.. autodocfunction:: cubicweb.ext.rest.rql_role +.. autodocfunction:: cubicweb.ext.rest.bookmark_role diff -r 0020aa12af07 -r 59a29405688c ext/rest.py --- a/ext/rest.py Wed Apr 03 12:17:24 2013 +0200 +++ b/ext/rest.py Thu Apr 04 17:45:09 2013 +0200 @@ -36,6 +36,7 @@ from itertools import chain from logging import getLogger from os.path import join +from urlparse import urlsplit from docutils import statemachine, nodes, utils, io from docutils.core import Publisher @@ -128,6 +129,63 @@ set_classes(options) return [nodes.raw('', content, format='html')], [] +def bookmark_role(role, rawtext, text, lineno, inliner, options={}, content=[]): + """:bookmark:`` or :bookmark:`:` + + Example: :bookmark:`1234:table` + + Replace the directive with the output of applying the view to the resultset + returned by the query stored in the bookmark. By default, the view is the one + stored in the bookmark, but it can be overridden by the directive as in the + example above. + + "X eid %(userid)s" can be used in the RQL query stored in the Bookmark, for + this query will be executed with the argument {'userid': _cw.user.eid}. + """ + _cw = inliner.document.settings.context._cw + text = text.strip() + try: + if ':' in text: + eid, vid = text.rsplit(u':', 1) + eid = int(eid) + else: + eid, vid = int(text), None + except ValueError: + msg = inliner.reporter.error( + 'EID number must be a positive number; "%s" is invalid.' + % text, line=lineno) + prb = inliner.problematic(rawtext, rawtext, msg) + return [prb], [msg] + try: + bookmark = _cw.entity_from_eid(eid) + except UnknownEid: + msg = inliner.reporter.error('Unknown EID %s.' % text, line=lineno) + prb = inliner.problematic(rawtext, rawtext, msg) + return [prb], [msg] + try: + params = dict(_cw.url_parse_qsl(urlsplit(bookmark.path).query)) + rql = params['rql'] + if vid is None: + vid = params.get('vid') + except (ValueError, KeyError), exc: + msg = inliner.reporter.error('Could not parse bookmark path %s [%s].' + % (bookmark.path, exc), line=lineno) + prb = inliner.problematic(rawtext, rawtext, msg) + return [prb], [msg] + try: + rset = _cw.execute(rql, {'userid': _cw.user.eid}) + if rset: + if vid is None: + vid = vid_from_rset(_cw, rset, _cw.vreg.schema) + else: + vid = 'noresult' + view = _cw.vreg['views'].select(vid, _cw, rset=rset) + content = view.render() + except Exception, exc: + content = 'An error occured while interpreting directive bookmark: %r' % exc + set_classes(options) + return [nodes.raw('', content, format='html')], [] + def winclude_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """Include a reST file as part of the content of this reST file. @@ -323,6 +381,7 @@ _INITIALIZED = True register_canonical_role('eid', eid_reference_role) register_canonical_role('rql', rql_role) + register_canonical_role('bookmark', bookmark_role) directives.register_directive('winclude', winclude_directive) if pygments_directive is not None: directives.register_directive('sourcecode', pygments_directive) diff -r 0020aa12af07 -r 59a29405688c ext/test/unittest_rest.py --- a/ext/test/unittest_rest.py Wed Apr 03 12:17:24 2013 +0200 +++ b/ext/test/unittest_rest.py Thu Apr 04 17:45:09 2013 +0200 @@ -75,5 +75,12 @@ out = rest_publish(context, ':rql:`Any X WHERE X is CWUser`') self.assertEqual(out, u'

CWUser_plural

\n') + def test_bookmark_role(self): + context = self.context() + rset = self.execute('INSERT Bookmark X: X title "hello", X path "/view?rql=Any X WHERE X is CWUser"') + eid = rset[0][0] + out = rest_publish(context, ':bookmark:`%s`' % eid) + self.assertEqual(out, u'

CWUser_plural

\n') + if __name__ == '__main__': unittest_main()