merge stable branch into default
authorNicolas Chauvat <nicolas.chauvat@logilab.fr>
Fri, 29 May 2009 20:22:39 +0200
changeset 2011 758ccc0a9d16
parent 2010 c594323929cb (diff)
parent 2007 62d72d65e50d (current diff)
child 2015 3009899e1e51
merge stable branch into default
server/schemahooks.py
--- a/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -2,7 +2,7 @@
 relations between entitites.
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 :license: Library General Public License version 2 - http://www.gnu.org/licenses
 """
--- a/__pkginfo__.py	Fri May 29 16:11:49 2009 +0200
+++ b/__pkginfo__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,6 +1,7 @@
 # pylint: disable-msg=W0622,C0103
 """cubicweb global packaging information for the cubicweb knowledge management
 software
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
 distname = "cubicweb"
--- a/_exceptions.py	Fri May 29 16:11:49 2009 +0200
+++ b/_exceptions.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/appobject.py	Fri May 29 16:11:49 2009 +0200
+++ b/appobject.py	Fri May 29 20:22:39 2009 +0200
@@ -1,12 +1,13 @@
 """Base class for dynamically loaded objects manipulated in the web interface
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
-from datetime import datetime, timedelta
+from datetime import datetime, timedelta, time
 
 from logilab.common.decorators import classproperty
 from logilab.common.deprecation import obsolete
@@ -17,7 +18,7 @@
 from cubicweb import Unauthorized, NoSelectableObject
 from cubicweb.vregistry import VObject, AndSelector
 from cubicweb.selectors import yes
-from cubicweb.utils import UStringIO, ustrftime
+from cubicweb.utils import UStringIO, ustrftime, strptime, todate, todatetime
 
 ONESECOND = timedelta(0, 1, 0)
 
@@ -187,14 +188,8 @@
         return rql
 
     def view(self, __vid, rset=None, __fallback_vid=None, **kwargs):
-        """shortcut to self.vreg.render method avoiding to pass self.req"""
-        try:
-            view = self.vreg.select_view(__vid, self.req, rset, **kwargs)
-        except NoSelectableObject:
-            if __fallback_vid is None:
-                raise
-            view = self.vreg.select_view(__fallback_vid, self.req, rset, **kwargs)
-        return view.render(**kwargs)
+        """shortcut to self.vreg.view method avoiding to pass self.req"""
+        return self.vreg.view(__vid, self.req, rset, __fallback_vid, **kwargs)
 
     def initialize_varmaker(self):
         varmaker = self.req.get_page_data('rql_varmaker')
@@ -300,6 +295,35 @@
             return self.req.property_value('ui.float-format') % num
         return u''
 
+    def parse_datetime(self, value, etype='Datetime'):
+        """get a datetime or time from a string (according to etype)
+        Datetime formatted as Date are accepted
+        """
+        assert etype in ('Datetime', 'Date', 'Time'), etype
+        # XXX raise proper validation error
+        if etype == 'Datetime':
+            format = self.req.property_value('ui.datetime-format')
+            try:
+                return todatetime(strptime(value, format))
+            except ValueError:
+                pass
+        elif etype == 'Time':
+            format = self.req.property_value('ui.time-format')
+            try:
+                # (adim) I can't find a way to parse a Time with a custom format
+                date = strptime(value, format) # this returns a DateTime
+                return time(date.hour, date.minute, date.second)
+            except ValueError:
+                raise ValueError('can\'t parse %r (expected %s)' % (value, format))
+        try:
+            format = self.req.property_value('ui.date-format')
+            dt = strptime(value, format)
+            if etype == 'Datetime':
+                return todatetime(dt)
+            return todate(dt)
+        except ValueError:
+            raise ValueError('can\'t parse %r (expected %s)' % (value, format))
+
     # security related methods ################################################
 
     def ensure_ro_rql(self, rql):
--- a/common/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 hg stserver side and on the client side
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 from logilab.common.adbh import FunctionDescr
--- a/common/appobject.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/appobject.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""pre 3.2 bw compat"""
+"""pre 3.2 bw compat
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 # pylint: disable-msg=W0614,W0401
 from warnings import warn
 warn('moved to cubicweb.appobject', DeprecationWarning, stacklevel=2)
--- a/common/entity.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/entity.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""pre 3.2 bw compat"""
+"""pre 3.2 bw compat
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 # pylint: disable-msg=W0614,W0401
 from warnings import warn
 warn('moved to cubicweb.entity', DeprecationWarning, stacklevel=2)
--- a/common/i18n.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/i18n.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Some i18n/gettext utilities.
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/common/mail.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/mail.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Common utilies to format / semd emails.
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/common/migration.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/migration.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 version
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/common/mixins.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/mixins.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
@@ -236,8 +237,8 @@
 
     @obsolete('use EntityFieldsForm.subject_in_state_vocabulary')
     def subject_in_state_vocabulary(self, rschema, limit=None):
-        from cubicweb.web.form import EntityFieldsForm
-        return EntityFieldsForm(self.req, None, entity=self).subject_in_state_vocabulary(rschema, limit)
+        form = self.vreg.select_object('forms', 'edition', self.req, entity=self)
+        return form.subject_in_state_vocabulary(rschema, limit)
 
 
 
--- a/common/mttransforms.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/mttransforms.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """mime type transformation engine for cubicweb, based on mtconverter
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/common/schema.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/schema.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""pre 3.0 bw compat"""
+"""pre 3.0 bw compat
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 # pylint: disable-msg=W0614,W0401
 from warnings import warn
 warn('moved to cubicweb.schema', DeprecationWarning, stacklevel=2)
--- a/common/selectors.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/selectors.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""pre 3.2 bw compat"""
+"""pre 3.2 bw compat
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 # pylint: disable-msg=W0614,W0401
 from warnings import warn
 warn('moved to cubicweb.selectors', DeprecationWarning, stacklevel=2)
--- a/common/tags.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/tags.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """helper classes to generate simple (X)HTML tags
 
 :organization: Logilab
-:copyright: 2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/common/test/data/migration/0.0.3_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/test/data/migration/0.0.3_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,8 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 coucou
--- a/common/test/data/migration/0.0.4_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/test/data/migration/0.0.4_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,8 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 coucou
--- a/common/test/data/migration/0.1.0_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/test/data/migration/0.1.0_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,8 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 coucou
--- a/common/test/data/migration/0.1.0_common.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/test/data/migration/0.1.0_common.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,7 @@
-"""common to all configuration"""
+"""common to all configuration
+
+:organization: Logilab
+:copyright: 2001-2009 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/common/test/data/migration/0.1.0_repository.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/test/data/migration/0.1.0_repository.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,7 @@
-"""repository specific"""
+"""repository specific
+
+:organization: Logilab
+:copyright: 2001-2009 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/common/test/data/migration/0.1.0_web.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/test/data/migration/0.1.0_web.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,7 @@
-"""web only"""
+"""web only
+
+:organization: Logilab
+:copyright: 2001-2009 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/common/test/data/migration/0.1.2_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/test/data/migration/0.1.2_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,8 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 coucou
--- a/common/test/data/server_migration/bootstrapmigration_repository.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/test/data/server_migration/bootstrapmigration_repository.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,7 @@
-"""allways executed before all others in server migration"""
+"""allways executed before all others in server migration
+
+:organization: Logilab
+:copyright: 2001-2009 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/common/test/unittest_mail.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/test/unittest_mail.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,11 @@
 # -*- coding: utf-8 -*-
-"""unit tests for module cubicweb.common.mail"""
+"""unit tests for module cubicweb.common.mail
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 import os
 import pwd
--- a/common/test/unittest_migration.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/test/unittest_migration.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""cubicweb.common.migration unit tests"""
+"""cubicweb.common.migration unit tests
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from os.path import abspath
 from logilab.common.testlib import TestCase, unittest_main
--- a/common/test/unittest_mixins.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/test/unittest_mixins.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.testlib import unittest_main
 from cubicweb.devtools.apptest import EnvBasedTC
 
--- a/common/test/unittest_uilib.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/test/unittest_uilib.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,11 @@
 # -*- coding: utf-8 -*-
-"""unittests for cubicweb.common.uilib"""
+"""unittests for cubicweb.common.uilib
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 __docformat__ = "restructuredtext en"
 
--- a/common/uilib.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/uilib.py	Fri May 29 20:22:39 2009 +0200
@@ -4,8 +4,9 @@
 contains some functions designed to help implementation of cubicweb user interface
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/common/utils.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/utils.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""pre 3.2 bw compat"""
+"""pre 3.2 bw compat
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 # pylint: disable-msg=W0614,W0401
 from warnings import warn
 warn('moved to cubicweb.utils', DeprecationWarning, stacklevel=2)
--- a/common/view.py	Fri May 29 16:11:49 2009 +0200
+++ b/common/view.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""pre 3.2 bw compat"""
+"""pre 3.2 bw compat
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 # pylint: disable-msg=W0614,W0401
 from warnings import warn
 warn('moved to cubicweb.view', DeprecationWarning, stacklevel=2)
--- a/cwconfig.py	Fri May 29 16:11:49 2009 +0200
+++ b/cwconfig.py	Fri May 29 20:22:39 2009 +0200
@@ -2,13 +2,14 @@
 """common configuration utilities for cubicweb
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 
 .. envvar:: CW_CUBES_PATH
 
    Augments the default search path for cubes
 
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
--- a/cwctl.py	Fri May 29 16:11:49 2009 +0200
+++ b/cwctl.py	Fri May 29 20:22:39 2009 +0200
@@ -1,6 +1,7 @@
 """%%prog %s [options] %s
 
 CubicWeb main applications controller.
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 %s"""
 
 import sys
--- a/cwvreg.py	Fri May 29 16:11:49 2009 +0200
+++ b/cwvreg.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """extend the generic VRegistry with some cubicweb specific stuff
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
@@ -248,6 +249,16 @@
                 self.exception('error while trying to list possible %s views for %s',
                                vid, rset)
 
+    def view(self, __vid, req, rset=None, __fallback_vid=None, **kwargs):
+        """shortcut to self.vreg.render method avoiding to pass self.req"""
+        try:
+            view = self.select_view(__vid, req, rset, **kwargs)
+        except NoSelectableObject:
+            if __fallback_vid is None:
+                raise
+            view = self.select_view(__fallback_vid, req, rset, **kwargs)
+        return view.render(**kwargs)
+
     def select_box(self, oid, *args, **kwargs):
         """return the most specific view according to the result set"""
         try:
@@ -269,12 +280,11 @@
         except (NoSelectableObject, ObjectNotFound):
             return
 
-    def select_view(self, __vid, req, rset, **kwargs):
+    def select_view(self, __vid, req, rset=None, **kwargs):
         """return the most specific view according to the result set"""
         views = self.registry_objects('views', __vid)
         return self.select(views, req, rset, **kwargs)
 
-
     # properties handling #####################################################
 
     def user_property_keys(self, withsitewide=False):
--- a/dbapi.py	Fri May 29 16:11:49 2009 +0200
+++ b/dbapi.py	Fri May 29 20:22:39 2009 +0200
@@ -5,8 +5,9 @@
 (most parts of this document are reported here in docstrings)
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/devtools/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Test tools for cubicweb
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
@@ -328,7 +329,7 @@
         pass
     if removecube:
         try:
-            os.remove('%s-cube' % dbfile)
+            os.remove('%s-template' % dbfile)
         except OSError:
             pass
 
@@ -338,11 +339,11 @@
     # remove database file if it exists (actually I know driver == 'sqlite' :)
     dbfile = source['system']['db-name']
     cleanup_sqlite(dbfile)
-    cube = '%s-cube' % dbfile
-    if exists(cube):
-        shutil.copy(cube, dbfile)
+    template = '%s-template' % dbfile
+    if exists(template):
+        shutil.copy(template, dbfile)
     else:
         # initialize the database
         from cubicweb.server import init_repository
         init_repository(config, interactive=False, vreg=vreg)
-        shutil.copy(dbfile, cube)
+        shutil.copy(dbfile, template)
--- a/devtools/_apptest.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/_apptest.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Hidden internals for the devtools.apptest module
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/devtools/apptest.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/apptest.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """This module provides misc utilities to test applications
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/devtools/cwtwill.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/cwtwill.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """cubicweb extensions for twill
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 import re
--- a/devtools/devctl.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/devctl.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 cubes development
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/devtools/fake.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/fake.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Fake objects to ease testing of cubicweb without a fully working environment
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/devtools/fill.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/fill.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 """This modules defines func / methods for creating test repositories
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/devtools/htmlparser.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/htmlparser.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""defines a validating HTML parser used in web application tests"""
+"""defines a validating HTML parser used in web application tests
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 import re
 
--- a/devtools/livetest.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/livetest.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """provide utilies for web (live) unit testing
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 import socket
--- a/devtools/migrtest.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/migrtest.py	Fri May 29 20:22:39 2009 +0200
@@ -27,11 +27,12 @@
 
 The permissions on .pgpass must disallow any access to world or group;
 achieve this by the command chmod 0600 ~/.pgpass. If the permissions
-are less strict than this, the file will be ignored. 
+are less strict than this, the file will be ignored.
 
 :organization: Logilab
-:copyright: 2001-2006 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/devtools/pkginfo.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/pkginfo.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""distutils / __pkginfo__ helpers for cubicweb applications"""
+"""distutils / __pkginfo__ helpers for cubicweb applications
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 import os
 from os.path import isdir, join
--- a/devtools/repotest.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/repotest.py	Fri May 29 20:22:39 2009 +0200
@@ -3,8 +3,9 @@
 This module contains functions to initialize a new repository.
 
 :organization: Logilab
-:copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2003-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/devtools/stresstester.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/stresstester.py	Fri May 29 20:22:39 2009 +0200
@@ -21,8 +21,9 @@
   -o / --report-output <filename>
      Write profiler report into <filename> rather than on stdout
 
-Copyright (c) 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+Copyright (c) 2003-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
 http://www.logilab.fr/ -- mailto:contact@logilab.fr
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
 __revision__ = "$Id: stresstester.py,v 1.3 2006-03-05 14:35:27 syt Exp $"
--- a/devtools/test/data/schema/custom.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/test/data/schema/custom.py	Fri May 29 20:22:39 2009 +0200
@@ -1,2 +1,9 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 Person = import_erschema('Person')
 Person.add_relation(Date(), 'birthday')
--- a/devtools/test/data/views/bug.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/test/data/views/bug.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""only for unit tests !"""
+"""only for unit tests !
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from cubicweb.view import EntityView
 from cubicweb.selectors import implements
--- a/devtools/test/unittest_dbfill.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/test/unittest_dbfill.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,11 @@
 # -*- coding: iso-8859-1 -*-
-"""unit tests for database value generator"""
+"""unit tests for database value generator
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 import os.path as osp
 import re
--- a/devtools/test/unittest_fill.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/test/unittest_fill.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""unit tests for cubicweb.devtools.fill module"""
+"""unit tests for cubicweb.devtools.fill module
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from logilab.common.testlib import TestCase, unittest_main
 
--- a/devtools/test/unittest_testlib.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/test/unittest_testlib.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""unittests for gct.apptest module"""
+"""unittests for gct.apptest module
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from cStringIO import StringIO
 from unittest import TestSuite
--- a/devtools/testlib.py	Fri May 29 16:11:49 2009 +0200
+++ b/devtools/testlib.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """this module contains base classes for web tests
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/doc/book/en/conf.py	Fri May 29 16:11:49 2009 +0200
+++ b/doc/book/en/conf.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,11 @@
 # -*- coding: utf-8 -*-
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 #
 # Cubicweb documentation build configuration file, created by
 # sphinx-quickstart on Fri Oct 31 09:10:36 2008.
--- a/doc/book/fr/conf.py	Fri May 29 16:11:49 2009 +0200
+++ b/doc/book/fr/conf.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,11 @@
 # -*- coding: utf-8 -*-
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 #
 # Cubicweb documentation build configuration file, created by
 # sphinx-quickstart on Fri Oct 31 09:10:36 2008.
--- a/doc/book/mode_plan.py	Fri May 29 16:11:49 2009 +0200
+++ b/doc/book/mode_plan.py	Fri May 29 20:22:39 2009 +0200
@@ -5,6 +5,7 @@
 >>> ren('A01','A03')
 rename A010-joe.en.txt to A030-joe.en.txt
 accept [y/N]?
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
 def ren(a,b):
--- a/doc/tools/generate_modules.py	Fri May 29 16:11:49 2009 +0200
+++ b/doc/tools/generate_modules.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""generate list of modules for sphinx doc"""
+"""generate list of modules for sphinx doc
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 import sys
 
--- a/entities/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/entities/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """base application's entities class implementation: `AnyEntity`
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
@@ -241,13 +242,13 @@
 
     @obsolete('use EntityFieldsForm.subject_relation_vocabulary')
     def subject_relation_vocabulary(self, rtype, limit):
-        from cubicweb.web.form import EntityFieldsForm
-        return EntityFieldsForm(self.req, None, entity=self).subject_relation_vocabulary(rtype, limit)
+        form = self.vreg.select_object('forms', 'edition', self.req, entity=self)
+        return form.subject_relation_vocabulary(rtype, limit)
 
     @obsolete('use EntityFieldsForm.object_relation_vocabulary')
     def object_relation_vocabulary(self, rtype, limit):
-        from cubicweb.web.form import EntityFieldsForm
-        return EntityFieldsForm(self.req, None, entity=self).object_relation_vocabulary(rtype, limit)
+        form = self.vreg.select_object('forms', 'edition', self.req, entity=self)
+        return form.object_relation_vocabulary(rtype, limit)
 
     @obsolete('use AutomaticEntityForm.[e]relations_by_category')
     def relations_by_category(self, categories=None, permission=None):
--- a/entities/authobjs.py	Fri May 29 16:11:49 2009 +0200
+++ b/entities/authobjs.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """entity classes user and group entities
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/entities/lib.py	Fri May 29 16:11:49 2009 +0200
+++ b/entities/lib.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """entity classes for optional library entities
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/entities/schemaobjs.py	Fri May 29 16:11:49 2009 +0200
+++ b/entities/schemaobjs.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """schema definition related entities
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
@@ -19,7 +20,7 @@
     fetch_attrs, fetch_order = fetch_config(['name'])
 
     def dc_title(self):
-        return self.req._(self.name)
+        return u'%s (%s)' % (self.name, self.req._(self.name))
 
     def dc_long_title(self):
         stereotypes = []
@@ -42,7 +43,7 @@
     fetch_attrs, fetch_order = fetch_config(['name'])
 
     def dc_title(self):
-        return self.req._(self.name)
+        return u'%s (%s)' % (self.name, self.req._(self.name))
 
     def dc_long_title(self):
         stereotypes = []
--- a/entities/test/data/schema.py	Fri May 29 16:11:49 2009 +0200
+++ b/entities/test/data/schema.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 class Company(EntityType):
     name = String()
 
--- a/entities/test/unittest_base.py	Fri May 29 16:11:49 2009 +0200
+++ b/entities/test/unittest_base.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,11 @@
 # -*- coding: utf-8 -*-
-"""unit tests for cubicweb.entities.base module"""
+"""unit tests for cubicweb.entities.base module
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from logilab.common.testlib import unittest_main
 from logilab.common.decorators import clear_cache
--- a/entities/wfobjs.py	Fri May 29 16:11:49 2009 +0200
+++ b/entities/wfobjs.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """workflow definition and history related entities
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/entity.py	Fri May 29 16:11:49 2009 +0200
+++ b/entity.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Base class for entity objects manipulated in clients
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
@@ -723,9 +724,8 @@
         If `eid` is None in one of these couples, it should be
         interpreted as a separator in case vocabulary results are grouped
         """
-        from cubicweb.web.form import EntityFieldsForm
         from logilab.common.testlib import mock_object
-        form = EntityFieldsForm(self.req, entity=self)
+        form = self.vreg.select_object('forms', 'edition', self.req, entity=self)
         field = mock_object(name=rtype, role=role)
         return form.form_field_vocabulary(field, limit)
 
--- a/etwist/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/etwist/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,2 +1,8 @@
-""" CW - nevow/twisted client """
+""" CW - nevow/twisted client 
 
+:organization: Logilab
+:copyright: 2001-2009 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/etwist/request.py	Fri May 29 16:11:49 2009 +0200
+++ b/etwist/request.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Twisted request handler for CubicWeb
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/etwist/server.py	Fri May 29 16:11:49 2009 +0200
+++ b/etwist/server.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """twisted server for CubicWeb web applications
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
@@ -196,7 +197,7 @@
         if self.url_rewriter is not None:
             # XXX should occur before authentication?
             try:
-                path = self.url_rewriter.rewrite(host, origpath)
+                path = self.url_rewriter.rewrite(host, origpath, req)
             except Redirect, ex:
                 return self.redirect(req, ex.location)
             request.uri.replace(origpath, path, 1)
--- a/etwist/test/unittest_server.py	Fri May 29 16:11:49 2009 +0200
+++ b/etwist/test/unittest_server.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.devtools.apptest import EnvBasedTC
 from cubicweb.etwist.server import host_prefixed_baseurl
 
--- a/etwist/twconfig.py	Fri May 29 16:11:49 2009 +0200
+++ b/etwist/twconfig.py	Fri May 29 20:22:39 2009 +0200
@@ -8,8 +8,9 @@
   if the repository part of the software is installed
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/etwist/twctl.py	Fri May 29 16:11:49 2009 +0200
+++ b/etwist/twctl.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """cubicweb-clt handlers for twisted
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 import sys
--- a/ext/html4zope.py	Fri May 29 16:11:49 2009 +0200
+++ b/ext/html4zope.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,11 @@
 # Author: David Goodger
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 # Contact: goodger@users.sourceforge.net
 # Revision: $Revision: 1.2 $
 # Date: $Date: 2005-07-04 16:36:50 $
--- a/ext/rest.py	Fri May 29 16:11:49 2009 +0200
+++ b/ext/rest.py	Fri May 29 20:22:39 2009 +0200
@@ -13,8 +13,9 @@
 * `sourcecode` (if pygments is installed), source code colorization
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/ext/tal.py	Fri May 29 16:11:49 2009 +0200
+++ b/ext/tal.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """provides simpleTAL extensions for CubicWeb
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 __docformat__ = "restructuredtext en"
--- a/ext/test/unittest_rest.py	Fri May 29 16:11:49 2009 +0200
+++ b/ext/test/unittest_rest.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.testlib import unittest_main
 from cubicweb.devtools.apptest import EnvBasedTC
 
--- a/gettext.py	Fri May 29 16:11:49 2009 +0200
+++ b/gettext.py	Fri May 29 20:22:39 2009 +0200
@@ -8,6 +8,7 @@
 languages.  L10N refers to the adaptation of your program, once
 internationalized, to the local language and cultural habits.
 
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
 # This module represents the integration of work, contributions, feedback, and
--- a/goa/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """cubicweb on google appengine
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/appobjects/components.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/appobjects/components.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """overrides some base views for cubicweb on google appengine
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/appobjects/dbmgmt.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/appobjects/dbmgmt.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 restoration).
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/appobjects/gauthservice.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/appobjects/gauthservice.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """authentication using google authentication service
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/appobjects/sessions.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/appobjects/sessions.py	Fri May 29 20:22:39 2009 +0200
@@ -1,12 +1,13 @@
 """persistent sessions stored in big table
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 
 XXX TODO:
 * cleanup persistent session
 * use user as ancestor?
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/db.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/db.py	Fri May 29 20:22:39 2009 +0200
@@ -25,8 +25,9 @@
 * XXX ListProperty
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/dbinit.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/dbinit.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """some utility functions for datastore initialization.
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/dbmyams.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/dbmyams.py	Fri May 29 20:22:39 2009 +0200
@@ -6,8 +6,9 @@
 
 XXX proprify this knowing we'll use goa.db
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 
 from os.path import join
--- a/goa/gaesource.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/gaesource.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Adapter for google appengine source.
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/goaconfig.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/goaconfig.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """google appengine configuration
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/goactl.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/goactl.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """cubicweb on appengine plugins for cubicweb-ctl
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/goavreg.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/goavreg.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """goa specific registry
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/overrides/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/overrides/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,8 @@
 # server.__init__
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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/goa/overrides/mttransforms.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/overrides/mttransforms.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """mime type transformation engine for cubicweb, based on mtconverter
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/overrides/rqlannotation.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/overrides/rqlannotation.py	Fri May 29 20:22:39 2009 +0200
@@ -1,7 +1,8 @@
 """
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/overrides/server__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/overrides/server__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,11 @@
 # server debugging flag
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 DEBUG = False
 
 # sqlite'stored procedures have to be registered at connexion opening time
--- a/goa/overrides/server_utils.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/overrides/server_utils.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 class RepoThread(object):
     def __init__(self, *args):
--- a/goa/overrides/toolsutils.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/overrides/toolsutils.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 import sys
 from cubicweb import warning
 
--- a/goa/rqlinterpreter.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/rqlinterpreter.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """provide a minimal RQL support for google appengine dbmodel
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/skel/custom.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/skel/custom.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 def postinit(vreg):
     """this callback is called at the end of initialization process
     and can be used to load explicit modules (views or entities).
--- a/goa/skel/loader.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/skel/loader.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 if __name__ == '__main__':
 
     from os.path import dirname, abspath
--- a/goa/skel/main.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/skel/main.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 to change anything here.
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/skel/schema.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/skel/schema.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.schema import format_constraint
 
 class Blog(EntityType):
--- a/goa/skel/views.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/skel/views.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,11 @@
 # custom application views
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from datetime import date
 
 from cubicweb.utils import last_day
--- a/goa/test/data/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/test/data/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,7 @@
-"""zou"""
+"""zou
+
+:organization: Logilab
+:copyright: 2001-2009 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/goa/test/data/schema.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/test/data/schema.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 
 class YamsEntity(EntityType):
--- a/goa/test/data/settings.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/test/data/settings.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,8 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 TEMPLATE_DEBUG = False
--- a/goa/test/data/views.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/test/data/views.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,11 @@
 # -*- coding: utf-8 -*-
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 import os
 os.environ["DJANGO_SETTINGS_MODULE"] = 'data.settings'
 
--- a/goa/test/pytestconf.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/test/pytestconf.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,5 @@
 """this pytestconf automatically adds the mx's python version in the PYTHONPATH
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 import sys
 import os.path as osp
--- a/goa/test/unittest_db.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/test/unittest_db.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,11 @@
 # -*- coding: utf-8 -*-
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.goa.testlib import *
 
 from cubicweb import Binary
--- a/goa/test/unittest_editcontroller.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/test/unittest_editcontroller.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.goa.testlib import *
 
 from urllib import unquote
--- a/goa/test/unittest_metadata.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/test/unittest_metadata.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.goa.testlib import *
 
 import time
--- a/goa/test/unittest_rql.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/test/unittest_rql.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.goa.testlib import *
 
 from cubicweb import Binary
--- a/goa/test/unittest_schema.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/test/unittest_schema.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.goa.testlib import *
 
 class Article(db.Model):
--- a/goa/test/unittest_views.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/test/unittest_views.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.goa.testlib import *
 
 from cubicweb.interfaces import ICalendarable
--- a/goa/testlib.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/testlib.py	Fri May 29 20:22:39 2009 +0200
@@ -1,7 +1,8 @@
 """
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/goa/tools/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/tools/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,7 @@
-"""lax tools cube"""
+"""lax tools cube
+
+:organization: Logilab
+:copyright: 2001-2009 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/goa/tools/generate_schema_img.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/tools/generate_schema_img.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 import sys
 from os.path import dirname, abspath, join
 from yams import schema2dot
--- a/goa/tools/laxctl.py	Fri May 29 16:11:49 2009 +0200
+++ b/goa/tools/laxctl.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """provides all lax instances management commands into a single utility script
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/hercule.py	Fri May 29 16:11:49 2009 +0200
+++ b/hercule.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """RQL client for cubicweb, connecting to application using pyro
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/interfaces.py	Fri May 29 16:11:49 2009 +0200
+++ b/interfaces.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Specific views for entities implementing IDownloadable
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 __docformat__ = "restructuredtext en"
--- a/md5crypt.py	Fri May 29 16:11:49 2009 +0200
+++ b/md5crypt.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,11 @@
 #########################################################
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 # md5crypt.py
 #
 # 0423.2000 by michal wallace http://www.sabren.com/
--- a/misc/cwdesklets/rqlsensor/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/cwdesklets/rqlsensor/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 import webbrowser
 reload(webbrowser)
 
--- a/misc/cwfs/cwfs.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/cwfs/cwfs.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 class Schema :
 
     def __init__(self, schema) :
--- a/misc/cwfs/cwfs_test.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/cwfs/cwfs_test.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.testlib import TestCase, unittest_main
 
 import cubicwebfs
--- a/misc/cwzope/cwzope.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/cwzope/cwzope.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from AccessControl import getSecurityManager 
 
 from cubicweb.dbapi import connect, Connection, Cursor
--- a/misc/migration/2.42.0_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/migration/2.42.0_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,2 +1,9 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 synchronize_rschema('created_by')
 synchronize_rschema('owned_by')
--- a/misc/migration/2.42.1_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/migration/2.42.1_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 if confirm('remove deprecated database constraints?'):
     execute = session.system_sql
     session.set_pool()
--- a/misc/migration/2.43.0_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/migration/2.43.0_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,8 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 synchronize_permissions('EmailAddress')
--- a/misc/migration/2.44.0_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/migration/2.44.0_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 change_relation_props('CWAttribute', 'cardinality', 'String', internationalizable=True)
 change_relation_props('CWRelation', 'cardinality', 'String', internationalizable=True)
 
