backport stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 11 Jun 2010 14:59:08 +0200
changeset 5736 375819ec7d43
parent 5728 12d3da7b3bcf (current diff)
parent 5735 548b8f99f758 (diff)
child 5738 74bd8123fb07
backport stable
__pkginfo__.py
entity.py
mail.py
req.py
selectors.py
server/repository.py
server/sources/native.py
web/application.py
--- a/.hgtags	Fri Jun 11 08:39:21 2010 +0200
+++ b/.hgtags	Fri Jun 11 14:59:08 2010 +0200
@@ -129,3 +129,5 @@
 2b962bb9eee8ee7156a12cf137428c292f8e3b35 cubicweb-debian-version-3.8.2-1
 7e6c6a2a272d0a95fd42248f3125e45185f0eef1 cubicweb-version-3.8.3
 1ccaa924786047be66b44f6dbc76e6631f56b04a cubicweb-debian-version-3.8.3-1
+d00d1fab42afec8607fc84d862becfd7f58850f1 cubicweb-version-3.8.4
+b7883287f40c853e8278edc3f24326f2c9549954 cubicweb-debian-version-3.8.4-1
--- a/__pkginfo__.py	Fri Jun 11 08:39:21 2010 +0200
+++ b/__pkginfo__.py	Fri Jun 11 14:59:08 2010 +0200
@@ -22,7 +22,7 @@
 
 modname = distname = "cubicweb"
 
-numversion = (3, 8, 3)
+numversion = (3, 8, 4)
 version = '.'.join(str(num) for num in numversion)
 
 description = "a repository of entities / relations for knowledge management"
--- a/debian/changelog	Fri Jun 11 08:39:21 2010 +0200
+++ b/debian/changelog	Fri Jun 11 14:59:08 2010 +0200
@@ -1,3 +1,9 @@
+cubicweb (3.8.4-1) unstable; urgency=low
+
+  * new upstream release
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr>  Fri, 11 Jun 2010 11:36:50 +0200
+
 cubicweb (3.8.3-1) unstable; urgency=low
 
   * new upstream release
--- a/req.py	Fri Jun 11 08:39:21 2010 +0200
+++ b/req.py	Fri Jun 11 14:59:08 2010 +0200
@@ -307,6 +307,8 @@
         try:
             view =  self.vreg[__registry].select(__vid, self, rset=rset, **initargs)
         except RegistryException:
+            if __fallback_oid is None:
+                raise
             view =  self.vreg[__registry].select(__fallback_oid, self,
                                                  rset=rset, **initargs)
         return view.render(w=w, **kwargs)
@@ -315,7 +317,7 @@
         """return a string for a date time according to instance's
         configuration
         """
-        if date:
+        if date is not None:
             if date_format is None:
                 if time:
                     date_format = self.property_value('ui.datetime-format')
@@ -328,7 +330,7 @@
         """return a string for a time according to instance's
         configuration
         """
-        if time:
+        if time is not None:
             return ustrftime(time, self.property_value('ui.time-format'))
         return u''
 
--- a/selectors.py	Fri Jun 11 08:39:21 2010 +0200
+++ b/selectors.py	Fri Jun 11 14:59:08 2010 +0200
@@ -759,7 +759,7 @@
 
     * `action`, a relation schema action (e.g. one of 'read', 'add', 'delete',
       default to 'read') which must be granted to the user, else a 0 score will
-      be returned
+      be returned. Give None if you don't want any permission checking.
 
     * `strict`, boolean (default to False) telling what to do when the user has
       not globally the permission for the action (eg the action is not granted
@@ -817,11 +817,11 @@
         if self.target_etype is not None:
             try:
                 rdef = rschema.role_rdef(eschema, self.target_etype, self.role)
-                if not rdef.may_have_permission(self.action, req):
+                if self.action and not rdef.may_have_permission(self.action, req):
                     return 0
             except KeyError:
                 return 0
-        else:
+        elif self.action:
             return rschema.may_have_permission(self.action, req, eschema, self.role)
         return 1
 
@@ -829,13 +829,14 @@
         rschema = self._get_rschema(entity)
         if rschema is None:
             return 0 # relation not supported
-        if self.target_etype is not None:
-            rschema = rschema.role_rdef(entity.e_schema, self.target_etype, self.role)
-        if self.role == 'subject':
-            if not rschema.has_perm(entity._cw, 'add', fromeid=entity.eid):
+        if self.action:
+            if self.target_etype is not None:
+                rschema = rschema.role_rdef(entity.e_schema, self.target_etype, self.role)
+            if self.role == 'subject':
+                if not rschema.has_perm(entity._cw, self.action, fromeid=entity.eid):
+                    return 0
+            elif not rschema.has_perm(entity._cw, self.action, toeid=entity.eid):
                 return 0
-        elif not rschema.has_perm(entity._cw, 'add', toeid=entity.eid):
-            return 0
         return 1
 
 
--- a/server/repository.py	Fri Jun 11 08:39:21 2010 +0200
+++ b/server/repository.py	Fri Jun 11 14:59:08 2010 +0200
@@ -92,7 +92,7 @@
                                 {'x': eidfrom, 'y': eidto})
     if card[1] in '1?':
         with security_enabled(session, read=False):
