Merge with 3.26
authorPhilippe Pepiot <philippe.pepiot@logilab.fr>
Thu, 28 Jun 2018 16:49:57 +0200
changeset 12338 b5533de552c4
parent 12328 b570d3094e32 (current diff)
parent 12337 04ff0d3ef1d3 (diff)
child 12341 921dfb88b115
Merge with 3.26
flake8-ok-files.txt
requirements/test-web.txt
--- a/cubicweb/ext/rest.py	Thu Jun 28 10:17:15 2018 +0200
+++ b/cubicweb/ext/rest.py	Thu Jun 28 16:49:57 2018 +0200
@@ -229,7 +229,7 @@
         include_file = io.FileInput(
             source_path=path, encoding=encoding,
             error_handler=state.document.settings.input_encoding_error_handler,
-            handle_io_errors=None)
+        )
     except IOError as error:
         severe = state_machine.reporter.severe(
               'Problems with "%s" directive path:\n%s: %s.'
@@ -404,7 +404,7 @@
     """
     req = context._cw
     if isinstance(data, text_type):
-        encoding = 'unicode'
+        encoding = 'utf-8'
         # remove unprintable characters unauthorized in xml
         data = data.translate(ESC_UCAR_TABLE)
     else:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cubicweb/web/test/unittest_views_wdoc.py	Thu Jun 28 16:49:57 2018 +0200
@@ -0,0 +1,17 @@
+from cubicweb.devtools import testlib
+
+
+class WdocViewsTC(testlib.CubicWebTC):
+
+    def test(self):
+        with self.admin_access.web_request(fid='main') as req:
+            page = req.view('wdoc')
+        self.assertIn(u'Site documentation', page)
+        # This part is renderend through rst extension (..winclude directive).
+        self.assertIn(u'This web application is based on the CubicWeb knowledge management system',
+                      page)
+
+
+if __name__ == '__main__':
+    import unittest
+    unittest.main()
--- a/cubicweb/web/views/wdoc.py	Thu Jun 28 10:17:15 2018 +0200
+++ b/cubicweb/web/views/wdoc.py	Thu Jun 28 16:49:57 2018 +0200
@@ -21,15 +21,14 @@
 """
 
 
+import io
 from itertools import chain
 from os.path import join
-from bisect import bisect_right
-from datetime import date
+from xml.etree.ElementTree import parse
 
-from logilab.common.changelog import ChangeLog
-from logilab.common.date import strptime, todate
+from six import text_type
+
 from logilab.common.registry import yes
-from logilab.mtconverter import CHARSET_DECL_RGX
 
 from cubicweb.predicates import match_form_params
 from cubicweb.view import StartupView
@@ -39,44 +38,38 @@
 
 # table of content management #################################################
 
-try:
-    from xml.etree.ElementTree import parse
-except ImportError:
-    from elementtree.ElementTree import parse
 
-def build_toc_index(node, index):
+def build_toc_index(node, parent, index):
     try:
         nodeidx = node.attrib['resource']
-        assert not nodeidx in index, nodeidx
-        index[nodeidx] = node
+        assert nodeidx not in index, nodeidx
+        index[nodeidx] = node, parent
     except KeyError:
         pass
     for child in node:
-        build_toc_index(child, index)
-        child.parent = node
+        build_toc_index(child, node, index)
+
 
 def get_insertion_point(section, index):
     if section.attrib.get('insertafter'):
-        snode = index[section.attrib['insertafter']]
-        node = snode.parent
-        idx = node.getchildren().index(snode) + 1
+        snode, node = index[section.attrib['insertafter']]
+        idx = list(node).index(snode) + 1
     elif section.attrib.get('insertbefore'):
-        snode = index[section.attrib['insertbefore']]
-        node = snode.parent
+        snode, node = index[section.attrib['insertbefore']]
         idx = node.getchildren().index(snode)
     elif 'appendto' in section.attrib:
-        node = index[section.attrib['appendto']]
+        node, _ = index[section.attrib['appendto']]
         idx = None
     else:
         node, idx = None, None
     return node, idx
 
+
 def build_toc(config):
     alltocfiles = reversed(tuple(config.locate_all_files('toc.xml')))
     maintoc = parse(next(alltocfiles)).getroot()
-    maintoc.parent = None
     index = {}
-    build_toc_index(maintoc, index)
+    build_toc_index(maintoc, None, index)
     # insert component documentation into the tree according to their toc.xml
     # file
     for fpath in alltocfiles:
@@ -89,25 +82,27 @@
                 node.append(section)
             else:
                 node.insert(idx, section)
-            section.parent = node
-            build_toc_index(section, index)
+            build_toc_index(section, node, index)
     return index
 
+
 def title_for_lang(node, lang):
     fallback_title = None
     for title in node.findall('title'):
         title_lang = title.attrib['{http://www.w3.org/XML/1998/namespace}lang']
         if title_lang == lang:
-            return unicode(title.text)
+            return text_type(title.text)
         if title_lang == 'en':
-            fallback_title = unicode(title.text)
+            fallback_title = text_type(title.text)
     return fallback_title
 
+
 def subsections(node):
     return [child for child in node if child.tag == 'section']
 
 # help views ##################################################################
 
+
 class InlineHelpView(StartupView):
     __select__ = match_form_params('fid')
     __regid__ = 'wdoc'
@@ -126,23 +121,21 @@
             raise NotFound
         self.tocindex = build_toc(vreg.config)
         try:
-            node = self.tocindex[fid]
+            node, parent = self.tocindex[fid]
         except KeyError:
-            node = None
+            node, parent = None, None
         else:
-            self.navigation_links(node)
+            self.navigation_links(node, parent)
             self.w(u'<div class="hr"></div>')
             self.w(u'<h1>%s</h1>' % (title_for_lang(node, self._cw.lang)))
-        data = open(join(resourcedir, rid)).read()
-        self.w(rest_publish(self, data))
+        with io.open(join(resourcedir, rid)) as f:
+            self.w(rest_publish(self, f.read()))
         if node is not None:
             self.subsections_links(node)
             self.w(u'<div class="hr"></div>')
-            self.navigation_links(node)
+            self.navigation_links(node, parent)
 
-    def navigation_links(self, node):
-        req = self._cw
-        parent = node.parent
+    def navigation_links(self, node, parent):
         if parent is None:
             return
         brothers = subsections(parent)
@@ -165,7 +158,7 @@
         self.w(u'<span class="%s">' % htmlclass)
         self.w(u'%s : ' % self._cw._(msgid))
         self.w(u'<a href="%s">%s</a>' % (
-            self._cw.build_url('doc/'+node.attrib['resource']),
+            self._cw.build_url('doc/' + node.attrib['resource']),
             title_for_lang(node, self._cw.lang)))
         self.w(u'</span>\n')
 
@@ -178,14 +171,13 @@
         self.w(u'<ul class="docsum">')
         for child in sub:
             self.w(u'<li><a href="%s">%s</a>' % (
-                self._cw.build_url('doc/'+child.attrib['resource']),
+                self._cw.build_url('doc/' + child.attrib['resource']),
                 title_for_lang(child, self._cw.lang)))
             self.subsections_links(child, False)
             self.w(u'</li>')
         self.w(u'</ul>\n')
 
 
-
 class InlineHelpImageView(StartupView):
     __regid__ = 'wdocimages'
     __select__ = match_form_params('fid')
@@ -203,8 +195,8 @@
                 break
         else:
             raise NotFound
-        self.w(open(join(resourcedir, rid)).read())
-
+        with io.open(join(resourcedir, rid)) as f:
+            self.w(f.read())
 
 
 class HelpAction(action.Action):
--- a/flake8-ok-files.txt	Thu Jun 28 10:17:15 2018 +0200
+++ b/flake8-ok-files.txt	Thu Jun 28 16:49:57 2018 +0200
@@ -126,6 +126,7 @@
 cubicweb/web/views/json.py
 cubicweb/web/views/searchrestriction.py
 cubicweb/web/views/staticcontrollers.py
+cubicweb/web/views/wdoc.py
 cubicweb/web/views/workflow.py
 cubicweb/web/views/uicfg.py
 cubicweb/web/webctl.py
--- a/requirements/test-web.txt	Thu Jun 28 10:17:15 2018 +0200
+++ b/requirements/test-web.txt	Thu Jun 28 16:49:57 2018 +0200
@@ -1,3 +1,4 @@
+docutils
 Twisted < 16.0.0
 requests
 webtest