--- a/misc/migration/2.45.0_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/migration/2.45.0_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,11 @@
 # following functions have been renamed, but keep old definition for bw compat
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 sql('''CREATE AGGREGATE group_concat (
   basetype = anyelement,
   sfunc = array_append,
--- a/misc/migration/2.46.0_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/migration/2.46.0_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 
 rql('SET X value "navtop" WHERE X pkey ~= "contentnavigation.%.context", X value "header"')
--- a/misc/migration/2.47.0_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/migration/2.47.0_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 synchronize_permissions('primary_email')
 synchronize_rschema('wf_info_for')
 synchronize_rschema('use_email')
--- a/misc/migration/2.48.8_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/migration/2.48.8_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,2 +1,9 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 for etype in ('CWRType', 'CWAttribute', 'CWRelation', 'CWConstraint', 'CWConstraintType'):
     synchronize_permissions(etype)
--- a/misc/migration/2.49.3_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/migration/2.49.3_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,8 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 add_entity_type('Decimal')
--- a/misc/migration/2.50.0_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/migration/2.50.0_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,8 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 add_relation_type('specializes')
--- a/misc/migration/2.99.0_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/migration/2.99.0_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb import CW_MIGRATION_MAP
 
 for pk, in rql('Any K WHERE X is CWProperty, X pkey IN (%s), X pkey K'
--- a/misc/migration/3.1.5_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/migration/3.1.5_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,8 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 synchronize_permissions('condition')
--- a/misc/migration/3.2.0_Any.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/migration/3.2.0_Any.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 rql('SET X value "main-template" WHERE X is CWProperty, '
     'X pkey "ui.main-template", X value "main"')
 checkpoint()
--- a/misc/migration/bootstrapmigration_repository.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/migration/bootstrapmigration_repository.py	Fri May 29 20:22:39 2009 +0200
@@ -3,8 +3,9 @@
 it should only include low level schema changes
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 if applcubicwebversion < (3, 2, 2) and cubicwebversion >= (3, 2, 1):
--- a/misc/migration/postcreate.py	Fri May 29 16:11:49 2009 +0200
+++ b/misc/migration/postcreate.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""cubicweb post creation script, set user's workflow"""
+"""cubicweb post creation script, set user's workflow
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 activatedeid = add_state(_('activated'), 'CWUser', initial=True)
 deactivatedeid = add_state(_('deactivated'), 'CWUser')
--- a/rset.py	Fri May 29 16:11:49 2009 +0200
+++ b/rset.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """The `ResultSet` class which is returned as result of a rql query
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/rtags.py	Fri May 29 16:11:49 2009 +0200
+++ b/rtags.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """relation tags store
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/schema.py	Fri May 29 16:11:49 2009 +0200
+++ b/schema.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """classes to define schemas for CubicWeb
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/schemas/Bookmark.py	Fri May 29 16:11:49 2009 +0200
+++ b/schemas/Bookmark.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 class Bookmark(MetaUserEntityType):
     """define an entity type, used to build the application schema"""
--- a/schemas/base.py	Fri May 29 16:11:49 2009 +0200
+++ b/schemas/base.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """core CubicWeb schema, but not necessary at bootstrap time
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/schemas/bootstrap.py	Fri May 29 16:11:49 2009 +0200
+++ b/schemas/bootstrap.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """core CubicWeb schema necessary for bootstrapping the actual application's schema
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 from cubicweb.schema import format_constraint
@@ -57,7 +58,7 @@
     constrained_by = SubjectRelation('CWConstraint', cardinality='*1', composite='subject')
 
     cardinality = String(maxsize=2, internationalizable=True,
-                         vocabulary=[_('?1'), _('11'), _('??'), _('1?')],
+                         vocabulary=[_('?1'), _('11')],
                          description=_('subject/object cardinality'))
     ordernum = Int(description=('control subject entity\'s relations order'), default=0)
 
--- a/schemas/workflow.py	Fri May 29 16:11:49 2009 +0200
+++ b/schemas/workflow.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """workflow related schemas
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 class State(MetaEntityType):
--- a/schemaviewer.py	Fri May 29 16:11:49 2009 +0200
+++ b/schemaviewer.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """an helper class to display CubicWeb schema using ureports
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
@@ -93,10 +94,10 @@
         return data
 
     def eschema_link_url(self, eschema):
-        return self.req.build_url('cwetype/%s?vid=eschema' % eschema)
+        return self.req.build_url('cwetype/%s' % eschema)
 
     def rschema_link_url(self, rschema):
-        return self.req.build_url('cwrtype/%s?vid=eschema' % rschema)
+        return self.req.build_url('cwrtype/%s' % rschema)
 
     def possible_views(self, etype):
         rset = self.req.etype_rset(etype)
--- a/selectors.py	Fri May 29 16:11:49 2009 +0200
+++ b/selectors.py	Fri May 29 20:22:39 2009 +0200
@@ -36,10 +36,10 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
-
 __docformat__ = "restructuredtext en"
 
 import logging
@@ -245,6 +245,7 @@
         if kwargs.get('entity'):
             score = self.score_entity(kwargs['entity'])
         elif row is None:
+            col = col or 0
             for row, rowvalue in enumerate(rset.rows):
                 if rowvalue[col] is None: # outer join
                     continue
@@ -255,6 +256,7 @@
                     return escore
                 score += escore
         else:
+            col = col or 0
             etype = rset.description[row][col]
             if etype is not None: # outer join
                 score = self.score(req, rset, row, col)
@@ -273,9 +275,13 @@
 # very basic selectors ########################################################
 
 class yes(Selector):
-    """return arbitrary score"""
-    def __init__(self, score=1):
+    """return arbitrary score
+
+    default score of 0.5 so any other selector take precedence
+    """
+    def __init__(self, score=0.5):
         self.score = score
+
     def __call__(self, *args, **kwargs):
         return self.score
 
--- a/server/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -4,8 +4,9 @@
 This module contains functions to initialize a new repository.
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/checkintegrity.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/checkintegrity.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 is checked.
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/hookhelper.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/hookhelper.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """helper functions for application hooks
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/hooks.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/hooks.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 entities...
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/hooksmanager.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/hooksmanager.py	Fri May 29 20:22:39 2009 +0200
@@ -23,8 +23,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/migractions.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/migractions.py	Fri May 29 20:22:39 2009 +0200
@@ -11,8 +11,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/msplanner.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/msplanner.py	Fri May 29 20:22:39 2009 +0200
@@ -70,8 +70,9 @@
 
 
 :organization: Logilab
-:copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2003-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/mssteps.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/mssteps.py	Fri May 29 20:22:39 2009 +0200
@@ -6,8 +6,9 @@
   for now)
 
 :organization: Logilab
-:copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2003-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/pool.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/pool.py	Fri May 29 20:22:39 2009 +0200
@@ -11,8 +11,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/querier.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/querier.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 security checking and data aggregation.
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/repository.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/repository.py	Fri May 29 20:22:39 2009 +0200
@@ -11,8 +11,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/rqlannotation.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/rqlannotation.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 code generation.
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/rqlrewrite.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/rqlrewrite.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """RQL rewriting utilities, used for read security checking
 
 :organization: Logilab
-:copyright: 2007-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2007-2009 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
 """
 
 from rql import nodes, stmts, TypeResolverException
--- a/server/schemaserial.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/schemaserial.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """functions for schema / permissions (de)serialization using RQL
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/securityhooks.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/securityhooks.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 the user connected to a session
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/server.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/server.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Pyro RQL server
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/serverconfig.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/serverconfig.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """server.serverconfig definition
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/serverctl.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/serverctl.py	Fri May 29 20:22:39 2009 +0200
@@ -1,11 +1,13 @@
 """cubicweb-ctl commands and command handlers specific to the server.serverconfig
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
+import sys
 import os
 
 from logilab.common.configuration import REQUIRED, Configuration, ini_format_section
@@ -117,7 +119,7 @@
                     _sconfig.set_option(attr, val)
             sconfig = _sconfig
         optsbysect = list(sconfig.options_by_section())
-        assert len(optsbysect) == 1
+        assert len(optsbysect) == 1, 'all options for a source should be in the same group'
         ini_format_section(stream, uri, optsbysect[0][1])
         if hasattr(sconfig, 'adapter'):
             print >> stream
@@ -418,6 +420,51 @@
             cnx.commit()
             print 'grants given to %s on application %s' % (appid, user)
 
+class ResetAdminPasswordCommand(Command):
+    """Reset the administrator password.
+
+    <application>
+      the identifier of the application
+    """
+    name = 'reset-admin-pwd'
+    arguments = '<application>'
+
+    def run(self, args):
+        """run the command with its specific arguments"""
+        from cubicweb.server.sqlutils import sqlexec, SQL_PREFIX
+        from cubicweb.server.utils import crypt_password, manager_userpasswd
+        appid = pop_arg(args, 1, msg="No application specified !")
+        config = ServerConfiguration.config_for(appid)
+        sourcescfg = config.sources()
+        try:
+            adminlogin = sourcescfg['admin']['login']
+        except KeyError:
+            print 'could not get cubicweb administrator login'
+            sys.exit(1)
+        cnx = source_cnx(sourcescfg['system'])
+        cursor = cnx.cursor()
+        _, passwd = manager_userpasswd(adminlogin, confirm=True,
+                                       passwdmsg='new password for %s' % adminlogin)
+        try:
+            sqlexec("UPDATE %(sp)sCWUser SET %(sp)supassword='%(p)s' WHERE %(sp)slogin='%(l)s'"
+                    % {'sp': SQL_PREFIX,
+                       'p': crypt_password(passwd), 'l': adminlogin},
+                    cursor, withpb=False)
+            sconfig = Configuration(options=USER_OPTIONS)
+            sconfig['login'] = adminlogin
+            sconfig['password'] = passwd
+            sourcescfg['admin'] = sconfig
+            sourcesfile = config.sources_file()
+            generate_sources_file(sourcesfile, sourcescfg)
+            restrict_perms_to_user(sourcesfile)
+        except Exception, ex:
+            cnx.rollback()
+            import traceback
+            traceback.print_exc()
+            print 'An error occured:', ex
+        else:
+            cnx.commit()
+            print 'password reset, sources file regenerated'
 
 
 class StartRepositoryCommand(Command):
@@ -735,6 +782,7 @@
 register_commands( (CreateApplicationDBCommand,
                     InitApplicationCommand,
                     GrantUserOnApplicationCommand,
+                    ResetAdminPasswordCommand,
                     StartRepositoryCommand,
                     DBDumpCommand,
                     DBRestoreCommand,
--- a/server/session.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/session.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Repository users' and internal' sessions.
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/sources/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/sources/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """cubicweb server sources support
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/sources/extlite.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/sources/extlite.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """provide an abstract class for external sources using a sqlite database helper
 
 :organization: Logilab
-:copyright: 2007-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2007-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/sources/ldapuser.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/sources/ldapuser.py	Fri May 29 20:22:39 2009 +0200
@@ -3,7 +3,7 @@
 this source is for now limited to a read-only CWUser source
 
 :organization: Logilab
-:copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 
 
@@ -18,6 +18,7 @@
 WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
 FOR A PARTICULAR PURPOSE.
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
 from base64 import b64decode
--- a/server/sources/native.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/sources/native.py	Fri May 29 20:22:39 2009 +0200
@@ -7,8 +7,9 @@
   it for fast querying.
   
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/sources/pyrorql.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/sources/pyrorql.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Source to query another RQL repository using pyro
 
 :organization: Logilab
-:copyright: 2007-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2007-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/sources/rql2sql.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/sources/rql2sql.py	Fri May 29 20:22:39 2009 +0200
@@ -25,8 +25,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/sqlutils.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/sqlutils.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """SQL utilities functions and classes.
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/ssplanner.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/ssplanner.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """plan execution of rql queries on a single source
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/server/test/data/config1/application_hooks.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/data/config1/application_hooks.py	Fri May 29 20:22:39 2009 +0200
@@ -2,6 +2,7 @@
 
  Copyright (c) 2003-2007 LOGILAB S.A. (Paris, FRANCE).
  http://www.logilab.fr/ -- mailto:contact@logilab.fr
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
 HOOKS = {"after_add_relation" : {"concerned_by" : [lambda: None]}}
--- a/server/test/data/config2/application_hooks.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/data/config2/application_hooks.py	Fri May 29 20:22:39 2009 +0200
@@ -2,6 +2,7 @@
 
  Copyright (c) 2003-2007 LOGILAB S.A. (Paris, FRANCE).
  http://www.logilab.fr/ -- mailto:contact@logilab.fr
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
 HOOKS = {"after_delete_relation" : {"todo_by" : [lambda: 1]}}
--- a/server/test/data/extern_mapping.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/data/extern_mapping.py	Fri May 29 20:22:39 2009 +0200
@@ -1,2 +1,9 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 support_entities = {'Card': True, 'Affaire': True, 'State': True}
 support_relations = {'in_state': True, 'documented_by': True, 'multisource_inlined_rel': True}
--- a/server/test/data/hooks.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/data/hooks.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.server.hooksmanager import SystemHook
 
 CALLED_EVENTS = {}
--- a/server/test/data/migration/postcreate.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/data/migration/postcreate.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""cubicweb post creation script, set note's workflow"""
+"""cubicweb post creation script, set note's workflow
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 todoeid = add_state(u'todo', 'Note', initial=True)
 doneeid = add_state(u'done', 'Note')
--- a/server/test/data/migrschema/Affaire.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/data/migrschema/Affaire.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 class Affaire(EntityType):
     permissions = {
--- a/server/test/data/migrschema/Folder2.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/data/migrschema/Folder2.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.schema import format_constraint
 
 class Folder2(MetaUserEntityType):
--- a/server/test/data/migrschema/Note.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/data/migrschema/Note.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 class Note(EntityType):
 
     permissions = {'read':   ('managers', 'users', 'guests',),
--- a/server/test/data/schema/Affaire.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/data/schema/Affaire.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.schema import format_constraint
 
 class Affaire(WorkflowableEntityType):
--- a/server/test/data/schema/Societe.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/data/schema/Societe.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 class Societe(EntityType):
     permissions = {
         'read': ('managers', 'users', 'guests'),
--- a/server/test/data/schema/custom.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/data/schema/custom.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 
 class test(AttributeRelationType):
--- a/server/test/data/schema/note.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/data/schema/note.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 class para(AttributeRelationType):
     permissions = {
--- a/server/test/data/site_erudi.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/data/site_erudi.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.adbh import FunctionDescr
 from rql.utils import register_function
 
--- a/server/test/unittest_checkintegrity.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_checkintegrity.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 import sys
 from StringIO import StringIO
 from logilab.common.testlib import TestCase, unittest_main
--- a/server/test/unittest_config.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_config.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""tests for server config"""
+"""tests for server config
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from os.path import join, dirname
 
--- a/server/test/unittest_hookhelper.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_hookhelper.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,11 @@
 # -*- coding: utf-8 -*-
-"""unit/functional tests for cubicweb.server.hookhelper"""
+"""unit/functional tests for cubicweb.server.hookhelper
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from logilab.common.testlib import unittest_main
 from cubicweb.devtools.apptest import RepositoryBasedTC
--- a/server/test/unittest_hooksmanager.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_hooksmanager.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,5 @@
 """unit tests for the hooks manager
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
 from logilab.common.testlib import TestCase, unittest_main
--- a/server/test/unittest_ldapuser.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_ldapuser.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""cubicweb.server.sources.ldapusers unit and functional tests"""
+"""cubicweb.server.sources.ldapusers unit and functional tests
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from logilab.common.testlib import TestCase, unittest_main, mock_object
 from cubicweb.devtools import init_test_database, TestServerConfiguration
--- a/server/test/unittest_migractions.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_migractions.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,5 @@
 """unit tests for module cubicweb.server.migractions
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
 from datetime import date
--- a/server/test/unittest_msplanner.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_msplanner.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.decorators import clear_cache
 from cubicweb.devtools import init_test_database
 from cubicweb.devtools.repotest import BasePlannerTC, do_monkey_patch, undo_monkey_patch, test_plan
--- a/server/test/unittest_multisources.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_multisources.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from os.path import dirname, join, abspath
 from datetime import datetime, timedelta
 
--- a/server/test/unittest_querier.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_querier.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,6 @@
 # -*- coding: iso-8859-1 -*-
 """unit tests for modules cubicweb.server.querier and cubicweb.server.querier_steps
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 from datetime import date, datetime
 
--- a/server/test/unittest_repository.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_repository.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,11 @@
 # -*- coding: iso-8859-1 -*-
-"""unit tests for module cubicweb.server.repository"""
+"""unit tests for module cubicweb.server.repository
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 import os
 import sys
--- a/server/test/unittest_rql2sql.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_rql2sql.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 """unit tests for module cubicweb.server.sources.rql2sql"""
 
--- a/server/test/unittest_rqlannotation.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_rqlannotation.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,6 @@
 # -*- coding: iso-8859-1 -*-
 """unit tests for modules cubicweb.server.rqlannotation
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
 from cubicweb.devtools import init_test_database
--- a/server/test/unittest_rqlrewrite.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_rqlrewrite.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.testlib import unittest_main, TestCase
 from logilab.common.testlib import mock_object
 
--- a/server/test/unittest_schemaserial.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_schemaserial.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,5 @@
 """unit tests for schema rql (de)serialization
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
 import sys
--- a/server/test/unittest_security.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_security.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,5 @@
 """functional tests for server'security
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 import sys
 
--- a/server/test/unittest_session.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_session.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.testlib import TestCase, unittest_main, mock_object
 
 from cubicweb.server.session import _make_description
--- a/server/test/unittest_sqlutils.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_sqlutils.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,5 @@
 """unit tests for module cubicweb.server.sqlutils
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
 import sys
--- a/server/test/unittest_ssplanner.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_ssplanner.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.devtools import init_test_database
 from cubicweb.devtools.repotest import BasePlannerTC, test_plan
 from cubicweb.server.ssplanner import SSPlanner
--- a/server/test/unittest_tools.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/test/unittest_tools.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.testlib import TestCase, unittest_main
 
 class ImportTC(TestCase):
--- a/server/utils.py	Fri May 29 16:11:49 2009 +0200
+++ b/server/utils.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Some utilities for the CubicWeb server.
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
@@ -63,23 +64,21 @@
 DEFAULT_MSG = 'we need a manager connection on the repository \
 (the server doesn\'t have to run, even should better not)'
 
-def manager_userpasswd(user=None, passwd=None, msg=DEFAULT_MSG, confirm=False):
+def manager_userpasswd(user=None, msg=DEFAULT_MSG, confirm=False,
+                       passwdmsg='password'):
     if not user:
         print msg
         while not user:
             user = raw_input('login: ')
-        passwd = getpass('password: ')
-        if confirm:
-            while True:
-                passwd2 = getpass('confirm password: ')
-                if passwd == passwd2:
-                    break
-                print 'password doesn\'t match'
-                passwd = getpass('password: ')
         user = unicode(user, sys.stdin.encoding)
-    elif not passwd:
-        assert not confirm
-        passwd = getpass('password for %s: ' % user)
+    passwd = getpass('%s: ' % passwdmsg)
+    if confirm:
+        while True:
+            passwd2 = getpass('confirm password: ')
+            if passwd == passwd2:
+                break
+            print 'password doesn\'t match'
+            passwd = getpass('password: ')
     # XXX decode password using stdin encoding then encode it using appl'encoding
     return user, passwd
 
--- a/setup.py	Fri May 29 16:11:49 2009 +0200
+++ b/setup.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,11 @@
 #!/usr/bin/env python
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 # pylint: disable-msg=W0142,W0403,W0404,W0613,W0622,W0622,W0704,R0904,C0103,E0611
 #
 # Copyright (c) 2003-2009 LOGILAB S.A. (Paris, FRANCE).
--- a/skeleton/entities.py	Fri May 29 16:11:49 2009 +0200
+++ b/skeleton/entities.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,7 @@
-"""this contains the cube-specific entities' classes"""
+"""this contains the cube-specific entities' classes
+
+:organization: Logilab
+:copyright: 2001-2009 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/skeleton/migration/postcreate.py	Fri May 29 16:11:49 2009 +0200
+++ b/skeleton/migration/postcreate.py	Fri May 29 20:22:39 2009 +0200
@@ -1,2 +1,9 @@
 # postcreate script. You could setup a workflow here for example
+"""
 
+:organization: Logilab
+:copyright: 2001-2009 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/skeleton/migration/precreate.py	Fri May 29 16:11:49 2009 +0200
+++ b/skeleton/migration/precreate.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
 # Instructions here will be read before reading the schema
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 # You could create your own groups here, like in :
 #   add_entity('CWGroup', name=u'mygroup')
--- a/skeleton/schema.py	Fri May 29 16:11:49 2009 +0200
+++ b/skeleton/schema.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,8 @@
 # cube's specific schema
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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/skeleton/setup.py	Fri May 29 16:11:49 2009 +0200
+++ b/skeleton/setup.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,11 @@
 #!/usr/bin/env python
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 # pylint: disable-msg=W0404,W0622,W0704,W0613,W0152
 # Copyright (c) 2003-2009 LOGILAB S.A. (Paris, FRANCE).
 # http://www.logilab.fr/ -- mailto:contact@logilab.fr
--- a/skeleton/test/pytestconf.py	Fri May 29 16:11:49 2009 +0200
+++ b/skeleton/test/pytestconf.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 import os
 import pwd
 
--- a/skeleton/test/realdb_test_CUBENAME.py	Fri May 29 16:11:49 2009 +0200
+++ b/skeleton/test/realdb_test_CUBENAME.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.devtools import buildconfig, loadconfig
 from cubicweb.devtools.testlib import RealDBTest
 
--- a/skeleton/test/test_CUBENAME.py	Fri May 29 16:11:49 2009 +0200
+++ b/skeleton/test/test_CUBENAME.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""template automatic tests"""
+"""template automatic tests
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from logilab.common.testlib import TestCase, unittest_main
 
--- a/skeleton/views.py	Fri May 29 16:11:49 2009 +0200
+++ b/skeleton/views.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,7 @@
-"""cube-specific forms/views/actions/components"""
+"""cube-specific forms/views/actions/components
+
+:organization: Logilab
+:copyright: 2001-2009 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/sobjects/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/sobjects/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,7 @@
-"""server side objects"""
+"""server side objects
+
+:organization: Logilab
+:copyright: 2001-2009 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/sobjects/email.py	Fri May 29 16:11:49 2009 +0200
+++ b/sobjects/email.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """hooks to ensure use_email / primary_email relations consistency
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/sobjects/hooks.py	Fri May 29 16:11:49 2009 +0200
+++ b/sobjects/hooks.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """various library content hooks
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/sobjects/notification.py	Fri May 29 16:11:49 2009 +0200
+++ b/sobjects/notification.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """some hooks and views to handle notification on entity's changes
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/sobjects/supervising.py	Fri May 29 16:11:49 2009 +0200
+++ b/sobjects/supervising.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/sobjects/test/data/schema.py	Fri May 29 16:11:49 2009 +0200
+++ b/sobjects/test/data/schema.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 class comments(RelationDefinition):
     subject = 'Comment'
     object = 'Card'
--- a/sobjects/test/data/sobjects/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/sobjects/test/data/sobjects/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.selectors import implements
 from cubicweb.sobjects.notification import StatusChangeMixIn, NotificationView
 
--- a/sobjects/test/unittest_email.py	Fri May 29 16:11:49 2009 +0200
+++ b/sobjects/test/unittest_email.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.devtools.apptest import EnvBasedTC
 
 class EmailAddressHooksTC(EnvBasedTC):
--- a/sobjects/test/unittest_hooks.py	Fri May 29 16:11:49 2009 +0200
+++ b/sobjects/test/unittest_hooks.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.testlib import unittest_main
 from cubicweb.devtools.apptest import EnvBasedTC
 
--- a/sobjects/test/unittest_notification.py	Fri May 29 16:11:49 2009 +0200
+++ b/sobjects/test/unittest_notification.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,11 @@
 # -*- coding: iso-8859-1 -*-
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from socket import gethostname
 
 from logilab.common.testlib import unittest_main, TestCase
--- a/sobjects/test/unittest_supervising.py	Fri May 29 16:11:49 2009 +0200
+++ b/sobjects/test/unittest_supervising.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,11 @@
 # -*- coding: iso-8859-1 -*-
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 import re
 
 from logilab.common.testlib import unittest_main
--- a/test/data/cubes/file/__pkginfo__.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/data/cubes/file/__pkginfo__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,11 @@
 # pylint: disable-msg=W0622
-"""cubicweb-file packaging information"""
+"""cubicweb-file packaging information
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 distname = "cubicweb-file"
 modname = distname.split('-', 1)[1]
--- a/test/data/cubes/mycube/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/data/cubes/mycube/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,7 @@
-"""mycube's __init__"""
+"""mycube's __init__
+
+:organization: Logilab
+:copyright: 2001-2009 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/test/data/cubes/mycube/__pkginfo__.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/data/cubes/mycube/__pkginfo__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,1 +1,8 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 distname = 'cubicweb-mycube'
--- a/test/data/entities.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/data/entities.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.entities import AnyEntity, fetch_config
 
 class Societe(AnyEntity):
--- a/test/data/erqlexpr_on_ertype.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/data/erqlexpr_on_ertype.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 class ToTo(EntityType):
     permissions = {
         'read': ('managers',),
--- a/test/data/rqlexpr_on_ertype_read.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/data/rqlexpr_on_ertype_read.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 class ToTo(EntityType):
     permissions = {
         'read': ('managers',),
--- a/test/data/rrqlexpr_on_attr.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/data/rrqlexpr_on_attr.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 class ToTo(EntityType):
     permissions = {
         'read': ('managers',),
--- a/test/data/rrqlexpr_on_eetype.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/data/rrqlexpr_on_eetype.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 class ToTo(EntityType):
     permissions = {
         'read': ('managers', RRQLExpression('S bla Y'),),
--- a/test/data/schema.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/data/schema.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 class Personne(EntityType):
     nom = String(required=True)
     prenom = String()
--- a/test/unittest_cwconfig.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/unittest_cwconfig.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 import sys
 import os
 from os.path import dirname, join, abspath
--- a/test/unittest_cwctl.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/unittest_cwctl.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 import sys
 import os
 from cStringIO import StringIO
--- a/test/unittest_dbapi.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/unittest_dbapi.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb import ConnectionError
 from cubicweb.dbapi import ProgrammingError
 from cubicweb.devtools.apptest import EnvBasedTC
--- a/test/unittest_entity.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/unittest_entity.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,11 @@
 # -*- coding: utf-8 -*-
-"""unit tests for cubicweb.web.views.entities module"""
+"""unit tests for cubicweb.web.views.entities module
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from datetime import datetime
 
--- a/test/unittest_rset.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/unittest_rset.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,11 @@
 # coding: utf-8
-"""unit tests for module cubicweb.common.utils"""
+"""unit tests for module cubicweb.common.utils
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from __future__ import with_statement
 
 from logilab.common.testlib import TestCase, unittest_main
--- a/test/unittest_rtags.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/unittest_rtags.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.testlib import TestCase, unittest_main
 from cubicweb.rtags import RelationTags, RelationTagsSet
 
--- a/test/unittest_schema.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/unittest_schema.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""unit tests for module cubicweb.schema"""
+"""unit tests for module cubicweb.schema
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 import sys
 from os.path import join, isabs, basename, dirname
--- a/test/unittest_selectors.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/unittest_selectors.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """unit tests for selectors mechanism
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 from logilab.common.testlib import TestCase, unittest_main
--- a/test/unittest_utils.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/unittest_utils.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""unit tests for module cubicweb.common.utils"""
+"""unit tests for module cubicweb.common.utils
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from logilab.common.testlib import TestCase, unittest_main
 
--- a/test/unittest_vregistry.py	Fri May 29 16:11:49 2009 +0200
+++ b/test/unittest_vregistry.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.testlib import unittest_main, TestCase
 
 from os.path import join
--- a/toolsutils.py	Fri May 29 16:11:49 2009 +0200
+++ b/toolsutils.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """some utilities for cubicweb tools
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/utils.py	Fri May 29 16:11:49 2009 +0200
+++ b/utils.py	Fri May 29 20:22:39 2009 +0200
@@ -1,15 +1,16 @@
 """Some utilities for CubicWeb server/clients.
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
 import locale
 from md5 import md5
 from datetime import datetime, timedelta, date
-from time import time
+from time import time, mktime
 from random import randint, seed
 from calendar import monthrange
 
@@ -37,6 +38,9 @@
     assert isinstance(somedate, date), repr(somedate)
     return datetime(somedate.year, somedate.month, somedate.day)
 
+def datetime2ticks(date):
+    return mktime(date.timetuple()) * 1000
+
 ONEDAY = timedelta(days=1)
 ONEWEEK = timedelta(days=7)
 
@@ -99,7 +103,7 @@
 
 def make_uid(key):
     """forge a unique identifier"""
-    msg = str(key) + "%.10f"%time() + str(randint(0, 1000000))
+    msg = str(key) + "%.10f" % time() + str(randint(0, 1000000))
     return md5(msg).hexdigest()
 
 
--- a/view.py	Fri May 29 16:11:49 2009 +0200
+++ b/view.py	Fri May 29 20:22:39 2009 +0200
@@ -2,10 +2,12 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
+_ = unicode
 
 from cStringIO import StringIO
 
@@ -18,8 +20,6 @@
 from cubicweb.appobject import AppRsetObject
 from cubicweb.utils import UStringIO, HTMLStream
 
-_ = unicode
-
 
 # robots control
 NOINDEX = u'<meta name="ROBOTS" content="NOINDEX" />'
@@ -206,7 +206,7 @@
 
     # view utilities ##########################################################
 
-    def wview(self, __vid, rset, __fallback_vid=None, **kwargs):
+    def wview(self, __vid, rset=None, __fallback_vid=None, **kwargs):
         """shortcut to self.view method automatically passing self.w as argument
         """
         self.view(__vid, rset, __fallback_vid, w=self.w, **kwargs)
@@ -221,21 +221,6 @@
         """simple helper that escapes `data` and writes into `self.w`"""
         self.w(html_escape(data))
 
-    def action(self, actionid, row=0):
-        """shortcut to get action object with id `actionid`"""
-        return self.vreg.select_action(actionid, self.req, self.rset,
-                                       row=row)
-
-    def action_url(self, actionid, label=None, row=0):
-        """simple method to be able to display `actionid` as a link anywhere
-        """
-        action = self.vreg.select_action(actionid, self.req, self.rset,
-                                         row=row)
-        if action:
-            label = label or self.req._(action.title)
-            return u'<a href="%s">%s</a>' % (html_escape(action.url()), label)
-        return u''
-
     def html_headers(self):
         """return a list of html headers (eg something to be inserted between
         <head> and </head> of the returned page
--- a/vregistry.py	Fri May 29 16:11:49 2009 +0200
+++ b/vregistry.py	Fri May 29 20:22:39 2009 +0200
@@ -15,8 +15,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -3,8 +3,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
--- a/web/_exceptions.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/_exceptions.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 """exceptions used in the core of the CubicWeb web application
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/action.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/action.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """abstract action classes for CubicWeb web client
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/application.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/application.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """CubicWeb web client application object
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/box.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/box.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """abstract box classes for CubicWeb web client
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/component.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/component.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """abstract component class and base components definition for CubicWeb web client
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/controller.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/controller.py	Fri May 29 20:22:39 2009 +0200
@@ -2,15 +2,15 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
 import datetime
 
 from cubicweb import typed_eid
-from cubicweb.utils import strptime, todate, todatetime
 from cubicweb.selectors import yes, require_group_compat
 from cubicweb.appobject import AppObject
 from cubicweb.web import LOGGER, Redirect, RequestError
@@ -107,35 +107,6 @@
             raise RequestError('missing required parameter(s): %s'
                                % ','.join(missing))
 
-    def parse_datetime(self, value, etype='Datetime'):
-        """get a datetime or time from a string (according to etype)
-        Datetime formatted as Date are accepted
-        """
-        assert etype in ('Datetime', 'Date', 'Time'), etype
-        # XXX raise proper validation error
-        if etype == 'Datetime':
-            format = self.req.property_value('ui.datetime-format')
-            try:
-                return todatetime(strptime(value, format))
-            except:
-                pass
-        elif etype == 'Time':
-            format = self.req.property_value('ui.time-format')
-            try:
-                # (adim) I can't find a way to parse a Time with a custom format
-                date = strptime(value, format) # this returns a DateTime
-                return datetime.time(date.hour, date.minute, date.second)
-            except:
-                raise ValueError('can\'t parse %r (expected %s)' % (value, format))
-        try:
-            format = self.req.property_value('ui.date-format')
-            dt = strptime(value, format)
-            if etype == 'Datetime':
-                return todatetime(dt)
-            return todate(dt)
-        except:
-            raise ValueError('can\'t parse %r (expected %s)' % (value, format))
-
 
     def notify_edited(self, entity):
         """called by edit_entity() to notify which entity is edited"""
--- a/web/data/cubicweb.calendar.css	Fri May 29 16:11:49 2009 +0200
+++ b/web/data/cubicweb.calendar.css	Fri May 29 20:22:39 2009 +0200
@@ -1,7 +1,7 @@
 /* styles for the calendar views
  *
  *  :organization: Logilab
- *  :copyright: 2003-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+ *  :copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
  *  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
  */
 
@@ -74,7 +74,7 @@
 }
 
 table.omcalendar tr td {
-  padding: 3px 0.5em 1em;                         
+  padding: 3px 0.5em 1em;
 }
 
 table.omcalendar tr td div.task {
@@ -82,11 +82,11 @@
   height: 2.5ex;
 }
 
-table.omcalendar tr td div.task div.tooltip { 
-  display: none; 
+table.omcalendar tr td div.task div.tooltip {
+  display: none;
 }
 
-table.omcalendar tr td:hover div.task:hover div.tooltip { 
+table.omcalendar tr td:hover div.task:hover div.tooltip {
   font-style: normal;
   display: block;
   position: absolute;
@@ -101,6 +101,7 @@
 
 
 table.omcalendar tr td.outOfRange { background-color: #ddd; }
+table.omcalendar tr td.today { border: 2px solid #2952A3; }
 
 
 table.omcalendar div.col0       { background-color: #FFB117; }
@@ -138,7 +139,7 @@
   min-height: 600px;
   width: 100%;
   table-layout: auto;
-  
+
 }
 
 
@@ -209,10 +210,10 @@
 /******************************************************************************/
 
 table.calendarPageHeader,
-table.smallCalendars, 
+table.smallCalendars,
  table.bigCalendars {
  width: 90%;
- border-collapse:separate; 
+ border-collapse:separate;
  margin: 0px 1em;
 }
 
@@ -232,20 +233,20 @@
  background: #cfceb7;
 }
 
-.calendar th.month a{ 
+.calendar th.month a{
  font: bold 110%  Georgia, Verdana;
  color : #fff;
  }
 
-table.weekCalendar{ 
+table.weekCalendar{
 }
 
-table.weekCalendar th{ 
+table.weekCalendar th{
  text-align : left;
  padding: 0.6em 0.4em;
  }
 
-table.weekCalendar td{ 
+table.weekCalendar td{
  padding: 0.2em 0.4em }
 
 .semesterCalendar .amCell, .semesterCalendar .amCellEmpty{
@@ -254,7 +255,7 @@
   border-right:thin dotted;
 }
 
-table.semesterCalendar th{ 
+table.semesterCalendar th{
  padding: 0.6em 0.4em;
 }
 
@@ -263,25 +264,25 @@
   border-left:1px dotted #ccc;
 }
 
-.weeknum{ 
+.weeknum{
  width:10%
  }
 
-.cell, .cellEmpty{ 
+.cell, .cellEmpty{
  border:1px solid #ccc;
  padding: 3px 0.5em 2em;
  width:10%;
 }
 
-.cellDay{ 
+.cellDay{
  border:1px solid #ccc;
  border-bottom : none;
- padding: 3px 0.5em 3px;  
+ padding: 3px 0.5em 3px;
  width:10%;}
 
 .amCell, .pmCell,
 .amCellEmpty, .pmCellEmpty{
- padding: 3px 0.5em 3px;  
+ padding: 3px 0.5em 3px;
  border:1px solid #ccc;
  border-top:none;
  width:10%;
@@ -309,22 +310,22 @@
 
 .cell span.cellTitle,
 .cellEmpty span.cellTitle {
- background-color:transparent; 
+ background-color:transparent;
 }
 
-div.cellContent{ 
+div.cellContent{
  padding: 0.1em;
  font-size:90%;
  }
 
-.weeknum, th.weekday{ 
+.weeknum, th.weekday{
  padding:0.2em 0.4em;
  color : #666;
  font-size:90%;}
 
-div.event{ 
+div.event{
  padding : 0.1em 0px;
- margin:0.2em 0px; 
+ margin:0.2em 0px;
  background: #eee;
 }
 
--- a/web/data/cubicweb.python.js	Fri May 29 16:11:49 2009 +0200
+++ b/web/data/cubicweb.python.js	Fri May 29 20:22:39 2009 +0200
@@ -21,23 +21,23 @@
     var res = new Date()
     res.setTime(this.getTime() + (days * ONE_DAY))
     return res
-}
+};
 
 Date.prototype.sub = function(days) {
     return this.add(-days);
-}
+};
 
 Date.prototype.iadd = function(days) {
     // in-place add
     this.setTime(this.getTime() + (days * ONE_DAY))
     // avoid strange rounding problems !!
     this.setHours(12);
-}
+};
 
 Date.prototype.isub = function(days) {
     // in-place sub
     this.setTime(this.getTime() - (days * ONE_DAY))
-}
+};
 
 /*
  * returns the first day of the next month
@@ -50,7 +50,7 @@
 	var d2 = new Date(this.getFullYear(), this.getMonth()+1, 1);
 	return d2;
     }
-}
+};
 
 /*
  * returns the day of week, 0 being monday, 6 being sunday
@@ -58,8 +58,15 @@
 Date.prototype.getRealDay = function() {
     // getDay() returns 0 for Sunday ==> 6 for Saturday
     return (this.getDay()+6) % 7;
-}
+};
 
+Date.prototype.strftime = function(fmt) {
+    if (this.toLocaleFormat !== undefined) { // browser dependent
+	return this.toLocaleFormat(fmt);
+    }
+    // XXX implement at least a decent fallback implementation
+    return this.getFullYear() + '/' + (this.getMonth()+1) + '/' + this.getDate();
+};
 
 var _DATE_FORMAT_REGXES = {
     'Y': new RegExp('^-?[0-9]+'),
--- a/web/facet.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/facet.py	Fri May 29 20:22:39 2009 +0200
@@ -2,13 +2,15 @@
 a search
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
 from itertools import chain
 from copy import deepcopy
+from datetime import date
 
 from logilab.mtconverter import html_escape
 
@@ -19,7 +21,7 @@
 from rql import parse, nodes
 
 from cubicweb import Unauthorized, typed_eid
-from cubicweb.utils import make_uid
+from cubicweb.utils import datetime2ticks, make_uid, ustrftime
 from cubicweb.selectors import match_context_prop, partial_relation_possible
 from cubicweb.appobject import AppRsetObject
 from cubicweb.web.htmlwidgets import HTMLWidget
@@ -475,29 +477,6 @@
                                             self.attrtype, self.comparator)
 
 
-class RangeFacet(AttributeFacet):
-
-    def get_widget(self):
-        """return the widget instance to use to display this facet
-        """
-        values = set(value for _, value in self.vocabulary() if value is not None)
-        return FacetRangeWidget(self, min(values), max(values))
-
-    def add_rql_restrictions(self):
-        infvalue = self.req.form.get('%s_inf' % self.id)
-        if not infvalue:
-            return
-        supvalue = self.req.form.get('%s_sup' % self.id)
-        self.rqlst.add_constant_restriction(self.filtered_variable,
-                                            self.rtype,
-                                            u'%s' % infvalue,
-                                            'Float', '>=')
-        self.rqlst.add_constant_restriction(self.filtered_variable,
-                                            self.rtype,
-                                            u'%s' % supvalue,
-                                            'Float', '<=')
-
-
 class FilterRQLBuilder(object):
     """called by javascript to get a rql string from filter form"""
 
@@ -518,6 +497,54 @@
         return select.as_string(), toupdate
 
 
+class RangeFacet(AttributeFacet):
+    attrtype = 'Float' # only numerical types are supported
+
+    @property
+    def wdgclass(self):
+        return FacetRangeWidget
+
+    def get_widget(self):
+        """return the widget instance to use to display this facet
+        """
+        values = set(value for _, value in self.vocabulary() if value is not None)
+        return self.wdgclass(self, min(values), max(values))
+
+    def infvalue(self):
+        return self.req.form.get('%s_inf' % self.id)
+
+    def supvalue(self):
+        return self.req.form.get('%s_sup' % self.id)
+
+    def formatvalue(self, value):
+        return unicode(value)
+
+    def add_rql_restrictions(self):
+        infvalue = self.infvalue()
+        if infvalue is None: # nothing sent
+            return
+        supvalue = self.supvalue()
+        self.rqlst.add_constant_restriction(self.filtered_variable,
+                                            self.rtype,
+                                            self.formatvalue(infvalue),
+                                            self.attrtype, '>=')
+        self.rqlst.add_constant_restriction(self.filtered_variable,
+                                            self.rtype,
+                                            self.formatvalue(supvalue),
+                                            self.attrtype, '<=')
+
+class DateRangeFacet(RangeFacet):
+    attrtype = 'Date' # only date types are supported
+
+    @property
+    def wdgclass(self):
+        fmt = self.req.property_value('ui.date-format')
+        self.req.html_headers.define_var('DATE_FMT', fmt)
+        return DateFacetRangeWidget
+
+    def formatvalue(self, value):
+        return '"%s"' % date.fromtimestamp(float(value) / 1000).strftime('%Y/%m/%d')
+
 ## html widets ################################################################
 
 class FacetVocabularyWidget(HTMLWidget):
@@ -549,7 +576,7 @@
             cssclass += ' overflowed'
         self.w(u'<div class="facetBody%s">\n' % cssclass)
         for item in self.items:
-            item.render(self.w)
+            item.render(w=self.w)
         self.w(u'</div>\n')
         self.w(u'</div>\n')
 
@@ -576,11 +603,15 @@
 	min: %(minvalue)s,
 	max: %(maxvalue)s,
         values: [%(minvalue)s, %(maxvalue)s],
+        stop: function(event, ui) { // submit when the user stops sliding
+           var form = $('#%(sliderid)s').closest('form');
+           buildRQL.apply(null, evalJSON(form.attr('cubicweb:facetargs')));
+        },
     	slide: function(event, ui) {
-	    $('#%(sliderid)s_inf').html(ui.values[0]);
-	    $('#%(sliderid)s_sup').html(ui.values[1]);
-	    $('input[name=%(facetid)s_inf]').val(ui.values[0]);
-	    $('input[name=%(facetid)s_sup]').val(ui.values[1]);
+            $('#%(sliderid)s_inf').html(ui.values[0]);
+            $('#%(sliderid)s_sup').html(ui.values[1]);
+            $('input[name=%(facetid)s_inf]').val(ui.values[0]);
+            $('input[name=%(facetid)s_sup]').val(ui.values[1]);
     	}
    });
 '''
@@ -589,6 +620,9 @@
         self.minvalue = minvalue
         self.maxvalue = maxvalue
 
+    def formatvalue(self, value):
+        return value
+
     def _render(self):
         facet = self.facet
         facet.req.add_js('ui.slider.js')
@@ -606,7 +640,8 @@
         self.w(u'<div class="facetTitle" cubicweb:facetName="%s">%s</div>\n' %
                (facetid, title))
         self.w(u'<span id="%s_inf">%s</span> - <span id="%s_sup">%s</span>'
-               % (sliderid, self.minvalue, sliderid, self.maxvalue))
+               % (sliderid, self.formatvalue(self.minvalue),
+                  sliderid, self.formatvalue(self.maxvalue)))
         self.w(u'<input type="hidden" name="%s_inf" value="%s" />'
                % (facetid, self.minvalue))
         self.w(u'<input type="hidden" name="%s_sup" value="%s" />'
@@ -615,6 +650,35 @@
         self.w(u'</div>\n')
 
 
+class DateFacetRangeWidget(FacetRangeWidget):
+    onload = u'''
+    jQuery("#%(sliderid)s").slider({
+    	range: true,
+	min: %(minvalue)s,
+	max: %(maxvalue)s,
+        values: [%(minvalue)s, %(maxvalue)s],
+        stop: function(event, ui) { // submit when the user stops sliding
+UI = ui;
+           var form = $('#%(sliderid)s').closest('form');
+           buildRQL.apply(null, evalJSON(form.attr('cubicweb:facetargs')));
+        },
+    	slide: function(event, ui) {
+            $('#%(sliderid)s_inf').html( (new Date(ui.values[0])).strftime(DATE_FMT));
+            $('#%(sliderid)s_sup').html( (new Date(ui.values[1])).strftime(DATE_FMT));
+            $('input[name=%(facetid)s_inf]').val(ui.values[0]);
+            $('input[name=%(facetid)s_sup]').val(ui.values[1]);
+    	}
+   });
+'''
+    def __init__(self, facet, minvalue, maxvalue):
+        super(DateFacetRangeWidget, self).__init__(facet,
+                                                   datetime2ticks(minvalue),
+                                                   datetime2ticks(maxvalue))
+    def formatvalue(self, value):
+        datefmt = self.facet.req.property_value('ui.date-format')
+        return ustrftime(date.fromtimestamp(float(value) / 1000), datefmt)
+
+
 class FacetItem(HTMLWidget):
 
     selected_img = "black-check.png"
@@ -648,4 +712,3 @@
 
     def _render(self):
         pass
-
--- a/web/form.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/form.py	Fri May 29 20:22:39 2009 +0200
@@ -1,33 +1,23 @@
 """abstract form classes for CubicWeb web client
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
-from warnings import warn
-
-from logilab.common.compat import any
-from logilab.common.decorators import iclassmethod
-
 from cubicweb.appobject import AppRsetObject
-from cubicweb.selectors import yes, non_final_entity, match_kwargs, one_line_rset
 from cubicweb.view import NOINDEX, NOFOLLOW
 from cubicweb.common import tags
-from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param, stdmsgs
-from cubicweb.web.httpcache import NoHTTPCacheManager
-from cubicweb.web.controller import NAV_FORM_PARAMETERS
-from cubicweb.web.formfields import (Field, StringField, RelationField,
-                                     HiddenInitialValueField)
-from cubicweb.web import formrenderers
-from cubicweb.web import formwidgets as fwdgs
+from cubicweb.web import stdmsgs, httpcache, formfields
+
 
 class FormViewMixIn(object):
     """abstract form view mix-in"""
     category = 'form'
     controller = 'edit'
-    http_cache_manager = NoHTTPCacheManager
+    http_cache_manager = httpcache.NoHTTPCacheManager
     add_to_breadcrumbs = False
 
     def html_headers(self):
@@ -90,7 +80,7 @@
     domid = 'entityForm'
     category = 'form'
     controller = 'edit'
-    http_cache_manager = NoHTTPCacheManager
+    http_cache_manager = httpcache.NoHTTPCacheManager
     add_to_breadcrumbs = False
 
     def html_headers(self):
@@ -198,7 +188,7 @@
             if hasattr(base, '_fields_'):
                 allfields += base._fields_
         clsfields = (item for item in classdict.items()
-                     if isinstance(item[1], Field))
+                     if isinstance(item[1], formfields.Field))
         for fieldname, field in sorted(clsfields, key=lambda x: x[1].creation_rank):
             if not field.name:
                 field.set_name(fieldname)
@@ -212,491 +202,6 @@
     found
     """
 
-class FieldsForm(FormMixIn, AppRsetObject):
+class Form(FormMixIn, AppRsetObject):
     __metaclass__ = metafieldsform
     __registry__ = 'forms'
-    __select__ = yes()
-
-    renderer_cls = formrenderers.FormRenderer
-    is_subform = False
-
-    # attributes overrideable through __init__
-    internal_fields = ('__errorurl',) + NAV_FORM_PARAMETERS
-    needs_js = ('cubicweb.ajax.js', 'cubicweb.edition.js',)
-    needs_css = ('cubicweb.form.css',)
-    domid = 'form'
-    title = None
-    action = None
-    onsubmit = "return freezeFormButtons('%(domid)s');"
-    cssclass = None
-    cssstyle = None
-    cwtarget = None
-    redirect_path = None
-    set_error_url = True
-    copy_nav_params = False
-    form_buttons = None # form buttons (button widgets instances)
-
-    def __init__(self, req, rset=None, row=None, col=None, submitmsg=None,
-                 **kwargs):
-        super(FieldsForm, self).__init__(req, rset, row=row, col=col)
-        self.fields = list(self.__class__._fields_)
-        for key, val in kwargs.items():
-            if key in NAV_FORM_PARAMETERS:
-                self.form_add_hidden(key, val)
-            else:
-                assert hasattr(self.__class__, key) and not key[0] == '_', key
-                setattr(self, key, val)
-        if self.set_error_url:
-            self.form_add_hidden('__errorurl', self.session_key())
-        if self.copy_nav_params:
-            for param in NAV_FORM_PARAMETERS:
-                if not param in kwargs:
-                    value = req.form.get(param)
-                    if value:
-                        self.form_add_hidden(param, value)
-        if submitmsg is not None:
-            self.form_add_hidden('__message', submitmsg)
-        self.context = None
-        if 'domid' in kwargs:# session key changed
-            self.restore_previous_post(self.session_key())
-
-    @iclassmethod
-    def field_by_name(cls_or_self, name, role='subject'):
-        """return field with the given name and role.
-        Raise FieldNotFound if the field can't be found.
-        """
-        if isinstance(cls_or_self, type):
-            fields = cls_or_self._fields_
-        else:
-            fields = cls_or_self.fields
-        for field in fields:
-            if field.name == name and field.role == role:
-                return field
-        raise FieldNotFound(name)
-
-    @iclassmethod
-    def fields_by_name(cls_or_self, name, role='subject'):
-        """return a list of fields with the given name and role"""
-        if isinstance(cls_or_self, type):
-            fields = cls_or_self._fields_
-        else:
-            fields = cls_or_self.fields
-        return [field for field in fields
-                if field.name == name and field.role == role]
-
-    @iclassmethod
-    def remove_field(cls_or_self, field):
-        """remove a field from form class or instance"""
-        if isinstance(cls_or_self, type):
-            fields = cls_or_self._fields_
-        else:
-            fields = cls_or_self.fields
-        fields.remove(field)
-
-    @iclassmethod
-    def append_field(cls_or_self, field):
-        """append a field to form class or instance"""
-        if isinstance(cls_or_self, type):
-            fields = cls_or_self._fields_
-        else:
-            fields = cls_or_self.fields
-        fields.append(field)
-
-    @property
-    def form_needs_multipart(self):
-        """true if the form needs enctype=multipart/form-data"""
-        return any(field.needs_multipart for field in self.fields)
-
-    def form_add_hidden(self, name, value=None, **kwargs):
-        """add an hidden field to the form"""
-        field = StringField(name=name, widget=fwdgs.HiddenInput, initial=value,
-                            **kwargs)
-        if 'id' in kwargs:
-            # by default, hidden input don't set id attribute. If one is
-            # explicitly specified, ensure it will be set
-            field.widget.setdomid = True
-        self.append_field(field)
-        return field
-
-    def add_media(self):
-        """adds media (CSS & JS) required by this widget"""
-        if self.needs_js:
-            self.req.add_js(self.needs_js)
-        if self.needs_css:
-            self.req.add_css(self.needs_css)
-
-    def form_render(self, **values):
-        """render this form, using the renderer given in args or the default
-        FormRenderer()
-        """
-        renderer = values.pop('renderer', self.renderer_cls())
-        return renderer.render(self, values)
-
-    def form_build_context(self, rendervalues=None):
-        """build form context values (the .context attribute which is a
-        dictionary with field instance as key associated to a dictionary
-        containing field 'name' (qualified), 'id', 'value' (for display, always
-        a string).
-
-        rendervalues is an optional dictionary containing extra kwargs given to
-        form_render()
-        """
-        self.context = context = {}
-        # ensure rendervalues is a dict
-        if rendervalues is None:
-            rendervalues = {}
-        # use a copy in case fields are modified while context is build (eg
-        # __linkto handling for instance)
-        for field in self.fields[:]:
-            for field in field.actual_fields(self):
-                field.form_init(self)
-                value = self.form_field_display_value(field, rendervalues)
-                context[field] = {'value': value,
-                                  'name': self.form_field_name(field),
-                                  'id': self.form_field_id(field),
-                                  }
-
-    def form_field_display_value(self, field, rendervalues, load_bytes=False):
-        """return field's *string* value to use for display
-
-        looks in
-        1. previously submitted form values if any (eg on validation error)
-        2. req.form
-        3. extra kw args given to render_form
-        4. field's typed value
-
-        values found in 1. and 2. are expected te be already some 'display'
-        value while those found in 3. and 4. are expected to be correctly typed.
-        """
-        value = self._req_display_value(field)
-        if value is None:
-            if field.name in rendervalues:
-                value = rendervalues[field.name]
-            else:
-                value = self.form_field_value(field, load_bytes)
-                if callable(value):
-                    value = value(self)
-            if value != INTERNAL_FIELD_VALUE:
-                value = field.format_value(self.req, value)
-        return value
-
-    def _req_display_value(self, field):
-        qname = self.form_field_name(field)
-        if qname in self.form_previous_values:
-            return self.form_previous_values[qname]
-        if qname in self.req.form:
-            return self.req.form[qname]
-        if field.name in self.req.form:
-            return self.req.form[field.name]
-        return None
-
-    def form_field_value(self, field, load_bytes=False):
-        """return field's *typed* value"""
-        myattr = '%s_%s_default' % (field.role, field.name)
-        if hasattr(self, myattr):
-            return getattr(self, myattr)()
-        value = field.initial
-        if callable(value):
-            value = value(self)
-        return value
-
-    def form_field_error(self, field):
-        """return validation error for widget's field, if any"""
-        if self._field_has_error(field):
-            self.form_displayed_errors.add(field.name)
-            return u'<span class="error">%s</span>' % self.form_valerror.errors[field.name]
-        return u''
-
-    def form_field_format(self, field):
-        """return MIME type used for the given (text or bytes) field"""
-        return self.req.property_value('ui.default-text-format')
-
-    def form_field_encoding(self, field):
-        """return encoding used for the given (text) field"""
-        return self.req.encoding
-
-    def form_field_name(self, field):
-        """return qualified name for the given field"""
-        return field.name
-
-    def form_field_id(self, field):
-        """return dom id for the given field"""
-        return field.id
-
-    def form_field_vocabulary(self, field, limit=None):
-        """return vocabulary for the given field. Should be overriden in
-        specific forms using fields which requires some vocabulary
-        """
-        raise NotImplementedError
-
-    def _field_has_error(self, field):
-        """return true if the field has some error in given validation exception
-        """
-        return self.form_valerror and field.name in self.form_valerror.errors
-
-
-class EntityFieldsForm(FieldsForm):
-    __select__ = (match_kwargs('entity') | (one_line_rset & non_final_entity()))
-
-    internal_fields = FieldsForm.internal_fields + ('__type', 'eid', '__maineid')
-    domid = 'entityForm'
-
-    def __init__(self, *args, **kwargs):
-        self.edited_entity = kwargs.pop('entity', None)
-        msg = kwargs.pop('submitmsg', None)
-        super(EntityFieldsForm, self).__init__(*args, **kwargs)
-        if self.edited_entity is None:
-            self.edited_entity = self.complete_entity(self.row or 0, self.col or 0)
-        self.form_add_hidden('__type', eidparam=True)
-        self.form_add_hidden('eid')
-        if msg:
-            # If we need to directly attach the new object to another one
-            self.form_add_hidden('__message', msg)
-        if not self.is_subform:
-            for linkto in self.req.list_form_param('__linkto'):
-                self.form_add_hidden('__linkto', linkto)
-                msg = '%s %s' % (msg, self.req._('and linked'))
-        # in case of direct instanciation
-        self.schema = self.edited_entity.schema
-        self.vreg = self.edited_entity.vreg
-
-    def _field_has_error(self, field):
-        """return true if the field has some error in given validation exception
-        """
-        return super(EntityFieldsForm, self)._field_has_error(field) \
-               and self.form_valerror.eid == self.edited_entity.eid
-
-    def _relation_vocabulary(self, rtype, targettype, role,
-                            limit=None, done=None):
-        """return unrelated entities for a given relation and target entity type
-        for use in vocabulary
-        """
-        if done is None:
-            done = set()
-        rset = self.edited_entity.unrelated(rtype, targettype, role, limit)
-        res = []
-        for entity in rset.entities():
-            if entity.eid in done:
-                continue
-            done.add(entity.eid)
-            res.append((entity.view('combobox'), entity.eid))
-        return res
-
-    def _req_display_value(self, field):
-        value = super(EntityFieldsForm, self)._req_display_value(field)
-        if value is None:
-            value = self.edited_entity.linked_to(field.name, field.role)
-            if value:
-                searchedvalues = ['%s:%s:%s' % (field.name, eid, field.role)
-                                  for eid in value]
-                # remove associated __linkto hidden fields
-                for field in self.fields_by_name('__linkto'):
-                    if field.initial in searchedvalues:
-                        self.remove_field(field)
-            else:
-                value = None
-        return value
-
-    def _form_field_default_value(self, field, load_bytes):
-        defaultattr = 'default_%s' % field.name
-        if hasattr(self.edited_entity, defaultattr):
-            # XXX bw compat, default_<field name> on the entity
-            warn('found %s on %s, should be set on a specific form'
-                 % (defaultattr, self.edited_entity.id), DeprecationWarning)
-            value = getattr(self.edited_entity, defaultattr)
-            if callable(value):
-                value = value()
-        else:
-            value = super(EntityFieldsForm, self).form_field_value(field,
-                                                                   load_bytes)
-        return value
-
-    def form_build_context(self, values=None):
-        """overriden to add edit[s|o] hidden fields and to ensure schema fields
-        have eidparam set to True
-
-        edit[s|o] hidden fields are used to indicate the value for the
-        associated field before the (potential) modification made when
-        submitting the form.
-        """
-        eschema = self.edited_entity.e_schema
-        for field in self.fields[:]:
-            for field in field.actual_fields(self):
-                fieldname = field.name
-                if fieldname != 'eid' and (
-                    (eschema.has_subject_relation(fieldname) or
-                     eschema.has_object_relation(fieldname))):
-                    field.eidparam = True
-                    self.fields.append(HiddenInitialValueField(field))
-        return super(EntityFieldsForm, self).form_build_context(values)
-
-    def form_field_value(self, field, load_bytes=False):
-        """return field's *typed* value
-
-        overriden to deal with
-        * special eid / __type / edits- / edito- fields
-        * lookup for values on edited entities
-        """
-        attr = field.name
-        entity = self.edited_entity
-        if attr == 'eid':
-            return entity.eid
-        if not field.eidparam:
-            return super(EntityFieldsForm, self).form_field_value(field, load_bytes)
-        if attr.startswith('edits-') or attr.startswith('edito-'):
-            # edit[s|o]- fieds must have the actual value stored on the entity
-            assert hasattr(field, 'visible_field')
-            vfield = field.visible_field
-            assert vfield.eidparam
-            if entity.has_eid():
-                return self.form_field_value(vfield)
-            return INTERNAL_FIELD_VALUE
-        if attr == '__type':
-            return entity.id
-        if self.schema.rschema(attr).is_final():
-            attrtype = entity.e_schema.destination(attr)
-            if attrtype == 'Password':
-                return entity.has_eid() and INTERNAL_FIELD_VALUE or ''
-            if attrtype == 'Bytes':
-                if entity.has_eid():
-                    if load_bytes:
-                        return getattr(entity, attr)
-                    # XXX value should reflect if some file is already attached
-                    return True
-                return False
-            if entity.has_eid() or attr in entity:
-                value = getattr(entity, attr)
-            else:
-                value = self._form_field_default_value(field, load_bytes)
-            return value
-        # non final relation field
-        if entity.has_eid() or entity.relation_cached(attr, field.role):
-            value = [r[0] for r in entity.related(attr, field.role)]
-        else:
-            value = self._form_field_default_value(field, load_bytes)
-        return value
-
-    def form_field_format(self, field):
-        """return MIME type used for the given (text or bytes) field"""
-        entity = self.edited_entity
-        if field.eidparam and entity.e_schema.has_metadata(field.name, 'format') and (
-            entity.has_eid() or '%s_format' % field.name in entity):
-            return self.edited_entity.attr_metadata(field.name, 'format')
-        return self.req.property_value('ui.default-text-format')
-
-    def form_field_encoding(self, field):
-        """return encoding used for the given (text) field"""
-        entity = self.edited_entity
-        if field.eidparam and entity.e_schema.has_metadata(field.name, 'encoding') and (
-            entity.has_eid() or '%s_encoding' % field.name in entity):
-            return self.edited_entity.attr_metadata(field.name, 'encoding')
-        return super(EntityFieldsForm, self).form_field_encoding(field)
-
-    def form_field_name(self, field):
-        """return qualified name for the given field"""
-        if field.eidparam:
-            return eid_param(field.name, self.edited_entity.eid)
-        return field.name
-
-    def form_field_id(self, field):
-        """return dom id for the given field"""
-        if field.eidparam:
-            return eid_param(field.id, self.edited_entity.eid)
-        return field.id
-
-    def form_field_vocabulary(self, field, limit=None):
-        """return vocabulary for the given field"""
-        role, rtype = field.role, field.name
-        method = '%s_%s_vocabulary' % (role, rtype)
-        try:
-            vocabfunc = getattr(self, method)
-        except AttributeError:
-            try:
-                # XXX bw compat, <role>_<rtype>_vocabulary on the entity
-                vocabfunc = getattr(self.edited_entity, method)
-            except AttributeError:
-                vocabfunc = getattr(self, '%s_relation_vocabulary' % role)
-            else:
-                warn('found %s on %s, should be set on a specific form'
-                     % (method, self.edited_entity.id), DeprecationWarning)
-        # NOTE: it is the responsibility of `vocabfunc` to sort the result
-        #       (direclty through RQL or via a python sort). This is also
-        #       important because `vocabfunc` might return a list with
-        #       couples (label, None) which act as separators. In these
-        #       cases, it doesn't make sense to sort results afterwards.
-        return vocabfunc(rtype, limit)
-
-    def subject_relation_vocabulary(self, rtype, limit=None):
-        """defaut vocabulary method for the given relation, looking for
-        relation's object entities (i.e. self is the subject)
-        """
-        entity = self.edited_entity
-        if isinstance(rtype, basestring):
-            rtype = entity.schema.rschema(rtype)
-        done = None
-        assert not rtype.is_final(), rtype
-        if entity.has_eid():
-            done = set(e.eid for e in getattr(entity, str(rtype)))
-        result = []
-        rsetsize = None
-        for objtype in rtype.objects(entity.e_schema):
-            if limit is not None:
-                rsetsize = limit - len(result)
-            result += self._relation_vocabulary(rtype, objtype, 'subject',
-                                                rsetsize, done)
-            if limit is not None and len(result) >= limit:
-                break
-        return result
-
-    def object_relation_vocabulary(self, rtype, limit=None):
-        """defaut vocabulary method for the given relation, looking for
-        relation's subject entities (i.e. self is the object)
-        """
-        entity = self.edited_entity
-        if isinstance(rtype, basestring):
-            rtype = entity.schema.rschema(rtype)
-        done = None
-        if entity.has_eid():
-            done = set(e.eid for e in getattr(entity, 'reverse_%s' % rtype))
-        result = []
-        rsetsize = None
-        for subjtype in rtype.subjects(entity.e_schema):
-            if limit is not None:
-                rsetsize = limit - len(result)
-            result += self._relation_vocabulary(rtype, subjtype, 'object',
-                                                rsetsize, done)
-            if limit is not None and len(result) >= limit:
-                break
-        return result
-
-    def subject_in_state_vocabulary(self, rtype, limit=None):
-        """vocabulary method for the in_state relation, looking for relation's
-        object entities (i.e. self is the subject) according to initial_state,
-        state_of and next_state relation
-        """
-        entity = self.edited_entity
-        if not entity.has_eid() or not entity.in_state:
-            # get the initial state
-            rql = 'Any S where S state_of ET, ET name %(etype)s, ET initial_state S'
-            rset = self.req.execute(rql, {'etype': str(entity.e_schema)})
-            if rset:
-                return [(rset.get_entity(0, 0).view('combobox'), rset[0][0])]
-            return []
-        results = []
-        for tr in entity.in_state[0].transitions(entity):
-            state = tr.destination_state[0]
-            results.append((state.view('combobox'), state.eid))
-        return sorted(results)
-
-
-class CompositeForm(FieldsForm):
-    """form composed for sub-forms"""
-
-    def __init__(self, *args, **kwargs):
-        super(CompositeForm, self).__init__(*args, **kwargs)
-        self.forms = []
-
-    def form_add_subform(self, subform):
-        """mark given form as a subform and append it"""
-        subform.is_subform = True
-        self.forms.append(subform)
--- a/web/formfields.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/formfields.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """field classes for form construction
 
 :organization: Logilab
-:copyright: 2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2009 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
 """
 __docformat__ = "restructuredtext en"
 
@@ -19,6 +20,7 @@
     HiddenInput, TextInput, FileInput, PasswordInput, TextArea, FCKEditor,
     Radio, Select, DateTimePicker)
 
