backport stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 23 Sep 2011 14:18:13 +0200
changeset 7845 2172978be237
parent 7841 287813c487b7 (current diff)
parent 7844 0208c65a88a5 (diff)
child 7846 dd3f0871d8b7
backport stable
devtools/testlib.py
entities/authobjs.py
hooks/test/unittest_syncschema.py
schemas/base.py
server/migractions.py
server/repository.py
server/session.py
test/unittest_rqlrewrite.py
web/test/unittest_viewselector.py
web/views/autoform.py
web/views/primary.py
web/views/schema.py
web/views/tableview.py
--- a/appobject.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/appobject.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -241,7 +241,7 @@
         for selector in selectors:
             try:
                 selector = _instantiate_selector(selector)
-            except:
+            except Exception:
                 pass
             #assert isinstance(selector, Selector), selector
             if isinstance(selector, cls):
--- a/cwconfig.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/cwconfig.py	Fri Sep 23 14:18:13 2011 +0200
@@ -144,7 +144,8 @@
 from threading import Lock
 from os.path import (exists, join, expanduser, abspath, normpath,
                      basename, isdir, dirname, splitext)
-from warnings import warn
+from warnings import warn, filterwarnings
+
 from logilab.common.decorators import cached, classproperty
 from logilab.common.deprecation import deprecated
 from logilab.common.logging_ext import set_log_methods, init_log
@@ -618,7 +619,7 @@
                 try:
                     __import__('cubes.%s.ccplugin' % cube)
                     cls.info('loaded cubicweb-ctl plugin from %s', cube)