-            session.execute('DELETE X %sY WHERE Y eid %%(y)s, '
+            session.execute('DELETE X %s Y WHERE Y eid %%(y)s, '
                             'NOT X eid %%(x)s' % rtype,
                             {'x': eidfrom, 'y': eidto})
 
--- a/server/sources/native.py	Fri Jun 11 08:39:21 2010 +0200
+++ b/server/sources/native.py	Fri Jun 11 14:59:08 2010 +0200
@@ -744,7 +744,6 @@
 
 
     def create_eid(self, session):
-        self.debug('create eid')
         # lock needed to prevent 'Connection is busy with results for another command (0)' errors with SQLServer
         self._eid_creation_lock.acquire()
         try:
--- a/test/unittest_uilib.py	Fri Jun 11 08:39:21 2010 +0200
+++ b/test/unittest_uilib.py	Fri Jun 11 14:59:08 2010 +0200
@@ -94,6 +94,54 @@
             got = uilib.text_cut(text, 30)
             self.assertEquals(got, expected)
 
+    def test_soup2xhtml_1_1(self):
+        self.assertEquals(uilib.soup2xhtml('hop <div>', 'ascii'),
+                          'hop <div/>')
+        self.assertEquals(uilib.soup2xhtml('<div> hop', 'ascii'),
+                          '<div> hop</div>')
+        self.assertEquals(uilib.soup2xhtml('hop <div> hop', 'ascii'),
+                          'hop <div> hop</div>')
+
+    def test_soup2xhtml_1_2(self):
+        self.assertEquals(uilib.soup2xhtml('hop </div>', 'ascii'),
+                          'hop ')
+        self.assertEquals(uilib.soup2xhtml('</div> hop', 'ascii'),
+                          '<div/> hop')
+        self.assertEquals(uilib.soup2xhtml('hop </div> hop', 'ascii'),
+                          '<div>hop </div> hop')
+
+    def test_soup2xhtml_2_1(self):
+        self.assertEquals(uilib.soup2xhtml('hop <body>', 'ascii'),
+                          'hop ')
+        self.assertEquals(uilib.soup2xhtml('<body> hop', 'ascii'),
+                          ' hop')
+        self.assertEquals(uilib.soup2xhtml('hop <body> hop', 'ascii'),
+                          'hop  hop')
+
+    def test_soup2xhtml_2_2(self):
+        self.assertEquals(uilib.soup2xhtml('hop </body>', 'ascii'),
+                          'hop ')
+        self.assertEquals(uilib.soup2xhtml('</body> hop', 'ascii'),
+                          ' hop')
+        self.assertEquals(uilib.soup2xhtml('hop </body> hop', 'ascii'),
+                          'hop  hop')
+
+    def test_soup2xhtml_3_1(self):
+        self.assertEquals(uilib.soup2xhtml('hop <html>', 'ascii'),
+                          'hop ')
+        self.assertEquals(uilib.soup2xhtml('<html> hop', 'ascii'),
+                          ' hop')
+        self.assertEquals(uilib.soup2xhtml('hop <html> hop', 'ascii'),
+                          'hop  hop')
+
+    def test_soup2xhtml_3_2(self):
+        self.assertEquals(uilib.soup2xhtml('hop </html>', 'ascii'),
+                          'hop ')
+        self.assertEquals(uilib.soup2xhtml('</html> hop', 'ascii'),
+                          ' hop')
+        self.assertEquals(uilib.soup2xhtml('hop </html> hop', 'ascii'),
+                          'hop  hop')
+
 if __name__ == '__main__':
     unittest_main()
 
--- a/uilib.py	Fri Jun 11 08:39:21 2010 +0200
+++ b/uilib.py	Fri Jun 11 14:59:08 2010 +0200
@@ -18,9 +18,10 @@
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
 """user interface libraries
 
-contains some functions designed to help implementation of cubicweb user interface
+contains some functions designed to help implementation of cubicweb user
+interface.
+"""
 
-"""
 __docformat__ = "restructuredtext en"
 
 import csv
@@ -123,7 +124,7 @@
 
 fallback_safe_cut = safe_cut
 
-
+REM_ROOT_HTML_TAGS = re.compile('</(body|html)>', re.U)
 try:
     from lxml import etree
 except (ImportError, AttributeError):
@@ -133,12 +134,13 @@
 
     def soup2xhtml(data, encoding):
         """tidy (at least try) html soup and return the result
+
         Note: the function considers a string with no surrounding tag as valid
               if <div>`data`</div> can be parsed by an XML parser
         """
-        # normalize line break
-        # see http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7.1
-        data = u'\n'.join(data.splitlines())
+        # remove spurious </body> and </html> tags, then normalize line break
+        # (see http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7.1)
+        data = REM_ROOT_HTML_TAGS.sub('', u'\n'.join(data.splitlines()))
         # XXX lxml 1.1 support still needed ?
         xmltree = etree.HTML('<div>%s</div>' % data)
         # NOTE: lxml 1.1 (etch platforms) doesn't recognize
@@ -146,7 +148,13 @@
         #       why we specify an encoding and re-decode to unicode later
         body = etree.tostring(xmltree[0], encoding=encoding)
         # remove <body> and </body> and decode to unicode
-        return body[11:-13].decode(encoding)
+        snippet = body[6:-7].decode(encoding)
+        # take care to bad xhtml (for instance starting with </div>) which
+        # may mess with the <div> we added below. Only remove it if it's
+        # still there...
+        if snippet.startswith('<div>') and snippet.endswith('</div>'):
+            snippet = snippet[5:-6]
+        return snippet
 
     if hasattr(etree.HTML('<div>test</div>'), 'iter'):
 
--- a/web/application.py	Fri Jun 11 08:39:21 2010 +0200
+++ b/web/application.py	Fri Jun 11 14:59:08 2010 +0200
@@ -58,12 +58,11 @@
         assert self.cleanup_anon_session_time > 0
         self.authmanager = vreg['components'].select('authmanager', vreg=vreg)
         if vreg.config.anonymous_user() is not None:
-            self.clean_sessions_interval = min(
-                5 * 60,
-                self.cleanup_session_time / 2.,
-                self.cleanup_anon_session_time / 2.)
+            self.clean_sessions_interval = max(
+                5 * 60, min(self.cleanup_session_time / 2.,
+                            self.cleanup_anon_session_time / 2.))
         else:
-            self.clean_sessions_interval = min(
+            self.clean_sessions_interval = max(
                 5 * 60,
                 self.cleanup_session_time / 2.)
 
--- a/web/wdoc/ChangeLog_en	Fri Jun 11 08:39:21 2010 +0200
+++ b/web/wdoc/ChangeLog_en	Fri Jun 11 14:59:08 2010 +0200
@@ -6,6 +6,11 @@
 .. _OWL: http://www.w3.org/TR/owl-features/
 .. _pdfexport: http://www.cubicweb.org/project/cubicweb-pdfexport
 
+2010-06-11  --  3.8.4
+   * support full text prefix search for instances using postgres > 8.4 as database: try it
+     by using search such as 'cubic*'
+
+
 2010-04-20  --  3.8.0
    * nicer schema_ and workflow views (clickable image!)
 
--- a/web/wdoc/ChangeLog_fr	Fri Jun 11 08:39:21 2010 +0200
+++ b/web/wdoc/ChangeLog_fr	Fri Jun 11 14:59:08 2010 +0200
@@ -6,6 +6,10 @@
 .. _OWL: http://www.w3.org/TR/owl-features/
 .. _pdfexport: http://www.cubicweb.org/project/cubicweb-pdfexport
 
+2010-06-11  --  3.8.4
+   * support pour la recherche de préfixe pour les instances utilisant postgres > 8.4 :
+     essayez en cherchant par ex. 'cubic*'
+
 2010-04-20  --  3.8.0
 
    * amélioration des vues de schema_ et des vues de workflows