+
 class Field(object):
     """field class is introduced to control what's displayed in forms. It makes
     the link between something to edit and its display in the form. Actual
@@ -79,16 +81,13 @@
         self.label = label or name
         self.help = help
         self.required = required
-        if widget is not None:
-            self.widget = widget
-        if isinstance(self.widget, type):
-            self.widget = self.widget()
         self.initial = initial
         self.choices = choices
         self.sort = sort
         self.internationalizable = internationalizable
         self.eidparam = eidparam
         self.role = role
+        self.init_widget(widget)
         # ordering number for this field instance
         self.creation_rank = Field.__creation_rank
         Field.__creation_rank += 1
@@ -101,6 +100,14 @@
     def __repr__(self):
         return self.__unicode__().encode('utf-8')
 
+    def init_widget(self, widget):
+        if widget is None and self.choices:
+            widget = Select()
+        if widget is not None:
+            self.widget = widget
+        if isinstance(self.widget, type):
+            self.widget = self.widget()
+
     def set_name(self, name):
         """automatically set .id and .label when name is set"""
         assert name
@@ -176,10 +183,21 @@
         """
         pass
 
+
 class StringField(Field):
+    widget = TextArea
+
     def __init__(self, max_length=None, **kwargs):
+        self.max_length = max_length # must be set before super call
         super(StringField, self).__init__(**kwargs)