-                except:
+                except Exception:
                     cls.exception('while loading plugin %s', pluginfile)
             elif exists(oldpluginfile):
                 warn('[3.6] %s: ecplugin module should be renamed to ccplugin' % cube,
@@ -626,12 +627,12 @@
                 try:
                     __import__('cubes.%s.ecplugin' % cube)
                     cls.info('loaded cubicweb-ctl plugin from %s', cube)
-                except:
+                except Exception:
                     cls.exception('while loading plugin %s', oldpluginfile)
             elif exists(initfile):
                 try:
                     __import__('cubes.%s' % cube)
-                except:
+                except Exception:
                     cls.exception('while loading cube %s', cube)
             else:
                 cls.warning('no __init__ file in cube %s', cube)
@@ -696,6 +697,9 @@
         return vregpath
 
     def __init__(self, debugmode=False):
+        if debugmode:
+            # in python 2.7, DeprecationWarning are not shown anymore by default
+            filterwarnings('default', category=DeprecationWarning)
         register_stored_procedures()
         self._cubes = None
         super(CubicWebNoAppConfiguration, self).__init__()
--- a/cwctl.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/cwctl.py	Fri Sep 23 14:18:13 2011 +0200
@@ -554,7 +554,7 @@
         pid = int(open(pidf).read().strip())
         try:
             kill(pid, signal.SIGTERM)
-        except:
+        except Exception:
             print >> sys.stderr, "process %s seems already dead." % pid
         else:
             try:
@@ -564,7 +564,7 @@
                 print >> sys.stderr, 'trying SIGKILL'
                 try:
                     kill(pid, signal.SIGKILL)
-                except:
+                except Exception:
                     # probably dead now
                     pass
                 wait_process_end(pid)
--- a/dataimport.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/dataimport.py	Fri Sep 23 14:18:13 2011 +0200
@@ -554,7 +554,7 @@
             self.tell("Run import function '%s'..." % func_name)
             try:
                 func(self)
-            except:
+            except Exception:
                 if self.catcherrors:
                     self.record_error(func_name, 'While calling %s' % func.__name__)
                 else:
--- a/dbapi.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/dbapi.py	Fri Sep 23 14:18:13 2011 +0200
@@ -301,7 +301,7 @@
     def set_default_language(self, vreg):
         try:
             self.lang = vreg.property_value('ui.language')
-        except: # property may not be registered
+        except Exception: # property may not be registered
             self.lang = 'en'
         # use req.__ to translate a message without registering it to the catalog
         try:
@@ -532,7 +532,7 @@
         if self._closed is None and self._close_on_del:
             try:
                 self.close()
-            except:
+            except Exception:
                 pass
 
     # connection initialization methods ########################################
--- a/devtools/__init__.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/devtools/__init__.py	Fri Sep 23 14:18:13 2011 +0200
@@ -577,7 +577,7 @@
                 templcursor.close()
                 cnx.close()
             init_repository(self.config, interactive=False)
-        except:
+        except BaseException:
             if self.dbcnx is not None:
                 self.dbcnx.rollback()
             print >> sys.stderr, 'building', self.dbname, 'failed'
@@ -752,13 +752,13 @@
                             value = value.rsplit('.', 1)[0]
                             try:
                                 row[cellindex] = strptime(value, '%Y-%m-%d %H:%M:%S')
-                            except:
+                            except Exception:
                                 row[cellindex] = strptime(value, '%Y-%m-%d')
                         if vtype == 'Time' and type(value) is unicode:
                             found_date = True
                             try:
                                 row[cellindex] = strptime(value, '%H:%M:%S')
-                            except:
+                            except Exception:
                                 # DateTime used as Time?
                                 row[cellindex] = strptime(value, '%Y-%m-%d %H:%M:%S')
                         if vtype == 'Interval' and type(value) is int:
--- a/devtools/fill.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/devtools/fill.py	Fri Sep 23 14:18:13 2011 +0200
@@ -352,7 +352,7 @@
         if objtype:
             rql += ', %s is %s' % (selectvar, objtype)
         rset = cursor.execute(rql)
-    except:
+    except Exception:
         print "could restrict eid_list with given constraints (%r)" % constraints
         return []
     return set(eid for eid, in rset.rows)
--- a/devtools/stresstester.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/devtools/stresstester.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -38,7 +38,7 @@
   -o / --report-output <filename>
      Write profiler report into <filename> rather than on stdout
 
-Copyright (c) 2003-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
+Copyright (c) 2003-2011 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
 http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 
@@ -73,9 +73,7 @@
                 start = clock()
                 try:
                     cursor.execute(query)
-                except KeyboardInterrupt:
-                    raise
-                except:
+                except Exception:
                     TB_LOCK.acquire()
                     traceback.print_exc()
                     TB_LOCK.release()
--- a/devtools/testlib.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/devtools/testlib.py	Fri Sep 23 14:18:13 2011 +0200
@@ -233,7 +233,7 @@
         # web resources
         try:
             config.global_set_option('embed-allowed', re.compile('.*'))
-        except: # not in server only configuration
+        except Exception: # not in server only configuration
             pass
 
     #XXX this doesn't need to a be classmethod anymore
@@ -787,15 +787,13 @@
         """
         try:
             output = viewfunc(**kwargs)
-        except (SystemExit, KeyboardInterrupt):
-            raise
-        except:
+        except Exception:
             # hijack exception: generative tests stop when the exception
             # is not an AssertionError
             klass, exc, tcbk = sys.exc_info()
             try:
                 msg = '[%s in %s] %s' % (klass, view.__regid__, exc)
-            except:
+            except Exception:
                 msg = '[%s in %s] undisplayable exception' % (klass, view.__regid__)
             raise AssertionError, msg, tcbk
         return self._check_html(output, view, template)
@@ -837,9 +835,7 @@
     def assertWellFormed(self, validator, content, context=None):
         try:
             return validator.parse_string(content)
-        except (SystemExit, KeyboardInterrupt):
-            raise
-        except:
+        except Exception:
             # hijack exception: generative tests stop when the exception
             # is not an AssertionError
             klass, exc, tcbk = sys.exc_info()
@@ -851,7 +847,7 @@
 
             try:
                 str_exc = str(exc)
-            except:
+            except Exception:
                 str_exc = 'undisplayable exception'
             msg += str_exc
             if content is not None:
@@ -1154,7 +1150,7 @@
         reg._selected = {}
         try:
             orig_select_best = reg.__class__.__orig_select_best
-        except:
+        except Exception:
             orig_select_best = reg.__class__._select_best
         def instr_select_best(self, *args, **kwargs):
             selected = orig_select_best(self, *args, **kwargs)
--- a/doc/book/en/admin/pyro.rst	Fri Sep 23 09:17:37 2011 +0200
+++ b/doc/book/en/admin/pyro.rst	Fri Sep 23 14:18:13 2011 +0200
@@ -1,14 +1,19 @@
 Working with a distributed client (using Pyro)
 ==============================================
 
+.. _UsingPyro:
+
 In some circumstances, it is practical to split the repository and
-web-client parts of the application, for load-balancing reasons. Or
+web-client parts of the application for load-balancing reasons. Or
 one wants to access the repository from independant scripts to consult
 or update the database.
 
+Prerequisites
+-------------
+
 For this to work, several steps have to be taken in order.
 
-You must first ensure that the apropriate software is installed and
+You must first ensure that the appropriate software is installed and
 running (see ref:`setup`)::
 
   pyro-nsd -x -p 6969
@@ -21,19 +26,40 @@
 
   pyro-instance-id=myinstancename
 
-Finally, the client (for instance in the case of a script) must
-connect specifically, as in the following example code:
+Connect to the CubicWeb repository from a python script
+-------------------------------------------------------
+
+Assuming pyro-nsd is running and your instance is configured with ``pyro-server=yes``,
+you will be able to use :mod:`cubicweb.dbapi` api to initiate the connection.
+
+.. note::
+    Regardless of whether your instance is pyro activated or not, you can still
+    achieve this by using cubicweb-ctl shell scripts in a simpler way, as by default
+    it creates a repository 'in-memory' instead of connecting through pyro. That
+    also means you've to be on the host where the instance is running.
+
+Finally, the client (for instance a python script) must connect specifically
+as in the following example code:
 
 .. sourcecode:: python
 
     from cubicweb import dbapi
 
-    def pyro_connect(instname, login, password, pyro_ns_host):
-        cnx = dbapi.connect(instname, login, password, pyro_ns_host)
-        cnx.load_appobjects()
-        return cnx
+    cnx = dbapi.connect(database='instance-id', user='admin', password='admin')
+    cnx.load_appobjects()
+    cur = cnx.cursor()
+    for name in (u'Personal', u'Professional', u'Computers'):
+        cur.execute('INSERT Tag T: T name %(n)s', {'n': name})
+    cnx.commit()
 
-The 'cnx.load_appobjects()' line is optional. Without it you will get
-data through the connection roughly as you would from a DBAPI
-connection. With it, provided the cubicweb-client part is installed
-and accessible, you get the ORM goodies.
+Calling :meth:`cubicweb.dbapi.load_appobjects`, will populates The `cubicweb
+registries`_ with the application objects installed on the host where the script
+runs. You'll then be allowed to use the ORM goodies and custom entity methods and
+views. Of course this is optional, without it you can still get the repository
+data through the connection but in a roughly way: only RQL cursors will be
+available, e.g. you can't even build entity objects from the result set.
+
+
+
+.. _cubicweb registries: VRegistryIntro_
+
--- a/doc/book/en/annexes/faq.rst	Fri Sep 23 09:17:37 2011 +0200
+++ b/doc/book/en/annexes/faq.rst	Fri Sep 23 14:18:13 2011 +0200
@@ -148,25 +148,12 @@
     to anonymous user, which will automatically execute what is
     decribed above.
 
-How to load data from a script ?
---------------------------------
-
-The following script aims at loading data within a script assuming pyro-nsd is
-running and your instance is configured with ``pyro-server=yes``, otherwise
-you would not be able to use dbapi.
-
-.. sourcecode:: python
+How to load data from a python script ?
+---------------------------------------
+Please, refer to the `Pyro chapter`_.
 
-    from cubicweb import dbapi
+.. _`Pyro chapter`: UsingPyro_
 
-    cnx = dbapi.connect(database='instance-id', user='admin', password='admin')
-    cur = cnx.cursor()
-    for name in (u'Personal', u'Professional', u'Computers'):
-        cur.execute('INSERT Tag T: T name %(n)s', {'n': name})
-    cnx.commit()
-
-Wether your instance as pyro activated or not, you can still acheive this by
-using cubicweb-ctl shell scripts.
 
 How to format an entity date attribute ?
 ----------------------------------------
--- a/doc/book/en/devweb/views/baseviews.rst	Fri Sep 23 09:17:37 2011 +0200
+++ b/doc/book/en/devweb/views/baseviews.rst	Fri Sep 23 14:18:13 2011 +0200
@@ -1,137 +1,17 @@
-.. -*- coding: utf-8 -*-
-
 Base views
 ----------
 
-*CubicWeb* provides a lot of standard views, that can be found in
+|cubicweb| provides a lot of standard views, that can be found in
 :mod:`cubicweb.web.views` sub-modules.
 
 A certain number of views are used to build the web interface, which apply to one
-or more entities. As other appobject, Their identifier is what distinguish them
+or more entities. As other appobjects, their identifier is what distinguish them
 from each others. The most generic ones, found in
 :mod:`cubicweb.web.views.baseviews`, are described below.
 
-HTML views
-~~~~~~~~~~
-
-Special views
-`````````````
-
-*noresult*
-    This view is the default view used when no result has been found
-    (e.g. empty result set).
-
-*final*
-    Display the value of a cell without trasnformation (in case of a non final
-    entity, we see the eid). Applicable on any result set.
-
-.. note::
-
-   `final` entities are merely attributes.
-
-*null*
-    This view is the default view used when nothing needs to be rendered.
-    It is always applicable.
-
-
-Entity views
-````````````
-
-*incontext, outofcontext*
-
-    Those are used to display a link to an entity, whose label depends on the
-    entity having to be displayed in or out of context (of another entity): some
-    entities make sense in the context of another entity. For instance, the
-    `Version` of a `Project` in forge. So one may expect that 'incontext' will
-    be called when display a version from within the context of a project, while
-    'outofcontext"' will be called in other cases. In our example, the
-    'incontext' view of the version would be something like '0.1.2', while the
-    'outofcontext' view would include the project name, e.g. 'baz 0.1.2' (since
-    only a version number without the associated project doesn't make sense if
-    you don't know yet that you're talking about the famous 'baz' project. |cubicweb|
-    tries to make guess and call 'incontext'/'outofcontext' nicely. When it can't
-    know, the 'oneline' view should be used.
-
-    By default it respectively produces the result of `textincontext` and
-    `textoutofcontext` wrapped in a link leading to the primary view of the
-    entity.
-
-
-*oneline*
-
-    This view is used when we can't tell if the entity should be considered as
-    displayed in or out of context. By default it produces the result of `text`
-    in a link leading to the primary view of the entity.
+You'll probably want to customize one or more of the described views which are
+default, generic, implementations.
 
 
-List
-`````
-
-*list*
-
-    This view displays a list of entities by creating a HTML list (`<ul>`) and
-    call the view `listitem` for each entity of the result set. The 'list' view
-    will generate html like:
-
-    .. sourcecode:: html
-
-      <ul class="section">
-        <li>"result of 'subvid' view for a row</li>
-        ...
-      </ul>
-
-
-*simplelist*
-
-  This view is not 'ul' based, and rely on div behaviour to separate items. html
-  will look like
-
-    .. sourcecode:: html
-
-      <div class="section">"result of 'subvid' view for a row</div>
-      ...
-
-
-  It relies on base :class:`~cubicweb.view.View` class implementation of the
-  :meth:`call` method to insert those <div>.
-
-
-*sameetypelist*
+.. automodule:: cubicweb.web.views.baseviews
 
-    This view displays a list of entities of the same type, in HTML section
-    (`<div>`) and call the view `sameetypelistitem` for each entity of the result
-    set. It's designed to get a more adapted global list when displayed entities
-    are all of the same type.
-
-
-*csv*
-
-    This view displays each entity in a coma separated list. It is NOT related to
-    the well-known text file format.
-
-
-Those list view can be given a 'subvid' arguments, telling the view to use of
-each item in the list. When not specified, the value of the 'redirect_vid'
-attribute of :class:`ListItemView` (for 'listview') or of :class:`SimpleListView`
-will be used. This default to 'outofcontext' for 'list' / 'incontext' for
-'simplelist'
-
-
-Text entity views
-~~~~~~~~~~~~~~~~~
-
-Basic html view have some variantsto be used when generating raw text, not html
-(for notifications for instance).
-
-*text*
-
-    This is the simplest text view for an entity. By default it returns the
-    result of the `.dc_title` method, which is cut to fit the
-    `navigation.short-line-size` property if necessary.
-
-*textincontext, textoutofcontext*
-
-    Similar to the `text` view, but called when an entity is considered out or in
-    context (see description of incontext/outofcontext html views for more
-    information on this). By default it returns respectively the result of the
-    methods `.dc_title()` and `.dc_long_title()` of the entity.
--- a/doc/book/en/devweb/views/primary.rst	Fri Sep 23 09:17:37 2011 +0200
+++ b/doc/book/en/devweb/views/primary.rst	Fri Sep 23 14:18:13 2011 +0200
@@ -10,11 +10,11 @@
 It is automatically selected on a one line result set containing an
 entity.
 
-This view is supposed to render a maximum of informations about the
+It lives in the :mod:`cubicweb.web.views.primary` module.
+
+The *primary* view is supposed to render a maximum of informations about the
 entity.
 
-It lives in the :mod:`cubicweb.web.views.primary` module.
-
 .. _primary_view_layout:
 
 Layout
@@ -139,8 +139,6 @@
 that can't be done using rql for instance.
 
 
-
-
 .. sourcecode:: python
 
    pv_section = uicfg.primaryview_section
@@ -163,62 +161,8 @@
    ``tag_subject_of``. To avoid warnings during execution, they should be set to
    ``'*'``.
 
-Rendering methods and attributes
-````````````````````````````````
 
-The basic layout of a primary view is as in the
-:ref:`primary_view_layout` section. This layout is actually drawn by
-the `render_entity` method.
-
-The methods you may want to modify while customizing a ``PrimaryView``
-are:
-
-*render_entity_title(self, entity)*
-    Renders the entity title, by default using entity's :meth:`dc_title()` method.
-
-*render_entity_attributes(self, entity)*
-    Renders all attributes and relations in the 'attributes' section . The
-    :attr:`skip_none` attribute controls the display of `None` valued attributes.
-
-*render_entity_relations(self, entity)*
-    Renders all relations in the 'relations' section.
-
-*render_side_boxes(self, entity, boxes)*
-    Renders side boxes on the right side of the content. This will generate a box
-    for each relation in the 'sidebox' section, as well as explicit box
-    appobjects selectable in this context.
-
-The placement of relations in the relations section or in side boxes
-can be controlled through the :ref:`primary_view_configuration` mechanism.
-
-*content_navigation_components(self, context)*
-    This method is applicable only for entity type implementing the interface
-    `IPrevNext`. This interface is for entities which can be linked to a previous
-    and/or next entity. This method will render the navigation links between
-    entities of this type, either at the top or at the bottom of the page
-    given the context (navcontent{top|bottom}).
-
-Also, please note that by setting the following attributes in your
-subclass, you can already customize some of the rendering:
-
-*show_attr_label*
-    Renders the attribute label next to the attribute value if set to `True`.
-    Otherwise, does only display the attribute value.
-
-*show_rel_label*
-    Renders the relation label next to the relation value if set to `True`.
-    Otherwise, does only display the relation value.
-
-*skip_none*
-    Does not render an attribute value that is None if set to `True`.
-
-*main_related_section*
-    Renders the relations of the entity if set to `True`.
-
-A good practice is for you to identify the content of your entity type for which
-the default rendering does not answer your need so that you can focus on the specific
-method (from the list above) that needs to be modified. We do not advise you to
-overwrite ``render_entity`` unless you want a completely different layout.
+.. automodule:: cubicweb.web.views.primary
 
 
 Example of customization and creation
@@ -329,3 +273,4 @@
 
 .. image:: ../../images/lax-book_10-blog-with-two-entries_en.png
    :alt: a blog and all its entries
+
--- a/doc/tools/pyjsrest.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/doc/tools/pyjsrest.py	Fri Sep 23 14:18:13 2011 +0200
@@ -102,7 +102,7 @@
     for fileid in INDEX_IN_ORDER:
         try:
             index.remove(fileid)
-        except:
+        except Exception:
             raise Exception(
         'Bad file id %s referenced in INDEX_IN_ORDER in %s, '
         'fix this please' % (fileid, __file__))
--- a/entities/adapters.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/entities/adapters.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2010-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -137,7 +137,7 @@
                 value = entity.printable_value(rschema, format='text/plain')
             except TransformError:
                 continue
-            except:
+            except Exception:
                 self.exception("can't add value of %s to text index for entity %s",
                                rschema, entity.eid)
                 continue
--- a/entities/authobjs.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/entities/authobjs.py	Fri Sep 23 14:18:13 2011 +0200
@@ -82,7 +82,7 @@
             prop = self._cw.execute(
                 'CWProperty X WHERE X pkey %(k)s, X for_user U, U eid %(u)s',
                 {'k': pkey, 'u': self.eid}).get_entity(0, 0)
-        except:
+        except Exception:
             kwargs = dict(pkey=unicode(pkey), value=value)
             if self.is_in_group('managers'):
                 kwargs['for_user'] = self
--- a/etwist/server.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/etwist/server.py	Fri Sep 23 14:18:13 2011 +0200
@@ -308,7 +308,7 @@
             # so we deferred that part to the cubicweb thread
             request.process_multipart()
             return self._render_request(request)
-        except:
+        except Exception:
             errorstream = StringIO()
             traceback.print_exc(file=errorstream)
             return HTTPResponse(stream='<pre>%s</pre>' % errorstream.getvalue(),
--- a/ext/rest.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/ext/rest.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -71,7 +71,7 @@
     try:
         try:
             eid_num, rest = text.split(u':', 1)
-        except:
+        except ValueError:
             eid_num, rest = text, '#'+text
         eid_num = int(eid_num)
         if eid_num < 0:
--- a/hooks/notification.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/hooks/notification.py	Fri Sep 23 14:18:13 2011 +0200
@@ -191,7 +191,7 @@
     def _call(self):
         try:
             title = self.entity.dc_title()
-        except:
+        except Exception:
             # may raise an error during deletion process, for instance due to
             # missing required relation
             title = '#%s' % self.entity.eid
--- a/hooks/syncschema.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/hooks/syncschema.py	Fri Sep 23 14:18:13 2011 +0200
@@ -87,7 +87,7 @@
         session.system_sql(str('ALTER TABLE %s ADD %s integer'
                                % (table, column)), rollback_on_failure=False)
         session.info('added column %s to table %s', column, table)
-    except:
+    except Exception:
         # silent exception here, if this error has not been raised because the
         # column already exists, index creation will fail anyway
         session.exception('error while adding column %s to table %s',
@@ -221,8 +221,8 @@
             cwuser_cls = self.session.vreg['etypes'].etype_class('CWUser')
             for session in repo._sessions.values():
                 session.user.__class__ = cwuser_cls
-        except:
-            self.critical('error while setting schmea', exc_info=True)
+        except Exception:
+            self.critical('error while setting schema', exc_info=True)
 
     def rollback_event(self):
         self.precommit_event()
--- a/hooks/test/unittest_syncschema.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/hooks/test/unittest_syncschema.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -182,7 +182,7 @@
             self.assertFalse(self.index_exists('State', 'state_of'))
             rset = self.execute('Any X, Y WHERE X state_of Y')
             self.assertEqual(len(rset), 2) # user states
-        except:
+        except Exception:
             import traceback
             traceback.print_exc()
         finally:
--- a/mail.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/mail.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -67,7 +67,7 @@
         values = b64decode(str(values + '='*padding), '.-')
         values = dict(v.split('=') for v in values.split('&'))
         fromappid, host = qualif.split('.', 1)
-    except:
+    except Exception:
         return None
     if appid != fromappid or host != gethostname():
         return None
--- a/migration.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/migration.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -488,7 +488,7 @@
                     try:
                         oper, version = constraint.split()
                         self.reverse_dependencies[name].add( (oper, version, cube) )
-                    except:
+                    except Exception:
                         self.warnings.append(
                             'cube %s depends on %s but constraint badly '
                             'formatted: %s' % (cube, name, constraint))
--- a/misc/cwdesklets/rqlsensor/__init__.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/misc/cwdesklets/rqlsensor/__init__.py	Fri Sep 23 14:18:13 2011 +0200
@@ -15,9 +15,6 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
 import webbrowser
 reload(webbrowser)
 
@@ -89,7 +86,7 @@
         cursor = cnx.cursor()
         try:
             rset = cursor.execute(rql)
-        except:
+        except Exception:
             del self._v_cnx
             raise
         self._urls = []
@@ -101,7 +98,7 @@
             output.set('resultbg[%s]' % i, 'black')
             try:
                 self._urls.append(base % 'Any X WHERE X eid %s' % line[0])
-            except:
+            except Exception:
                 self._urls.append('')
             i += 1
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/migration/3.13.6_Any.py	Fri Sep 23 14:18:13 2011 +0200
@@ -0,0 +1,1 @@
+sync_schema_props_perms('CWSourceSchemaConfig')
--- a/req.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/req.py	Fri Sep 23 14:18:13 2011 +0200
@@ -66,7 +66,7 @@
         self.vreg = vreg
         try:
             encoding = vreg.property_value('ui.encoding')
-        except: # no vreg or property not registered
+        except Exception: # no vreg or property not registered
             encoding = 'utf-8'
         self.encoding = encoding
         # cache result of execution for (rql expr / eids),
--- a/rqlrewrite.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/rqlrewrite.py	Fri Sep 23 14:18:13 2011 +0200
@@ -337,43 +337,58 @@
         """introduce the given snippet in a subquery"""
         subselect = stmts.Select()
         snippetrqlst = n.Exists(transformedsnippet.copy(subselect))
+        get_rschema = self.schema.rschema
         aliases = []
-        rels_done = set()
-        for i, (selectvar, snippetvar) in enumerate(varmap):
+        done = set()
+        for i, (selectvar, _) in enumerate(varmap):
+            need_null_test = False
             subselectvar = subselect.get_variable(selectvar)
             subselect.append_selected(n.VariableRef(subselectvar))
             aliases.append(selectvar)
-            vi = self.varinfos[i]
-            need_null_test = False
-            stinfo = vi['stinfo']
-            for rel in stinfo['relations']:
-                if rel in rels_done:
-                    continue
-                rels_done.add(rel)
-                rschema = self.schema.rschema(rel.r_type)
-                if rschema.final or (rschema.inlined and
-                                     not rel in stinfo['rhsrelations']):
-                    rel.children[0].name = selectvar # XXX explain why
-                    subselect.add_restriction(rel.copy(subselect))
-                    for vref in rel.children[1].iget_nodes(n.VariableRef):
-                        if isinstance(vref.variable, n.ColumnAlias):
-                            # XXX could probably be handled by generating the
-                            # subquery into the detected subquery
-                            raise BadSchemaDefinition(
-                                "cant insert security because of usage two inlined "
-                                "relations in this query. You should probably at "
-                                "least uninline %s" % rel.r_type)
-                        subselect.append_selected(vref.copy(subselect))
-                        aliases.append(vref.name)
-                    self.select.remove_node(rel)
-                    # when some inlined relation has to be copied in the
-                    # subquery, we need to test that either value is NULL or
-                    # that the snippet condition is satisfied
-                    if rschema.inlined and rel.optional:
-                        need_null_test = True
+            todo = [(selectvar, self.varinfos[i]['stinfo'])]
+            while todo:
+                varname, stinfo = todo.pop()
+                done.add(varname)
+                for rel in stinfo['relations'] - stinfo['rhsrelations']:
+                    if rel in done:
+                        continue
+                    done.add(rel)
+                    rschema = get_rschema(rel.r_type)
+                    if rschema.final or rschema.inlined:
+                        rel.children[0].name = varname # XXX explain why
+                        subselect.add_restriction(rel.copy(subselect))
+                        for vref in rel.children[1].iget_nodes(n.VariableRef):
+                            if isinstance(vref.variable, n.ColumnAlias):
+                                # XXX could probably be handled by generating the
+                                # subquery into the detected subquery
+                                raise BadSchemaDefinition(
+                                    "cant insert security because of usage two inlined "
+                                    "relations in this query. You should probably at "
+                                    "least uninline %s" % rel.r_type)
+                            subselect.append_selected(vref.copy(subselect))
+                            aliases.append(vref.name)
+                        self.select.remove_node(rel)
+                        # when some inlined relation has to be copied in the
+                        # subquery and that relation is optional, we need to
+                        # test that either value is NULL or that the snippet
+                        # condition is satisfied
+                        if varname == selectvar and rel.optional and rschema.inlined:
+                            need_null_test = True
+                        # also, if some attributes or inlined relation of the
+                        # object variable are accessed, we need to get all those
+                        # from the subquery as well
+                        if vref.name not in done and rschema.inlined:
+                            # we can use vref here define in above for loop
+                            ostinfo = vref.variable.stinfo
+                            for orel in ostinfo['relations'] - ostinfo['rhsrelations']:
+                                orschema = get_rschema(orel.r_type)
+                                if orschema.final or orschema.inlined:
+                                    todo.append( (vref.name, ostinfo) )
+                                    break
             if need_null_test:
                 snippetrqlst = n.Or(
-                    n.make_relation(subselectvar, 'is', (None, None), n.Constant,
+                    n.make_relation(subselect.get_variable(selectvar), 'is',
+                                    (None, None), n.Constant,
                                     operator='='),
                     snippetrqlst)
         subselect.add_restriction(snippetrqlst)
--- a/schemas/base.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/schemas/base.py	Fri Sep 23 14:18:13 2011 +0200
@@ -306,7 +306,6 @@
 
 class CWSourceSchemaConfig(EntityType):
     __permissions__ = ENTITY_MANAGERS_PERMISSIONS
-    __unique_together__ = [('cw_for_source', 'cw_schema')]
     cw_for_source = SubjectRelation(
         'CWSource', inlined=True, cardinality='1*', composite='object',
         __permissions__=RELATION_MANAGERS_PERMISSIONS)
--- a/server/checkintegrity.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/server/checkintegrity.py	Fri Sep 23 14:18:13 2011 +0200
@@ -47,7 +47,7 @@
     sqlcursor.execute('SELECT type, source FROM entities WHERE eid=%s' % eid)
     try:
         etype, source = sqlcursor.fetchone()
-    except:
+    except Exception:
         eids[eid] = False
         return False
     if source and source != 'system':
@@ -58,7 +58,7 @@
                                {'x': eid}):
                 eids[eid] = True
                 return True
-        except: # TypeResolverError, Unauthorized...
+        except Exception: # TypeResolverError, Unauthorized...
             pass
         eids[eid] = False
         return False
--- a/server/migractions.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/server/migractions.py	Fri Sep 23 14:18:13 2011 +0200
@@ -161,7 +161,7 @@
                   migrscript, funcname, *args, **kwargs)
         except ExecutionError, err:
             print >> sys.stderr, "-> %s" % err
-        except:
+        except BaseException:
             self.rollback()
             raise
 
@@ -1374,7 +1374,7 @@
             prop = self.rqlexec(
                 'CWProperty X WHERE X pkey %(k)s, NOT X for_user U',
                 {'k': pkey}, ask_confirm=False).get_entity(0, 0)
-        except:
+        except Exception:
             self.cmd_create_entity('CWProperty', pkey=unicode(pkey), value=value)
         else:
             prop.set_attributes(value=value)
@@ -1492,14 +1492,14 @@
         if not ask_confirm or self.confirm('Execute sql: %s ?' % sql):
             try:
                 cu = self.session.system_sql(sql, args)
-            except:
+            except Exception:
                 ex = sys.exc_info()[1]
                 if self.confirm('Error: %s\nabort?' % ex, pdb=True):
                     raise
                 return
             try:
                 return cu.fetchall()
-            except:
+            except Exception:
                 # no result to fetch
                 return
 
--- a/server/msplanner.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/server/msplanner.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1640,7 +1640,7 @@
         self._pending_vrefs = []
         try:
             res = self.visit_default(node, newroot, terms)[0]
-        except:
+        except Exception:
             # when a relation isn't supported, we should dereference potentially
             # introduced variable refs
             for vref in self._pending_vrefs:
--- a/server/pool.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/server/pool.py	Fri Sep 23 14:18:13 2011 +0200
@@ -73,7 +73,7 @@
             # catch exceptions, rollback other sources anyway
             try:
                 cnx.rollback()
-            except:
+            except Exception:
                 source.critical('rollback error', exc_info=sys.exc_info())
                 # error on rollback, the connection is much probably in a really
                 # bad state. Replace it by a new one.
@@ -86,12 +86,12 @@
         for cu in self._cursors.values():
             try:
                 cu.close()
-            except:
+            except Exception:
                 continue
         for _, cnx in self.source_cnxs.values():
             try:
                 cnx.close()
-            except:
+            except Exception:
                 continue
 
     # internals ###############################################################
@@ -135,7 +135,7 @@
             try:
                 # properly close existing connection if any
                 self.source_cnxs[source.uri][1].close()
-            except:
+            except Exception:
                 pass
             source.info('trying to reconnect')
             self.source_cnxs[source.uri] = (source, source.get_connection())
--- a/server/repository.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/server/repository.py	Fri Sep 23 14:18:13 2011 +0200
@@ -343,7 +343,7 @@
             self.looping_task(cleanup_session_interval, self.clean_sessions)
         assert isinstance(self._looping_tasks, list), 'already started'
         for i, (interval, func, args) in enumerate(self._looping_tasks):
-            self._looping_tasks[i] = task = utils.LoopTask(interval, func, args)
+            self._looping_tasks[i] = task = utils.LoopTask(self, interval, func, args)
             self.info('starting task %s with interval %.2fs', task.name,
                       interval)
             task.start()
@@ -412,7 +412,7 @@
             cnxset = self._cnxsets_pool.get_nowait()
             try:
                 cnxset.close(True)
-            except:
+            except Exception:
                 self.exception('error while closing %s' % cnxset)
                 continue
         if self.pyro_registered:
@@ -791,7 +791,7 @@
             return session.commit()
         except (ValidationError, Unauthorized):
             raise
-        except:
+        except Exception:
             self.exception('unexpected error')
             raise
 
@@ -802,7 +802,7 @@
             session = self._get_session(sessionid)
             session.set_tx_data(txid)
             session.rollback()
-        except:
+        except Exception:
             self.exception('unexpected error')
             raise
 
@@ -905,7 +905,7 @@
         for sessionid in self._sessions.keys():
             try:
                 self.close(sessionid, checkshuttingdown=False)
-            except:
+            except Exception: # XXX BaseException?
                 self.exception('error while closing session %s' % sessionid)
 
     def clean_sessions(self):
--- a/server/schemaserial.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/server/schemaserial.py	Fri Sep 23 14:18:13 2011 +0200
@@ -135,7 +135,7 @@
             try:
                 sqlexec('UPDATE deleted_entities SET type=%(n)s WHERE type=%(x)s',
                         {'x': etype, 'n': netype})
-            except:
+            except Exception:
                 pass
             tocleanup = [eid]
             tocleanup += (eid for eid, cached in repo._type_source_cache.iteritems()
--- a/server/serverctl.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/server/serverctl.py	Fri Sep 23 14:18:13 2011 +0200
@@ -248,7 +248,7 @@
                         cursor.execute, 'DROP USER %s' % user) is not ERROR:
                         print '-> user %s dropped.' % user
                 cnx.commit()
-            except:
+            except BaseException:
                 cnx.rollback()
                 raise
 
@@ -363,7 +363,7 @@
                 createdb(helper, source, dbcnx, cursor)
                 dbcnx.commit()
                 print '-> database %s created.' % dbname
-            except:
+            except BaseException:
                 dbcnx.rollback()
                 raise
         cnx = system_source_cnx(source, special_privs='CREATE LANGUAGE',
--- a/server/session.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/server/session.py	Fri Sep 23 14:18:13 2011 +0200
@@ -574,7 +574,7 @@
             return self.DEFAULT_SECURITY
         try:
             return txstore.write_security
-        except:
+        except AttributeError:
             txstore.write_security = self.DEFAULT_SECURITY
             return txstore.write_security
 
@@ -776,7 +776,7 @@
                 self._threaddata.ctx_count += 1
                 try:
                     cnxset.cnxset_set()
-                except:
+                except Exception:
                     self._threaddata.cnxset = None
                     self.repo._free_cnxset(cnxset)
                     raise
@@ -970,7 +970,7 @@
                         operation.handle_event('precommit_event')
                     self.pending_operations[:] = processed
                     self.debug('precommit session %s done', self.id)
-                except:
+                except BaseException:
                     # if error on [pre]commit:
                     #
                     # * set .failed = True on the operation causing the failure
@@ -985,7 +985,7 @@
                     for operation in reversed(processed):
                         try:
                             operation.handle_event('revertprecommit_event')
-                        except:
+                        except BaseException:
                             self.critical('error while reverting precommit',
                                           exc_info=True)
                     # XXX use slice notation since self.pending_operations is a
@@ -1000,7 +1000,7 @@
                     operation.processed = 'postcommit'
                     try:
                         operation.handle_event('postcommit_event')
-                    except:
+                    except BaseException:
                         self.critical('error while postcommit',
                                       exc_info=sys.exc_info())
                 self.debug('postcommit session %s done', self.id)
@@ -1031,7 +1031,7 @@
                     try:
                         operation = self.pending_operations.pop(0)
                         operation.handle_event('rollback_event')
-                    except:
+                    except BaseException:
                         self.critical('rollback error', exc_info=sys.exc_info())
                         continue
                 cnxset.rollback()
--- a/server/sources/__init__.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/server/sources/__init__.py	Fri Sep 23 14:18:13 2011 +0200
@@ -177,7 +177,7 @@
         # cw < 3.10 bw compat
         try:
             processed['adapter'] = confdict['adapter']
-        except:
+        except KeyError:
             pass
         # check for unknown options
         if confdict and not confdict.keys() == ['adapter']:
--- a/server/sources/extlite.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/server/sources/extlite.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -296,7 +296,7 @@
             try:
                 session.cnxset.connection(self.uri).rollback()
                 self.critical('transaction has been rollbacked')
-            except:
+            except Exception:
                 pass
             raise
         return cursor
--- a/server/sources/ldapuser.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/server/sources/ldapuser.py	Fri Sep 23 14:18:13 2011 +0200
@@ -273,7 +273,7 @@
         if self._conn is None:
             try:
                 self._connect()
-            except:
+            except Exception:
                 self.exception('unable to connect to ldap:')
         return ConnectionWrapper(self._conn)
 
@@ -570,7 +570,7 @@
                     try:
                         for i in range(len(value)):
                             value[i] = unicode(value[i], 'utf8')
-                    except:
+                    except Exception:
                         pass
                 if isinstance(value, list) and len(value) == 1:
                     rec_dict[key] = value = value[0]
--- a/server/sources/native.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/server/sources/native.py	Fri Sep 23 14:18:13 2011 +0200
@@ -413,7 +413,8 @@
         self.init_creating(source_entity._cw.cnxset)
         try:
             # test if 'asource' column exists
-            source_entity._cw.system_sql('SELECT asource FROM entities LIMIT 1')
+            query = self.dbhelper.sql_add_limit_offset('SELECT asource FROM entities', 1)
+            source_entity._cw.system_sql(query)
         except Exception, ex:
             self.eid_type_source = self.eid_type_source_pre_131
 
--- a/server/sources/pyrorql.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/server/sources/pyrorql.py	Fri Sep 23 14:18:13 2011 +0200
@@ -226,7 +226,7 @@
                         self.cross_relations.remove(ertype)
                 else:
                     self.dont_cross_relations.remove(ertype)
-        except:
+        except Exception:
             self.error('while updating mapping consequently to removal of %s',
                        schemacfg)
 
@@ -275,7 +275,7 @@
                         entity = rset.get_entity(0, 0)
                         entity.complete(entity.e_schema.indexable_attributes())
                         source.index_entity(session, entity)
-                except:
+                except Exception:
                     self.exception('while updating %s with external id %s of source %s',
                                    etype, extid, self.uri)
                     continue
@@ -288,7 +288,7 @@
                         entity = session.entity_from_eid(eid, etype)
                         repo.delete_info(session, entity, self.uri, extid,
                                          scleanup=self.eid)
-                except:
+                except Exception:
                     self.exception('while updating %s with external id %s of source %s',
                                    etype, extid, self.uri)
                     continue
@@ -667,7 +667,7 @@
         value = const.eval(self.kwargs)
         try:
             return None, self._const_var[value]
-        except:
+        except Exception:
             var = self._varmaker.next()
             self.need_translation = True
             restr = '%s eid %s' % (var, self.visit_constant(const))
--- a/server/test/data/site_cubicweb.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/server/test/data/site_cubicweb.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -20,14 +20,10 @@
 from logilab.database.sqlite import register_sqlite_pyfunc
 from rql.utils import register_function
 
-try:
-    class DUMB_SORT(FunctionDescr):
-        pass
+class DUMB_SORT(FunctionDescr):
+    pass
 
-    register_function(DUMB_SORT)
-    def dumb_sort(something):
-        return something
-    register_sqlite_pyfunc(dumb_sort)
-except:
-    # already registered
-    pass
+register_function(DUMB_SORT)
+def dumb_sort(something):
+    return something
+register_sqlite_pyfunc(dumb_sort)
--- a/server/utils.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/server/utils.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -16,6 +16,7 @@
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
 """Some utilities for the CubicWeb server."""
+
 __docformat__ = "restructuredtext en"
 
 import sys
@@ -121,11 +122,12 @@
 
 class LoopTask(object):
     """threaded task restarting itself once executed"""
-    def __init__(self, interval, func, args):
+    def __init__(self, repo, interval, func, args):
         if interval <= 0:
             raise ValueError('Loop task interval must be > 0 '
                              '(current value: %f for %s)' % \
                              (interval, func_name(func)))
+        self.repo = repo
         self.interval = interval
         def auto_restart_func(self=self, func=func, args=args):
             restart = True
@@ -138,7 +140,7 @@
             except BaseException:
                 restart = False
             finally:
-                if restart:
+                if restart and not self.repo.shutting_down:
                     self.start()
         self.func = auto_restart_func
         self.name = func_name(func)
@@ -167,7 +169,7 @@
         def auto_remove_func(self=self, func=target):
             try:
                 func()
-            except:
+            except Exception:
                 logger = logging.getLogger('cubicweb.repository')
                 logger.exception('Unhandled exception in RepoThread %s', self._name)
                 raise
--- a/sobjects/textparsers.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/sobjects/textparsers.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -83,7 +83,7 @@
                     trinfo = iworkflowable.fire_transition(tr)
                     caller.fire_event('state-changed', {'trinfo': trinfo,
                                                         'entity': entity})
-                except:
+                except Exception:
                     self.exception('while changing state of %s', entity)
             else:
                 self.error("can't pass transition %s on entity %s",
--- a/test/data/rewrite/schema.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/test/data/rewrite/schema.py	Fri Sep 23 14:18:13 2011 +0200
@@ -63,3 +63,15 @@
     object = 'Card'
     inlined = True
     cardinality = '?*'
+
+class inlined_note(RelationDefinition):
+    subject = 'Card'
+    object = 'Note'
+    inlined = True
+    cardinality = '?*'
+
+class inlined_affaire(RelationDefinition):
+    subject = 'Note'
+    object = 'Affaire'
+    inlined = True
+    cardinality = '?*'
--- a/test/unittest_rqlrewrite.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/test/unittest_rqlrewrite.py	Fri Sep 23 14:18:13 2011 +0200
@@ -236,6 +236,18 @@
                                            ('A2', 'X'): (c2,),
                                            }, {})
 
+    def test_optional_var_inlined_linked(self):
+        c1 = ('X require_permission P')
+        c2 = ('X inlined_card O, O require_permission P')
+        rqlst = parse('Any A,W WHERE A inlined_card C?, C inlined_note N, '
+                      'N inlined_affaire W')
+        rewrite(rqlst, {('C', 'X'): (c1,)}, {})
+        self.failUnlessEqual(rqlst.as_string(),
+                             'Any A,W WHERE A inlined_card C?, A is Affaire '
+                             'WITH C,N,W BEING (Any C,N,W WHERE C inlined_note N, '
+                             'N inlined_affaire W, EXISTS(C require_permission B), '
+                             'C is Card, N is Note, W is Affaire)')
+
     def test_relation_optimization_1_lhs(self):
         # since Card in_state State as monovalued cardinality, the in_state
         # relation used in the rql expression can be ignored and S replaced by
@@ -246,6 +258,7 @@
         self.assertEqual(rqlst.as_string(),
                              "Any C WHERE C in_state STATE, C is Card, "
                              "EXISTS(STATE name 'hop'), STATE is State")
+
     def test_relation_optimization_1_rhs(self):
         snippet = ('TW subworkflow_exit X, TW name "hop"')
         rqlst = parse('WorkflowTransition C WHERE C subworkflow_exit EXIT')
--- a/uilib.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/uilib.py	Fri Sep 23 14:18:13 2011 +0200
@@ -406,10 +406,10 @@
 def exc_message(ex, encoding):
     try:
         return unicode(ex)
-    except:
+    except Exception:
         try:
             return unicode(str(ex), encoding, 'replace')
-        except:
+        except Exception:
             return unicode(repr(ex), encoding, 'replace')
 
 
@@ -423,7 +423,7 @@
     res.append(u'\n')
     try:
         res.append(u'\t Error: %s\n' % exception)
-    except:
+    except Exception:
         pass
     return u'\n'.join(res)
 
--- a/view.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/view.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -174,7 +174,7 @@
         stream = self.set_stream(w)
         try:
             view_func(**context)
-        except:
+        except Exception:
             self.debug('view call %s failed (context=%s)', view_func, context)
             raise
         # return stream content if we have created it
@@ -375,7 +375,19 @@
 
     def call(self, **kwargs):
         if self.cw_rset is None:
-            self.entity_call(self.cw_extra_kwargs.pop('entity'))
+            # * cw_extra_kwargs is the place where extra selection arguments are
+            #   stored
+            # * when calling req.view('somevid', entity=entity), 'entity' ends
+            #   up in cw_extra_kwargs and kwargs
+            #
+            # handle that to avoid a TypeError with a sanity check
+            #
+            # Notice that could probably be avoided by handling entity_call in
+            # .render
+            entity = self.cw_extra_kwargs.pop('entity')
+            if 'entity' in kwargs:
+                assert kwargs.pop('entity') is entity
+            self.entity_call(entity, **kwargs)
         else:
             super(EntityView, self).call(**kwargs)
 
--- a/web/application.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/application.py	Fri Sep 23 14:18:13 2011 +0200
@@ -423,7 +423,7 @@
             if req.cnx and not commited:
                 try:
                     req.cnx.rollback()
-                except:
+                except Exception:
                     pass # ignore rollback error at this point
         self.info('query %s executed in %s sec', req.relative_path(), clock() - tstart)
         return result
@@ -460,7 +460,7 @@
             errview = self.vreg['views'].select('error', req)
             template = self.main_template_id(req)
             content = self.vreg['views'].main_template(req, template, view=errview)
-        except:
+        except Exception:
             content = self.vreg['views'].main_template(req, 'error-template')
         raise StatusResponse(code, content)
 
--- a/web/captcha.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/captcha.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -17,8 +17,8 @@
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
 """Simple captcha library, based on PIL. Monkey patch functions in this module
 if you want something better...
+"""
 
-"""
 __docformat__ = "restructuredtext en"
 
 from random import randint, choice
--- a/web/data/cubicweb.ajax.js	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/data/cubicweb.ajax.js	Fri Sep 23 14:18:13 2011 +0200
@@ -705,7 +705,7 @@
 
 function setTab(tabname, cookiename) {
     // set appropriate cookie
-    loadRemote('json', ajaxFuncArgs('set_cookie', null, cookiename, tabname));
+    jQuery.cookie(cookiename, tabname, {path: '/'});
     // trigger show + tabname event
     triggerLoad(tabname);
 }
--- a/web/data/cubicweb.js	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/data/cubicweb.js	Fri Sep 23 14:18:13 2011 +0200
@@ -53,7 +53,13 @@
     },
 
     evalJSON: function (json) { // trust source
-        return eval("(" + json + ")");
+        try {
+            return eval("(" + json + ")");
+        } catch(e) {
+          cw.log(e);
+          cw.log('The faulty json source was', json);
+          throw (e);
+       }
     },
 
     urlEncode: function (str) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/data/jquery.cookie.js	Fri Sep 23 14:18:13 2011 +0200