-        self.max_length = max_length
+
+    def init_widget(self, widget):
+        if widget is None:
+            if self.choices:
+                widget = Select()
+            elif self.max_length and self.max_length < 257:
+                widget = TextInput()
+        super(StringField, self).init_widget(widget)
         if isinstance(self.widget, TextArea):
             self.init_text_area(self.widget)
 
@@ -222,7 +240,6 @@
             else:
                 # else we want a format selector
                 fkwargs['widget'] = Select()
-                fkwargs['widget'].attrs['size'] = 1
                 fcstr = FormatConstraint()
                 fkwargs['choices'] = fcstr.vocabulary(req=req)
                 fkwargs['internationalizable'] = True
@@ -341,6 +358,7 @@
             self.widget.attrs.setdefault('size', 5)
             self.widget.attrs.setdefault('maxlength', 15)
 
+
 class BooleanField(Field):
     widget = Radio
 
@@ -380,6 +398,7 @@
     format_prop = 'ui.datetime-format'
     widget = TextInput
 
+
 class HiddenInitialValueField(Field):
     def __init__(self, visible_field):
         name = 'edit%s-%s' % (visible_field.role[0], visible_field.name)
@@ -469,18 +488,11 @@
             # init StringField parameters according to constraints
             for cstr in constraints:
                 if isinstance(cstr, StaticVocabularyConstraint):
-                    kwargs.setdefault('widget', Select())
                     kwargs.setdefault('choices', cstr.vocabulary)
-                    if card in '?1':
-                        if isinstance(kwargs['widget'], type):
-                            kwargs['widget'] = kwargs['widget']()
-                        kwargs['widget'].attrs.setdefault('size', 1)
+                    break
             for cstr in constraints:
                 if isinstance(cstr, SizeConstraint) and cstr.max is not None:
-                    if cstr.max < 257:
-                        kwargs.setdefault('widget', TextInput())
                     kwargs['max_length'] = cstr.max
-            kwargs.setdefault('widget', TextArea())
             return StringField(**kwargs)
         if fieldclass is FileField:
             for metadata in ('format', 'encoding'):
@@ -492,6 +504,7 @@
     kwargs['role'] = role
     return RelationField.fromcardinality(card, **kwargs)
 