@@ -0,0 +1,41 @@
+/**
+ * jQuery Cookie plugin
+ *
+ * Copyright (c) 2010 Klaus Hartl (stilbuero.de)
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+jQuery.cookie = function (key, value, options) {
+
+    // key and at least value given, set cookie...
+    if (arguments.length > 1 && String(value) !== "[object Object]") {
+        options = jQuery.extend({}, options);
+
+        if (value === null || value === undefined) {
+            options.expires = -1;
+        }
+
+        if (typeof options.expires === 'number') {
+            var days = options.expires, t = options.expires = new Date();
+            t.setDate(t.getDate() + days);
+        }
+
+        value = String(value);
+
+        return (document.cookie = [
+            encodeURIComponent(key), '=',
+            options.raw ? value : encodeURIComponent(value),
+            options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
+            options.path ? '; path=' + options.path : '',
+            options.domain ? '; domain=' + options.domain : '',
+            options.secure ? '; secure' : ''
+        ].join(''));
+    }
+
+    // key and possibly options given, get cookie...
+    options = value || {};
+    var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent;
+    return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
+};
--- a/web/test/unittest_session.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/test/unittest_session.py	Fri Sep 23 14:18:13 2011 +0200
@@ -2,7 +2,7 @@
 """unit tests for cubicweb.web.application
 
 :organization: Logilab
-:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
+:copyright: 2001-2011 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
--- a/web/test/unittest_viewselector.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/test/unittest_viewselector.py	Fri Sep 23 14:18:13 2011 +0200
@@ -76,7 +76,7 @@
             return
         try:
             self.assertSetEqual(content.keys(), expected)
-        except:
+        except Exception:
             print registry, sorted(expected), sorted(content.keys())
             print 'no more', [v for v in expected if not v in content.keys()]
             print 'missing', [v for v in content.keys() if not v in expected]
@@ -126,7 +126,6 @@
                               ('rsetxml', xmlrss.XMLRsetView),
                               ('rss', xmlrss.RSSView),
                               ('sameetypelist', baseviews.SameETypeListView),
-                              ('secondary', baseviews.SecondaryView),
                               ('security', management.SecurityManagementView),
                               ('table', tableview.TableView),
                               ('text', baseviews.TextView),
@@ -150,7 +149,6 @@
                               ('rsetxml', xmlrss.XMLRsetView),
                               ('rss', xmlrss.RSSView),
                               ('sameetypelist', baseviews.SameETypeListView),
-                              ('secondary', baseviews.SecondaryView),
                               ('security', management.SecurityManagementView),
                               ('table', tableview.TableView),
                               ('text', baseviews.TextView),
@@ -204,7 +202,6 @@
                               ('primary', primary.PrimaryView),] + RDFVIEWS + [
                               ('rsetxml', xmlrss.XMLRsetView),
                               ('rss', xmlrss.RSSView),
-                              ('secondary', baseviews.SecondaryView),
                               ('security', management.SecurityManagementView),
                               ('table', tableview.TableView),
                               ('text', baseviews.TextView),
@@ -240,7 +237,6 @@
                               ('rsetxml', xmlrss.XMLRsetView),
                               ('rss', xmlrss.RSSView),
                               ('sameetypelist', baseviews.SameETypeListView),
-                              ('secondary', baseviews.SecondaryView),
                               ('security', management.SecurityManagementView),
                               ('table', tableview.TableView),
                               ('text', baseviews.TextView),
@@ -468,7 +464,7 @@
         try:
             obj = self.vreg['views'].select(vid, req, rset=rset, **args)
             return obj.render(**args)
-        except:
+        except Exception:
             print vid, rset, args
             raise
 
--- a/web/uicfg.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/uicfg.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
--- a/web/views/autoform.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/views/autoform.py	Fri Sep 23 14:18:13 2011 +0200
@@ -325,7 +325,7 @@
     def _entity(self):
         try:
             cls = self._cw.vreg['etypes'].etype_class(self.etype)
-        except:
+        except Exception:
             self.w(self._cw._('no such entity type %s') % self.etype)
             return
         entity = cls(self._cw)
--- a/web/views/basecontrollers.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/views/basecontrollers.py	Fri Sep 23 14:18:13 2011 +0200
@@ -23,6 +23,7 @@
 _ = unicode
 
 from logilab.common.date import strptime
+from logilab.common.deprecation import deprecated
 
 from cubicweb import (NoSelectableObject, ObjectNotFound, ValidationError,
                       AuthenticationError, typed_eid)
@@ -546,8 +547,8 @@
             self._cw.set_cookie(cookies, statename)
 
     @jsonize
+    @deprecated("[3.13] use jQuery.cookie(cookiename, cookievalue, {path: '/'}) in js land instead")
     def js_set_cookie(self, cookiename, cookievalue):
-        # XXX we should consider jQuery.Cookie
         cookiename, cookievalue = str(cookiename), str(cookievalue)
         cookies = self._cw.get_cookie()
         cookies[cookiename] = cookievalue
--- a/web/views/baseviews.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/views/baseviews.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -15,12 +15,64 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""Set of HTML generic base views:
+"""
+HTML views
+~~~~~~~~~~
+
+Special views
+`````````````
+
+.. autoclass:: NullView
+.. autoclass:: NoResultView
+.. autoclass:: FinalView
+
+
+Base entity views
+`````````````````
+
+.. autoclass:: InContextView
+.. autoclass:: OutOfContextView
+.. autoclass:: OneLineView
 
-* noresult, final
-* primary, sidebox
-* oneline, incontext, outofcontext, text
-* list
+Those are used to display a link to an entity, whose label depends on the entity
+having to be displayed in or out of context (of another entity): some entities
+make sense in the context of another entity. For instance, the `Version` of a
+`Project` in forge. So one may expect that 'incontext' will be called when
+display a version from within the context of a project, while 'outofcontext"'
+will be called in other cases. In our example, the 'incontext' view of the
+version would be something like '0.1.2', while the 'outofcontext' view would
+include the project name, e.g. 'baz 0.1.2' (since only a version number without
+the associated project doesn't make sense if you don't know yet that you're
+talking about the famous 'baz' project. |cubicweb| tries to make guess and call
+'incontext'/'outofcontext' nicely. When it can't know, the 'oneline' view should
+be used.
+
+
+List entity views
+`````````````````
+
+.. autoclass:: ListView
+.. autoclass:: SimpleListView
+.. autoclass:: SameETypeListView
+.. autoclass:: CSVView
+
+Those list views can be given a 'subvid' arguments, telling the view to use of
+each item in the list. When not specified, the value of the 'redirect_vid'
+attribute of :class:`ListItemView` (for 'listview') or of
+:class:`SimpleListView` will be used. This default to 'outofcontext' for 'list'
+/ 'incontext' for 'simplelist'
+
+
+Text entity views
+~~~~~~~~~~~~~~~~~
+
+Basic HTML view have some variants to be used when generating raw text, not HTML
+(for notifications for instance). Also, as explained above, some of the HTML
+views use those text views as a basis.
+
+.. autoclass:: TextView
+.. autoclass:: InContextTextView
+.. autoclass:: OutOfContextView
 """
 
 __docformat__ = "restructuredtext en"
@@ -42,7 +94,12 @@
 
 
 class NullView(AnyRsetView):
-    """default view when no result has been found"""
+    """:__regid__: *null*
+
+    This view is the default view used when nothing needs to be rendered. It is
+    always applicable and is usually used as fallback view when calling
+    :meth:`_cw.view` to display nothing if the result set is empty.
+    """
     __regid__ = 'null'
     __select__ = yes()
     def call(self, **kwargs):
@@ -51,9 +108,16 @@
 
 
 class NoResultView(View):
-    """default view when no result has been found"""
+    """:__regid__: *noresult*
+
+    This view is the default view to be used when no result has been found
+    (i.e. empty result set).
+
+    It's usually used as fallback view when calling :meth:`_cw.view` to display
+    "no results" if the result set is empty.
+    """
+    __regid__ = 'noresult'
     __select__ = empty_rset()
-    __regid__ = 'noresult'
 
     def call(self, **kwargs):
         self.w(u'<div class="searchMessage"><strong>%s</strong></div>\n'
@@ -61,8 +125,11 @@
 
 
 class FinalView(AnyRsetView):
-    """display values without any transformation (i.e. get a number for
-    entities)
+    """:__regid__: *final*
+
+    Display the value of a result set cell with minimal transformations
+    (i.e. you'll get a number for entities). It is applicable on any result set,
+    though usually dedicated for cells containing an attribute's value.
     """
     __regid__ = 'final'
     # record generated i18n catalog messages
@@ -126,21 +193,51 @@
         self.wdata(printable_value(self._cw, etype, value, props))
 
 
-# XXX deprecated
-class SecondaryView(EntityView):
-    __regid__ = 'secondary'
-    title = _('secondary')
+class InContextView(EntityView):
+    """:__regid__: *incontext*
+
+    This view is used whenthe entity should be considered as displayed in its
+    context. By default it produces the result of `textincontext` wrapped in a
+    link leading to the primary view of the entity.
+    """
+    __regid__ = 'incontext'
+
+    def cell_call(self, row, col):
+        entity = self.cw_rset.get_entity(row, col)
+        desc = cut(entity.dc_description(), 50)
+        self.w(u'<a href="%s" title="%s">' % (
+            xml_escape(entity.absolute_url()), xml_escape(desc)))
+        self.w(xml_escape(self._cw.view('textincontext', self.cw_rset,
+                                        row=row, col=col)))
+        self.w(u'</a>')
 
-    def cell_call(self, row, col, **kwargs):
-        """the secondary view for an entity
-        secondary = icon + view(oneline)
-        """
+
+class OutOfContextView(EntityView):
+    """:__regid__: *outofcontext*
+
+    This view is used whenthe entity should be considered as displayed out of
+    its context. By default it produces the result of `textoutofcontext` wrapped
+    in a link leading to the primary view of the entity.
+    """
+    __regid__ = 'outofcontext'
+
+    def cell_call(self, row, col):
         entity = self.cw_rset.get_entity(row, col)
-        self.w(u'&#160;')
-        self.wview('oneline', self.cw_rset, row=row, col=col)
+        desc = cut(entity.dc_description(), 50)
+        self.w(u'<a href="%s" title="%s">' % (
+            xml_escape(entity.absolute_url()), xml_escape(desc)))
+        self.w(xml_escape(self._cw.view('textoutofcontext', self.cw_rset,
+                                        row=row, col=col)))
+        self.w(u'</a>')
 
 
 class OneLineView(EntityView):
+    """:__regid__: *oneline*
+
+    This view is used when we can't tell if the entity should be considered as
+    displayed in or out of context. By default it produces the result of the
+    `text` view in a link leading to the primary view of the entity.
+    """
     __regid__ = 'oneline'
     title = _('oneline')
 
@@ -153,18 +250,25 @@
         self.w(u'</a>')
 
 
+# text views ###################################################################
+
 class TextView(EntityView):
-    """the simplest text view for an entity"""
+    """:__regid__: *text*
+
+    This is the simplest text view for an entity. By default it returns the
+    result of the entity's `dc_title()` method, which is cut to fit the
+    `navigation.short-line-size` property if necessary.
+    """
     __regid__ = 'text'
     title = _('text')
     content_type = 'text/plain'
 
     def call(self, **kwargs):
-        """the view is called for an entire result set, by default loop
-        other rows of the result set and call the same view on the
-        particular row
+        """The view is called for an entire result set, by default loop other
+        rows of the result set and call the same view on the particular row.
 
-        Views applicable on None result sets have to override this method
+        Subclasses views that are applicable on None result sets will have to
+        override this method.
         """
         rset = self.cw_rset
         if rset is None:
@@ -180,40 +284,14 @@
                    self._cw.property_value('navigation.short-line-size')))
 
 
-class MetaDataView(EntityView):
-    """paragraph view of some metadata"""
-    __regid__ = 'metadata'
-    show_eid = True
+class InContextTextView(TextView):
+    """:__regid__: *textincontext*
 
-    def cell_call(self, row, col):
-        _ = self._cw._
-        entity = self.cw_rset.get_entity(row, col)
-        self.w(u'<div>')
-        if self.show_eid:
-            self.w(u'%s #%s - ' % (entity.dc_type(), entity.eid))
-        if entity.modification_date != entity.creation_date:
-            self.w(u'<span>%s</span> ' % _('latest update on'))
-            self.w(u'<span class="value">%s</span>, '
-                   % self._cw.format_date(entity.modification_date))
-        # entities from external source may not have a creation date (eg ldap)
-        if entity.creation_date:
-            self.w(u'<span>%s</span> ' % _('created on'))
-            self.w(u'<span class="value">%s</span>'
-                   % self._cw.format_date(entity.creation_date))
-        if entity.creator:
-            if entity.creation_date:
-                self.w(u' <span>%s</span> ' % _('by'))
-            else:
-                self.w(u' <span>%s</span> ' % _('created_by'))
-            self.w(u'<span class="value">%s</span>' % entity.creator.name())
-        meta = entity.cw_metainformation()
-        if meta['source']['uri'] != 'system':
-            self.w(u' (<span>%s</span>' % _('cw_source'))
-            self.w(u' <span class="value">%s</span>)' % meta['source']['uri'])
-        self.w(u'</div>')
-
-
-class InContextTextView(TextView):
+    Similar to the `text` view, but called when an entity is considered in
+    context (see description of incontext HTML view for more information on
+    this). By default it displays what's returned by the `dc_title()` method of
+    the entity.
+    """
     __regid__ = 'textincontext'
     title = None # not listed as a possible view
     def cell_call(self, row, col):
@@ -222,6 +300,13 @@
 
 
 class OutOfContextTextView(InContextTextView):
+    """:__regid__: *textoutofcontext*
+
+    Similar to the `text` view, but called when an entity is considered out of
+    context (see description of outofcontext HTML view for more information on
+    this). By default it displays what's returned by the `dc_long_title()`
+    method of the entity.
+    """
     __regid__ = 'textoutofcontext'
 
     def cell_call(self, row, col):
@@ -229,35 +314,26 @@
         self.w(entity.dc_long_title())
 
 
-class InContextView(EntityView):
-    __regid__ = 'incontext'
-
-    def cell_call(self, row, col):
-        entity = self.cw_rset.get_entity(row, col)
-        desc = cut(entity.dc_description(), 50)
-        self.w(u'<a href="%s" title="%s">' % (
-            xml_escape(entity.absolute_url()), xml_escape(desc)))
-        self.w(xml_escape(self._cw.view('textincontext', self.cw_rset,
-                                        row=row, col=col)))
-        self.w(u'</a>')
-
-
-class OutOfContextView(EntityView):
-    __regid__ = 'outofcontext'
-
-    def cell_call(self, row, col):
-        entity = self.cw_rset.get_entity(row, col)
-        desc = cut(entity.dc_description(), 50)
-        self.w(u'<a href="%s" title="%s">' % (
-            xml_escape(entity.absolute_url()), xml_escape(desc)))
-        self.w(xml_escape(self._cw.view('textoutofcontext', self.cw_rset,
-                                        row=row, col=col)))
-        self.w(u'</a>')
-
-
 # list views ##################################################################
 
 class ListView(EntityView):
+    """:__regid__: *list*
+
+    This view displays a list of entities by creating a HTML list (`<ul>`) and
+    call the view `listitem` for each entity of the result set. The 'list' view
+    will generate HTML like:
+
+    .. sourcecode:: html
+
+      <ul class="section">
+        <li>"result of 'subvid' view for a row</li>
+        ...
+      </ul>
+
+    If you wish to use a different view for each entity, either subclass and
+    change the :attr:`item_vid` class attribute or specify a `subvid` argument
+    when calling this view.
+    """
     __regid__ = 'list'
     title = _('list')
     item_vid = 'listitem'
@@ -312,7 +388,21 @@
 
 
 class SimpleListView(ListItemView):
-    """list without bullets"""
+    """:__regid__: *simplelist*
+
+    Similar to :class:~cubicweb.web.views.baseviews.ListView but using '<div>'
+    instead of '<ul>'. It rely on '<div>' behaviour to separate items. HTML will
+    look like
+
+    .. sourcecode:: html
+
+      <div class="section">"result of 'subvid' view for a row</div>
+      ...
+
+
+    It relies on base :class:`~cubicweb.view.View` class implementation of the
+    :meth:`call` method to insert those <div>.
+    """
     __regid__ = 'simplelist'
     redirect_vid = 'incontext'
 
@@ -330,8 +420,13 @@
 
 
 class SameETypeListView(EntityView):
-    """list of entities of the same type, when asked explicitly for same etype list
-    view (for instance, display gallery if only images)
+    """:__regid__: *sameetypelist*
+
+    This view displays a list of entities of the same type, in HTML section
+    ('<div>') and call the view `sameetypelistitem` for each entity of the
+    result set. It's designed to get a more adapted global list when displayed
+    entities are all of the same type (for instance, display gallery if there
+    are only images entities).
     """
     __regid__ = 'sameetypelist'
     __select__ = EntityView.__select__ & one_etype_rset()
@@ -361,6 +456,11 @@
 
 
 class CSVView(SimpleListView):
+    """:__regid__: *csv*
+
+    This view displays each entity in a coma separated list. It is NOT related
+    to the well-known text file format.
+    """
     __regid__ = 'csv'
     redirect_vid = 'incontext'
 
@@ -377,12 +477,48 @@
                 self.w(u", ")
 
 
+# XXX to be documented views ###################################################
+
+class MetaDataView(EntityView):
+    """paragraph view of some metadata"""
+    __regid__ = 'metadata'
+    show_eid = True
+
+    def cell_call(self, row, col):
+        _ = self._cw._
+        entity = self.cw_rset.get_entity(row, col)
+        self.w(u'<div>')
+        if self.show_eid:
+            self.w(u'%s #%s - ' % (entity.dc_type(), entity.eid))
+        if entity.modification_date != entity.creation_date:
+            self.w(u'<span>%s</span> ' % _('latest update on'))
+            self.w(u'<span class="value">%s</span>, '
+                   % self._cw.format_date(entity.modification_date))
+        # entities from external source may not have a creation date (eg ldap)
+        if entity.creation_date:
+            self.w(u'<span>%s</span> ' % _('created on'))
+            self.w(u'<span class="value">%s</span>'
+                   % self._cw.format_date(entity.creation_date))
+        if entity.creator:
+            if entity.creation_date:
+                self.w(u' <span>%s</span> ' % _('by'))
+            else:
+                self.w(u' <span>%s</span> ' % _('created_by'))
+            self.w(u'<span class="value">%s</span>' % entity.creator.name())
+        meta = entity.cw_metainformation()
+        if meta['source']['uri'] != 'system':
+            self.w(u' (<span>%s</span>' % _('cw_source'))
+            self.w(u' <span class="value">%s</span>)' % meta['source']['uri'])
+        self.w(u'</div>')
+
+
 class TreeItemView(ListItemView):
     __regid__ = 'treeitem'
 
     def cell_call(self, row, col):
         self.wview('incontext', self.cw_rset, row=row, col=col)
 
+
 class TextSearchResultView(EntityView):
     """this view is used to display full-text search
 
@@ -405,7 +541,7 @@
                 value = xml_escape(entity.printable_value(attr, format='text/plain').lower())
             except TransformError, ex:
                 continue
-            except:
+            except Exception:
                 continue
             if searched in value:
                 contexts = []
@@ -425,26 +561,6 @@
         self.wview('oneline', self.cw_rset, row=row, col=col)
 
 
-# XXX bw compat
-
-from logilab.common.deprecation import class_moved
-
-try:
-    from cubicweb.web.views.tableview import TableView
-    TableView = class_moved(TableView)
-except ImportError:
-    pass # gae has no tableview module (yet)
-
-from cubicweb.web.views import boxes, xmlrss, primary
-PrimaryView = class_moved(primary.PrimaryView)
-SideBoxView = class_moved(boxes.SideBoxView)
-XmlView = class_moved(xmlrss.XMLView)
-XmlItemView = class_moved(xmlrss.XMLItemView)
-XmlRsetView = class_moved(xmlrss.XMLRsetView)
-RssView = class_moved(xmlrss.RSSView)
-RssItemView = class_moved(xmlrss.RSSItemView)
-
-
 class GroupByView(EntityView):
     """grouped view of a result set. The `group_key` method return the group
     key of an entities (a string or tuple of string).
@@ -452,7 +568,7 @@
     For each group, display a link to entities of this group by generating url
     like <basepath>/<key> or <basepath>/<key item 1>/<key item 2>.
     """
-    __abstrack__ = True
+    __abstract__ = True
     __select__ = EntityView.__select__ & match_kwargs('basepath')
     entity_attribute = None
     reversed = False
@@ -550,3 +666,29 @@
         url = self.index_url(basepath, key, vtitle=vtitle)
         title = self._cw._('archive for %(author)s') % {'author': key}
         return tags.a(label, href=url, title=title)
+
+
+# bw compat ####################################################################
+
+from logilab.common.deprecation import class_moved, class_deprecated
+
+from cubicweb.web.views import boxes, xmlrss, primary, tableview
+PrimaryView = class_moved(primary.PrimaryView)
+SideBoxView = class_moved(boxes.SideBoxView)
+XmlView = class_moved(xmlrss.XMLView)
+XmlItemView = class_moved(xmlrss.XMLItemView)
+XmlRsetView = class_moved(xmlrss.XMLRsetView)
+RssView = class_moved(xmlrss.RSSView)
+RssItemView = class_moved(xmlrss.RSSItemView)
+TableView = class_moved(tableview.TableView)
+
+
+class SecondaryView(EntityView):
+    __metaclass__ = class_deprecated
+    __deprecation_warning__ = '[3.9] the secondary view is deprecated, use one of oneline/incontext/outofcontext'
+    __regid__ = 'secondary'
+
+    def cell_call(self, row, col, **kwargs):
+        entity = self.cw_rset.get_entity(row, col)
+        self.w(u'&#160;')
+        self.wview('oneline', self.cw_rset, row=row, col=col)
--- a/web/views/cwsources.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/views/cwsources.py	Fri Sep 23 14:18:13 2011 +0200
@@ -24,27 +24,41 @@
 
 from itertools import repeat, chain
 
+from cubicweb import Unauthorized
 from cubicweb.selectors import is_instance, score_entity, match_user_groups
 from cubicweb.view import EntityView, StartupView
 from cubicweb.schema import META_RTYPES, VIRTUAL_RTYPES, display_name
 from cubicweb.web import uicfg, formwidgets as wdgs
-from cubicweb.web.views import tabs, actions, add_etype_button
+from cubicweb.web.views import tabs, actions, ibreadcrumbs, add_etype_button
 
 
 _abaa = uicfg.actionbox_appearsin_addmenu
+# there are explicit 'add' buttons for those
 _abaa.tag_object_of(('CWSourceSchemaConfig', 'cw_schema', '*'), False)
 _abaa.tag_object_of(('CWSourceSchemaConfig', 'cw_for_source', '*'), False)
+_abaa.tag_object_of(('CWSourceSchemaConfig', 'cw_host_config_of', '*'), False)
 
 _afs = uicfg.autoform_section
 _afs.tag_attribute(('CWSource', 'synchronizing'), 'main', 'hidden')
 _afs.tag_object_of(('*', 'cw_for_source', 'CWSource'), 'main', 'hidden')
+
 _affk = uicfg.autoform_field_kwargs
 _affk.tag_attribute(('CWSource', 'parser'), {'widget': wdgs.TextInput})
 
 # source primary views #########################################################
 
 _pvs = uicfg.primaryview_section
+_pvs.tag_attribute(('CWSource', 'name'), 'hidden')
 _pvs.tag_object_of(('*', 'cw_for_source', 'CWSource'), 'hidden')
+_pvs.tag_object_of(('*', 'cw_host_config_of', 'CWSource'), 'hidden')
+
+_pvdc = uicfg.primaryview_display_ctrl
+_pvdc.tag_attribute(('CWSource', 'type'), {'vid': 'attribute'})# disable reledit
+
+_rc = uicfg.reledit_ctrl
+_rc.tag_attribute(('CWSource', 'config'), {'rvid': 'verbatim'})
+_rc.tag_attribute(('CWSourceHostConfig', 'config'), {'rvid': 'verbatim'})
+_rc.tag_attribute(('CWSourceSchemaConfig', 'options'), {'rvid': 'verbatim'})
 
 
 class CWSourcePrimaryView(tabs.TabbedPrimaryView):
@@ -57,6 +71,23 @@
     __regid__ = 'cwsource-main'
     __select__ = tabs.PrimaryTab.__select__ & is_instance('CWSource')
 
+    def render_entity_attributes(self, entity):
+        super(CWSourceMainTab, self).render_entity_attributes(entity)
+        self.w(add_etype_button(self._cw, 'CWSourceHostConfig',
+                                __linkto='cw_host_config_of:%s:subject' % entity.eid,
+                                __redirectpath=entity.rest_path()))
+        try:
+            hostconfig = self._cw.execute(
+                'Any X, XC, XH WHERE X cw_host_config_of S, S eid %(s)s, '
+                'X config XC, X match_host XH', {'s': entity.eid})
+        except Unauthorized:
+            pass
+        else:
+            if hostconfig:
+                self.w(u'<h3>%s</h3>' % self._cw._('CWSourceHostConfig_plural'))
+                self._cw.view('editable-table', hostconfig,
+                              displaycols=range(2), w=self.w)
+
 
 MAPPED_SOURCE_TYPES = set( ('pyrorql', 'datafeed') )
 
@@ -239,3 +270,11 @@
                 self._cw._('add a CWSource')))
             self.w(u'<div class="clear"></div>')
         self.wview('table', self._cw.execute(self.rql), displaycols=range(4))
+
+
+# breadcrumbs configuration ####################################################
+
+class CWsourceConfigIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
+    __select__ = is_instance('CWSourceHostConfig', 'CWSourceSchemaConfig')
+    def parent_entity(self):
+        return self.entity.cwsource
--- a/web/views/facets.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/views/facets.py	Fri Sep 23 14:18:13 2011 +0200
@@ -207,6 +207,7 @@
     __regid__ = 'facet.filtertable'
     __select__ = has_facets()
     wdg_stack_size = 8
+    compact_layout_threshold = 5
 
     def call(self, vid, divid, vidargs, cssclass=''):
         self.generate_form(self.w, self.cw_rset, divid, vid, vidargs,
@@ -214,10 +215,23 @@
                            # divid=divid XXX
                            )
 
+    def _simple_horizontal_layout(self, w, wdgs):
+        w(u'<table class="filter">\n')
+        w(u'<tr>\n')
+        for wdg in wdgs:
+            w(u'<td>')
+            wdg.render(w=w)
+            w(u'</td>')
+        w(u'</tr>\n')
+        w(u'</table>\n')
+
     def layout_widgets(self, w, wdgs):
         """layout widgets: put them in a table where each column should have
         sum(wdg.height()) < wdg_stack_size.
         """
+        if len(wdgs) < self.compact_layout_threshold:
+            self._simple_horizontal_layout(w, wdgs)
+            return
         w(u'<table class="filter">\n')
         widget_queue = []
         queue_height = 0
--- a/web/views/forms.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/views/forms.py	Fri Sep 23 14:18:13 2011 +0200
@@ -277,7 +277,7 @@
         for editedfield in splitstrip(editedfields):
             try:
                 name, role = editedfield.split('-')
-            except:
+            except Exception:
                 name = editedfield
                 role = None
             if entityform:
--- a/web/views/idownloadable.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/views/idownloadable.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -75,7 +75,7 @@
 
 class DownloadView(EntityView):
     """download view
-    
+
     this view is replacing the deprecated 'download' controller and allow
     downloading of entities providing the necessary interface
     """
--- a/web/views/magicsearch.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/views/magicsearch.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -387,7 +387,7 @@
             procname, query = uquery.split(':', 1)
             proc = self.by_name[procname.strip().lower()]
             uquery = query.strip()
-        except:
+        except Exception:
             # use processor chain
             unauthorized = None
             for proc in self.processors:
--- a/web/views/primary.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/views/primary.py	Fri Sep 23 14:18:13 2011 +0200
@@ -15,7 +15,26 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""The default primary view"""
+"""
+Public API of the PrimaryView class
+````````````````````````````````````
+.. autoclass:: cubicweb.web.views.primary.PrimaryView
+
+Views that may be used to display an entity's attribute or relation
+```````````````````````````````````````````````````````````````````
+
+Yoy may easily the display of an attribute or relation by simply configuring the
+view using one of `primaryview_display_ctrl` or `reledit_ctrl` to use one of the
+views describled below. For instance:
+
+.. sourcecode:: python
+
+    primaryview_display_ctrl.tag_attribute(('Foo', 'bar'), {'vid': 'attribute'})
+
+
+.. autoclass:: AttributeView
+.. autoclass:: URLAttributeView
+"""
 
 __docformat__ = "restructuredtext en"
 _ = unicode
@@ -34,7 +53,47 @@
 
 
 class PrimaryView(EntityView):
-    """the full view of an non final entity"""
+    """
+    The basic layout of a primary view is as in the :ref:`primary_view_layout`
+    section. This layout is actually drawn by the `render_entity` method.
+
+    The methods you may want to modify while customizing a ``PrimaryView``
+    are:
+
+    .. automethod:: cubicweb.web.views.primary.PrimaryView.render_entity_title
+    .. automethod:: cubicweb.web.views.primary.PrimaryView.render_entity_attributes
+    .. automethod:: cubicweb.web.views.primary.PrimaryView.render_entity_relations
+    .. automethod:: cubicweb.web.views.primary.PrimaryView.render_side_boxes
+
+    The placement of relations in the relations section or in side boxes
+    can be controlled through the :ref:`primary_view_configuration` mechanism.
+
+    .. automethod:: cubicweb.web.views.primary.PrimaryView.content_navigation_components
+
+    Also, please note that by setting the following attributes in your
+    subclass, you can already customize some of the rendering:
+
+    :attr:`show_attr_label`
+        Renders the attribute label next to the attribute value if set to `True`.
+        Otherwise, does only display the attribute value.
+
+    :attr:`show_rel_label`
+        Renders the relation label next to the relation value if set to `True`.
+        Otherwise, does only display the relation value.
+
+    :attr:`skip_none`
+        Does not render an attribute value that is None if set to `True`.
+
+    :attr:`main_related_section`
+        Renders the relations of the entity if set to `True`.
+
+    A good practice is for you to identify the content of your entity type for
+    which the default rendering does not answer your need so that you can focus
+    on the specific method (from the list above) that needs to be modified. We
+    do not advise you to overwrite ``render_entity`` unless you want a
+    completely different layout.
+    """
+
     __regid__ = 'primary'
     title = _('primary')
     show_attr_label = True
@@ -95,6 +154,12 @@
             self.w(u'</td></tr></table>')
 
     def content_navigation_components(self, context):
+        """This method is applicable only for entity type implementing the
+        interface `IPrevNext`. This interface is for entities which can be
+        linked to a previous and/or next entity. This method will render the
+        navigation links between entities of this type, either at the top or at
+        the bottom of the page given the context (navcontent{top|bottom}).
+        """
         self.w(u'<div class="%s">' % context)
         for comp in self._cw.vreg['ctxcomponents'].poss_visible_objects(
             self._cw, rset=self.cw_rset, view=self, context=context):
@@ -106,7 +171,9 @@
         self.w(u'</div>')
 
     def render_entity_title(self, entity):
-        """default implementation return dc_title"""
+        """Renders the entity title, by default using entity's
+        :meth:`dc_title()` method.
+        """
         title = xml_escape(entity.dc_title())
         if title:
             if self.is_primary():
@@ -128,6 +195,10 @@
         return u''
 
     def render_entity_attributes(self, entity):
+        """Renders all attributes and relations in the 'attributes' section. The
+        :attr:`skip_none` attribute controls the display of `None` valued
+        attributes.
+        """
         display_attributes = []
         for rschema, _, role, dispctrl in self._section_def(entity, 'attributes'):
             vid = dispctrl.get('vid', 'reledit')
@@ -165,6 +236,7 @@
         self.field(label, value, tr=False, table=table)
 
     def render_entity_relations(self, entity):
+        """Renders all relations in the 'relations' section."""
         for rschema, tschemas, role, dispctrl in self._section_def(entity, 'relations'):
             if rschema.final or dispctrl.get('rtypevid'):
                 vid = dispctrl.get('vid', 'reledit')
@@ -212,8 +284,9 @@
         self.w(u'</div>')
 
     def render_side_boxes(self, boxes):
-        """display side related relations:
-        non-meta in a first step, meta in a second step
+        """Renders side boxes on the right side of the content. This will
+        generate a box for each relation in the 'sidebox' section, as well as
+        explicit box appobjects selectable in this context.
         """
         for box in boxes:
             if isinstance(box, tuple):
@@ -305,6 +378,8 @@
 
     It will try to display nicely according to the number of items in the result
     set.
+
+    XXX include me in the doc
     """
     __regid__ = 'autolimited'
 
@@ -347,31 +422,29 @@
 
 
 class URLAttributeView(EntityView):
-    """use this view for attributes whose value is an url and that you want
-    to display as clickable link
+    """:__regid__: *urlattr*
+
+    This view will wrap an attribute value (hence expect a string) into an '<a>'
+    HTML tag to display a clickable link.
     """
     __regid__ = 'urlattr'
     __select__ = EntityView.__select__ & match_kwargs('rtype')
 
-    def cell_call(self, row, col, rtype, **kwargs):
-        entity = self.cw_rset.get_entity(row, col)
+    def entity_call(self, entity, rtype, **kwargs):
         url = entity.printable_value(rtype)
         if url:
             self.w(u'<a href="%s">%s</a>' % (url, url))
 
 class AttributeView(EntityView):
-    """use this view on an entity as an alternative to more sophisticated
-    views such as reledit.
+    """:__regid__: *attribute*
 
-    Ex. usage:
-
-    uicfg.primaryview_display_ctrl.tag_attribute(('Foo', 'bar'), {'vid': 'attribute'})
+    This view is generally used to disable the *reledit* feature. It works on
+    both relations and attributes.
     """
     __regid__ = 'attribute'
     __select__ = EntityView.__select__ & match_kwargs('rtype')
 
-    def cell_call(self, row, col, rtype, role, **kwargs):
-        entity = self.cw_rset.get_entity(row, col)
+    def entity_call(self, entity, rtype, **kwargs):
         if self._cw.vreg.schema.rschema(rtype).final:
             self.w(entity.printable_value(rtype))
         else:
@@ -384,12 +457,14 @@
 
 
 class ToolbarLayout(component.Layout):
+    # XXX include me in the doc
     __select__ = match_context('ctxtoolbar')
 
     def render(self, w):
         if self.init_rendering():
             self.cw_extra_kwargs['view'].render_body(w)
 
+
 ## default primary ui configuration ###########################################
 
 _pvs = uicfg.primaryview_section
--- a/web/views/reledit.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/views/reledit.py	Fri Sep 23 14:18:13 2011 +0200
@@ -104,7 +104,11 @@
                 self._handle_relation(rschema, role, divid, reload, formid, action)
 
     def _handle_attribute(self, rschema, role, divid, reload, action):
-        value = self.entity.printable_value(rschema.type)
+        rvid = self._rules.get('rvid', None)
+        if rvid is not None:
+            value = self._cw.view(rvid, entity=self.entity, rtype=rschema.type)
+        else:
+            value = self.entity.printable_value(rschema.type)
         if not self._should_edit_attribute(rschema):
             self.w(value)
             return
--- a/web/views/schema.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/views/schema.py	Fri Sep 23 14:18:13 2011 +0200
@@ -102,7 +102,7 @@
             # XXX get group entity and call it's incontext view
             groups = [u'<a class="%s" href="%s">%s</a>' % (
                 group, self._cw.build_url('cwgroup/%s' % group), label)
-                      for group, label in sorted((_(g), g) for g in groups)]
+                      for label, group in sorted((_(g), g) for g in groups)]
             w(u'<br/>'.join(groups))
             w(u'</td><td>')
             w(u'<br/>'.join(rqlexprs))
--- a/web/views/sessions.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/views/sessions.py	Fri Sep 23 14:18:13 2011 +0200
@@ -21,7 +21,8 @@
 
 __docformat__ = "restructuredtext en"
 
-from cubicweb import RepositoryError, Unauthorized, AuthenticationError
+from cubicweb import (RepositoryError, Unauthorized, AuthenticationError,
+                      BadConnectionId)
 from cubicweb.web import InvalidSession, Redirect
 from cubicweb.web.application import AbstractSessionManager
 from cubicweb.dbapi import DBAPISession
@@ -119,7 +120,7 @@
             req.cnx.commit()
         except (RepositoryError, Unauthorized):
             req.cnx.rollback()
-        except:
+        except Exception:
             req.cnx.rollback()
             raise
 
@@ -132,8 +133,6 @@
         if session.cnx:
             try:
                 session.cnx.close()
-            except:
-                # already closed, may occur if the repository session expired
-                # but not the web session
+            except BadConnectionId: # expired on the repository side
                 pass
             session.cnx = None
--- a/web/views/tableview.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/views/tableview.py	Fri Sep 23 14:18:13 2011 +0200
@@ -42,6 +42,9 @@
     title = _('table')
     finalview = 'final'
 
+    table_widget_class = TableWidget
+    table_column_class = TableColumn
+
     def form_filter(self, divid, displaycols, displayactions, displayfilter,
                     paginate, hidden=True):
         try:
@@ -144,7 +147,7 @@
         if paginate:
             self.divid = divid # XXX iirk (see usage in page_navigation_url)
             self.paginate(page_size=page_size, show_all_option=False)
-        table = TableWidget(self)
+        table = self.table_widget_class(self)
         for column in self.get_columns(computed_labels, displaycols, headers,
                                        subvid, cellvids, cellattrs, mainindex):
             table.append_column(column)
@@ -197,7 +200,7 @@
                     label = _label
             if colindex == mainindex and label is not None:
                 label += ' (%s)' % self.cw_rset.rowcount
-            column = TableColumn(label, colindex)
+            column = self.table_column_class(label, colindex)
             coltype = self.cw_rset.description[0][colindex]
             # compute column cell view (if coltype is None, it's a left outer
             # join, use the default non final subvid)
@@ -259,14 +262,17 @@
         :param cellvid: cell view (defaults to 'outofcontext')
         """
         etype, val = self.cw_rset.description[row][col], self.cw_rset[row][col]
-        if val is not None and etype is not None and not self._cw.vreg.schema.eschema(etype).final:
-            self.wview(cellvid or 'outofcontext', self.cw_rset, row=row, col=col)
-        elif val is None:
-            # This is usually caused by a left outer join and in that case,
-            # regular views will most certainly fail if they don't have
-            # a real eid
-            self.wview('final', self.cw_rset, row=row, col=col)
+        if etype is None or not self._cw.vreg.schema.eschema(etype).final:
+            if val is None:
+                # This is usually caused by a left outer join and in that case,
+                # regular views will most certainly fail if they don't have
+                # a real eid
+                # XXX if cellvid is e.g. reledit, we may wanna call it anyway
+                self.w(u'&#160;')
+            else:
+                self.wview(cellvid or 'outofcontext', self.cw_rset, row=row, col=col)
         else:
+            # XXX why do we need a fallback view here?
             self.wview(cellvid or 'final', self.cw_rset, 'null', row=row, col=col)
 
 
--- a/web/views/tabs.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/web/views/tabs.py	Fri Sep 23 14:18:13 2011 +0200
@@ -128,7 +128,7 @@
             entity.view(default, w=self.w)
             return
         self._cw.add_css('jquery.ui.css')
-        self._cw.add_js(('jquery.ui.js', 'cubicweb.ajax.js'))
+        self._cw.add_js(('jquery.ui.js', 'cubicweb.ajax.js', 'jquery.cookie.js'))
         # prune tabs : not all are to be shown
         tabs, active_tab = self.prune_tabs(tabs, default)
         # build the html structure
@@ -140,9 +140,7 @@
         for i, (tabid, domid, tabkwargs) in enumerate(tabs):
             w(u'<li>')
             w(u'<a href="#%s">' % domid)
-            w(u'<span onclick="%s">' % xml_escape(unicode(uilib.js.setTab(domid, self.cookie_name))))
             w(tabkwargs.pop('label', self._cw._(tabid)))
-            w(u'</span>')
             w(u'</a>')
             w(u'</li>')
             if domid == active_tab:
@@ -160,7 +158,12 @@
         # because the callback binding needs to be done before
         # XXX make work history: true
         self._cw.add_onload(u"""
-  jQuery('#entity-tabs-%(eeid)s').tabs( { selected: %(tabindex)s });
+  jQuery('#entity-tabs-%(eeid)s').tabs(
+    { selected: %(tabindex)s,
+      select: function(event, ui) {
+        setTab(ui.panel.id, '%(cookiename)s');
+      }
+    });
   setTab('%(domid)s', '%(cookiename)s');
 """ % {'tabindex'   : active_tab_idx,
        'domid'        : active_tab,
--- a/wsgi/__init__.py	Fri Sep 23 09:17:37 2011 +0200
+++ b/wsgi/__init__.py	Fri Sep 23 14:18:13 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -37,7 +37,7 @@
     """pretty prints `obj` if possible"""
     try:
         return _pformat(obj)
-    except:
+    except Exception:
         return u'<could not parse>'
 
 def qs2dict(qs):