+
 FIELDS = {
     'Boolean':  BooleanField,
     'Bytes':    FileField,
--- a/web/formrenderers.py	Fri May 29 16:11:49 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,479 +0,0 @@
-"""form renderers, responsible to layout a form to html
-
-:organization: Logilab
-:copyright: 2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
-"""
-__docformat__ = "restructuredtext en"
-
-from logilab.common import dictattr
-from logilab.mtconverter import html_escape
-
-from simplejson import dumps
-
-from cubicweb.common import tags
-from cubicweb.web import eid_param
-from cubicweb.web import formwidgets as fwdgs
-from cubicweb.web.widgets import checkbox
-from cubicweb.web.formfields import HiddenInitialValueField
-
-
-class FormRenderer(object):
-    """basic renderer displaying fields in a two columns table label | value
-
-    +--------------+--------------+
-    | field1 label | field1 input |
-    +--------------+--------------+
-    | field1 label | field2 input |
-    +--------------+--------------+
-    +---------+
-    | buttons |
-    +---------+
-    """
-    _options = ('display_fields', 'display_label', 'display_help',
-                'display_progress_div', 'table_class', 'button_bar_class')
-    display_fields = None # None -> all fields
-    display_label = True
-    display_help = True
-    display_progress_div = True
-    table_class = u'attributeForm'
-    button_bar_class = u'formButtonBar'
-
-    def __init__(self, **kwargs):
-        if self._set_options(kwargs):
-            raise ValueError('unconsumed arguments %s' % kwargs)
-
-    def _set_options(self, kwargs):
-        for key in self._options:
-            try:
-                setattr(self, key, kwargs.pop(key))
-            except KeyError:
-                continue
-        return kwargs
-
-    # renderer interface ######################################################
-
-    def render(self, form, values):
-        self._set_options(values)
-        form.add_media()
-        data = []
-        w = data.append
-        w(self.open_form(form, values))
-        if self.display_progress_div:
-            w(u'<div id="progress">%s</div>' % form.req._('validating...'))
-        w(u'<fieldset>')
-        w(tags.input(type=u'hidden', name=u'__form_id',
-                     value=values.get('formvid', form.id)))
-        if form.redirect_path:
-            w(tags.input(type='hidden', name='__redirectpath', value=form.redirect_path))
-        self.render_fields(w, form, values)
-        self.render_buttons(w, form)
-        w(u'</fieldset>')
-        w(u'</form>')
-        errormsg = self.error_message(form)
-        if errormsg:
-            data.insert(0, errormsg)
-        return '\n'.join(data)
-
-    def render_label(self, form, field):
-        label = form.req._(field.label)
-        attrs = {'for': form.context[field]['id']}
-        if field.required:
-            attrs['class'] = 'required'
-        return tags.label(label, **attrs)
-
-    def render_help(self, form, field):
-        help = []
-        descr = field.help
-        if descr:
-            help.append('<div class="helper">%s</div>' % form.req._(descr))
-        example = field.example_format(form.req)
-        if example:
-            help.append('<div class="helper">(%s: %s)</div>'
-                        % (form.req._('sample format'), example))
-        return u'&nbsp;'.join(help)
-
-    # specific methods (mostly to ease overriding) #############################
-
-    def error_message(self, form):
-        """return formatted error message
-
-        This method should be called once inlined field errors has been consumed
-        """
-        req = form.req
-        errex = form.form_valerror
-        # get extra errors
-        if errex is not None:
-            errormsg = req._('please correct the following errors:')
-            displayed = form.form_displayed_errors
-            errors = sorted((field, err) for field, err in errex.errors.items()
-                            if not field in displayed)
-            if errors:
-                if len(errors) > 1:
-                    templstr = '<li>%s</li>\n'
-                else:
-                    templstr = '&nbsp;%s\n'
-                for field, err in errors:
-                    if field is None:
-                        errormsg += templstr % err
-                    else:
-                        errormsg += templstr % '%s: %s' % (req._(field), err)
-                if len(errors) > 1:
-                    errormsg = '<ul>%s</ul>' % errormsg
-            return u'<div class="errorMessage">%s</div>' % errormsg
-        return u''
-
-    def open_form(self, form, values):
-        if form.form_needs_multipart:
-            enctype = 'multipart/form-data'
-        else:
-            enctype = 'application/x-www-form-urlencoded'
-        if form.action is None:
-            action = form.req.build_url('edit')
-        else:
-            action = form.action
-        tag = ('<form action="%s" method="post" enctype="%s"' % (
-            html_escape(action or '#'), enctype))
-        if form.domid:
-            tag += ' id="%s"' % form.domid
-        if form.onsubmit:
-            tag += ' onsubmit="%s"' % html_escape(form.onsubmit % dictattr(form))
-        if form.cssstyle:
-            tag += ' style="%s"' % html_escape(form.cssstyle)
-        if form.cssclass:
-            tag += ' class="%s"' % html_escape(form.cssclass)
-        if form.cwtarget:
-            tag += ' cubicweb:target="%s"' % html_escape(form.cwtarget)
-        return tag + '>'
-
-    def display_field(self, form, field):
-        if isinstance(field, HiddenInitialValueField):
-            field = field.visible_field
-        return (self.display_fields is None
-                or field.name in form.internal_fields
-                or (field.name, field.role) in self.display_fields
-                or (field.name, field.role) in form.internal_fields)
-
-    def render_fields(self, w, form, values):
-        form.form_build_context(values)
-        fields = self._render_hidden_fields(w, form)
-        if fields:
-            self._render_fields(fields, w, form)
-        self.render_child_forms(w, form, values)
-
-    def render_child_forms(self, w, form, values):
-        # render
-        for childform in getattr(form, 'forms', []):
-            self.render_fields(w, childform, values)
-
-    def _render_hidden_fields(self, w, form):
-        fields = form.fields[:]
-        for field in form.fields:
-            if not self.display_field(form, field):
-                fields.remove(field)
-            elif not field.is_visible():
-                w(field.render(form, self))
-                fields.remove(field)
-        return fields
-
-    def _render_fields(self, fields, w, form):
-        w(u'<table class="%s">' % self.table_class)
-        for field in fields:
-            w(u'<tr>')
-            if self.display_label:
-                w(u'<th class="labelCol">%s</th>' % self.render_label(form, field))
-            error = form.form_field_error(field)
-            if error:
-                w(u'<td class="error">')
-                w(error)
-            else:
-                w(u'<td>')
-            w(field.render(form, self))
-            if self.display_help:
-                w(self.render_help(form, field))
-            w(u'</td></tr>')
-        w(u'</table>')
-
-    def render_buttons(self, w, form):
-        w(u'<table class="%s">\n<tr>\n' % self.button_bar_class)
-        for button in form.form_buttons:
-            w(u'<td>%s</td>\n' % button.render(form))
-        w(u'</tr></table>')
-
-
-class HTableFormRenderer(FormRenderer):
-    """display fields horizontally in a table
-
-    +--------------+--------------+---------+
-    | field1 label | field2 label |         |
-    +--------------+--------------+---------+
-    | field1 input | field2 input | buttons
-    +--------------+--------------+---------+
-    """
-    display_help = False
-    def _render_fields(self, fields, w, form):
-        w(u'<table border="0">')
-        w(u'<tr>')
-        for field in fields:
-            if self.display_label:
-                w(u'<th class="labelCol">%s</th>' % self.render_label(form, field))
-            if self.display_help:
-                w(self.render_help(form, field))
-        # empty slot for buttons
-        w(u'<th class="labelCol">&nbsp;</th>')
-        w(u'</tr>')
-        w(u'<tr>')
-        for field in fields:
-            error = form.form_field_error(field)
-            if error:
-                w(u'<td class="error">')
-                w(error)
-            else:
-                w(u'<td>')
-            w(field.render(form, self))
-            w(u'</td>')
-        w(u'<td>')
-        for button in form.form_buttons:
-            w(button.render(form))
-        w(u'</td>')
-        w(u'</tr>')
-        w(u'</table>')
-
-    def render_buttons(self, w, form):
-        pass
-
-
-class EntityCompositeFormRenderer(FormRenderer):
-    """specific renderer for multiple entities edition form (muledit)"""
-
-    def render_fields(self, w, form, values):
-        if not form.is_subform:
-            w(u'<table class="listing">')
-        super(EntityCompositeFormRenderer, self).render_fields(w, form, values)
-        if not form.is_subform:
-            w(u'</table>')
-
-    def _render_fields(self, fields, w, form):
-        if form.is_subform:
-            entity = form.edited_entity
-            values = form.form_previous_values
-            qeid = eid_param('eid', entity.eid)
-            cbsetstate = "setCheckboxesState2('eid', %s, 'checked')" % html_escape(dumps(entity.eid))
-            w(u'<tr class="%s">' % (entity.row % 2 and u'even' or u'odd'))
-            # XXX turn this into a widget used on the eid field
-            w(u'<td>%s</td>' % checkbox('eid', entity.eid, checked=qeid in values))
-            for field in fields:
-                error = form.form_field_error(field)
-                if error:
-                    w(u'<td class="error">')
-                    w(error)
-                else:
-                    w(u'<td>')
-                if isinstance(field.widget, (fwdgs.Select, fwdgs.CheckBox, fwdgs.Radio)):
-                    field.widget.attrs['onchange'] = cbsetstate
-                elif isinstance(field.widget, fwdgs.Input):
-                    field.widget.attrs['onkeypress'] = cbsetstate
-                w(u'<div>%s</div>' % field.render(form, self))
-                w(u'</td>')
-        else:
-            # main form, display table headers
-            w(u'<tr class="header">')
-            w(u'<th align="left">%s</th>'
-              % tags.input(type='checkbox', title=form.req._('toggle check boxes'),
-                           onclick="setCheckboxesState('eid', this.checked)"))
-            for field in self.forms[0].fields:
-                if self.display_field(form, field) and field.is_visible():
-                    w(u'<th>%s</th>' % form.req._(field.label))
-        w(u'</tr>')
-
-
-
-class EntityFormRenderer(FormRenderer):
-    """specific renderer for entity edition form (edition)"""
-    _options = FormRenderer._options + ('display_relations_form',)
-    display_relations_form = True
-
-    def render(self, form, values):
-        rendered = super(EntityFormRenderer, self).render(form, values)
-        return rendered + u'</div>' # close extra div introducted by open_form
-
-    def open_form(self, form, values):
-        attrs_fs_label = ('<div class="iformTitle"><span>%s</span></div>'
-                          % form.req._('main informations'))
-        attrs_fs_label += '<div class="formBody">'
-        return attrs_fs_label + super(EntityFormRenderer, self).open_form(form, values)
-
-    def render_fields(self, w, form, values):
-        super(EntityFormRenderer, self).render_fields(w, form, values)
-        self.inline_entities_form(w, form)
-        if form.edited_entity.has_eid() and self.display_relations_form:
-            self.relations_form(w, form)
-
-    def _render_fields(self, fields, w, form):
-        if not form.edited_entity.has_eid() or form.edited_entity.has_perm('update'):
-            super(EntityFormRenderer, self)._render_fields(fields, w, form)
-
-    def render_buttons(self, w, form):
-        if len(form.form_buttons) == 3:
-            w("""<table width="100%%">
-  <tbody>
-   <tr><td align="center">
-     %s
-   </td><td style="align: right; width: 50%%;">
-     %s
-     %s
-   </td></tr>
-  </tbody>
- </table>""" % tuple(button.render(form) for button in form.form_buttons))
-        else:
-            super(EntityFormRenderer, self).render_buttons(w, form)
-
-    def relations_form(self, w, form):
-        srels_by_cat = form.srelations_by_category('generic', 'add')
-        if not srels_by_cat:
-            return u''
-        req = form.req
-        _ = req._
-        label = u'%s :' % _('This %s' % form.edited_entity.e_schema).capitalize()
-        eid = form.edited_entity.eid
-        w(u'<fieldset class="subentity">')
-        w(u'<legend class="iformTitle">%s</legend>' % label)
-        w(u'<table id="relatedEntities">')
-        for rschema, target, related in form.relations_table():
-            # already linked entities
-            if related:
-                w(u'<tr><th class="labelCol">%s</th>' % rschema.display_name(req, target))
-                w(u'<td>')
-                w(u'<ul>')
-                for viewparams in related:
-                    w(u'<li class="invisible">%s<div id="span%s" class="%s">%s</div></li>'
-                      % (viewparams[1], viewparams[0], viewparams[2], viewparams[3]))
-                if not form.force_display and form.maxrelitems < len(related):
-                    link = (u'<span class="invisible">'
-                            '[<a href="javascript: window.location.href+=\'&amp;__force_display=1\'">%s</a>]'
-                            '</span>' % form.req._('view all'))
-                    w(u'<li class="invisible">%s</li>' % link)
-                w(u'</ul>')
-                w(u'</td>')
-                w(u'</tr>')
-        pendings = list(form.restore_pending_inserts())
-        if not pendings:
-            w(u'<tr><th>&nbsp;</th><td>&nbsp;</td></tr>')
-        else:
-            for row in pendings:
-                # soon to be linked to entities
-                w(u'<tr id="tr%s">' % row[1])
-                w(u'<th>%s</th>' % row[3])
-                w(u'<td>')
-                w(u'<a class="handle" title="%s" href="%s">[x]</a>' %
-                  (_('cancel this insert'), row[2]))
-                w(u'<a id="a%s" class="editionPending" href="%s">%s</a>'
-                  % (row[1], row[4], html_escape(row[5])))
-                w(u'</td>')
-                w(u'</tr>')
-        w(u'<tr id="relationSelectorRow_%s" class="separator">' % eid)
-        w(u'<th class="labelCol">')
-        w(u'<span>%s</span>' % _('add relation'))
-        w(u'<select id="relationSelector_%s" tabindex="%s" '
-          'onchange="javascript:showMatchingSelect(this.options[this.selectedIndex].value,%s);">'
-          % (eid, req.next_tabindex(), html_escape(dumps(eid))))
-        w(u'<option value="">%s</option>' % _('select a relation'))
-        for i18nrtype, rschema, target in srels_by_cat:
-            # more entities to link to
-            w(u'<option value="%s_%s">%s</option>' % (rschema, target, i18nrtype))
-        w(u'</select>')
-        w(u'</th>')
-        w(u'<td id="unrelatedDivs_%s"></td>' % eid)
-        w(u'</tr>')
-        w(u'</table>')
-        w(u'</fieldset>')
-
-    def inline_entities_form(self, w, form):
-        """create a form to edit entity's inlined relations"""
-        if not hasattr(form, 'inlined_relations'):
-            return
-        entity = form.edited_entity
-        __ = form.req.__
-        for rschema, targettypes, role in form.inlined_relations():
-            # show inline forms only if there's one possible target type
-            # for rschema
-            if len(targettypes) != 1:
-                self.warning('entity related by the %s relation should have '
-                             'inlined form but there is multiple target types, '
-                             'dunno what to do', rschema)
-                continue
-            targettype = targettypes[0].type
-            if form.should_inline_relation_form(rschema, targettype, role):
-                w(u'<div id="inline%sslot">' % rschema)
-                existant = entity.has_eid() and entity.related(rschema)
-                if existant:
-                    # display inline-edition view for all existing related entities
-                    w(form.view('inline-edition', existant, rtype=rschema, role=role,
-                                ptype=entity.e_schema, peid=entity.eid))
-                if role == 'subject':
-                    card = rschema.rproperty(entity.e_schema, targettype, 'cardinality')[0]
-                else:
-                    card = rschema.rproperty(targettype, entity.e_schema, 'cardinality')[1]
-                # there is no related entity and we need at least one: we need to
-                # display one explicit inline-creation view
-                if form.should_display_inline_creation_form(rschema, existant, card):
-                    w(form.view('inline-creation', None, etype=targettype,
-                                peid=entity.eid, ptype=entity.e_schema,
-                                rtype=rschema, role=role))
-                # we can create more than one related entity, we thus display a link
-                # to add new related entities
-                if form.should_display_add_new_relation_link(rschema, existant, card):
-                    divid = "addNew%s%s%s:%s" % (targettype, rschema, role, entity.eid)
-                    w(u'<div class="inlinedform" id="%s" cubicweb:limit="true">'
-                      % divid)
-                    js = "addInlineCreationForm('%s', '%s', '%s', '%s')" % (
-                        entity.eid, targettype, rschema, role)
-                    if card in '1?':
-                        js = "toggleVisibility('%s'); %s" % (divid, js)
-                    w(u'<a class="addEntity" id="add%s:%slink" href="javascript: %s" >+ %s.</a>'
-                      % (rschema, entity.eid, js, __('add a %s' % targettype)))
-                    w(u'</div>')
-                    w(u'<div class="trame_grise">&nbsp;</div>')
-                w(u'</div>')
-
-
-class EntityInlinedFormRenderer(EntityFormRenderer):
-    """specific renderer for entity inlined edition form
-    (inline-[creation|edition])
-    """
-    def render(self, form, values):
-        form.add_media()
-        data = []
-        w = data.append
-        try:
-            w(u'<div id="div-%(divid)s" onclick="%(divonclick)s">' % values)
-        except KeyError:
-            w(u'<div id="div-%(divid)s">' % values)
-        else:
-            w(u'<div id="notice-%s" class="notice">%s</div>' % (
-                values['divid'], form.req._('click on the box to cancel the deletion')))
-        w(u'<div class="iformBody">')
-        values['removemsg'] = form.req.__('remove this %s' % form.edited_entity.e_schema)
-        w(u'<div class="iformTitle"><span>%(title)s</span> '
-          '#<span class="icounter">1</span> '
-          '[<a href="javascript: %(removejs)s;noop();">%(removemsg)s</a>]</div>'
-          % values)
-        # cleanup values
-        for key in ('title', 'removejs', 'removemsg'):
-            values.pop(key)
-        self.render_fields(w, form, values)
-        w(u'</div></div>')
-        return '\n'.join(data)
-
-    def render_fields(self, w, form, values):
-        form.form_build_context(values)
-        w(u'<fieldset id="fs-%(divid)s">' % values)
-        fields = self._render_hidden_fields(w, form)
-        w(u'</fieldset>')
-        w(u'<fieldset class="subentity">')
-        if fields:
-            self._render_fields(fields, w, form)
-        self.render_child_forms(w, form, values)
-        self.inline_entities_form(w, form)
-        w(u'</fieldset>')
-
--- a/web/formwidgets.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/formwidgets.py	Fri May 29 20:22:39 2009 +0200
@@ -1,12 +1,14 @@
 """widget classes for form construction
 
 :organization: Logilab
-:copyright: 2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2009 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
 """
 __docformat__ = "restructuredtext en"
 
 from datetime import date
+from warnings import warn
 
 from cubicweb.common import tags
 from cubicweb.web import stdmsgs, INTERNAL_FIELD_VALUE
@@ -109,6 +111,11 @@
         return u'\n'.join(inputs)
 
 
+class PasswordSingleInput(Input):
+    """<input type='password'> without a confirmation field"""
+    type = 'password'
+
+
 class FileInput(Input):
     """<input type='file'>"""
     type = 'file'
@@ -170,8 +177,8 @@
 
     def render(self, form, field):
         name, curvalues, attrs = self._render_attrs(form, field)
-        if not 'size' in attrs and self._multiple:
-            attrs['size'] = '5'
+        if not 'size' in attrs:
+            attrs['size'] = self._multiple and '5' or '1'
         options = []
         optgroup_opened = False
         for label, value in field.vocabulary(form):
@@ -299,6 +306,17 @@
     wdgtype = 'SuggestField'
     loadtype = 'auto'
 
+    def __init__(self, *args, **kwargs):
+        try:
+            self.autocomplete_initfunc = kwargs.pop('autocomplete_initfunc')
+        except KeyError:
+            warn('use autocomplete_initfunc argument of %s constructor '
+                 'instead of relying on autocomplete_initfuncs dictionary on '
+                 'the entity class' % self.__class__.__name__,
+                 DeprecationWarning)
+            self.autocomplete_initfunc = None
+        super(AutoCompletionWidget, self).__init__(*args, **kwargs)
+
     def _render_attrs(self, form, field):
         name, values, attrs = super(AutoCompletionWidget, self)._render_attrs(form, field)
         init_ajax_attributes(attrs, self.wdgtype, self.loadtype)
@@ -307,7 +325,11 @@
         return name, values, attrs
 
     def _get_url(self, entity, field):
-        fname = entity.autocomplete_initfuncs[field.name]
+        if self.autocomplete_initfunc is None:
+            # XXX for bw compat
+            fname = entity.autocomplete_initfuncs[field.name]
+        else:
+            fname = self.autocomplete_initfunc
         return entity.req.build_url('json', fname=fname, mode='remote',
                                     pageid=entity.req.pageid)
 
@@ -317,7 +339,12 @@
     wdgtype = 'StaticFileSuggestField'
 
     def _get_url(self, entity, field):
-        return entity.req.datadir_url + entity.autocomplete_initfuncs[field.name]
+        if self.autocomplete_initfunc is None:
+            # XXX for bw compat
+            fname = entity.autocomplete_initfuncs[field.name]
+        else:
+            fname = self.autocomplete_initfunc
+        return entity.req.datadir_url + fname
 
 
 class RestrictedAutoCompletionWidget(AutoCompletionWidget):
--- a/web/htmlwidgets.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/htmlwidgets.py	Fri May 29 20:22:39 2009 +0200
@@ -4,8 +4,9 @@
 serialization time
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 from logilab.mtconverter import html_escape
--- a/web/httpcache.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/httpcache.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/request.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/request.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """abstract class for http request
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/test/data/schema/testschema.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/data/schema/testschema.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 class Salesterm(EntityType):
     described_by_test = SubjectRelation('File', cardinality='1*', composite='subject')
     amount = Int(constraints=[IntervalBoundConstraint(0, 100)])
--- a/web/test/data/views.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/data/views.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.web import Redirect
 from cubicweb.web.application import CubicWebPublisher
 
--- a/web/test/test_views.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/test_views.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""automatic tests"""
+"""automatic tests
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from cubicweb.devtools.testlib import WebTest, AutomaticWebTest
 from cubicweb.view import AnyRsetView
--- a/web/test/unittest_application.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_application.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,11 @@
 # -*- coding: iso-8859-1 -*-
-"""unit tests for cubicweb.web.application"""
+"""unit tests for cubicweb.web.application
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from logilab.common.testlib import TestCase, unittest_main
 import base64, Cookie
--- a/web/test/unittest_controller.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_controller.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,6 @@
 """cubicweb.web.controller unit tests
 
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 
 from datetime import datetime, date, time
--- a/web/test/unittest_form.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_form.py	Fri May 29 20:22:39 2009 +0200
@@ -1,13 +1,22 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
+
 from logilab.common.testlib import unittest_main, mock_object
+
 from cubicweb import Binary
 from cubicweb.devtools.testlib import WebTest
-from cubicweb.web.form import EntityFieldsForm, FieldsForm
-from cubicweb.web.formrenderers import FormRenderer
 from cubicweb.web.formfields import (IntField, StringField, RichTextField,
                                      DateTimeField, DateTimePicker,
                                      FileField, EditableFileField)
 from cubicweb.web.formwidgets import PasswordInput
+from cubicweb.web.views.forms import EntityFieldsForm, FieldsForm
 from cubicweb.web.views.workflow import ChangeStateForm
+from cubicweb.web.views.formrenderers import FormRenderer
 
 
 class FieldsFormTC(WebTest):
@@ -26,7 +35,6 @@
         super(EntityFieldsFormTC, self).setUp()
         self.req = self.request()
         self.entity = self.user(self.req)
-        self.renderer = FormRenderer()
 
     def test_form_field_vocabulary_unrelated(self):
         b = self.add_entity('BlogEntry', title=u'di mascii code', content=u'a best-seller')
@@ -116,7 +124,8 @@
 
     def _render_entity_field(self, name, form):
         form.form_build_context({})
-        return form.field_by_name(name).render(form, self.renderer)
+        renderer = FormRenderer(self.req)
+        return form.field_by_name(name).render(form, renderer)
 
     def _test_richtextfield(self, expected):
         class RTFForm(EntityFieldsForm):
@@ -146,8 +155,8 @@
 
     def test_filefield(self):
         class FFForm(EntityFieldsForm):
-            data = FileField(format_field=StringField(name='data_format'),
-                             encoding_field=StringField(name='data_encoding'))
+            data = FileField(format_field=StringField(name='data_format', max_length=50),
+                             encoding_field=StringField(name='data_encoding', max_length=20))
         file = self.add_entity('File', name=u"pouet.txt", data_encoding=u'UTF-8',
                                data=Binary('new widgets system'))
         form = FFForm(self.req, redirect_path='perdu.com', entity=file)
@@ -155,8 +164,8 @@
                               '''<input id="data:%(eid)s" name="data:%(eid)s" tabindex="0" type="file" value=""/>
 <a href="javascript: toggleVisibility(&#39;data:%(eid)s-advanced&#39;)" title="show advanced fields"><img src="http://testing.fr/cubicweb/data/puce_down.png" alt="show advanced fields"/></a>
 <div id="data:%(eid)s-advanced" class="hidden">
-<label for="data_format:%(eid)s">data_format</label><input id="data_format:%(eid)s" name="data_format:%(eid)s" tabindex="1" type="text" value="text/plain"/><br/><br/>
-<label for="data_encoding:%(eid)s">data_encoding</label><input id="data_encoding:%(eid)s" name="data_encoding:%(eid)s" tabindex="2" type="text" value="UTF-8"/><br/><br/>
+<label for="data_format:%(eid)s">data_format</label><input id="data_format:%(eid)s" name="data_format:%(eid)s" tabindex="1" type="text" value="text/plain"/><br/>
+<label for="data_encoding:%(eid)s">data_encoding</label><input id="data_encoding:%(eid)s" name="data_encoding:%(eid)s" tabindex="2" type="text" value="UTF-8"/><br/>
 </div>
 <br/>
 <input name="data:%(eid)s__detach" type="checkbox"/>
@@ -166,8 +175,8 @@
 
     def test_editablefilefield(self):
         class EFFForm(EntityFieldsForm):
-            data = EditableFileField(format_field=StringField(name='data_format'),
-                                     encoding_field=StringField(name='data_encoding'))
+            data = EditableFileField(format_field=StringField(name='data_format', max_length=50),
+                                     encoding_field=StringField(name='data_encoding', max_length=20))
             def form_field_encoding(self, field):
                 return 'ascii'
             def form_field_format(self, field):
@@ -179,8 +188,8 @@
                               '''<input id="data:%(eid)s" name="data:%(eid)s" tabindex="0" type="file" value=""/>
 <a href="javascript: toggleVisibility(&#39;data:%(eid)s-advanced&#39;)" title="show advanced fields"><img src="http://testing.fr/cubicweb/data/puce_down.png" alt="show advanced fields"/></a>
 <div id="data:%(eid)s-advanced" class="hidden">
-<label for="data_format:%(eid)s">data_format</label><input id="data_format:%(eid)s" name="data_format:%(eid)s" tabindex="1" type="text" value="text/plain"/><br/><br/>
-<label for="data_encoding:%(eid)s">data_encoding</label><input id="data_encoding:%(eid)s" name="data_encoding:%(eid)s" tabindex="2" type="text" value="UTF-8"/><br/><br/>
+<label for="data_format:%(eid)s">data_format</label><input id="data_format:%(eid)s" name="data_format:%(eid)s" tabindex="1" type="text" value="text/plain"/><br/>
+<label for="data_encoding:%(eid)s">data_encoding</label><input id="data_encoding:%(eid)s" name="data_encoding:%(eid)s" tabindex="2" type="text" value="UTF-8"/><br/>
 </div>
 <br/>
 <input name="data:%(eid)s__detach" type="checkbox"/>
--- a/web/test/unittest_formfields.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_formfields.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""unittests for cw.web.formfields"""
+"""unittests for cw.web.formfields
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from logilab.common.testlib import TestCase, unittest_main
 
@@ -6,9 +12,9 @@
 
 from cubicweb.devtools import TestServerConfiguration
 from cubicweb.devtools.testlib import EnvBasedTC
-from cubicweb.web.form import EntityFieldsForm
 from cubicweb.web.formwidgets import PasswordInput, TextArea, Select
 from cubicweb.web.formfields import *
+from cubicweb.web.views.forms import EntityFieldsForm
 
 from cubes.file.entities import File
 
--- a/web/test/unittest_magicsearch.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_magicsearch.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,11 @@
 # -*- coding: utf-8 -*-
-"""Unit tests for magic_search service"""
+"""Unit tests for magic_search service
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 import sys
 
--- a/web/test/unittest_urlpublisher.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_urlpublisher.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,11 @@
 # -*- coding: utf-8 -*-
-"""Unit tests for url publishing service"""
+"""Unit tests for url publishing service
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 import re
 
--- a/web/test/unittest_urlrewrite.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_urlrewrite.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.testlib import TestCase, unittest_main
 
 from cubicweb.devtools._apptest import FakeRequest
--- a/web/test/unittest_views_actions.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_views_actions.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.testlib import unittest_main
 
 from cubicweb.devtools.apptest import EnvBasedTC
--- a/web/test/unittest_views_apacherewrite.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_views_apacherewrite.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.testlib import TestCase, unittest_main
 
 from cubicweb.web.views.apacherewrite import *
@@ -16,22 +23,23 @@
                             rules=[('/(.*)', r'/m_%(cat)s/\1')]),
                 ]
         urlrewriter = MyAppRules()
+        req = None # not used in the above rules, so keep a simple TestCase here
         try:
-            urlrewriter.rewrite('logilab.fr', '/whatever')
+            urlrewriter.rewrite('logilab.fr', '/whatever', req)
             self.fail('redirect exception expected')
         except Redirect, ex:
             self.assertEquals(ex.location, 'http://www.logilab.fr/whatever')
-        self.assertEquals(urlrewriter.rewrite('www.logilab.fr', '/whatever'),
+        self.assertEquals(urlrewriter.rewrite('www.logilab.fr', '/whatever', req),
                           '/whatever')
-        self.assertEquals(urlrewriter.rewrite('www.logilab.fr', '/json/bla'),
+        self.assertEquals(urlrewriter.rewrite('www.logilab.fr', '/json/bla', req),
                           '/json/bla')
-        self.assertEquals(urlrewriter.rewrite('abcd.logilab.fr', '/json/bla'),
+        self.assertEquals(urlrewriter.rewrite('abcd.logilab.fr', '/json/bla', req),
                           '/json/bla')
-        self.assertEquals(urlrewriter.rewrite('abcd.logilab.fr', '/data/bla'),
+        self.assertEquals(urlrewriter.rewrite('abcd.logilab.fr', '/data/bla', req),
                           '/data/bla')
-        self.assertEquals(urlrewriter.rewrite('abcd.logilab.fr', '/whatever'),
+        self.assertEquals(urlrewriter.rewrite('abcd.logilab.fr', '/whatever', req),
                           '/m_abcd/whatever')
-        self.assertEquals(urlrewriter.rewrite('abcd.fr', '/whatever'),
+        self.assertEquals(urlrewriter.rewrite('abcd.fr', '/whatever', req),
                           '/whatever')
 
 
--- a/web/test/unittest_views_basecontrollers.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_views_basecontrollers.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""cubicweb.web.views.basecontrollers unit tests"""
+"""cubicweb.web.views.basecontrollers unit tests
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 import simplejson
 
 from logilab.common.testlib import unittest_main, mock_object
--- a/web/test/unittest_views_baseforms.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_views_baseforms.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""cubicweb.web.views.baseforms unit tests"""
+"""cubicweb.web.views.baseforms unit tests
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from StringIO import StringIO
 from datetime import date
--- a/web/test/unittest_views_basetemplates.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_views_basetemplates.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.devtools.testlib import WebTest
 from cubicweb.devtools.htmlparser import DTDValidator
 
--- a/web/test/unittest_views_baseviews.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_views_baseviews.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from simplejson import loads
 
 from logilab.common.testlib import unittest_main
--- a/web/test/unittest_views_editforms.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_views_editforms.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.testlib import unittest_main
 from cubicweb.devtools.apptest import EnvBasedTC
 from cubicweb.devtools.testlib import WebTest
--- a/web/test/unittest_views_embeding.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_views_embeding.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from logilab.common.testlib import TestCase, unittest_main
 
--- a/web/test/unittest_views_navigation.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_views_navigation.py	Fri May 29 20:22:39 2009 +0200
@@ -1,4 +1,10 @@
-"""cubicweb.web.views.navigation unit tests"""
+"""cubicweb.web.views.navigation unit tests
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 
 from logilab.common.testlib import unittest_main, mock_object
 from cubicweb.devtools.apptest import EnvBasedTC
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/test/unittest_views_pyviews.py	Fri May 29 20:22:39 2009 +0200
@@ -0,0 +1,25 @@
+from logilab.common.testlib import unittest_main
+from cubicweb.devtools.apptest import EnvBasedTC
+
+class PyViewsTC(EnvBasedTC):
+
+    def test_pyvaltable(self):
+        content = self.vreg.view('pyvaltable', self.request(),
+                                 pyvalue=[[1, 'a'], [2, 'b']],
+                                 headers=['num', 'char'])
+        self.assertEquals(content.strip(), '''<table class="listing">
+<tr><th>num</th><th>char</th></tr>
+<tr><td>1</td><td>a</td></tr>
+<tr><td>2</td><td>b</td></tr>
+</table>''')
+
+    def test_pyvallist(self):
+        content = self.vreg.view('pyvallist', self.request(),
+                                 pyvalue=[1, 'a'])
+        self.assertEquals(content.strip(), '''<ul>
+<li>1</li>
+<li>a</li>
+</ul>''')
+
+if __name__ == '__main__':
+    unittest_main()
--- a/web/test/unittest_views_searchrestriction.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_views_searchrestriction.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from cubicweb.devtools.apptest import EnvBasedTC
 from cubicweb.web.facet import insert_attr_select_relation, prepare_facets_rqlst
 
--- a/web/test/unittest_viewselector.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_viewselector.py	Fri May 29 20:22:39 2009 +0200
@@ -1,5 +1,6 @@
 # -*- coding: iso-8859-1 -*-
 """XXX rename, split, reorganize this
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 from logilab.common.testlib import unittest_main
 
--- a/web/test/unittest_web.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_web.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 from logilab.common.testlib import TestCase, unittest_main
 from cubicweb.web import ajax_replace_url as  arurl
 class AjaxReplaceUrlTC(TestCase):
--- a/web/test/unittest_webconfig.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/test/unittest_webconfig.py	Fri May 29 20:22:39 2009 +0200
@@ -1,3 +1,10 @@
+"""
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
 import os
 
 from logilab.common.testlib import TestCase, unittest_main
--- a/web/test/unittest_widgets.py	Fri May 29 16:11:49 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,369 +0,0 @@
-"""cubicweb.common.widget unit tests"""
-
-from datetime import datetime
-NOW = datetime.now()
-
-from logilab.common.testlib import unittest_main
-from cubicweb.devtools.apptest import EnvBasedTC
-
-from cubicweb.common.mttransforms import HAS_TAL
-from cubicweb.web.widgets import widget, AutoCompletionWidget
-
-
-class WidgetsTC(EnvBasedTC):
-
-    def get_widget(self, etype, rname, rtype):
-        rschema = self.schema[rname]
-        return widget(self.vreg, etype, rschema, rtype, role='subject')
-
-
-    def test_hidden_widget(self):
-        w = self.get_widget('State', 'eid', 'Int')
-        self.assertEquals(w.name, 'eid')
-        self.assertEquals(w.render_example(self.request()), '')
-        self.assertDictEquals(w.attrs, {})
-        entity = self.etype_instance('State')
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), True)
-        self.assertEquals(w.render(entity), '')
-        self.assertEquals(w.edit_render(entity),
-                           u'<input type="hidden" name="eid" value="X" />')
-
-    def test_textarea_widget(self):
-        self.add_entity('CWProperty', pkey=u'ui.fckeditor', value=u'')
-        self.commit()
-        w = self.get_widget('State', 'description', 'String')
-        self.assertEquals(w.name, 'description')
-        self.assertEquals(w.render_example(self.request()), '')
-        self.assertDictEquals(w.attrs, {'accesskey': 'd'})
-        entity = self.etype_instance('State')
-        entity.eid = 'X'
-        entity
-        self.assertEquals(w.required(entity), False)
-        self.assertEquals(w.render(entity), '')
-        if HAS_TAL:
-            tal_format = u'\n<option value="text/cubicweb-page-template" >text/cubicweb-page-template</option>'
-        else:
-            tal_format = u''
-        self.assertTextEquals(w.edit_render(entity),
-                           u'''<input type="hidden" name="edits-description:X" value="__cubicweb_internal_field__"/>
-<input type="hidden" name="edits-description_format:X" value="__cubicweb_internal_field__"/>
-
-<select name="description_format:X" id="description_format:X" tabindex="0">
-<option value="text/rest" >text/rest</option>
-<option value="text/html" selected="selected">text/html</option>
-<option value="text/plain" >text/plain</option>%s
-</select><br/><textarea onkeypress="autogrow(this)" name="description:X" accesskey="d" cols="80" id="description:X" rows="20" tabindex="1"></textarea>''' % tal_format)
-
-    def test_textarea_widget_previous_value(self):
-        self.add_entity('CWProperty', pkey=u'ui.fckeditor', value=u'')
-        self.commit()
-        w = self.get_widget('State', 'description', 'String')
-        req = self.request()
-        req.data['formvalues'] = {'description:X': 'a description'}
-        entity = self.etype_instance('State', req)
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), False)
-        self.assertEquals(w.render(entity), '')
-        if HAS_TAL:
-            tal_format = u'\n<option value="text/cubicweb-page-template" >text/cubicweb-page-template</option>'
-        else:
-            tal_format = u''
-        self.assertTextEquals(w.edit_render(entity),
-                           u'''<input type="hidden" name="edits-description:X" value="__cubicweb_internal_field__"/>
-<input type="hidden" name="edits-description_format:X" value="__cubicweb_internal_field__"/>
-
-<select name="description_format:X" id="description_format:X" tabindex="0">
-<option value="text/rest" >text/rest</option>
-<option value="text/html" selected="selected">text/html</option>
-<option value="text/plain" >text/plain</option>%s
-</select><br/><textarea onkeypress="autogrow(this)" name="description:X" accesskey="d" cols="80" id="description:X" rows="20" tabindex="1">a description</textarea>''' % tal_format)
-
-    def test_fckeditor_widget(self):
-        w = self.get_widget('State', 'description', 'String')
-        req = self.request()
-        entity = self.etype_instance('State', req)
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), False)
-        self.assertEquals(w.render(entity), '')
-        self.assertTextEquals(w.edit_render(entity),
-                           u'''<input type="hidden" name="edits-description:X" value="__cubicweb_internal_field__"/>
-<input type="hidden" name="edits-description_format:X" value=""/>
-<input type="hidden" name="description_format:X" value="text/html"/>
-<textarea cubicweb:type="wysiwyg" onkeypress="autogrow(this)" name="description:X" accesskey="d" cols="80" id="description:X" rows="20" tabindex="0"></textarea>''')
-
-    def test_string_widget(self):
-        w = self.get_widget('Personne', 'nom', 'String')
-        self.assertEquals(w.name, 'nom')
-        self.assertEquals(w.render_example(self.request()), '')
-        self.assertDictEquals(w.attrs, {'accesskey': 'n', 'maxlength': 64, 'size': 40})
-        entity = self.etype_instance('Personne')
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), True)
-        self.assertEquals(w.render(entity), '')
-        self.assertEquals(w.edit_render(entity),
-                           u'<input type="hidden" name="edits-nom:X" value="__cubicweb_internal_field__"/>\n'
-                          '<input type="text" name="nom:X" value="" accesskey="n" id="nom:X" maxlength="64" size="40" tabindex="0"/>')
-
-    def test_string_widget_previous_value(self):
-        w = self.get_widget('Personne', 'nom', 'String')
-        self.assertEquals(w.name, 'nom')
-        self.assertEquals(w.render_example(self.request()), '')
-        self.assertDictEquals(w.attrs, {'accesskey': 'n', 'maxlength': 64, 'size': 40})
-        req = self.request()
-        req.data['formvalues'] = {'nom:X': 'a name'}
-        entity = self.etype_instance('Personne', req)
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), True)
-        self.assertEquals(w.render(entity), '')
-        self.assertEquals(w.edit_render(entity),
-                           u'<input type="hidden" name="edits-nom:X" value="__cubicweb_internal_field__"/>\n'
-                          '<input type="text" name="nom:X" value="a name" accesskey="n" id="nom:X" maxlength="64" size="40" tabindex="0"/>')
-
-    def test_static_combo_widget(self):
-        w = self.get_widget('Personne', 'promo', 'String')
-        self.assertEquals(w.name, 'promo')
-        self.assertEquals(w.render_example(self.request()), '')
-        self.assertDictEquals(w.attrs, {})
-        entity = self.etype_instance('Personne')
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), False)
-        self.assertEquals(w.render(entity), '')
-        self.assertTextEquals(w.edit_render(entity),
-                           u'<input type="hidden" name="edits-promo:X" value="__cubicweb_internal_field__"/>\n\n'
-                          '<select name="promo:X" id="promo:X" tabindex="0">\n'
-                          '<option value="bon" >bon</option>\n'
-                          '<option value="pasbon" >pasbon</option>\n'
-                          '</select>')
-
-    def test_static_combo_widget_previous_value(self):
-        w = self.get_widget('Personne', 'promo', 'String')
-        self.assertEquals(w.name, 'promo')
-        self.assertEquals(w.render_example(self.request()), '')
-        self.assertDictEquals(w.attrs, {})
-        req = self.request()
-        req.data['formvalues'] = {'promo:X': 'pasbon'}
-        entity = self.etype_instance('Personne', req)
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), False)
-        self.assertEquals(w.render(entity), '')
-        self.assertTextEquals(w.edit_render(entity),
-                           u'<input type="hidden" name="edits-promo:X" value="__cubicweb_internal_field__"/>\n\n'
-                          '<select name="promo:X" id="promo:X" tabindex="0">\n'
-                          '<option value="bon" >bon</option>\n'
-                          '<option value="pasbon" selected="selected">pasbon</option>\n'
-                          '</select>')
-
-    def test_integer_widget(self):
-        w = self.get_widget('Personne', 'tel', 'Int')
-        self.assertEquals(w.name, 'tel')
-        self.assertEquals(w.render_example(self.request()), '23')
-        self.assertDictEquals(w.attrs, {'accesskey': 't', 'maxlength': 15, 'size': 5})
-        entity = self.etype_instance('Personne')
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), False)
-        self.assertEquals(w.render(entity), '')
-        self.assertEquals(w.edit_render(entity),
-                           u'<input type="hidden" name="edits-tel:X" value="__cubicweb_internal_field__"/>\n'
-                          '<input type="text" name="tel:X" value="" accesskey="t" id="tel:X" maxlength="15" size="5" tabindex="0"/>')
-
-    def test_integer_widget_previous_value(self):
-        w = self.get_widget('Personne', 'tel', 'Int')
-        self.assertEquals(w.name, 'tel')
-        self.assertEquals(w.render_example(self.request()), '23')
-        self.assertDictEquals(w.attrs, {'accesskey': 't', 'maxlength': 15, 'size': 5})
-        req = self.request()
-        req.data['formvalues'] = {'tel:X': '0123456789'}
-        entity = self.etype_instance('Personne', req)
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), False)
-        self.assertEquals(w.render(entity), '')
-        self.assertEquals(w.edit_render(entity),
-                           u'<input type="hidden" name="edits-tel:X" value="__cubicweb_internal_field__"/>\n'
-                          '<input type="text" name="tel:X" value="0123456789" accesskey="t" id="tel:X" maxlength="15" size="5" tabindex="0"/>')
-
-    def test_datetime_widget(self):
-        w = self.get_widget('Personne', 'datenaiss', 'Datetime')
-        self.assertEquals(w.name, 'datenaiss')
-        example = '%s, or without time: %s' % (
-            NOW.strftime(self.vreg.property_value('ui.datetime-format')),
-            NOW.strftime(self.vreg.property_value('ui.date-format')))
-        self.assertEquals(w.render_example(self.request()), example)
-        self.assertDictEquals(w.attrs, {'accesskey': 'd', 'maxlength': 16, 'size': 16})
-        entity = self.etype_instance('Personne')
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), False)
-        self.assertEquals(w.render(entity), '')
-        self.assertEquals(w.edit_render(entity),
-                           u'<input type="hidden" name="edits-datenaiss:X" value="__cubicweb_internal_field__"/>\n'
-                          '<input type="text" name="datenaiss:X" value="" accesskey="d" id="datenaiss:X" maxlength="16" size="16" tabindex="0"/>'
-                          '<a onclick="toggleCalendar(\'datenaiss:Xhelper\', \'datenaiss:X\', %s, %s);" class="calhelper">\n<img src="http://testing.fr/cubicweb/data/calendar.gif" title="calendar" alt="" /></a><div class="calpopup hidden" id="datenaiss:Xhelper"></div>' % (NOW.year, NOW.month))
-
-    def test_datetime_widget_previous_value(self):
-        w = self.get_widget('Personne', 'datenaiss', 'Datetime')
-        self.assertEquals(w.name, 'datenaiss')
-        self.assertDictEquals(w.attrs, {'accesskey': 'd', 'maxlength': 16, 'size': 16})
-        req = self.request()
-        req.data['formvalues'] = {'datenaiss:X': '2000/01/01'}
-        entity = self.etype_instance('Personne', req)
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), False)
-        self.assertEquals(w.render(entity), '')
-        self.assertEquals(w.edit_render(entity),
-                           u'<input type="hidden" name="edits-datenaiss:X" value="__cubicweb_internal_field__"/>\n'
-                          '<input type="text" name="datenaiss:X" value="2000/01/01" accesskey="d" id="datenaiss:X" maxlength="16" size="16" tabindex="0"/>'
-                          '<a onclick="toggleCalendar(\'datenaiss:Xhelper\', \'datenaiss:X\', %s, %s);" class="calhelper">\n<img src="http://testing.fr/cubicweb/data/calendar.gif" title="calendar" alt="" /></a><div class="calpopup hidden" id="datenaiss:Xhelper"></div>' % (NOW.year, NOW.month))
-
-
-
-    def test_float_widget(self):
-        w = self.get_widget('Personne', 'salary', 'Float')
-        self.assertEquals(w.name, 'salary')
-        format = self.vreg.property_value('ui.float-format')
-        self.assertEquals(w.render_example(self.request()), format % 1.23)
-        self.assertDictEquals(w.attrs, {'accesskey': 's', 'maxlength': 15, 'size': 5})
-        entity = self.etype_instance('Personne')
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), False)
-        self.assertEquals(w.render(entity), '')
-        self.assertEquals(w.edit_render(entity),
-                          u'<input type="hidden" name="edits-salary:X" value="__cubicweb_internal_field__"/>\n'
-                          '<input type="text" name="salary:X" value="" accesskey="s" id="salary:X" maxlength="15" size="5" tabindex="0"/>')
-
-
-    def test_float_widget_previous_value(self):
-        w = self.get_widget('Personne', 'salary', 'Float')
-        self.assertEquals(w.name, 'salary')
-        format = self.vreg.property_value('ui.float-format')
-        self.assertEquals(w.render_example(self.request()), format % 1.23)
-        self.assertDictEquals(w.attrs, {'accesskey': 's', 'maxlength': 15, 'size': 5})
-        req = self.request()
-        req.data['formvalues'] = {'salary:X': 7.89}
-        entity = self.etype_instance('Personne', req)
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), False)
-        self.assertEquals(w.render(entity), '')
-        self.assertEquals(w.edit_render(entity),
-                          u'<input type="hidden" name="edits-salary:X" value="__cubicweb_internal_field__"/>\n'
-                          '<input type="text" name="salary:X" value="7.89" accesskey="s" id="salary:X" maxlength="15" size="5" tabindex="0"/>')
-
-
-    def test_bool_widget(self):
-        w = self.get_widget('Personne', 'test', 'Boolean')
-        self.assertEquals(w.name, 'test')
-        self.assertEquals(w.render_example(self.request()), '')
-        self.assertDictEquals(w.attrs, {'accesskey': 't'})
-        entity = self.etype_instance('Personne')
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), False)
-        self.assertEquals(w.render(entity), '')
-        self.assertEquals(w.edit_render(entity),
-                           u'''<input type="hidden" name="edits-test:X" value="__cubicweb_internal_field__"/>
-
-<input type="radio" name="test:X" value="1" accesskey="t" id="test:X" tabindex="0"/>yes<br/>
-<input type="radio" name="test:X" value="" accesskey="t" tabindex="0" checked="checked"/>no<br/>''')
-
-    def test_bool_widget_previous_value(self):
-        w = self.get_widget('Personne', 'test', 'Boolean')
-        self.assertEquals(w.name, 'test')
-        self.assertEquals(w.render_example(self.request()), '')
-        self.assertDictEquals(w.attrs, {'accesskey': 't'})
-        req = self.request()
-        req.data['formvalues'] = {'test:X': 'checked'}
-        entity = self.etype_instance('Personne', req)
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), False)
-        self.assertEquals(w.render(entity), '')
-        self.assertEquals(w.edit_render(entity),
-                           u'''<input type="hidden" name="edits-test:X" value="__cubicweb_internal_field__"/>
-
-<input type="radio" name="test:X" value="1" accesskey="t" id="test:X" tabindex="0" checked="checked"/>yes<br/>
-<input type="radio" name="test:X" value="" accesskey="t" tabindex="0"/>no<br/>''')
-
-
-    def test_password_widget(self):
-        w = self.get_widget('CWUser', 'upassword', 'Password')
-        self.assertEquals(w.name, 'upassword')
-        self.assertEquals(w.render_example(self.request()), '')
-        self.assertDictEquals(w.attrs, {'accesskey': 'u'})
-        entity = self.etype_instance('CWUser')
-        entity.eid = 'X'
-        self.assertEquals(w.required(entity), True)
-        self.assertEquals(w.render(entity), '')
-        self.assertEquals(w.edit_render(entity),
-                           u'<input type="hidden" name="edits-upassword:X" value="__cubicweb_internal_field__"/>\n'
-                          '<input type="password" name="upassword:X" value="" accesskey="u" id="upassword:X" tabindex="0"/><br/>\n'
-                          '<input type="password" name="upassword-confirm:X" id="upassword-confirm:X" tabindex="1"/>&nbsp;<span class="emphasis">(confirm password)</span>')
-
-    def test_autocompletion_widget(self):
-        entity = self.etype_instance('Personne')
-        entity.widgets['nom'] = 'AutoCompletionWidget'
-        entity.autocomplete_initfuncs = {'nom' : 'getnames'}
-        try:
-            w = self.get_widget(entity, 'nom', 'String')
-            self.failUnless(isinstance(w, AutoCompletionWidget))
-            self.assertEquals(w.name, 'nom')
-            self.assertEquals(w.render_example(self.request()), '')
-            self.assertDictEquals(w.attrs, {'accesskey': 'n', 'maxlength': 64, 'size': 40})
-            entity.eid = 'X'
-            self.assertEquals(w.required(entity), True)
-            self.assertEquals(w.render(entity), '')
-
-            self.assertTextEquals(w.edit_render(entity),
-                                  u'<input type="hidden" name="edits-nom:X" value="__cubicweb_internal_field__"/>\n'
-                                  u'<input type="text" name="nom:X" value="" cubicweb:dataurl="http://testing.fr/cubicweb/json?pageid=None&amp;mode=remote&amp;fname=getnames" class="widget required" id="nom:X" tabindex="0" cubicweb:loadtype="auto" cubicweb:wdgtype="SuggestField"  cubicweb:accesskey="n" cubicweb:maxlength="64" cubicweb:size="40" />')
-
-        finally:
-            del entity.widgets['nom']
-
-
-    def test_autocompletion_widget_previous_value(self):
-        req = self.request()
-        req.data['formvalues'] = {'nom:X': 'a name'}
-        entity = self.etype_instance('Personne', req)
-        entity.widgets['nom'] = 'AutoCompletionWidget'
-        entity.autocomplete_initfuncs = {'nom' : 'getnames'}
-        try:
-            w = self.get_widget(entity, 'nom', 'String')
-            self.failUnless(isinstance(w, AutoCompletionWidget))
-            self.assertEquals(w.name, 'nom')
-            self.assertEquals(w.render_example(self.request()), '')
-            self.assertDictEquals(w.attrs, {'accesskey': 'n', 'maxlength': 64, 'size': 40})
-            entity.eid = 'X'
-            self.assertEquals(w.required(entity), True)
-            self.assertEquals(w.render(entity), '')
-            self.assertTextEquals(w.edit_render(entity),
-                                  u'<input type="hidden" name="edits-nom:X" value="__cubicweb_internal_field__"/>\n'
-                                  u'<input type="text" name="nom:X" value="a name" cubicweb:dataurl="http://testing.fr/cubicweb/json?pageid=None&amp;mode=remote&amp;fname=getnames" class="widget required" id="nom:X" tabindex="0" cubicweb:loadtype="auto" cubicweb:wdgtype="SuggestField"  cubicweb:accesskey="n" cubicweb:maxlength="64" cubicweb:size="40" />')
-
-        finally:
-            del entity.widgets['nom']
-
-
-    def test_nonregr_float_widget_with_none(self):
-        w = self.get_widget('Personne', 'salary', 'Float')
-        self.assertEquals(w.name, 'salary')
-        format = self.vreg.property_value('ui.float-format')
-        self.assertEquals(w.render_example(self.request()), format % 1.23)
-        self.assertDictEquals(w.attrs, {'accesskey': 's', 'maxlength': 15, 'size': 5})
-        req = self.request()
-        entity = self.etype_instance('Personne', req)
-        entity.eid = 'X'
-        entity.salary = None
-        self.assertEquals(w.required(entity), False)
-        self.assertEquals(w.render(entity), '')
-        self.assertEquals(w.edit_render(entity),
-                          u'<input type="hidden" name="edits-salary:X" value="__cubicweb_internal_field__"/>\n'
-                          '<input type="text" name="salary:X" value="" accesskey="s" id="salary:X" maxlength="15" size="5" tabindex="0"/>')
-
-
-    def test_custom_widget_for_non_final_relation(self):
-        entity = self.etype_instance('Personne', self.request())
-        entity.widgets['travaille'] = 'AutoCompletionWidget'
-        entity.autocomplete_initfuncs = {'nom' : 'getnames'}
-        w = self.get_widget(entity, 'travaille', 'Societe')
-        self.failUnless(isinstance(w, AutoCompletionWidget))
-
-
-if __name__ == '__main__':
-    unittest_main()
--- a/web/uicfg.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/uicfg.py	Fri May 29 20:22:39 2009 +0200
@@ -1,6 +1,3 @@
-# :organization: Logilab
-# :copyright: 2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """This module regroups a set of structures that may be used to configure
 various places of the generated web interface.
 
@@ -63,6 +60,10 @@
 Automatic form configuration
 ````````````````````````````
 
+:organization: Logilab
+:copyright: 2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Views, forms, actions... for the CubicWeb web client
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/actions.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/actions.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Set of HTML base actions
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/ajaxedit.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/ajaxedit.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Set of views allowing edition of entities/relations using ajax
 
 :organization: Logilab
-:copyright: 2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/apacherewrite.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/apacherewrite.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 are much more limited for the moment)
 
 :organization: Logilab
-:copyright: 2007-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2007-2009 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
 """
 
 __docformat__ = "restructuredtext en"
@@ -87,8 +88,11 @@
     id = 'urlrewriter'
     rules = []
 
-    def rewrite(self, host, path):
-        for cond in self.rules:
+    def get_rules(self, req):
+        return self.rules
+
+    def rewrite(self, host, path, req):
+        for cond in self.get_rules(req):
             if cond.match(host=host, path=path):
                 return cond.process(path)
         return path
--- a/web/views/authentication.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/authentication.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """user authentication component
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/autoform.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/autoform.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """The automatic entity form.
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
@@ -11,13 +12,13 @@
 
 from cubicweb import typed_eid
 from cubicweb.web import stdmsgs, uicfg
-from cubicweb.web.form import FieldNotFound, EntityFieldsForm
+from cubicweb.web.form import FieldNotFound
 from cubicweb.web.formfields import guess_field
 from cubicweb.web.formwidgets import Button, SubmitButton
-from cubicweb.web.views.editforms import toggleable_relation_link, relation_id
+from cubicweb.web.views import forms, editforms
 
 
-class AutomaticEntityForm(EntityFieldsForm):
+class AutomaticEntityForm(forms.EntityFieldsForm):
     """base automatic form to edit any entity.
 
     Designed to be fully generated from schema but highly configurable through:
@@ -32,7 +33,7 @@
     cwtarget = 'eformframe'
     cssclass = 'entityForm'
     copy_nav_params = True
-    form_buttons = [SubmitButton(stdmsgs.BUTTON_OK),
+    form_buttons = [SubmitButton(),
                     Button(stdmsgs.BUTTON_APPLY, cwaction='apply'),
                     Button(stdmsgs.BUTTON_CANCEL, cwaction='cancel')]
     attrcategories = ('primary', 'secondary')
@@ -234,13 +235,13 @@
         for label, rschema, role in self.srelations_by_category('generic', 'add'):
             relatedrset = entity.related(rschema, role, limit=self.related_limit)
             if rschema.has_perm(self.req, 'delete'):
-                toggleable_rel_link_func = toggleable_relation_link
+                toggleable_rel_link_func = editforms.toggleable_relation_link
             else:
                 toggleable_rel_link_func = lambda x, y, z: u''
             related = []
             for row in xrange(relatedrset.rowcount):
-                nodeid = relation_id(entity.eid, rschema, role,
-                                     relatedrset[row][0])
+                nodeid = editforms.relation_id(entity.eid, rschema, role,
+                                               relatedrset[row][0])
                 if nodeid in pending_deletes:
                     status = u'pendingDelete'
                     label = '+'
--- a/web/views/basecomponents.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/basecomponents.py	Fri May 29 20:22:39 2009 +0200
@@ -4,8 +4,9 @@
 * the logged user link
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
--- a/web/views/basecontrollers.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/basecontrollers.py	Fri May 29 20:22:39 2009 +0200
@@ -4,8 +4,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
@@ -22,9 +23,9 @@
 from cubicweb.view import STRICT_DOCTYPE, STRICT_DOCTYPE_NOEXT
 from cubicweb.common.mail import format_mail
 from cubicweb.web import ExplicitLogin, Redirect, RemoteCallFailed, json_dumps
-from cubicweb.web.formrenderers import FormRenderer
 from cubicweb.web.controller import Controller
 from cubicweb.web.views import vid_from_rset
+from cubicweb.web.views.formrenderers import FormRenderer
 try:
     from cubicweb.web.facet import (FilterRQLBuilder, get_facet,
                                     prepare_facets_rqlst)
@@ -340,7 +341,7 @@
                                        entity=entity)
         form.form_build_context()
         vfield = form.field_by_name('value')
-        renderer = FormRenderer()
+        renderer = FormRenderer(self.req)
         return vfield.render(form, renderer, tabindex=tabindex) \
                + renderer.render_help(form, vfield)
 
--- a/web/views/baseforms.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/baseforms.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 or a list of entities of the same type
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/basetemplates.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/basetemplates.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 """default templates for CubicWeb web client
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/baseviews.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/baseviews.py	Fri May 29 20:22:39 2009 +0200
@@ -7,8 +7,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 #from __future__ import with_statement
 __docformat__ = "restructuredtext en"
--- a/web/views/bookmark.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/bookmark.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Primary view for bookmarks + user's bookmarks box
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/boxes.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/boxes.py	Fri May 29 20:22:39 2009 +0200
@@ -9,8 +9,9 @@
 * startup views box
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
--- a/web/views/calendar.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/calendar.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """html calendar views
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
@@ -527,4 +528,3 @@
                                                    year=nextdate.year,
                                                    week=nextdate.isocalendar()[1])
         return prevlink, nextlink
-
--- a/web/views/csvexport.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/csvexport.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """csv export views
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/cwproperties.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/cwproperties.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Specific views for CWProperty
 
 :organization: Logilab
-:copyright: 2007-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2007-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
@@ -16,11 +17,10 @@
                                 match_user_groups)
 from cubicweb.view import StartupView
 from cubicweb.web import uicfg, stdmsgs
-from cubicweb.web.form import CompositeForm, EntityFieldsForm, FormViewMixIn
-from cubicweb.web.formrenderers import FormRenderer
+from cubicweb.web.form import FormViewMixIn
 from cubicweb.web.formfields import FIELDS, StringField
 from cubicweb.web.formwidgets import Select, Button, SubmitButton
-from cubicweb.web.views import primary
+from cubicweb.web.views import primary, formrenderers
 
 
 # some string we want to be internationalizable for nicer display of property
@@ -189,10 +189,11 @@
 
     def form(self, formid, keys, splitlabel=False):
         buttons = [SubmitButton()]
-        form = CompositeForm(self.req, domid=formid, action=self.build_url(),
-                             form_buttons=buttons,
-                             onsubmit="return validatePrefsForm('%s')" % formid,
-                             submitmsg=self.req._('changes applied'))
+        form = self.vreg.select_object('forms', 'composite', self.req,
+                                  domid=formid, action=self.build_url(),
+                                  form_buttons=buttons,
+                                  onsubmit="return validatePrefsForm('%s')" % formid,
+                                  submitmsg=self.req._('changes applied'))
         path = self.req.relative_path()
         if '?' in path:
             path, params = path.split('?', 1)
@@ -200,9 +201,9 @@
         form.form_add_hidden('__redirectpath', path)
         for key in keys:
             self.form_row(form, key, splitlabel)
-        renderer = CWPropertiesFormRenderer()
-        return form.form_render(display_progress_div=False,
-                                renderer=renderer)
+        renderer = self.vreg.select_object('formrenderers', 'cwproperties', self.req,
+                                           display_progress_div=False)
+        return form.form_render(renderer=renderer)
 
     def form_row(self, form, key, splitlabel):
         entity = self.entity_for_key(key)
@@ -210,8 +211,8 @@
             label = key.split('.')[-1]
         else:
             label = key
-        subform = EntityFieldsForm(self.req, entity=entity, set_error_url=False)
-
+        subform = self.vreg.select_object('forms', 'base', self.req, entity=entity,
+                                     set_error_url=False)
         subform.append_field(PropertyValueField(name='value', label=label,
                                                 eidparam=True))
         subform.vreg = self.vreg
@@ -358,8 +359,9 @@
 uicfg.autoform_field.tag_attribute(('CWProperty', 'value'), PropertyValueField)
 
 
-class CWPropertiesFormRenderer(FormRenderer):
+class CWPropertiesFormRenderer(formrenderers.FormRenderer):
     """specific renderer for properties"""
+    id = 'cwproperties'
 
     def open_form(self, form, values):
         err = '<div class="formsg"></div>'
--- a/web/views/cwuser.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/cwuser.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Specific views for users
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/debug.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/debug.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/editcontroller.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/editcontroller.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """The edit controller, handling form submitting.
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/editforms.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/editforms.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 or a list of entities of the same type
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
@@ -20,12 +21,10 @@
 from cubicweb.view import EntityView
 from cubicweb.common import tags
 from cubicweb.web import INTERNAL_FIELD_VALUE, stdmsgs, eid_param
-from cubicweb.web.form import CompositeForm, EntityFieldsForm, FormViewMixIn
+from cubicweb.web.form import FormViewMixIn
 from cubicweb.web.formfields import RelationField
 from cubicweb.web.formwidgets import Button, SubmitButton, ResetButton, Select
-from cubicweb.web.formrenderers import (FormRenderer, EntityFormRenderer,
-                                        EntityCompositeFormRenderer,
-                                        EntityInlinedFormRenderer)
+from cubicweb.web.views import forms
 
 
 def relation_id(eid, rtype, role, reid):
@@ -60,17 +59,19 @@
           % _('this action is not reversible!'))
         # XXX above message should have style of a warning
         w(u'<h4>%s</h4>\n' % _('Do you want to delete the following element(s) ?'))
-        form = CompositeForm(req, domid='deleteconf', copy_nav_params=True,
-                             action=self.build_url('edit'), onsubmit=onsubmit,
-                             form_buttons=[Button(stdmsgs.YES, cwaction='delete'),
-                                           Button(stdmsgs.NO, cwaction='cancel')])
+        form = self.vreg.select_object('forms', 'composite', req, domid='deleteconf',
+                                       copy_nav_params=True,
+                                       action=self.build_url('edit'), onsubmit=onsubmit,
+                                       form_buttons=[Button(stdmsgs.YES, cwaction='delete'),
+                                                     Button(stdmsgs.NO, cwaction='cancel')])
         done = set()
         w(u'<ul>\n')
         for entity in self.rset.entities():
             if entity.eid in done:
                 continue
             done.add(entity.eid)
-            subform = EntityFieldsForm(req, entity=entity, set_error_url=False)
+            subform = self.vreg.select_object('forms', 'base', req, entity=entity,
+                                              set_error_url=False)
             form.form_add_subform(subform)
             # don't use outofcontext view or any other that may contain inline edition form
             w(u'<li>%s</li>' % tags.a(entity.view('textoutofcontext'),
@@ -113,14 +114,18 @@
             self.w(value)
             return
         if rschema.is_final():
-            form = self._build_attribute_form(entity, value, rtype, role, reload, row, col, default)
+            form = self._build_attribute_form(entity, value, rtype, role,
+                                              reload, row, col, default)
         else:
-            form = self._build_relation_form(entity, value, rtype, role, row, col, vid, default)
+            form = self._build_relation_form(entity, value, rtype, role,
+                                             row, col, vid, default)
         form.form_add_hidden(u'__maineid', entity.eid)
-        renderer = FormRenderer(display_label=False, display_help=False,
-                                display_fields=[(rtype, role)],
-                                table_class='', button_bar_class='buttonbar',
-                                display_progress_div=False)
+        renderer = self.vreg.select_object('formrenderers', 'base', self.req,
+                                      entity=entity,
+                                      display_label=False, display_help=False,
+                                      display_fields=[(rtype, role)],
+                                      table_class='', button_bar_class='buttonbar',
+                                      display_progress_div=False)
         self.w(form.form_render(renderer=renderer))
 
     def _build_relation_form(self, entity, value, rtype, role, row, col, vid, default):
@@ -128,16 +133,17 @@
         divid = 'd%s' % make_uid('%s-%s' % (rtype, entity.eid))
         event_data = {'divid' : divid, 'eid' : entity.eid, 'rtype' : rtype, 'vid' : vid,
                       'default' : default, 'role' : role}
-        form = EntityFieldsForm(self.req, None, entity=entity, action='#',
-                                domid='%s-form' % divid,
-                                cssstyle='display: none',
-                                onsubmit=("return inlineValidateRelationForm('%(divid)s-form', '%(rtype)s', "
-                                          "'%(role)s', '%(eid)s', '%(divid)s', '%(vid)s', '%(default)s');" %
-                                          event_data),
-                                form_buttons=[SubmitButton(),
-                                              Button(stdmsgs.BUTTON_CANCEL,
-                                                     onclick="cancelInlineEdit(%s,\'%s\',\'%s\')" %\
-                                                         (entity.eid, rtype, divid))])
+        onsubmit = ("return inlineValidateRelationForm('%(divid)s-form', '%(rtype)s', "
+                    "'%(role)s', '%(eid)s', '%(divid)s', '%(vid)s', '%(default)s');"
+                    % event_data)
+        cancelclick = "cancelInlineEdit(%s,\'%s\',\'%s\')" % (
+            entity.eid, rtype, divid)
+        form = self.vreg.select_object('forms', 'base', self.req, entity=entity,
+                                       domid='%s-form' % divid, cssstyle='display: none',
+                                       onsubmit=onsubmit, action='#',
+                                       form_buttons=[SubmitButton(),
+                                                     Button(stdmsgs.BUTTON_CANCEL,
+                                                       onclick=cancelclick)])
         form.append_field(RelationField(name=rtype, role=role, sort=True,
                                         widget=Select(),
                                         label=u' '))
@@ -172,7 +178,6 @@
     __select__ = one_line_rset() & non_final_entity() & yes()
 
     title = _('edition')
-    renderer = EntityFormRenderer()
 
     def cell_call(self, row, col, **kwargs):
         entity = self.complete_entity(row, col)
@@ -185,7 +190,7 @@
                                        row=entity.row, col=entity.col, entity=entity,
                                        submitmsg=self.submited_message())
         self.init_form(form, entity)
-        self.w(form.form_render(renderer=self.renderer, formvid=u'edition'))
+        self.w(form.form_render(formvid=u'edition'))
 
     def init_form(self, form, entity):
         """customize your form before rendering here"""
@@ -289,7 +294,7 @@
         return self.req._('entity copied')
 
 
-class TableEditForm(CompositeForm):
+class TableEditForm(forms.CompositeForm):
     id = 'muledit'
     domid = 'entityForm'
     onsubmit = "return validateForm('%s', null);" % domid
@@ -319,7 +324,7 @@
         """
         #self.form_title(entity)
         form = self.vreg.select_object('forms', self.id, self.req, self.rset)
-        self.w(form.form_render(renderer=EntityCompositeFormRenderer()))
+        self.w(form.form_render())
 
 
 class InlineEntityEditionFormView(FormViewMixIn, EntityView):
@@ -350,14 +355,15 @@
     def render_form(self, entity, peid, rtype, role, **kwargs):
         """fetch and render the form"""
         form = self.vreg.select_object('forms', 'edition', self.req, None,
-                                       entity=entity, set_error_url=False,
+                                       entity=entity, form_renderer_id='inline',
+                                       set_error_url=False,
                                        copy_nav_params=False)
         self.add_hiddens(form, entity, peid, rtype, role)
         divid = '%s-%s-%s' % (peid, rtype, entity.eid)
         title = self.schema.rschema(rtype).display_name(self.req, role)
         removejs = self.removejs % (peid, rtype,entity.eid)
-        self.w(form.form_render(renderer=EntityInlinedFormRenderer(), divid=divid,
-                                title=title, removejs=removejs,**kwargs))
+        self.w(form.form_render(divid=divid, title=title, removejs=removejs,
+                                **kwargs))
 
     def add_hiddens(self, form, entity, peid, rtype, role):
         # to ease overriding (see cubes.vcsfile.views.forms for instance)
--- a/web/views/editviews.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/editviews.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Some views used to help to the edition process
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/emailaddress.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/emailaddress.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Specific views for email addresses entities
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/embedding.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/embedding.py	Fri May 29 20:22:39 2009 +0200
@@ -3,8 +3,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/error.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/error.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 as startup views and are used for standard error pages (404, 500, etc.)
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/facets.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/facets.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """the facets box and some basic facets
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/views/formrenderers.py	Fri May 29 20:22:39 2009 +0200
@@ -0,0 +1,501 @@
+"""form renderers, responsible to layout a form to html
+
+:organization: Logilab
+:copyright: 2009 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
+"""
+__docformat__ = "restructuredtext en"
+
+from logilab.common import dictattr
+from logilab.mtconverter import html_escape
+
+from simplejson import dumps
+
+from cubicweb.common import tags
+from cubicweb.appobject import AppRsetObject
+from cubicweb.selectors import entity_implements, yes
+from cubicweb.web import eid_param
+from cubicweb.web import formwidgets as fwdgs
+from cubicweb.web.widgets import checkbox
+from cubicweb.web.formfields import HiddenInitialValueField
+
+
+class FormRenderer(AppRsetObject):
+    """basic renderer displaying fields in a two columns table label | value
+
+    +--------------+--------------+
+    | field1 label | field1 input |
+    +--------------+--------------+
+    | field1 label | field2 input |
+    +--------------+--------------+
+    +---------+
+    | buttons |
+    +---------+
+    """
+    __registry__ = 'formrenderers'
+    id = 'default'
+
+    _options = ('display_fields', 'display_label', 'display_help',
+                'display_progress_div', 'table_class', 'button_bar_class',
+                # add entity since it may be given to select the renderer
+                'entity')
+    display_fields = None # None -> all fields
+    display_label = True
+    display_help = True
+    display_progress_div = True
+    table_class = u'attributeForm'
+    button_bar_class = u'formButtonBar'
+
+    def __init__(self, req=None, rset=None, row=None, col=None, **kwargs):
+        super(FormRenderer, self).__init__(req, rset, row, col)
+        if self._set_options(kwargs):
+            raise ValueError('unconsumed arguments %s' % kwargs)
+
+    def _set_options(self, kwargs):
+        for key in self._options:
+            try:
+                setattr(self, key, kwargs.pop(key))
+            except KeyError:
+                continue
+        return kwargs
+
+    # renderer interface ######################################################
+
+    def render(self, form, values):
+        self._set_options(values)
+        form.add_media()
+        data = []
+        w = data.append
+        w(self.open_form(form, values))
+        if self.display_progress_div:
+            w(u'<div id="progress">%s</div>' % self.req._('validating...'))
+        w(u'<fieldset>')
+        w(tags.input(type=u'hidden', name=u'__form_id',
+                     value=values.get('formvid', form.id)))
+        if form.redirect_path:
+            w(tags.input(type='hidden', name='__redirectpath', value=form.redirect_path))
+        self.render_fields(w, form, values)
+        self.render_buttons(w, form)
+        w(u'</fieldset>')
+        w(u'</form>')
+        errormsg = self.error_message(form)
+        if errormsg:
+            data.insert(0, errormsg)
+        return '\n'.join(data)
+
+    def render_label(self, form, field):
+        label = self.req._(field.label)
+        attrs = {'for': form.context[field]['id']}
+        if field.required:
+            attrs['class'] = 'required'
+        return tags.label(label, **attrs)
+
+    def render_help(self, form, field):
+        help = []
+        descr = field.help
+        if descr:
+            help.append('<div class="helper">%s</div>' % self.req._(descr))
+        example = field.example_format(self.req)
+        if example:
+            help.append('<div class="helper">(%s: %s)</div>'
+                        % (self.req._('sample format'), example))
+        return u'&nbsp;'.join(help)
+
+    # specific methods (mostly to ease overriding) #############################
+
+    def error_message(self, form):
+        """return formatted error message
+
+        This method should be called once inlined field errors has been consumed
+        """
+        req = self.req
+        errex = form.form_valerror
+        # get extra errors
+        if errex is not None:
+            errormsg = req._('please correct the following errors:')
+            displayed = form.form_displayed_errors
+            errors = sorted((field, err) for field, err in errex.errors.items()
+                            if not field in displayed)
+            if errors:
+                if len(errors) > 1:
+                    templstr = '<li>%s</li>\n'
+                else:
+                    templstr = '&nbsp;%s\n'
+                for field, err in errors:
+                    if field is None:
+                        errormsg += templstr % err
+                    else:
+                        errormsg += templstr % '%s: %s' % (req._(field), err)
+                if len(errors) > 1:
+                    errormsg = '<ul>%s</ul>' % errormsg
+            return u'<div class="errorMessage">%s</div>' % errormsg
+        return u''
+
+    def open_form(self, form, values):
+        if form.form_needs_multipart:
+            enctype = 'multipart/form-data'
+        else:
+            enctype = 'application/x-www-form-urlencoded'
+        if form.action is None:
+            action = self.req.build_url('edit')
+        else:
+            action = form.action
+        tag = ('<form action="%s" method="post" enctype="%s"' % (
+            html_escape(action or '#'), enctype))
+        if form.domid:
+            tag += ' id="%s"' % form.domid
+        if form.onsubmit:
+            tag += ' onsubmit="%s"' % html_escape(form.onsubmit % dictattr(form))
+        if form.cssstyle:
+            tag += ' style="%s"' % html_escape(form.cssstyle)
+        if form.cssclass:
+            tag += ' class="%s"' % html_escape(form.cssclass)
+        if form.cwtarget:
+            tag += ' cubicweb:target="%s"' % html_escape(form.cwtarget)
+        return tag + '>'
+
+    def display_field(self, form, field):
+        if isinstance(field, HiddenInitialValueField):
+            field = field.visible_field
+        return (self.display_fields is None
+                or field.name in form.internal_fields
+                or (field.name, field.role) in self.display_fields
+                or (field.name, field.role) in form.internal_fields)
+
+    def render_fields(self, w, form, values):
+        form.form_build_context(values)
+        fields = self._render_hidden_fields(w, form)
+        if fields:
+            self._render_fields(fields, w, form)
+        self.render_child_forms(w, form, values)
+
+    def render_child_forms(self, w, form, values):
+        # render
+        for childform in getattr(form, 'forms', []):
+            self.render_fields(w, childform, values)
+
+    def _render_hidden_fields(self, w, form):
+        fields = form.fields[:]
+        for field in form.fields:
+            if not self.display_field(form, field):
+                fields.remove(field)
+            elif not field.is_visible():
+                w(field.render(form, self))
+                fields.remove(field)
+        return fields
+
+    def _render_fields(self, fields, w, form):
+        w(u'<table class="%s">' % self.table_class)
+        for field in fields:
+            w(u'<tr>')
+            if self.display_label:
+                w(u'<th class="labelCol">%s</th>' % self.render_label(form, field))
+            error = form.form_field_error(field)
+            if error:
+                w(u'<td class="error">')
+                w(error)
+            else:
+                w(u'<td>')
+            w(field.render(form, self))
+            if self.display_help:
+                w(self.render_help(form, field))
+            w(u'</td></tr>')
+        w(u'</table>')
+
+    def render_buttons(self, w, form):
+        w(u'<table class="%s">\n<tr>\n' % self.button_bar_class)
+        for button in form.form_buttons:
+            w(u'<td>%s</td>\n' % button.render(form))
+        w(u'</tr></table>')
+
+
+class BaseFormRenderer(FormRenderer):
+    """use form_renderer_id = 'base' if you want base FormRenderer without
+    adaptation by selection
+    """
+    id = 'base'
+
+
+class HTableFormRenderer(FormRenderer):
+    """display fields horizontally in a table
+
+    +--------------+--------------+---------+
+    | field1 label | field2 label |         |
+    +--------------+--------------+---------+
+    | field1 input | field2 input | buttons
+    +--------------+--------------+---------+
+    """
+    id = 'htable'
+
+    display_help = False
+    def _render_fields(self, fields, w, form):
+        w(u'<table border="0">')
+        w(u'<tr>')
+        for field in fields:
+            if self.display_label:
+                w(u'<th class="labelCol">%s</th>' % self.render_label(form, field))
+            if self.display_help:
+                w(self.render_help(form, field))
+        # empty slot for buttons
+        w(u'<th class="labelCol">&nbsp;</th>')
+        w(u'</tr>')
+        w(u'<tr>')
+        for field in fields:
+            error = form.form_field_error(field)
+            if error:
+                w(u'<td class="error">')
+                w(error)
+            else:
+                w(u'<td>')
+            w(field.render(form, self))
+            w(u'</td>')
+        w(u'<td>')
+        for button in form.form_buttons:
+            w(button.render(form))
+        w(u'</td>')
+        w(u'</tr>')
+        w(u'</table>')
+
+    def render_buttons(self, w, form):
+        pass
+
+
+class EntityCompositeFormRenderer(FormRenderer):
+    """specific renderer for multiple entities edition form (muledit)"""
+    id = 'composite'
+
+    def render_fields(self, w, form, values):
+        if not form.is_subform:
+            w(u'<table class="listing">')
+        super(EntityCompositeFormRenderer, self).render_fields(w, form, values)
+        if not form.is_subform:
+            w(u'</table>')
+
+    def _render_fields(self, fields, w, form):
+        if form.is_subform:
+            entity = form.edited_entity
+            values = form.form_previous_values
+            qeid = eid_param('eid', entity.eid)
+            cbsetstate = "setCheckboxesState2('eid', %s, 'checked')" % html_escape(dumps(entity.eid))
+            w(u'<tr class="%s">' % (entity.row % 2 and u'even' or u'odd'))
+            # XXX turn this into a widget used on the eid field
+            w(u'<td>%s</td>' % checkbox('eid', entity.eid, checked=qeid in values))
+            for field in fields:
+                error = form.form_field_error(field)
+                if error:
+                    w(u'<td class="error">')
+                    w(error)
+                else:
+                    w(u'<td>')
+                if isinstance(field.widget, (fwdgs.Select, fwdgs.CheckBox, fwdgs.Radio)):
+                    field.widget.attrs['onchange'] = cbsetstate
+                elif isinstance(field.widget, fwdgs.Input):
+                    field.widget.attrs['onkeypress'] = cbsetstate
+                w(u'<div>%s</div>' % field.render(form, self))
+                w(u'</td>')
+        else:
+            # main form, display table headers
+            w(u'<tr class="header">')
+            w(u'<th align="left">%s</th>'
+              % tags.input(type='checkbox', title=self.req._('toggle check boxes'),
+                           onclick="setCheckboxesState('eid', this.checked)"))
+            for field in self.forms[0].fields:
+                if self.display_field(form, field) and field.is_visible():
+                    w(u'<th>%s</th>' % self.req._(field.label))
+        w(u'</tr>')
+
+
+class EntityFormRenderer(FormRenderer):
+    """specific renderer for entity edition form (edition)"""
+    __select__ = entity_implements('Any') & yes()
+
+    _options = FormRenderer._options + ('display_relations_form',)
+    display_relations_form = True
+
+    def render(self, form, values):
+        rendered = super(EntityFormRenderer, self).render(form, values)
+        return rendered + u'</div>' # close extra div introducted by open_form
+
+    def open_form(self, form, values):
+        attrs_fs_label = ('<div class="iformTitle"><span>%s</span></div>'
+                          % self.req._('main informations'))
+        attrs_fs_label += '<div class="formBody">'
+        return attrs_fs_label + super(EntityFormRenderer, self).open_form(form, values)
+
+    def render_fields(self, w, form, values):
+        super(EntityFormRenderer, self).render_fields(w, form, values)
+        self.inline_entities_form(w, form)
+        if form.edited_entity.has_eid() and self.display_relations_form:
+            self.relations_form(w, form)
+
+    def _render_fields(self, fields, w, form):
+        if not form.edited_entity.has_eid() or form.edited_entity.has_perm('update'):
+            super(EntityFormRenderer, self)._render_fields(fields, w, form)
+
+    def render_buttons(self, w, form):
+        if len(form.form_buttons) == 3:
+            w("""<table width="100%%">
+  <tbody>
+   <tr><td align="center">
+     %s
+   </td><td style="align: right; width: 50%%;">
+     %s
+     %s
+   </td></tr>
+  </tbody>
+ </table>""" % tuple(button.render(form) for button in form.form_buttons))
+        else:
+            super(EntityFormRenderer, self).render_buttons(w, form)
+
+    def relations_form(self, w, form):
+        srels_by_cat = form.srelations_by_category('generic', 'add')
+        if not srels_by_cat:
+            return u''
+        req = self.req
+        _ = req._
+        label = u'%s :' % _('This %s' % form.edited_entity.e_schema).capitalize()
+        eid = form.edited_entity.eid
+        w(u'<fieldset class="subentity">')
+        w(u'<legend class="iformTitle">%s</legend>' % label)
+        w(u'<table id="relatedEntities">')
+        for rschema, target, related in form.relations_table():
+            # already linked entities
+            if related:
+                w(u'<tr><th class="labelCol">%s</th>' % rschema.display_name(req, target))
+                w(u'<td>')
+                w(u'<ul>')
+                for viewparams in related:
+                    w(u'<li class="invisible">%s<div id="span%s" class="%s">%s</div></li>'
+                      % (viewparams[1], viewparams[0], viewparams[2], viewparams[3]))
+                if not form.force_display and form.maxrelitems < len(related):
+                    link = (u'<span class="invisible">'
+                            '[<a href="javascript: window.location.href+=\'&amp;__force_display=1\'">%s</a>]'
+                            '</span>' % self.req._('view all'))
+                    w(u'<li class="invisible">%s</li>' % link)
+                w(u'</ul>')
+                w(u'</td>')
+                w(u'</tr>')
+        pendings = list(form.restore_pending_inserts())
+        if not pendings:
+            w(u'<tr><th>&nbsp;</th><td>&nbsp;</td></tr>')
+        else:
+            for row in pendings:
+                # soon to be linked to entities
+                w(u'<tr id="tr%s">' % row[1])
+                w(u'<th>%s</th>' % row[3])
+                w(u'<td>')
+                w(u'<a class="handle" title="%s" href="%s">[x]</a>' %
+                  (_('cancel this insert'), row[2]))
+                w(u'<a id="a%s" class="editionPending" href="%s">%s</a>'
+                  % (row[1], row[4], html_escape(row[5])))
+                w(u'</td>')
+                w(u'</tr>')
+        w(u'<tr id="relationSelectorRow_%s" class="separator">' % eid)
+        w(u'<th class="labelCol">')
+        w(u'<span>%s</span>' % _('add relation'))
+        w(u'<select id="relationSelector_%s" tabindex="%s" '
+          'onchange="javascript:showMatchingSelect(this.options[this.selectedIndex].value,%s);">'
+          % (eid, req.next_tabindex(), html_escape(dumps(eid))))
+        w(u'<option value="">%s</option>' % _('select a relation'))
+        for i18nrtype, rschema, target in srels_by_cat:
+            # more entities to link to
+            w(u'<option value="%s_%s">%s</option>' % (rschema, target, i18nrtype))
+        w(u'</select>')
+        w(u'</th>')
+        w(u'<td id="unrelatedDivs_%s"></td>' % eid)
+        w(u'</tr>')
+        w(u'</table>')
+        w(u'</fieldset>')
+
+    def inline_entities_form(self, w, form):
+        """create a form to edit entity's inlined relations"""
+        if not hasattr(form, 'inlined_relations'):
+            return
+        entity = form.edited_entity
+        __ = self.req.__
+        for rschema, targettypes, role in form.inlined_relations():
+            # show inline forms only if there's one possible target type
+            # for rschema
+            if len(targettypes) != 1:
+                self.warning('entity related by the %s relation should have '
+                             'inlined form but there is multiple target types, '
+                             'dunno what to do', rschema)
+                continue
+            targettype = targettypes[0].type
+            if form.should_inline_relation_form(rschema, targettype, role):
+                w(u'<div id="inline%sslot">' % rschema)
+                existant = entity.has_eid() and entity.related(rschema)
+                if existant:
+                    # display inline-edition view for all existing related entities
+                    w(form.view('inline-edition', existant, rtype=rschema, role=role,
+                                ptype=entity.e_schema, peid=entity.eid))
+                if role == 'subject':
+                    card = rschema.rproperty(entity.e_schema, targettype, 'cardinality')[0]
+                else:
+                    card = rschema.rproperty(targettype, entity.e_schema, 'cardinality')[1]
+                # there is no related entity and we need at least one: we need to
+                # display one explicit inline-creation view
+                if form.should_display_inline_creation_form(rschema, existant, card):
+                    w(form.view('inline-creation', None, etype=targettype,
+                                peid=entity.eid, ptype=entity.e_schema,
+                                rtype=rschema, role=role))
+                # we can create more than one related entity, we thus display a link
+                # to add new related entities
+                if form.should_display_add_new_relation_link(rschema, existant, card):
+                    divid = "addNew%s%s%s:%s" % (targettype, rschema, role, entity.eid)
+                    w(u'<div class="inlinedform" id="%s" cubicweb:limit="true">'
+                      % divid)
+                    js = "addInlineCreationForm('%s', '%s', '%s', '%s')" % (
+                        entity.eid, targettype, rschema, role)
+                    if card in '1?':
+                        js = "toggleVisibility('%s'); %s" % (divid, js)
+                    w(u'<a class="addEntity" id="add%s:%slink" href="javascript: %s" >+ %s.</a>'
+                      % (rschema, entity.eid, js, __('add a %s' % targettype)))
+                    w(u'</div>')
+                    w(u'<div class="trame_grise">&nbsp;</div>')
+                w(u'</div>')
+
+
+class EntityInlinedFormRenderer(EntityFormRenderer):
+    """specific renderer for entity inlined edition form
+    (inline-[creation|edition])
+    """
+    id = 'inline'
+
+    def render(self, form, values):
+        form.add_media()
+        data = []
+        w = data.append
+        try:
+            w(u'<div id="div-%(divid)s" onclick="%(divonclick)s">' % values)
+        except KeyError:
+            w(u'<div id="div-%(divid)s">' % values)
+        else:
+            w(u'<div id="notice-%s" class="notice">%s</div>' % (
+                values['divid'], self.req._('click on the box to cancel the deletion')))
+        w(u'<div class="iformBody">')
+        values['removemsg'] = self.req.__('remove this %s' % form.edited_entity.e_schema)
+        w(u'<div class="iformTitle"><span>%(title)s</span> '
+          '#<span class="icounter">1</span> '
+          '[<a href="javascript: %(removejs)s;noop();">%(removemsg)s</a>]</div>'
+          % values)
+        # cleanup values
+        for key in ('title', 'removejs', 'removemsg'):
+            values.pop(key)
+        self.render_fields(w, form, values)
+        w(u'</div></div>')
+        return '\n'.join(data)
+
+    def render_fields(self, w, form, values):
+        form.form_build_context(values)
+        w(u'<fieldset id="fs-%(divid)s">' % values)
+        fields = self._render_hidden_fields(w, form)
+        w(u'</fieldset>')
+        w(u'<fieldset class="subentity">')
+        if fields:
+            self._render_fields(fields, w, form)
+        self.render_child_forms(w, form, values)
+        self.inline_entities_form(w, form)
+        w(u'</fieldset>')
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/views/forms.py	Fri May 29 20:22:39 2009 +0200
@@ -0,0 +1,524 @@
+"""some base form classes for CubicWeb web client
+
+:organization: Logilab
+:copyright: 2001-2009 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
+"""
+__docformat__ = "restructuredtext en"
+
+from warnings import warn
+
+from logilab.common.compat import any
+from logilab.common.decorators import iclassmethod
+
+from cubicweb.selectors import non_final_entity, match_kwargs, one_line_rset
+from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param
+from cubicweb.web import form, formwidgets as fwdgs
+from cubicweb.web.controller import NAV_FORM_PARAMETERS
+from cubicweb.web.formfields import HiddenInitialValueField, StringField
+
+
+class FieldsForm(form.Form):
+    id = 'base'
+
+    is_subform = False
+
+    # attributes overrideable through __init__
+    internal_fields = ('__errorurl',) + NAV_FORM_PARAMETERS
+    needs_js = ('cubicweb.ajax.js', 'cubicweb.edition.js',)
+    needs_css = ('cubicweb.form.css',)
+    domid = 'form'
+    title = None
+    action = None
+    onsubmit = "return freezeFormButtons('%(domid)s');"
+    cssclass = None
+    cssstyle = None
+    cwtarget = None
+    redirect_path = None
+    set_error_url = True
+    copy_nav_params = False
+    form_buttons = None # form buttons (button widgets instances)
+    form_renderer_id = 'default'
+
+    def __init__(self, req, rset=None, row=None, col=None, submitmsg=None,
+                 **kwargs):
+        super(FieldsForm, self).__init__(req, rset, row=row, col=col)
+        self.fields = list(self.__class__._fields_)
+        for key, val in kwargs.items():
+            if key in NAV_FORM_PARAMETERS:
+                self.form_add_hidden(key, val)
+            else:
+                assert hasattr(self.__class__, key) and not key[0] == '_', key
+                setattr(self, key, val)
+        if self.set_error_url:
+            self.form_add_hidden('__errorurl', self.session_key())
+        if self.copy_nav_params:
+            for param in NAV_FORM_PARAMETERS:
+                if not param in kwargs:
+                    value = req.form.get(param)
+                    if value:
+                        self.form_add_hidden(param, value)
+        if submitmsg is not None:
+            self.form_add_hidden('__message', submitmsg)
+        self.context = None
+        if 'domid' in kwargs:# session key changed
+            self.restore_previous_post(self.session_key())
+
+    @iclassmethod
+    def _fieldsattr(cls_or_self):
+        if isinstance(cls_or_self, type):
+            fields = cls_or_self._fields_
+        else:
+            fields = cls_or_self.fields
+        return fields
+
+    @iclassmethod
+    def field_by_name(cls_or_self, name, role='subject'):
+        """return field with the given name and role.
+        Raise FieldNotFound if the field can't be found.
+        """
+        for field in cls_or_self._fieldsattr():
+            if field.name == name and field.role == role:
+                return field
+        raise form.FieldNotFound(name)
+
+    @iclassmethod
+    def fields_by_name(cls_or_self, name, role='subject'):
+        """return a list of fields with the given name and role"""
+        return [field for field in cls_or_self._fieldsattr()
+                if field.name == name and field.role == role]
+
+    @iclassmethod
+    def remove_field(cls_or_self, field):
+        """remove a field from form class or instance"""
+        cls_or_self._fieldsattr().remove(field)
+
+    @iclassmethod
+    def append_field(cls_or_self, field):
+        """append a field to form class or instance"""
+        cls_or_self._fieldsattr().append(field)
+
+    @iclassmethod
+    def insert_field_before(cls_or_self, new_field, name, role='subject'):
+        field = cls_or_self.field_by_name(name, role)
+        fields = cls_or_self._fieldsattr()
+        fields.insert(fields.index(field), new_field)
+
+    @iclassmethod
+    def insert_field_after(cls_or_self, new_field, name, role='subject'):
+        field = cls_or_self.field_by_name(name, role)
+        fields = cls_or_self._fieldsattr()
+        fields.insert(fields.index(field)+1, new_field)
+
+    @property
+    def form_needs_multipart(self):
+        """true if the form needs enctype=multipart/form-data"""
+        return any(field.needs_multipart for field in self.fields)
+
+    def form_add_hidden(self, name, value=None, **kwargs):
+        """add an hidden field to the form"""
+        field = StringField(name=name, widget=fwdgs.HiddenInput, initial=value,
+                            **kwargs)
+        if 'id' in kwargs:
+            # by default, hidden input don't set id attribute. If one is
+            # explicitly specified, ensure it will be set
+            field.widget.setdomid = True
+        self.append_field(field)
+        return field
+
+    def add_media(self):
+        """adds media (CSS & JS) required by this widget"""
+        if self.needs_js:
+            self.req.add_js(self.needs_js)
+        if self.needs_css:
+            self.req.add_css(self.needs_css)
+
+    def form_render(self, **values):
+        """render this form, using the renderer given in args or the default
+        FormRenderer()
+        """
+        renderer = values.pop('renderer', None)
+        if renderer is None:
+            renderer = self.form_default_renderer()
+        return renderer.render(self, values)
+
+    def form_default_renderer(self):
+        return self.vreg.select_object('formrenderers', self.form_renderer_id,
+                                       self.req, self.rset,
+                                       row=self.row, col=self.col)
+
+    def form_build_context(self, rendervalues=None):
+        """build form context values (the .context attribute which is a
+        dictionary with field instance as key associated to a dictionary
+        containing field 'name' (qualified), 'id', 'value' (for display, always
+        a string).
+
+        rendervalues is an optional dictionary containing extra kwargs given to
+        form_render()
+        """
+        self.context = context = {}
+        # ensure rendervalues is a dict
+        if rendervalues is None:
+            rendervalues = {}
+        # use a copy in case fields are modified while context is build (eg
+        # __linkto handling for instance)
+        for field in self.fields[:]:
+            for field in field.actual_fields(self):
+                field.form_init(self)
+                value = self.form_field_display_value(field, rendervalues)
+                context[field] = {'value': value,
+                                  'name': self.form_field_name(field),
+                                  'id': self.form_field_id(field),
+                                  }
+
+    def form_field_display_value(self, field, rendervalues, load_bytes=False):
+        """return field's *string* value to use for display
+
+        looks in
+        1. previously submitted form values if any (eg on validation error)
+        2. req.form
+        3. extra kw args given to render_form
+        4. field's typed value
+
+        values found in 1. and 2. are expected te be already some 'display'
+        value while those found in 3. and 4. are expected to be correctly typed.
+        """
+        value = self._req_display_value(field)
+        if value is None:
+            if field.name in rendervalues:
+                value = rendervalues[field.name]
+            else:
+                value = self.form_field_value(field, load_bytes)
+                if callable(value):
+                    value = value(self)
+            if value != INTERNAL_FIELD_VALUE:
+                value = field.format_value(self.req, value)
+        return value
+
+    def _req_display_value(self, field):
+        qname = self.form_field_name(field)
+        if qname in self.form_previous_values:
+            return self.form_previous_values[qname]
+        if qname in self.req.form:
+            return self.req.form[qname]
+        if field.name in self.req.form:
+            return self.req.form[field.name]
+        return None
+
+    def form_field_value(self, field, load_bytes=False):
+        """return field's *typed* value"""
+        myattr = '%s_%s_default' % (field.role, field.name)
+        if hasattr(self, myattr):
+            return getattr(self, myattr)()
+        value = field.initial
+        if callable(value):
+            value = value(self)
+        return value
+
+    def form_field_error(self, field):
+        """return validation error for widget's field, if any"""
+        if self._field_has_error(field):
+            self.form_displayed_errors.add(field.name)
+            return u'<span class="error">%s</span>' % self.form_valerror.errors[field.name]
+        return u''
+
+    def form_field_format(self, field):
+        """return MIME type used for the given (text or bytes) field"""
+        return self.req.property_value('ui.default-text-format')
+
+    def form_field_encoding(self, field):
+        """return encoding used for the given (text) field"""
+        return self.req.encoding
+
+    def form_field_name(self, field):
+        """return qualified name for the given field"""
+        return field.name
+
+    def form_field_id(self, field):
+        """return dom id for the given field"""
+        return field.id
+
+    def form_field_vocabulary(self, field, limit=None):
+        """return vocabulary for the given field. Should be overriden in
+        specific forms using fields which requires some vocabulary
+        """
+        raise NotImplementedError
+
+    def _field_has_error(self, field):
+        """return true if the field has some error in given validation exception
+        """
+        return self.form_valerror and field.name in self.form_valerror.errors
+
+
+class EntityFieldsForm(FieldsForm):
+    id = 'base'
+    __select__ = (match_kwargs('entity') | (one_line_rset & non_final_entity()))
+
+    internal_fields = FieldsForm.internal_fields + ('__type', 'eid', '__maineid')
+    domid = 'entityForm'
+
+    def __init__(self, *args, **kwargs):
+        self.edited_entity = kwargs.pop('entity', None)
+        msg = kwargs.pop('submitmsg', None)
+        super(EntityFieldsForm, self).__init__(*args, **kwargs)
+        if self.edited_entity is None:
+            self.edited_entity = self.complete_entity(self.row or 0, self.col or 0)
+        self.form_add_hidden('__type', eidparam=True)
+        self.form_add_hidden('eid')
+        if msg:
+            # If we need to directly attach the new object to another one
+            self.form_add_hidden('__message', msg)
+        if not self.is_subform:
+            for linkto in self.req.list_form_param('__linkto'):
+                self.form_add_hidden('__linkto', linkto)
+                msg = '%s %s' % (msg, self.req._('and linked'))
+
+    def _field_has_error(self, field):
+        """return true if the field has some error in given validation exception
+        """
+        return super(EntityFieldsForm, self)._field_has_error(field) \
+               and self.form_valerror.eid == self.edited_entity.eid
+
+    def _relation_vocabulary(self, rtype, targettype, role,
+                            limit=None, done=None):
+        """return unrelated entities for a given relation and target entity type
+        for use in vocabulary
+        """
+        if done is None:
+            done = set()
+        rset = self.edited_entity.unrelated(rtype, targettype, role, limit)
+        res = []
+        for entity in rset.entities():
+            if entity.eid in done:
+                continue
+            done.add(entity.eid)
+            res.append((entity.view('combobox'), entity.eid))
+        return res
+
+    def _req_display_value(self, field):
+        value = super(EntityFieldsForm, self)._req_display_value(field)
+        if value is None:
+            value = self.edited_entity.linked_to(field.name, field.role)
+            if value:
+                searchedvalues = ['%s:%s:%s' % (field.name, eid, field.role)
+                                  for eid in value]
+                # remove associated __linkto hidden fields
+                for field in self.fields_by_name('__linkto'):
+                    if field.initial in searchedvalues:
+                        self.remove_field(field)
+            else:
+                value = None
+        return value
+
+    def _form_field_default_value(self, field, load_bytes):
+        defaultattr = 'default_%s' % field.name
+        if hasattr(self.edited_entity, defaultattr):
+            # XXX bw compat, default_<field name> on the entity
+            warn('found %s on %s, should be set on a specific form'
+                 % (defaultattr, self.edited_entity.id), DeprecationWarning)
+            value = getattr(self.edited_entity, defaultattr)
+            if callable(value):
+                value = value()
+        else:
+            value = super(EntityFieldsForm, self).form_field_value(field,
+                                                                   load_bytes)
+        return value
+
+    def form_default_renderer(self):
+        return self.vreg.select_object('formrenderers', self.form_renderer_id,
+                                       self.req, self.rset,
+                                       row=self.row, col=self.col,
+                                       entity=self.edited_entity)
+
+    def form_build_context(self, values=None):
+        """overriden to add edit[s|o] hidden fields and to ensure schema fields
+        have eidparam set to True
+
+        edit[s|o] hidden fields are used to indicate the value for the
+        associated field before the (potential) modification made when
+        submitting the form.
+        """
+        eschema = self.edited_entity.e_schema
+        for field in self.fields[:]:
+            for field in field.actual_fields(self):
+                fieldname = field.name
+                if fieldname != 'eid' and (
+                    (eschema.has_subject_relation(fieldname) or
+                     eschema.has_object_relation(fieldname))):
+                    field.eidparam = True
+                    self.fields.append(HiddenInitialValueField(field))
+        return super(EntityFieldsForm, self).form_build_context(values)
+
+    def form_field_value(self, field, load_bytes=False):
+        """return field's *typed* value
+
+        overriden to deal with
+        * special eid / __type / edits- / edito- fields
+        * lookup for values on edited entities
+        """
+        attr = field.name
+        entity = self.edited_entity
+        if attr == 'eid':
+            return entity.eid
+        if not field.eidparam:
+            return super(EntityFieldsForm, self).form_field_value(field, load_bytes)
+        if attr.startswith('edits-') or attr.startswith('edito-'):
+            # edit[s|o]- fieds must have the actual value stored on the entity
+            assert hasattr(field, 'visible_field')
+            vfield = field.visible_field
+            assert vfield.eidparam
+            if entity.has_eid():
+                return self.form_field_value(vfield)
+            return INTERNAL_FIELD_VALUE
+        if attr == '__type':
+            return entity.id
+        if self.schema.rschema(attr).is_final():
+            attrtype = entity.e_schema.destination(attr)
+            if attrtype == 'Password':
+                return entity.has_eid() and INTERNAL_FIELD_VALUE or ''
+            if attrtype == 'Bytes':
+                if entity.has_eid():
+                    if load_bytes:
+                        return getattr(entity, attr)
+                    # XXX value should reflect if some file is already attached
+                    return True
+                return False
+            if entity.has_eid() or attr in entity:
+                value = getattr(entity, attr)
+            else:
+                value = self._form_field_default_value(field, load_bytes)
+            return value
+        # non final relation field
+        if entity.has_eid() or entity.relation_cached(attr, field.role):
+            value = [r[0] for r in entity.related(attr, field.role)]
+        else:
+            value = self._form_field_default_value(field, load_bytes)
+        return value
+
+    def form_field_format(self, field):
+        """return MIME type used for the given (text or bytes) field"""
+        entity = self.edited_entity
+        if field.eidparam and entity.e_schema.has_metadata(field.name, 'format') and (
+            entity.has_eid() or '%s_format' % field.name in entity):
+            return self.edited_entity.attr_metadata(field.name, 'format')
+        return self.req.property_value('ui.default-text-format')
+
+    def form_field_encoding(self, field):
+        """return encoding used for the given (text) field"""
+        entity = self.edited_entity
+        if field.eidparam and entity.e_schema.has_metadata(field.name, 'encoding') and (
+            entity.has_eid() or '%s_encoding' % field.name in entity):
+            return self.edited_entity.attr_metadata(field.name, 'encoding')
+        return super(EntityFieldsForm, self).form_field_encoding(field)
+
+    def form_field_name(self, field):
+        """return qualified name for the given field"""
+        if field.eidparam:
+            return eid_param(field.name, self.edited_entity.eid)
+        return field.name
+
+    def form_field_id(self, field):
+        """return dom id for the given field"""
+        if field.eidparam:
+            return eid_param(field.id, self.edited_entity.eid)
+        return field.id
+
+    def form_field_vocabulary(self, field, limit=None):
+        """return vocabulary for the given field"""
+        role, rtype = field.role, field.name
+        method = '%s_%s_vocabulary' % (role, rtype)
+        try:
+            vocabfunc = getattr(self, method)
+        except AttributeError:
+            try:
+                # XXX bw compat, <role>_<rtype>_vocabulary on the entity
+                vocabfunc = getattr(self.edited_entity, method)
+            except AttributeError:
+                vocabfunc = getattr(self, '%s_relation_vocabulary' % role)
+            else:
+                warn('found %s on %s, should be set on a specific form'
+                     % (method, self.edited_entity.id), DeprecationWarning)
+        # NOTE: it is the responsibility of `vocabfunc` to sort the result
+        #       (direclty through RQL or via a python sort). This is also
+        #       important because `vocabfunc` might return a list with
+        #       couples (label, None) which act as separators. In these
+        #       cases, it doesn't make sense to sort results afterwards.
+        return vocabfunc(rtype, limit)
+
+    def subject_relation_vocabulary(self, rtype, limit=None):
+        """defaut vocabulary method for the given relation, looking for
+        relation's object entities (i.e. self is the subject)
+        """
+        entity = self.edited_entity
+        if isinstance(rtype, basestring):
+            rtype = entity.schema.rschema(rtype)
+        done = None
+        assert not rtype.is_final(), rtype
+        if entity.has_eid():
+            done = set(e.eid for e in getattr(entity, str(rtype)))
+        result = []
+        rsetsize = None
+        for objtype in rtype.objects(entity.e_schema):
+            if limit is not None:
+                rsetsize = limit - len(result)
+            result += self._relation_vocabulary(rtype, objtype, 'subject',
+                                                rsetsize, done)
+            if limit is not None and len(result) >= limit:
+                break
+        return result
+
+    def object_relation_vocabulary(self, rtype, limit=None):
+        """defaut vocabulary method for the given relation, looking for
+        relation's subject entities (i.e. self is the object)
+        """
+        entity = self.edited_entity
+        if isinstance(rtype, basestring):
+            rtype = entity.schema.rschema(rtype)
+        done = None
+        if entity.has_eid():
+            done = set(e.eid for e in getattr(entity, 'reverse_%s' % rtype))
+        result = []
+        rsetsize = None
+        for subjtype in rtype.subjects(entity.e_schema):
+            if limit is not None:
+                rsetsize = limit - len(result)
+            result += self._relation_vocabulary(rtype, subjtype, 'object',
+                                                rsetsize, done)
+            if limit is not None and len(result) >= limit:
+                break
+        return result
+
+    def subject_in_state_vocabulary(self, rtype, limit=None):
+        """vocabulary method for the in_state relation, looking for relation's
+        object entities (i.e. self is the subject) according to initial_state,
+        state_of and next_state relation
+        """
+        entity = self.edited_entity
+        if not entity.has_eid() or not entity.in_state:
+            # get the initial state
+            rql = 'Any S where S state_of ET, ET name %(etype)s, ET initial_state S'
+            rset = self.req.execute(rql, {'etype': str(entity.e_schema)})
+            if rset:
+                return [(rset.get_entity(0, 0).view('combobox'), rset[0][0])]
+            return []
+        results = []
+        for tr in entity.in_state[0].transitions(entity):
+            state = tr.destination_state[0]
+            results.append((state.view('combobox'), state.eid))
+        return sorted(results)
+
+
+class CompositeForm(FieldsForm):
+    """form composed for sub-forms"""
+    id = 'composite'
+    form_renderer_id = id
+
+    def __init__(self, *args, **kwargs):
+        super(CompositeForm, self).__init__(*args, **kwargs)
+        self.forms = []
+
+    def form_add_subform(self, subform):
+        """mark given form as a subform and append it"""
+        subform.is_subform = True
+        self.forms.append(subform)
--- a/web/views/ibreadcrumbs.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/ibreadcrumbs.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """navigation components definition for CubicWeb web client
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
--- a/web/views/idownloadable.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/idownloadable.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Specific views for entities implementing IDownloadable
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
--- a/web/views/igeocodable.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/igeocodable.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Specific views for entities implementing IGeocodable
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/iprogress.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/iprogress.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Specific views for entities implementing IProgress
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 __docformat__ = "restructuredtext en"
--- a/web/views/isioc.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/isioc.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Specific views for SIOC interfaces
 
 :organization: Logilab
-:copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2003-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/magicsearch.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/magicsearch.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 __docformat__ = "restructuredtext en"
--- a/web/views/management.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/management.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
@@ -14,13 +15,12 @@
 from cubicweb.view import AnyRsetView, StartupView, EntityView
 from cubicweb.common.uilib import html_traceback, rest_traceback
 from cubicweb.web import formwidgets
-from cubicweb.web.form import FieldsForm, EntityFieldsForm
 from cubicweb.web.formfields import guess_field
-from cubicweb.web.formrenderers import HTableFormRenderer
 
 SUBMIT_MSGID = _('Submit bug report')
 MAIL_SUBMIT_MSGID = _('Submit bug report by mail')
 
+
 class SecurityViewMixIn(object):
     """display security information for a given schema """
 
@@ -105,11 +105,13 @@
     def owned_by_edit_form(self, entity):
         self.w('<h3>%s</h3>' % self.req._('ownership'))
         msg = self.req._('ownerships have been changed')
-        form = EntityFieldsForm(self.req, None, entity=entity, submitmsg=msg,
-                                form_buttons=[formwidgets.SubmitButton()],
-                                domid='ownership%s' % entity.eid,
-                                __redirectvid='security',
-                                __redirectpath=entity.rest_path())
+        form = self.vreg.select_object('forms', 'base', self.req, entity=entity,
+                                       form_renderer_id='base',
+                                  submitmsg=msg,
+                                  form_buttons=[formwidgets.SubmitButton()],
+                                  domid='ownership%s' % entity.eid,
+                                  __redirectvid='security',
+                                  __redirectpath=entity.rest_path())
         field = guess_field(entity.e_schema, self.schema.rschema('owned_by'))
         form.append_field(field)
         self.w(form.form_render(display_progress_div=False))
@@ -162,11 +164,11 @@
         newperm = self.vreg.etype_class('CWPermission')(self.req, None)
         newperm.eid = self.req.varmaker.next()
         w(u'<p>%s</p>' % _('add a new permission'))
-        form = EntityFieldsForm(self.req, None, entity=newperm,
-                                form_buttons=[formwidgets.SubmitButton()],
-                                domid='reqperm%s' % entity.eid,
-                                __redirectvid='security',
-                                __redirectpath=entity.rest_path())
+        form = self.vreg.select_object('forms', 'base', self.req, entity=newperm,
+                                       form_buttons=[formwidgets.SubmitButton()],
+                                       domid='reqperm%s' % entity.eid,
+                                       __redirectvid='security',
+                                       __redirectpath=entity.rest_path())
         form.form_add_hidden('require_permission', entity.eid, role='object',
                              eidparam=True)
         permnames = getattr(entity, '__permissions__', None)
@@ -182,7 +184,9 @@
         form.append_field(field)
         field = guess_field(cwpermschema, self.schema.rschema('require_group'))
         form.append_field(field)
-        self.w(form.form_render(renderer=HTableFormRenderer(display_progress_div=False)))
+        renderer = self.select_object('formrenderers', 'htable', self.req,
+                                      display_progress_div=False)
+        self.w(form.form_render(renderer=renderer))
 
 
 class ErrorView(AnyRsetView):
@@ -238,7 +242,7 @@
         submiturl = self.config['submit-url']
         submitmail = self.config['submit-mail']
         if submiturl or submitmail:
-            form = FieldsForm(self.req, set_error_url=False)
+            form = self.select_object('forms', 'base', self.req, set_error_url=False)
             binfo = text_error_description(ex, excinfo, req, eversion, cversions)
             form.form_add_hidden('description', binfo)
             form.form_add_hidden('__bugreporting', '1')
--- a/web/views/massmailing.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/massmailing.py	Fri May 29 20:22:39 2009 +0200
@@ -1,10 +1,12 @@
 """Mass mailing form views
 
 :organization: Logilab
-:copyright: 2007-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2007-2009 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
 """
 __docformat__ = "restructuredtext en"
+_ = unicode
 
 import operator
 
@@ -13,12 +15,11 @@
 from cubicweb.view import EntityView
 from cubicweb.web import stdmsgs
 from cubicweb.web.action import Action
-from cubicweb.web.form import FieldsForm, FormViewMixIn
-from cubicweb.web.formrenderers import FormRenderer
+from cubicweb.web.form import FormViewMixIn
 from cubicweb.web.formfields import StringField
 from cubicweb.web.formwidgets import CheckBox, TextInput, AjaxWidget, ImgButton
+from cubicweb.web.views import forms, formrenderers
 
-_ = unicode
 
 class SendEmailAction(Action):
     id = 'sendemail'
@@ -36,18 +37,20 @@
                               **params)
 
 
-class MassMailingForm(FieldsForm):
+class MassMailingForm(forms.FieldsForm):
     id = 'massmailing'
 
     sender = StringField(widget=TextInput({'disabled': 'disabled'}), label=_('From:'))
     recipient = StringField(widget=CheckBox(), label=_('Recipients:'))
-    subject = StringField(label=_('Subject:'))
+    subject = StringField(label=_('Subject:'), max_length=256)
     mailbody = StringField(widget=AjaxWidget(wdgtype='TemplateTextField',
                                              inputid='mailbody'))
+
     form_buttons = [ImgButton('sendbutton', "javascript: $('#sendmail').submit()",
                               _('send email'), 'SEND_EMAIL_ICON'),
                     ImgButton('cancelbutton', "javascript: history.back()",
                               stdmsgs.BUTTON_CANCEL, 'CANCEL_EMAIL_ICON')]
+    form_renderer_id = id
 
     def form_field_vocabulary(self, field):
         if field.name == 'recipient':
@@ -78,7 +81,8 @@
             helpmsg, u'\n'.join(substs))
 
 
-class MassMailingFormRenderer(FormRenderer):
+class MassMailingFormRenderer(formrenderers.FormRenderer):
+    id = 'massmailing'
     button_bar_class = u'toolbar'
 
     def _render_fields(self, fields, w, form):
@@ -124,4 +128,4 @@
         from_addr = '%s <%s>' % (req.user.dc_title(), req.user.get_email())
         form = self.vreg.select_object('forms', 'massmailing', self.req, self.rset,
                                        action='sendmail', domid='sendmail')
-        self.w(form.form_render(sender=from_addr, renderer=MassMailingFormRenderer()))
+        self.w(form.form_render(sender=from_addr))
--- a/web/views/navigation.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/navigation.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """navigation components definition for CubicWeb web client
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/old_calendar.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/old_calendar.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """html calendar views
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 from datetime import date, time, timedelta
--- a/web/views/owl.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/owl.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """produces some Ontology Web Language schema and views
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/plots.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/plots.py	Fri May 29 20:22:39 2009 +0200
@@ -3,6 +3,7 @@
 :organization: Logilab
 :copyright: 2007-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
 __docformat__ = "restructuredtext en"
 
@@ -14,7 +15,7 @@
 from logilab.common import flatten
 from logilab.mtconverter import html_escape
 
-from cubicweb.utils import make_uid, UStringIO
+from cubicweb.utils import make_uid, UStringIO, datetime2ticks
 from cubicweb.vregistry import objectify_selector
 from cubicweb.web.views import baseviews
 
@@ -59,9 +60,6 @@
         filtered.append( (x, y) )
     return sorted(filtered)
 
-def datetime2ticks(date):
-    return time.mktime(date.timetuple()) * 1000
-
 class PlotWidget(object):
     # XXX refactor with cubicweb.web.views.htmlwidgets.HtmlWidget
     def _initialize_stream(self, w=None):
@@ -87,7 +85,7 @@
      lines: {show: true},
      grid: {hoverable: true},
      xaxis: {mode: %(mode)s}});
-jQuery('#%(figid)s').bind('plothover', onPlotHover);
+jQuery("#%(figid)s").bind("plothover", onPlotHover);
 '''
 
     def __init__(self, labels, plots, timemode=False):
@@ -138,7 +136,7 @@
         nbcols = len(self.rset.rows[0])
         for col in xrange(1, nbcols):
             data = [row[col] for row in self.rset]
-            plots.append(filterout_nulls(abscissa, plot))
+            plots.append(filterout_nulls(abscissa, data))
         plotwidget = FlotPlotWidget(varnames, plots, timemode=self.timemode)
         plotwidget.render(self.req, width, height, w=self.w)
 
@@ -177,10 +175,22 @@
 
         __select__ = at_least_two_columns() & second_column_is_number()
 
+        def _guess_vid(self, row):
+            etype = self.rset.description[row][0]
+            if self.schema.eschema(etype).is_final():
+                return 'final'
+            return 'textincontext'
+
         def call(self, title=None, width=None, height=None):
-            labels = ['%s: %s' % (row[0].encode(self.req.encoding), row[1])
-                      for row in self.rset]
-            values = [(row[1] or 0) for row in self.rset]
+            labels = []
+            values = []
+            for rowidx, (_, value) in enumerate(self.rset):
+                if value is not None:
+                    vid = self._guess_vid(rowidx)
+                    label = '%s: %s' % (self.view(vid, self.rset, row=rowidx, col=0),
+                                        value)
+                    labels.append(label.encode(self.req.encoding))
+                    values.append(value)
             pie = PieChartWidget(labels, values, pieclass=self.pieclass,
                                  title=title)
             if width is not None:
--- a/web/views/primary.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/primary.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """The default primary view
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/views/pyviews.py	Fri May 29 20:22:39 2009 +0200
@@ -0,0 +1,42 @@
+"""Views to display bare python values
+
+:organization: Logilab
+:copyright: 2009 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
+"""
+__docformat__ = "restructuredtext en"
+
+from cubicweb.view import View
+from cubicweb.selectors import match_kwargs
+
+class PyValTableView(View):
+    id = 'pyvaltable'
+    __select__ = match_kwargs('pyvalue')
+
+    def call(self, pyvalue, headers=None):
+        if headers is None:
+            headers = self.req.form.get('headers')
+        self.w(u'<table class="listing">\n')
+        if headers:
+            self.w(u'<tr>')
+            for header in headers:
+                self.w(u'<th>%s</th>' % header)
+            self.w(u'</tr>\n')
+        for row in pyvalue:
+            self.w(u'<tr>')
+            for cell in row:
+                self.w(u'<td>%s</td>' % cell)
+            self.w(u'</tr>\n')
+        self.w(u'</table>\n')
+
+
+class PyValListView(View):
+    id = 'pyvallist'
+    __select__ = match_kwargs('pyvalue')
+
+    def call(self, pyvalue):
+        self.w(u'<ul>\n')
+        for line in pyvalue:
+            self.w(u'<li>%s</li>\n' % line)
+        self.w(u'</ul>\n')
--- a/web/views/schema.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/schema.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Specific views for schema related entities
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
@@ -16,7 +17,8 @@
 from cubicweb.view import EntityView, StartupView
 from cubicweb.common import tags, uilib
 from cubicweb.web import action
-from cubicweb.web.views import TmpFileViewMixin, primary, baseviews
+from cubicweb.web.views import TmpFileViewMixin, primary, baseviews, tabs
+from cubicweb.web.facet import AttributeFacet
 
 
 class ViewSchemaAction(action.Action):
@@ -31,8 +33,6 @@
         return self.build_url(self.id)
 
 
-# schema entity types views ###################################################
-
 class CWRDEFPrimaryView(primary.PrimaryView):
     __select__ = implements('CWAttribute', 'CWRelation')
     cache_max_age = 60*60*2 # stay in http cache for 2 hours by default
@@ -42,6 +42,7 @@
                % (entity.dc_type().capitalize(),
                   html_escape(entity.dc_long_title())))
 
+# CWEType ######################################################################
 
 class CWETypeOneLineView(baseviews.OneLineView):
     __select__ = implements('CWEType')
@@ -55,32 +56,118 @@
         if final:
             self.w(u'</em>')
 
-
-# in memory schema views (yams class instances) ###############################
 SKIPPED_RELS = ('is', 'is_instance_of', 'identity', 'created_by', 'owned_by',
                 'has_text',)
 
-class CWETypeSchemaView(primary.PrimaryView):
-    id = 'eschema'
+class CWETypePrimaryView(tabs.TabsMixin, primary.PrimaryView):
     __select__ = implements('CWEType')
     title = _('in memory entity schema')
     main_related_section = False
     skip_rels = SKIPPED_RELS
+    tabs = [_('cwetype-schema-text'), _('cwetype-schema-image'), 
+            _('cwetype-schema-permissions'), _('cwetype-workflow')]
+    default_tab = 'cwetype-schema-text'
 
-    def render_entity_attributes(self, entity):
-        super(CWETypeSchemaView, self).render_entity_attributes(entity)
-        eschema = self.vreg.schema.eschema(entity.name)
-        viewer = SchemaViewer(self.req)
-        layout = viewer.visit_entityschema(eschema, skiprels=self.skip_rels)
-        self.w(uilib.ureport_as_html(layout))
-        if not eschema.is_final():
-            msg = self.req._('graphical schema for %s') % entity.name
-            self.w(tags.img(src=entity.absolute_url(vid='eschemagraph'),
-                            alt=msg))
+    def render_entity(self, entity):
+        self.render_entity_title(entity)
+        self.w(u'<div>%s</div>' % entity.description)
+        self.render_tabs(self.tabs, self.default_tab, entity)
+
+
+class CWETypeSTextView(EntityView):
+    id = 'cwetype-schema-text'
+    __select__ = EntityView.__select__ & implements('CWEType')
+
+    def cell_call(self, row, col):
+        entity = self.entity(row, col)
+        self.w(u'<h2>%s</h2>' % _('Attributes'))
+        rset = self.req.execute('Any N,F,D,GROUP_CONCAT(C),I,J,DE,A '
+                                'GROUPBY N,F,D,AA,A,I,J,DE '
+                                'ORDERBY AA WHERE A is CWAttribute, '
+                                'A ordernum AA, A defaultval D, '
+                                'A constrained_by C?, A description DE, '
+                                'A fulltextindexed I, A internationalizable J, '
+                                'A relation_type R, R name N, '
+                                'A to_entity O, O name F, '
+                                'A from_entity S, S eid %(x)s',
+                                {'x': entity.eid})
+        self.wview('editable-table', rset, 'null', displayfilter=True)
+        self.w(u'<h2>%s</h2>' % _('Relations'))
+        rset = self.req.execute('Any N,C,F,M,K,D,A ORDERBY N '
+                                'WITH N,C,F,M,D,K,A BEING ('
+                                '(Any N,C,F,M,K,D,A '
+                                'ORDERBY N WHERE A is CWRelation, '
+                                'A description D, A composite K?, '
+                                'A relation_type R, R name N, '
+                                'A to_entity O, O name F, '
+                                'A cardinality C, O meta M, '
+                                'A from_entity S, S eid %(x)s)'
+                                ' UNION '
+                                '(Any N,C,F,M,K,D,A '
+                                'ORDERBY N WHERE A is CWRelation, '
+                                'A description D, A composite K?, '
+                                'A relation_type R, R name N, '
+                                'A from_entity S, S name F, '
+                                'A cardinality C, S meta M, '
+                                'A to_entity O, O eid %(x)s))'
+                                ,{'x': entity.eid})
+        self.wview('editable-table', rset, 'null', displayfilter=True)
 
 
+class CWETypeSImageView(EntityView):
+    id = 'cwetype-schema-image'
+    __select__ = EntityView.__select__ & implements('CWEType')
+
+    def cell_call(self, row, col):
+        entity = self.entity(row, col)
+        url = entity.absolute_url(vid='schemagraph')
+        self.w(u'<img src="%s" alt="%s"/>' % (
+            html_escape(url),
+            html_escape(self.req._('graphical schema for %s') % entity.name)))
+
+class CWETypeSPermView(EntityView):
+    id = 'cwetype-schema-permissions'
+    __select__ = EntityView.__select__ & implements('CWEType')
+
+    def cell_call(self, row, col):
+        entity = self.entity(row, col)
+        self.w(u'<h2>%s</h2>' % _('Add permissions'))
+        rset = self.req.execute('Any P WHERE X add_permission P, '
+                                'X eid %(x)s', 
+                                {'x': entity.eid})
+        self.wview('outofcontext', rset, 'null')
+        self.w(u'<h2>%s</h2>' % _('Read permissions'))
+        rset = self.req.execute('Any P WHERE X read_permission P, '
+                                'X eid %(x)s', 
+                                {'x': entity.eid})
+        self.wview('outofcontext', rset, 'null')
+        self.w(u'<h2>%s</h2>' % _('Update permissions'))
+        rset = self.req.execute('Any P WHERE X update_permission P, '
+                                'X eid %(x)s', 
+                                {'x': entity.eid})
+        self.wview('outofcontext', rset, 'null')
+        self.w(u'<h2>%s</h2>' % _('Delete permissions'))
+        rset = self.req.execute('Any P WHERE X delete_permission P, '
+                                'X eid %(x)s', 
+                                {'x': entity.eid})
+        self.wview('outofcontext', rset, 'null')
+
+class CWETypeSWorkflowView(EntityView):
+    id = 'cwetype-workflow'
+    __select__ = EntityView.__select__ & implements('CWEType')
+
+    def cell_call(self, row, col):
+        entity = self.entity(row, col)
+        if entity.reverse_state_of:
+            self.w(u'<img src="%s" alt="%s"/>' % (
+                    html_escape(entity.absolute_url(vid='ewfgraph')),
+                    html_escape(self.req._('graphical workflow for %s') % entity.name)))
+        else:
+            self.w(u'<p>%s</p>' % _('There is no workflow defined for this entity.'))
+
+# CWRType ######################################################################
+
 class CWRTypeSchemaView(primary.PrimaryView):
-    id = 'eschema'
     __select__ = implements('CWRType')
     title = _('in memory relation schema')
     main_related_section = False
@@ -93,25 +180,12 @@
         self.w(uilib.ureport_as_html(layout))
         if not rschema.is_final():
             msg = self.req._('graphical schema for %s') % entity.name
-            self.w(tags.img(src=entity.absolute_url(vid='eschemagraph'),
+            self.w(tags.img(src=entity.absolute_url(vid='schemagraph'),
                             alt=msg))
 
 
 # schema images ###############################################################
 
-class ImageView(EntityView):
-    __select__ = implements('CWEType')
-    id = 'image'
-    title = _('image')
-
-    def cell_call(self, row, col):
-        entity = self.entity(row, col)
-        url = entity.absolute_url(vid='eschemagraph')
-        self.w(u'<img src="%s" alt="%s"/>' % (
-            html_escape(url),
-            html_escape(self.req._('graphical schema for %s') % entity.name)))
-
-
 class RestrictedSchemaDotPropsHandler(s2d.SchemaDotPropsHandler):
     def __init__(self, req):
         # FIXME: colors are arbitrary
@@ -187,7 +261,7 @@
                        prophdlr=RestrictedSchemaDotPropsHandler(self.req))
 
 class CWETypeSchemaImageView(TmpFileViewMixin, EntityView):
-    id = 'eschemagraph'
+    id = 'schemagraph'
     __select__ = implements('CWEType')
 
     content_type = 'image/png'
@@ -211,3 +285,15 @@
         visitor = OneHopRSchemaVisitor(self.req, rschema)
         s2d.schema2dot(outputfile=tmpfile, visitor=visitor,
                        prophdlr=RestrictedSchemaDotPropsHandler(self.req))
+
+### facets
+
+class CWMetaFacet(AttributeFacet):
+    id = 'cwmeta-facet'
+    __select__ = AttributeFacet.__select__ & implements('CWEType')
+    rtype = 'meta'
+
+class CWFinalFacet(AttributeFacet):
+    id = 'cwfinal-facet'
+    __select__ = AttributeFacet.__select__ & implements('CWEType')
+    rtype = 'final'
--- a/web/views/searchrestriction.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/searchrestriction.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 a search
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/sessions.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/sessions.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 object :/
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/startup.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/startup.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 apply to a result set.
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
@@ -12,12 +13,12 @@
 from logilab.mtconverter import html_escape
 
 from cubicweb.view import StartupView
-from cubicweb.selectors import match_user_groups
+from cubicweb.selectors import match_user_groups, implements
 from cubicweb.common.uilib import ureport_as_html
 from cubicweb.web import ajax_replace_url, uicfg, httpcache
+from cubicweb.web.views import tabs
 from cubicweb.web.views.management import SecurityViewMixIn
 
-
 class ManageView(StartupView):
     id = 'manage'
     title = _('manage')
@@ -163,42 +164,44 @@
     def display_folders(self):
         return 'Folder' in self.schema and self.req.execute('Any COUNT(X) WHERE X is Folder')[0][0]
 
-
-
-class SchemaView(StartupView):
+class SchemaView(tabs.TabsMixin, StartupView):
     id = 'schema'
     title = _('application schema')
+    tabs = [_('schema-text'), _('schema-image')]
+    default_tab = 'schema-image'
 
     def call(self):
         """display schema information"""
         self.req.add_js('cubicweb.ajax.js')
         self.req.add_css(('cubicweb.schema.css','cubicweb.acl.css'))
-        withmeta = int(self.req.form.get('withmeta', 0))
-        section = self.req.form.get('sec', '')
+        self.w(u'<h1>%s</h1>' % _('Schema of the data model'))
+        self.render_tabs(self.tabs, self.default_tab)
+
+class SchemaTabImageView(StartupView):
+    id = 'schema-image'
+
+    def call(self):
+        self.w(_(u'<div>This schema of the data model <em>excludes</em> the '
+                 u'meta-data, but you can also display a <a href="%s">complete '
+                 u'schema with meta-data</a>.</div>')
+               % html_escape(self.build_url('view', vid='schemagraph', withmeta=1)))
         self.w(u'<img src="%s" alt="%s"/>\n' % (
-            html_escape(self.req.build_url('view', vid='schemagraph', withmeta=withmeta)),
+            html_escape(self.req.build_url('view', vid='schemagraph', withmeta=0)),
             self.req._("graphical representation of the application'schema")))
-        if withmeta:
-            self.w(u'<div><a href="%s">%s</a></div>' % (
-                html_escape(self.build_url('schema', withmeta=0, sec=section)),
-                self.req._('hide meta-data')))
-        else:
-            self.w(u'<div><a href="%s">%s</a></div>' % (
-                html_escape(self.build_url('schema', withmeta=1, sec=section)),
-                self.req._('show meta-data')))
-        self.w(u'<a href="%s">%s</a><br/>' %
-               (html_escape(ajax_replace_url('detailed_schema', '', 'schematext',
-                                             skipmeta=int(not withmeta))),
-                self.req._('detailed schema view')))
-        if self.req.user.matching_groups('managers'):
-            self.w(u'<a href="%s">%s</a>' %
-                   (html_escape(ajax_replace_url('detailed_schema', '', 'schema_security',
-                                                 skipmeta=int(not withmeta))),
-                self.req._('security')))
-        self.w(u'<div id="detailed_schema">')
-        if section:
-            self.wview(section, None)
-        self.w(u'</div>')
+
+class SchemaTabTextView(StartupView):
+    id = 'schema-text'
+
+    def call(self):
+        self.w(u'<p>%s</p>' % _('This is the list of types defined in the data '
+                                'model ofin this application.'))
+        self.w(u'<p>%s</p>' % _('<em>meta</em> is True for types that are defined by the '
+                                'framework itself (e.g. User and Group). '
+                                '<em>final</em> is True for types that can not be the '
+                                'subject of a relation (e.g. Int and String).'))
+        rset = self.req.execute('Any X,M,F ORDERBY N WHERE X is CWEType, X name N, '
+                                'X meta M, X final F')
+        self.wview('editable-table', rset, displayfilter=True)
 
 
 class ManagerSchemaPermissionsView(StartupView, SecurityViewMixIn):
@@ -314,3 +317,4 @@
                                      skipmeta=skipmeta)
         self.w(ureport_as_html(layout))
 
+
--- a/web/views/tableview.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/tableview.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/tabs.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/tabs.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """base classes to handle tabbed views
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 
 __docformat__ = "restructuredtext en"
@@ -13,7 +14,7 @@
 from cubicweb.selectors import partial_has_related_entities
 from cubicweb.view import EntityView
 from cubicweb.common import tags, uilib
-
+from cubicweb.utils import make_uid
 
 class LazyViewMixin(object):
     """provides two convenience methods for the tab machinery
@@ -91,11 +92,11 @@
                 continue
         return selected_tabs
 
-    def render_tabs(self, tabs, default, entity):
+    def render_tabs(self, tabs, default, entity=None):
         # tabbed views do no support concatenation
         # hence we delegate to the default tab if there is more than on entity
         # in the result set
-        if len(self.rset) > 1:
+        if entity and len(self.rset) > 1:
             entity.view(default, w=self.w)
             return
         # XXX (syt) fix below add been introduced at some point to fix something
@@ -117,7 +118,11 @@
         active_tab = self.active_tab(tabs, default)
         # build the html structure
         w = self.w
-        w(u'<div id="entity-tabs-%s">' % entity.eid)
+        if entity:
+            w(u'<div id="entity-tabs-%s">' % entity.eid)
+        else:
+            uid = make_uid('tab')
+            w(u'<div id="entity-tabs-%s">' % uid)
         w(u'<ul>')
         for tab in tabs:
             w(u'<li>')
@@ -131,7 +136,10 @@
         w(u'</div>')
         for tab in tabs:
             w(u'<div id="as-%s">' % tab)
-            self.lazyview(tab, eid=entity.eid)
+            if entity:
+                self.lazyview(tab, eid=entity.eid)
+            else:
+                self.lazyview(tab, static=True)
             w(u'</div>')
         # call the set_tab() JS function *after* each tab is generated
         # because the callback binding needs to be done before
@@ -140,7 +148,7 @@
    set_tab('%(vid)s', '%(cookiename)s');
  """ % {'tabindex'   : tabs.index(active_tab),
         'vid'        : active_tab,
-        'eeid'       : entity.eid,
+        'eeid'       : (entity and entity.eid or uid),
         'cookiename' : self.cookie_name})
 
 
--- a/web/views/timeline.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/timeline.py	Fri May 29 20:22:39 2009 +0200
@@ -3,8 +3,9 @@
 cf. http://code.google.com/p/simile-widgets/
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/timetable.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/timetable.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """html calendar views
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 from logilab.mtconverter import html_escape
--- a/web/views/treeview.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/treeview.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Set of tree-building widgets, based on jQuery treeview plugin
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/urlpublishing.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/urlpublishing.py	Fri May 29 20:22:39 2009 +0200
@@ -18,8 +18,9 @@
 because of redirecting instead of direct traversal
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 
 __docformat__ = "restructuredtext en"
--- a/web/views/urlrewrite.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/urlrewrite.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """Rules based url rewriter component, to get configurable RESTful urls
 
 :organization: Logilab
-:copyright: 2007-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2007-2009 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
 """
 import re
 
--- a/web/views/vcard.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/vcard.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """vcard import / export
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/wdoc.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/wdoc.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """inline help system, using ReST file in products `wdoc` directory
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/views/workflow.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/workflow.py	Fri May 29 20:22:39 2009 +0200
@@ -4,8 +4,9 @@
 * workflow entities views (State, Transition, TrInfo)
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
@@ -21,21 +22,22 @@
 from cubicweb.web.form import FormViewMixIn
 from cubicweb.web.formfields import StringField,  RichTextField
 from cubicweb.web.formwidgets import HiddenInput, SubmitButton, Button
-from cubicweb.web.views import TmpFileViewMixin
-from cubicweb.web.views.boxes import EditBox
+from cubicweb.web.views import TmpFileViewMixin, forms
 
 
 # IWorkflowable views #########################################################
 
-class ChangeStateForm(form.EntityFieldsForm):
+class ChangeStateForm(forms.EntityFieldsForm):
     id = 'changestate'
 
+    form_renderer_id = 'base' # don't want EntityFormRenderer
+    form_buttons = [SubmitButton(stdmsgs.YES),
+                     Button(stdmsgs.NO, cwaction='cancel')]
+
     __method = StringField(name='__method', initial='set_state',
                            widget=HiddenInput)
     state = StringField(eidparam=True, widget=HiddenInput)
     trcomment = RichTextField(label=_('comment:'), eidparam=True)
-    form_buttons = [SubmitButton(stdmsgs.YES),
-                     Button(stdmsgs.NO, cwaction='cancel')]
 
 
 class ChangeStateFormView(FormViewMixIn, view.EntityView):
--- a/web/views/xbel.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/xbel.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """xbel views
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
--- a/web/views/xmlrss.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/views/xmlrss.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """base xml and rss views
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 _ = unicode
--- a/web/webconfig.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/webconfig.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """common web configuration for twisted/modpython applications
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/webctl.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/webctl.py	Fri May 29 20:22:39 2009 +0200
@@ -2,8 +2,9 @@
 web configuration
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/web/widgets.py	Fri May 29 16:11:49 2009 +0200
+++ b/web/widgets.py	Fri May 29 20:22:39 2009 +0200
@@ -4,8 +4,9 @@
 serialization time
 
 :organization: Logilab
-:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/wsgi/__init__.py	Fri May 29 16:11:49 2009 +0200
+++ b/wsgi/__init__.py	Fri May 29 20:22:39 2009 +0200
@@ -7,8 +7,9 @@
 WSGI corresponding PEP: http://www.python.org/dev/peps/pep-0333/
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 __docformat__ = "restructuredtext en"
 
--- a/wsgi/handler.py	Fri May 29 16:11:49 2009 +0200
+++ b/wsgi/handler.py	Fri May 29 20:22:39 2009 +0200
@@ -1,8 +1,9 @@
 """WSGI request handler for cubicweb
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 
 __docformat__ = "restructuredtext en"
--- a/wsgi/request.py	Fri May 29 16:11:49 2009 +0200
+++ b/wsgi/request.py	Fri May 29 20:22:39 2009 +0200
@@ -5,8 +5,9 @@
   http://www.djangoproject.com/
 
 :organization: Logilab
-:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 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
 """
 
 __docformat__ = "restructuredtext en"