Merging heads of old, closed branch tls-sprint
authorArthur Lutz <arthur.lutz@logilab.fr>
Thu, 04 Apr 2019 13:49:34 +0200
branchtls-sprint
changeset 12560 dc6d44e69a70
parent 2022 31412adee482 (current diff)
parent 1809 fb8c39cf0849 (diff)
child 12561 290f44d445a3
Merging heads of old, closed branch
--- a/_exceptions.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/_exceptions.py	Thu Apr 04 13:49:34 2019 +0200
@@ -26,9 +26,9 @@
     """a misconfiguration error"""
 
 class InternalError(CubicWebException):
-    """base class for exceptions which should not occurs"""    
+    """base class for exceptions which should not occurs"""
 
-class SecurityError(CubicWebException): 
+class SecurityError(CubicWebException):
     """base class for cubicweb server security exception"""
 
 class RepositoryError(CubicWebException):
@@ -39,7 +39,7 @@
 
 class CubicWebRuntimeError(CubicWebException):
     """base class for runtime exceptions"""
-    
+
 # repository exceptions #######################################################
 
 class ConnectionError(RepositoryError):
@@ -53,7 +53,7 @@
 class BadConnectionId(ConnectionError):
     """raised when a bad connection id is given or when an attempt to establish
     a connection failed"""
-    
+
 BadSessionId = BadConnectionId # XXX bw compat for pyro connections
 
 class UnknownEid(RepositoryError):
@@ -68,7 +68,7 @@
     """no source support a relation type"""
     msg = 'No source supports %r relation\'s type'
 
-    
+
 # security exceptions #########################################################
 
 class Unauthorized(SecurityError):
@@ -80,7 +80,7 @@
     var = None
     #def __init__(self, *args):
     #    self.args = args
-        
+
     def __str__(self):
         try:
             if self.args and len(self.args) == 2:
@@ -90,7 +90,7 @@
             return self.msg
         except Exception, ex:
             return str(ex)
-    
+
 # source exceptions ###########################################################
 
 class EidNotInSource(SourceException):
@@ -98,8 +98,8 @@
     source has failed
     """
     msg = 'No entity with eid %s in %s'
-    
-    
+
+
 # registry exceptions #########################################################
 
 class RegistryException(CubicWebException):
@@ -110,16 +110,16 @@
 
     this is usually a programming/typo error...
     """
-    
+
 class ObjectNotFound(RegistryException):
     """raised when an unregistered object is requested
 
     this may be a programming/typo or a misconfiguration error
     """
-    
+
 # class ViewNotFound(ObjectNotFound):
 #     """raised when an unregistered view is called"""
-    
+
 class NoSelectableObject(RegistryException):
     """some views with the given vid have been found but no
     one is applyable to the result set
@@ -144,5 +144,5 @@
     """server execution control error (already started, not running...)"""
 
 # pylint: disable-msg=W0611
-from logilab.common.clcommands import BadCommandUsage 
+from logilab.common.clcommands import BadCommandUsage
 
--- a/common/__init__.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/common/__init__.py	Thu Apr 04 13:49:34 2019 +0200
@@ -15,38 +15,38 @@
 class COMMA_JOIN(FunctionDescr):
     supported_backends = ('postgres', 'sqlite',)
     rtype = 'String'
-    
+
     @classmethod
     def st_description(cls, funcnode):
         return ', '.join(term.get_description()
                          for term in iter_funcnode_variables(funcnode))
-    
+
 register_function(COMMA_JOIN)  # XXX do not expose?
 
 
 class CONCAT_STRINGS(COMMA_JOIN):
     aggregat = True
-    
+
 register_function(CONCAT_STRINGS) # XXX bw compat
 
 class GROUP_CONCAT(CONCAT_STRINGS):
     supported_backends = ('mysql', 'postgres', 'sqlite',)
-    
+
 register_function(GROUP_CONCAT)
 
 
 class LIMIT_SIZE(FunctionDescr):
     supported_backends = ('postgres', 'sqlite',)
     rtype = 'String'
-    
+
     @classmethod
     def st_description(cls, funcnode):
         return funcnode.children[0].get_description()
-    
+
 register_function(LIMIT_SIZE)
 
 
 class TEXT_LIMIT_SIZE(LIMIT_SIZE):
     supported_backends = ('mysql', 'postgres', 'sqlite',)
-    
+
 register_function(TEXT_LIMIT_SIZE)
--- a/common/i18n.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/common/i18n.py	Thu Apr 04 13:49:34 2019 +0200
@@ -90,4 +90,3 @@
         except Exception:
             continue
     return errors
-                         
--- a/common/mail.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/common/mail.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,7 +1,7 @@
 """Common utilies to format / semd emails.
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
--- a/common/migration.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/common/migration.py	Thu Apr 04 13:49:34 2019 +0200
@@ -2,7 +2,7 @@
 version
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -125,10 +125,10 @@
 
     def repo_connect(self):
         return self.config.repository()
-        
+
     def migrate(self, vcconf, toupgrade, options):
         """upgrade the given set of cubes
-        
+
         `cubes` is an ordered list of 3-uple:
         (cube, fromversion, toversion)
         """
@@ -149,23 +149,23 @@
                                    'versions_map': vmap})
             self.scripts_session(scripts)
         else:
-            print 'no migration script to execute'            
+            print 'no migration script to execute'
 
     def shutdown(self):
         pass
-    
+
     def __getattribute__(self, name):
         try:
             return object.__getattribute__(self, name)
         except AttributeError:
             cmd = 'cmd_%s' % name
             if hasattr(self, cmd):
-                meth = getattr(self, cmd) 
+                meth = getattr(self, cmd)
                 return lambda *args, **kwargs: self.interact(args, kwargs,
                                                              meth=meth)
             raise
         raise AttributeError(name)
-            
+
     def interact(self, args, kwargs, meth):
         """execute the given method according to user's confirmation"""
         msg = 'execute command: %s(%s) ?' % (
@@ -224,7 +224,7 @@
         except ImportError:
             # readline not available
             pass
-        else:        
+        else:
             readline.set_completer(Completer(local_ctx).complete)
             readline.parse_and_bind('tab: complete')
             histfile = os.path.join(os.environ["HOME"], ".eshellhist")
@@ -256,7 +256,7 @@
                 else:
                     context[attr[4:]] = getattr(self, attr)
         return context
-    
+
     def process_script(self, migrscript, funcname=None, *args, **kwargs):
         """execute a migration script
         in interactive mode,  display the migration script path, ask for
@@ -280,7 +280,7 @@
                     self.critical('no %s in script %s', funcname, migrscript)
                     return None
                 return func(*args, **kwargs)
-                    
+
     def scripts_session(self, migrscripts):
         """execute some scripts in a transaction"""
         try:
@@ -311,7 +311,7 @@
     def cmd_option_type_changed(self, optname, oldtype, newvalue):
         """a configuration option's type has changed"""
         self._option_changes.append(('typechanged', optname, oldtype, newvalue))
-        
+
     def cmd_add_cubes(self, cubes):
         """modify the list of used cubes in the in-memory config
         returns newly inserted cubes, including dependencies
@@ -319,7 +319,7 @@
         if isinstance(cubes, basestring):
             cubes = (cubes,)
         origcubes = self.config.cubes()
-        newcubes = [p for p in self.config.expand_cubes(cubes) 
+        newcubes = [p for p in self.config.expand_cubes(cubes)
                        if not p in origcubes]
         if newcubes:
             for cube in cubes:
@@ -340,7 +340,7 @@
         assert cube in removed, \
                "can't remove cube %s, used as a dependancy" % cube
         return removed
-    
+
     def rewrite_configuration(self):
         # import locally, show_diffs unavailable in gae environment
         from cubicweb.toolsutils import show_diffs
--- a/common/test/unittest_mail.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/common/test/unittest_mail.py	Thu Apr 04 13:49:34 2019 +0200
@@ -17,14 +17,14 @@
     Another solution would be to use $LOGNAME, $USER or $USERNAME
     """
     return pwd.getpwuid(os.getuid())[0]
-    
+
 
 class EmailTC(EnvBasedTC):
 
     def test_format_mail(self):
         self.set_option('sender-addr', 'bim@boum.fr')
         self.set_option('sender-name', 'BimBam')
-        
+
         mail = format_mail({'name': 'oim', 'email': 'oim@logilab.fr'},
                            ['test@logilab.fr'], u'un petit cöucou', u'bïjour',
                            config=self.config)
@@ -47,7 +47,7 @@
         self.assertEquals(msg.get('reply-to'), u'oim <oim@logilab.fr>, BimBam <bim@boum.fr>')
         self.assertEquals(msg.get_payload(decode=True), u'un petit cöucou')
 
-        
+
     def test_format_mail_euro(self):
         mail = format_mail({'name': u'oîm', 'email': u'oim@logilab.fr'},
                            ['test@logilab.fr'], u'un petit cöucou €', u'bïjour €')
@@ -92,7 +92,7 @@
         self.assertEquals(msg.get('reply-to'), u'tutu <tutu@logilab.fr>')
         # set sender name and address as expected
         self.set_option('sender-name', 'cubicweb-test')
-        self.set_option('sender-addr', 'cubicweb-test@logilab.fr') 
+        self.set_option('sender-addr', 'cubicweb-test@logilab.fr')
         # anonymous notification: no name and no email specified
         msg = format_mail({'name': u'', 'email': u''},
                            ['test@logilab.fr'], u'un petit cöucou €', u'bïjour €',
@@ -119,4 +119,4 @@
 
 if __name__ == '__main__':
     unittest_main()
-    
+
--- a/common/test/unittest_migration.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/common/test/unittest_migration.py	Thu Apr 04 13:49:34 2019 +0200
@@ -24,7 +24,7 @@
 
     def cube_migration_scripts_dir(cls, cube):
         return TMIGRDIR
-    
+
 class MigrationToolsTC(TestCase):
     def setUp(self):
         self.config = MigrTestConfig('data')
@@ -32,7 +32,7 @@
         self.config.load_schema = lambda expand_cubes=False: Schema('test')
         self.config.__class__.cubicweb_vobject_path = frozenset()
         self.config.__class__.cube_vobject_path = frozenset()
-        
+
     def test_migration_files_base(self):
         self.assertListEquals(migration_files(self.config, [('cubicweb', (2,3,0), (2,4,0)),
                                                             ('TEMPLATE', (0,0,2), (0,0,3))]),
@@ -48,7 +48,7 @@
                               [SMIGRDIR+'bootstrapmigration_repository.py',
                                SMIGRDIR+'2.6.0_Any.sql',
                                TMIGRDIR+'0.0.4_Any.py'])
-        
+
 ##     def test_migration_files_overlap(self):
 ##         self.assertListEquals(migration_files(self.config, (2,4,0), (2,10,2),
 ##                                               (0,0,2), (0,1,2)),
@@ -62,7 +62,7 @@
 ##                                TMIGRDIR+'0.1.0_repository.py',
 ##                                TMIGRDIR+'0.1.2_Any.py',
 ##                                SMIGRDIR+'2.10.1_2.10.2_Any.sql'])
-        
+
     def test_migration_files_for_mode(self):
         from cubicweb.server.migractions import ServerMigrationHelper
         self.assertIsInstance(self.config.migration_handler(), ServerMigrationHelper)
--- a/common/test/unittest_mixins.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/common/test/unittest_mixins.py	Thu Apr 04 13:49:34 2019 +0200
@@ -8,7 +8,7 @@
                      {'x': s.eid})
         es = self.user().wf_state('activated')
         self.assertEquals(es.state_of[0].name, 'CWUser')
-        
+
     def test_wf_transition(self):
         t = self.add_entity('Transition', name=u'deactivate')
         self.execute('SET X transition_of ET WHERE ET name "Bookmark", X eid %(x)s',
@@ -20,6 +20,6 @@
         user = self.user()
         user.change_state(user.wf_state('deactivated').eid)
         self.assertEquals(user.state, 'deactivated')
-    
+
 if __name__ == '__main__':
     unittest_main()
--- a/cwconfig.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/cwconfig.py	Thu Apr 04 13:49:34 2019 +0200
@@ -8,7 +8,7 @@
 .. envvar:: CW_CUBES_PATH
 
    Augments the default search path for cubes
-   
+
 """
 __docformat__ = "restructuredtext en"
 
--- a/debian/changelog	Wed Jun 03 09:09:33 2009 +0200
+++ b/debian/changelog	Thu Apr 04 13:49:34 2019 +0200
@@ -1,3 +1,9 @@
+cubicweb (3.2.0-1) unstable; urgency=low
+
+  * new upstream release
+
+ -- Sylvain Thénault <sylvain.thenault@logilab.fr>  Thu, 14 May 2009 12:31:06 +0200
+
 cubicweb (3.1.4-1) unstable; urgency=low
 
   * new upstream release
--- a/debian/control	Wed Jun 03 09:09:33 2009 +0200
+++ b/debian/control	Thu Apr 04 13:49:34 2019 +0200
@@ -75,7 +75,7 @@
 Package: cubicweb-common
 Architecture: all
 XB-Python-Version: ${python:Versions}
-Depends: ${python:Depends}, graphviz, gettext, python-logilab-mtconverter (>= 0.6.0), python-logilab-common (>= 0.39.0), python-yams (>= 0.22.0), python-rql (>= 0.22.0)
+Depends: ${python:Depends}, graphviz, gettext, python-logilab-mtconverter (>= 0.6.0), python-logilab-common (>= 0.40.0), python-yams (>= 0.22.0), python-rql (>= 0.22.0)
 Recommends: python-simpletal (>= 4.0), python-lxml
 Conflicts: cubicweb-core
 Replaces: cubicweb-core
--- a/devtools/__init__.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/devtools/__init__.py	Thu Apr 04 13:49:34 2019 +0200
@@ -59,10 +59,10 @@
           'group': 'main', 'inputlevel': 1,
           }),
         ))
-                            
+
     if not os.environ.get('APYCOT_ROOT'):
         REGISTRY_DIR = normpath(join(CW_SOFTWARE_ROOT, '../cubes'))
-    
+
     def __init__(self, appid, log_threshold=logging.CRITICAL+10):
         ServerConfiguration.__init__(self, appid)
         self.global_set_option('log-file', None)
@@ -71,7 +71,7 @@
         self.load_cwctl_plugins()
 
     anonymous_user = TwistedConfiguration.anonymous_user.im_func
-        
+
     @property
     def apphome(self):
         if exists(self.appid):
@@ -79,7 +79,7 @@
         # application cube test
         return abspath('..')
     appdatahome = apphome
-    
+
     def main_config_file(self):
         """return application's control configuration file"""
         return join(self.apphome, '%s.conf' % self.name)
@@ -116,7 +116,7 @@
         if not sources:
             sources = DEFAULT_SOURCES
         return sources
-    
+
     def load_defaults(self):
         super(TestServerConfiguration, self).load_defaults()
         # note: don't call global set option here, OptionManager may not yet be initialized
@@ -146,25 +146,25 @@
 
     def available_languages(self, *args):
         return ('en', 'fr', 'de')
-    
+
     def ext_resources_file(self):
         """return application's external resources file"""
         return join(self.apphome, 'data', 'external_resources')
-    
+
     def pyro_enabled(self):
         # but export PYRO_MULTITHREAD=0 or you get problems with sqlite and threads
         return True
 
 
 class ApptestConfiguration(BaseApptestConfiguration):
-    
+
     def __init__(self, appid, log_threshold=logging.CRITICAL, sourcefile=None):
         BaseApptestConfiguration.__init__(self, appid, log_threshold=log_threshold)
         self.init_repository = sourcefile is None
         self.sourcefile = sourcefile
         import re
         self.global_set_option('embed-allowed', re.compile('.*'))
-        
+
 
 class RealDatabaseConfiguration(ApptestConfiguration):
     init_repository = False
@@ -180,7 +180,7 @@
                               'password': u'gingkow',
                               },
                    }
-    
+
     def __init__(self, appid, log_threshold=logging.CRITICAL, sourcefile=None):
         ApptestConfiguration.__init__(self, appid)
         self.init_repository = False
@@ -191,7 +191,7 @@
         By default, we run tests with the sqlite DB backend.
         One may use its own configuration by just creating a
         'sources' file in the test directory from wich tests are
-        launched. 
+        launched.
         """
         self._sources = self.sourcesdef
         return self._sources
@@ -220,11 +220,11 @@
     """
     return type('MyRealDBConfig', (RealDatabaseConfiguration,),
                 {'sourcesdef': read_config(filename)})
-    
+
 
 class LivetestConfiguration(BaseApptestConfiguration):
     init_repository = False
-    
+
     def __init__(self, cube=None, sourcefile=None, pyro_name=None,
                  log_threshold=logging.CRITICAL):
         TestServerConfiguration.__init__(self, cube, log_threshold=log_threshold)
@@ -254,7 +254,7 @@
             return False
 
 CubicWebConfiguration.cls_adjust_sys_path()
-                                                    
+
 def install_sqlite_path(querier):
     """This patch hotfixes the following sqlite bug :
        - http://www.sqlite.org/cvstrac/tktview?tn=1327,33
@@ -331,7 +331,7 @@
             os.remove('%s-cube' % dbfile)
         except OSError:
             pass
-    
+
 def init_test_database_sqlite(config, source, vreg=None):
     """initialize a fresh sqlite databse used for testing purpose"""
     import shutil
--- a/devtools/_apptest.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/devtools/_apptest.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,7 +1,7 @@
 """Hidden internals for the devtools.apptest module
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -20,7 +20,7 @@
 
 from cubicweb.devtools import ApptestConfiguration, init_test_database
 from cubicweb.devtools.fake import FakeRequest
-    
+
 SYSTEM_ENTITIES = ('CWGroup', 'CWUser',
                    'CWAttribute', 'CWRelation',
                    'CWConstraint', 'CWConstraintType', 'CWProperty',
@@ -35,7 +35,7 @@
     'is', 'is_instance_of', 'owned_by', 'created_by', 'specializes',
     # workflow related
     'state_of', 'transition_of', 'initial_state', 'allowed_transition',
-    'destination_state', 'in_state', 'wf_info_for', 'from_state', 'to_state', 
+    'destination_state', 'in_state', 'wf_info_for', 'from_state', 'to_state',
     'condition',
     # permission
     'in_group', 'require_group', 'require_permission',
@@ -46,7 +46,7 @@
     'relation_type', 'from_entity', 'to_entity',
     'constrained_by', 'cstrtype', 'widget',
     # deducted from other relations
-    'primary_email', 
+    'primary_email',
                     )
 
 def unprotected_entities(app_schema, strict=False):
@@ -58,7 +58,7 @@
         protected_entities = yams.schema.BASE_TYPES.union(set(SYSTEM_ENTITIES))
     entities = set(app_schema.entities())
     return entities - protected_entities
-    
+
 
 def ignore_relations(*relations):
     global SYSTEM_RELATIONS
@@ -68,7 +68,7 @@
     """TestEnvironment defines a context (e.g. a config + a given connection) in
     which the tests are executed
     """
-    
+
     def __init__(self, appid, reporter=None, verbose=False,
                  configcls=ApptestConfiguration, requestcls=FakeRequest):
         config = configcls(appid)
@@ -114,7 +114,7 @@
         self.cnx.vreg = self.vreg
         self.cnx.login = source['db-user']
         self.cnx.password = source['db-password']
-        
+
 
     def create_user(self, login, groups=('users',), req=None):
         req = req or self.create_request()
@@ -140,7 +140,7 @@
         if login == self.vreg.config.anonymous_user()[0]:
             self.cnx.anonymous_connection = True
         return self.cnx
-    
+
     def restore_connection(self):
         if not self.cnx is self._orig_cnx:
             try:
@@ -157,7 +157,7 @@
         """
         req = req or self.create_request(rql=rql)
         return self.cnx.cursor(req).execute(unicode(rql), args, eidkey)
-    
+
     def create_request(self, rql=None, **kwargs):
         """executes <rql>, builds a resultset, and returns a
         couple (rset, req) where req is a FakeRequest
@@ -167,14 +167,14 @@
         req = self.requestcls(self.vreg, form=kwargs)
         req.set_connection(self.cnx)
         return req
-        
+
     def get_rset_and_req(self, rql, optional_args=None, args=None, eidkey=None):
         """executes <rql>, builds a resultset, and returns a
         couple (rset, req) where req is a FakeRequest
         """
         return (self.execute(rql, args, eidkey),
                 self.create_request(rql=rql, **optional_args or {}))
-    
+
     def check_view(self, rql, vid, optional_args, template='main'):
         """checks if vreg.view() raises an exception in this environment
 
@@ -183,7 +183,7 @@
         """
         return self.call_view(vid, rql,
                               template=template, optional_args=optional_args)
-    
+
     def call_view(self, vid, rql, template='main', optional_args=None):
         """shortcut for self.vreg.view()"""
         assert template
@@ -227,7 +227,7 @@
             yield action
 
 class ExistingTestEnvironment(TestEnvironment):
-    
+
     def __init__(self, appid, sourcefile, verbose=False):
         config = ApptestConfiguration(appid, sourcefile=sourcefile)
         if verbose:
@@ -237,12 +237,12 @@
         self.cnx = init_test_database(driver=source['db-driver'],
                                       vreg=self.vreg)[1]
         if verbose:
-            print "init done" 
+            print "init done"
         self.app = CubicWebPublisher(config, vreg=self.vreg)
         self.verbose = verbose
         # this is done when the publisher is opening a connection
         self.cnx.vreg = self.vreg
-        
+
     def setup(self, config=None):
         """config is passed by TestSuite but is ignored in this environment"""
         cursor = self.cnx.cursor()
@@ -254,4 +254,3 @@
         cursor.execute('DELETE Any X WHERE X eid > %(x)s', {'x' : self.last_eid}, eid_key='x')
         print "cleaning done"
         self.cnx.commit()
-
--- a/devtools/cwtwill.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/devtools/cwtwill.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,4 +1,9 @@
-"""cubicweb extensions for twill"""
+"""cubicweb extensions for twill
+
+:organization: Logilab
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
 
 import re
 from urllib import quote
@@ -24,9 +29,9 @@
                 # if url is specified linkurl must match
                 if url and linkurl != url:
                     continue
-                return        
+                return
     raise AssertionError('link %s (%s) not found' % (text, url))
-        
+
 
 def view(rql, vid=''):
     """
@@ -56,7 +61,7 @@
     twc.go('view?rql=%s&vid=edition' % quote(rql))
 
 
-        
+
 
 def setvalue(formname, fieldname, value):
     """
@@ -104,5 +109,5 @@
     browser._browser.form = form
     browser.submit(submit_button)
 
-    
+
 # missing actions: delete, copy, changeview
--- a/devtools/fake.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/devtools/fake.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,7 +1,7 @@
 """Fake objects to ease testing of cubicweb without a fully working environment
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
--- a/devtools/fill.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/devtools/fill.py	Thu Apr 04 13:49:34 2019 +0200
@@ -33,7 +33,7 @@
         if isinstance(cst, StaticVocabularyConstraint):
             return cst.vocabulary()
     return None
-    
+
 
 def get_max_length(eschema, attrname):
     """returns the maximum length allowed for 'attrname'"""
@@ -75,7 +75,7 @@
             value = self.__generate_value(attrname, index, **kwargs)
         _GENERATED_VALUES.setdefault((self.e_schema.type, attrname), set()).add(value)
         return value
-        
+
     def __generate_value(self, attrname, index, **kwargs):
         """generates a consistent value for 'attrname'"""
         attrtype = str(self.e_schema.destination(attrname)).lower()
@@ -100,7 +100,7 @@
         if choices is None:
             return None
         return unicode(choice(choices)) # FIXME
-        
+
     def generate_string(self, attrname, index, format=None):
         """generates a consistent value for 'attrname' if it's a string"""
         # First try to get choices
@@ -133,7 +133,7 @@
     def generate_password(self, attrname, index):
         """generates a consistent value for 'attrname' if it's a password"""
         return u'toto'
-        
+
     def generate_integer(self, attrname, index):
         """generates a consistent value for 'attrname' if it's an integer"""
         choosed = self.generate_choice(attrname, index)
@@ -145,17 +145,17 @@
         else:
             maxvalue = maxvalue or index
         return randint(minvalue or 0, maxvalue)
-    
+
     generate_int = generate_integer
-    
+
     def generate_float(self, attrname, index):
         """generates a consistent value for 'attrname' if it's a float"""
         return float(randint(-index, index))
-    
+
     def generate_decimal(self, attrname, index):
         """generates a consistent value for 'attrname' if it's a float"""
         return Decimal(str(self.generate_float(attrname, index)))
-    
+
     def generate_date(self, attrname, index):
         """generates a random date (format is 'yyyy-mm-dd')"""
         return date(randint(2000, 2004), randint(1, 12), randint(1, 28))
@@ -163,11 +163,11 @@
     def generate_time(self, attrname, index):
         """generates a random time (format is ' HH:MM')"""
         return timedelta(0, 11, index%60) #'11:%02d' % (index % 60)
-    
+
     def generate_datetime(self, attrname, index):
         """generates a random date (format is 'yyyy-mm-dd HH:MM')"""
         return datetime(randint(2000, 2004), randint(1, 12), randint(1, 28), 11, index%60)
-        
+
 
     def generate_bytes(self, attrname, index, format=None):
         # modpython way
@@ -175,7 +175,7 @@
         fakefile.filename = "file_%s" % attrname
         fakefile.value = fakefile.getvalue()
         return fakefile
-    
+
     def generate_boolean(self, attrname, index):
         """generates a consistent value for 'attrname' if it's a boolean"""
         return index % 2 == 0
@@ -185,7 +185,7 @@
         # need this method else stupid values will be set which make mtconverter
         # raise exception
         return u'application/octet-stream'
-    
+
     def generate_Any_content_format(self, index, **kwargs):
         # content_format attribute of EmailPart has no vocabulary constraint, we
         # need this method else stupid values will be set which make mtconverter
@@ -250,7 +250,7 @@
                             args))
             assert not 'eid' in args, args
         else:
-            queries.append(('INSERT %s X' % etype, {}))        
+            queries.append(('INSERT %s X' % etype, {}))
     return queries
 
 
@@ -365,7 +365,7 @@
                     continue
                 subjcard, objcard = rschema.rproperty(subj, obj, 'cardinality')
                 # process mandatory relations first
-                if subjcard in '1+' or objcard in '1+': 
+                if subjcard in '1+' or objcard in '1+':
                     queries += self.make_relation_queries(sedict, oedict,
                                                           rschema, subj, obj)
                 else:
@@ -374,7 +374,7 @@
                 queries += self.make_relation_queries(sedict, oedict, rschema,
                                                       subj, obj)
         return queries
-        
+
     def qargs(self, subjeids, objeids, subjcard, objcard, subjeid, objeid):
         if subjcard in '?1':
             subjeids.remove(subjeid)
@@ -411,7 +411,7 @@
                         subjeids.remove(subjeid)
         if not subjeids:
             check_card_satisfied(objcard, objeids, subj, rschema, obj)
-            return 
+            return
         if not objeids:
             check_card_satisfied(subjcard, subjeids, subj, rschema, obj)
             return
@@ -452,7 +452,7 @@
                     used.add( (subjeid, objeid) )
                     yield q, self.qargs(subjeids, objeids, subjcard, objcard,
                                         subjeid, objeid)
-                    
+
 def check_card_satisfied(card, remaining, subj, rschema, obj):
     if card in '1+' and remaining:
         raise Exception("can't satisfy cardinality %s for relation %s %s %s"
@@ -466,8 +466,8 @@
     while objeid == avoid: # avoid infinite recursion like in X comment X
         objeid = choice(values)
     return objeid
-                    
-                
+
+
 
 # UTILITIES FUNCS ##############################################################
 def make_tel(num_tel):
--- a/devtools/livetest.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/devtools/livetest.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,4 +1,9 @@
-"""provide utilies for web (live) unit testing"""
+"""provide utilies for web (live) unit testing
+
+:organization: Logilab
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
 
 import socket
 import logging
@@ -41,9 +46,9 @@
                 return static.File(str(datadir), segments[1:])
         # Otherwise we use this single resource
         return self, ()
-    
-    
-    
+
+
+
 def make_site(cube, options=None):
     from cubicweb.etwist import twconfig # trigger configuration registration
     sourcefile = options.sourcefile
@@ -75,7 +80,7 @@
 def saveconf(templhome, port, user, passwd):
     import pickle
     conffile = file(join(templhome, 'test', 'livetest.conf'), 'w')
-    
+
     pickle.dump((port, user, passwd, get_starturl(port, user, passwd)),
                 conffile)
     conffile.close()
@@ -99,8 +104,8 @@
     from twill import browser as twb
     twc.OUT = new_output
     twb.OUT = new_output
-    
-    
+
+
 class LiveTestCase(TestCase):
 
     sourcefile = None
@@ -118,7 +123,7 @@
 
     def tearDown(self):
         self.teardown_db(self.cnx)
-    
+
 
     def setup_db(self, cnx):
         """override setup_db() to setup your environment"""
@@ -141,5 +146,3 @@
 
 if __name__ == '__main__':
     runserver()
-
-
--- a/devtools/repotest.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/devtools/repotest.py	Thu Apr 04 13:49:34 2019 +0200
@@ -103,7 +103,7 @@
 
 class RQLGeneratorTC(TestCase):
     schema = None # set this in concret test
-    
+
     def setUp(self):
         self.rqlhelper = RQLHelper(self.schema, special_relations={'eid': 'uid',
                                                                    'has_text': 'fti'})
@@ -114,7 +114,7 @@
     def tearDown(self):
         ExecutionPlan._check_permissions = _orig_check_permissions
         rqlannotation._select_principal = _orig_select_principal
-        
+
     def _prepare(self, rql):
         #print '******************** prepare', rql
         union = self.rqlhelper.parse(rql)
@@ -133,7 +133,7 @@
 
 class BaseQuerierTC(TestCase):
     repo = None # set this in concret test
-    
+
     def setUp(self):
         self.o = self.repo.querier
         self.session = self.repo._sessions.values()[0]
@@ -148,7 +148,7 @@
         return self.session.unsafe_execute('Any MAX(X)')[0][0]
     def cleanup(self):
         self.session.unsafe_execute('DELETE Any X WHERE X eid > %s' % self.maxeid)
-        
+
     def tearDown(self):
         undo_monkey_patch()
         self.session.rollback()
@@ -159,7 +159,7 @@
 
     def set_debug(self, debug):
         set_debug(debug)
-        
+
     def _rqlhelper(self):
         rqlhelper = self.o._rqlhelper
         # reset uid_func so it don't try to get type from eids
@@ -175,8 +175,8 @@
         for select in rqlst.children:
             select.solutions.sort()
         return self.o.plan_factory(rqlst, kwargs, self.session)
-        
-    def _prepare(self, rql, kwargs=None):    
+
+    def _prepare(self, rql, kwargs=None):
         plan = self._prepare_plan(rql, kwargs)
         plan.preprocess(plan.rqlst)
         rqlst = plan.rqlst.children[0]
@@ -195,10 +195,10 @@
 
     def execute(self, rql, args=None, eid_key=None, build_descr=True):
         return self.o.execute(self.session, rql, args, eid_key, build_descr)
-    
+
     def commit(self):
         self.session.commit()
-        self.session.set_pool()        
+        self.session.set_pool()
 
 
 class BasePlannerTC(BaseQuerierTC):
@@ -270,7 +270,7 @@
         def merge_input_maps(self, *args):
             pass
         def _choose_term(self, sourceterms):
-            pass    
+            pass
 _orig_merge_input_maps = PartPlanInformation.merge_input_maps
 _orig_choose_term = PartPlanInformation._choose_term
 
@@ -309,4 +309,3 @@
     ExecutionPlan.init_temp_table = _orig_init_temp_table
     PartPlanInformation.merge_input_maps = _orig_merge_input_maps
     PartPlanInformation._choose_term = _orig_choose_term
-
--- a/devtools/stresstester.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/devtools/stresstester.py	Thu Apr 04 13:49:34 2019 +0200
@@ -5,13 +5,13 @@
 OPTIONS:
   -h / --help
      Display this help message and exit.
-     
+
   -u / --user <user>
      Connect as <user> instead of being prompted to give it.
   -p / --password <password>
      Automatically give <password> for authentication instead of being prompted
      to give it.
-     
+
   -n / --nb-times <num>
      Repeat queries <num> times.
   -t / --nb-threads <num>
@@ -21,7 +21,7 @@
   -o / --report-output <filename>
      Write profiler report into <filename> rather than on stdout
 
-Copyright (c) 2003-2006 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+Copyright (c) 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 
@@ -49,7 +49,7 @@
         self._times = times
         self._queries = queries
         self._reporter = reporter
-        
+
     def run(self):
         cursor = self._cursor
         times = self._times
@@ -80,7 +80,7 @@
     threads and can write a report that summarizes all profile informations
     """
     profiler_lock = threading.Lock()
-    
+
     def __init__(self, queries):
         self._queries = tuple(queries)
         self._profile_results = [(0., 0)] * len(self._queries)
@@ -111,8 +111,8 @@
         table_layout = Table(3, rheaders = True, children = table_elems)
         TextWriter().format(table_layout, output)
         # output.write('\n'.join(tmp_output))
-        
-        
+
+
 def run(args):
     """run the command line tool"""
     try:
@@ -150,7 +150,7 @@
         user = raw_input('login: ')
     if password is None:
         password = getpass('password: ')
-    from cubicweb.cwconfig import application_configuration 
+    from cubicweb.cwconfig import application_configuration
     config = application_configuration(args[0])
     # get local access to the repository
     print "Creating repo", prof_file
@@ -176,7 +176,7 @@
     else:
         QueryExecutor(repo_cursor, repeat, queries, reporter = reporter).run()
     reporter.dump_report(report_output)
-    
-    
+
+
 if __name__ == '__main__':
     run(sys.argv[1:])
--- a/devtools/test/unittest_dbfill.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/devtools/test/unittest_dbfill.py	Thu Apr 04 13:49:34 2019 +0200
@@ -31,7 +31,7 @@
             return getattr(self, '_available_%s_%s' % (etype, attrname))(etype, attrname)
         except AttributeError:
             return None
-    
+
     def _available_Person_firstname(self, etype, attrname):
         return [f.strip() for f in file(osp.join(DATADIR, 'firstnames.txt'))]
 
@@ -51,11 +51,11 @@
         year = date.year
         month = date.month
         day = date.day
-        self.failUnless(day in range(1, 29), '%s not in [0;28]' % day) 
+        self.failUnless(day in range(1, 29), '%s not in [0;28]' % day)
         self.failUnless(month in range(1, 13), '%s not in [1;12]' % month)
         self.failUnless(year in range(2000, 2005),
                         '%s not in [2000;2004]' % year)
-        
+
 
     def test_string(self):
         """test string generation"""
@@ -89,7 +89,7 @@
         for index in range(5):
             date_value = self.person_valgen._generate_value('birthday', index)
             self._check_date(date_value)
-        
+
     def test_phone(self):
         """tests make_tel utility"""
         self.assertEquals(make_tel(22030405), '22 03 04 05')
@@ -102,14 +102,14 @@
                           u'yo')
         self.assertEquals(self.person_valgen._generate_value('description', 12),
                           u'yo')
-                          
-        
+
+
 
 class ConstraintInsertionTC(TestCase):
 
     def test_writeme(self):
         self.skip('Test automatic insertion / Schema Constraints')
-    
+
 
 if __name__ == '__main__':
     unittest_main()
--- a/devtools/test/unittest_fill.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/devtools/test/unittest_fill.py	Thu Apr 04 13:49:34 2019 +0200
@@ -20,7 +20,7 @@
         for attrname in attrvalues - set(self.attrvalues):
             delattr(_ValueGenerator, attrname)
 
-        
+
     def test_autoextend(self):
         self.failIf('generate_server' in dir(ValueGenerator))
         class MyValueGenerator(ValueGenerator):
--- a/devtools/test/unittest_testlib.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/devtools/test/unittest_testlib.py	Thu Apr 04 13:49:34 2019 +0200
@@ -22,14 +22,14 @@
             def test_error_view(self):
                 self.add_entity('Bug', title=u"bt")
                 self.view('raising', self.execute('Bug B'), template=None)
-            
+
             def test_correct_view(self):
                 self.view('primary', self.execute('CWUser U'), template=None)
-            
+
         tests = [MyWebTest('test_error_view'), MyWebTest('test_correct_view')]
         result = self.runner.run(TestSuite(tests))
         self.assertEquals(result.testsRun, 2)
-        self.assertEquals(len(result.errors), 0)        
+        self.assertEquals(len(result.errors), 0)
         self.assertEquals(len(result.failures), 1)
 
 
@@ -97,13 +97,13 @@
     def test_source1(self):
         """make sure source is stored correctly"""
         self.assertEquals(self.page_info.source, HTML_PAGE2)
-        
+
     def test_source2(self):
         """make sure source is stored correctly - raise exception"""
         parser = htmlparser.DTDValidator()
         self.assertRaises(AssertionError, parser.parse_string, HTML_PAGE_ERROR)
 
-        
+
     def test_has_title_no_level(self):
         """tests h? tags information"""
         self.assertEquals(self.page_info.has_title('Test'), True)
@@ -128,7 +128,7 @@
         self.assertEquals(self.page_info.has_title_regexp('h[23] title', 2), True)
         self.assertEquals(self.page_info.has_title_regexp('h[23] title', 3), True)
         self.assertEquals(self.page_info.has_title_regexp('h[23] title', 4), False)
-    
+
     def test_appears(self):
         """tests PageInfo.appears()"""
         self.assertEquals(self.page_info.appears('CW'), True)
@@ -151,4 +151,3 @@
 
 if __name__ == '__main__':
     unittest_main()
-
--- a/doc/book/fr/conf.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/doc/book/fr/conf.py	Thu Apr 04 13:49:34 2019 +0200
@@ -36,7 +36,7 @@
 
 # General substitutions.
 project = 'Cubicweb'
-copyright = '2008, Logilab'
+copyright = '2008-2009, Logilab'
 
 # The default replacements for |version| and |release|, also used in various
 # other places throughout the built documents.
--- a/doc/tools/generate_modules.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/doc/tools/generate_modules.py	Thu Apr 04 13:49:34 2019 +0200
@@ -12,7 +12,7 @@
 CubicWeb API
 ============
 """
-    EXCLUDE_DIRS = ('test', 'tests', 'examples', 'data', 'doc', '.hg', 'migration')  
+    EXCLUDE_DIRS = ('test', 'tests', 'examples', 'data', 'doc', '.hg', 'migration')
 
     def __init__(self, output_fn, mod_names):
         self.mod_names =  mod_names
@@ -21,7 +21,7 @@
 
     def done(self):
         self.fn.close()
-        
+
     def gen_module(self, mod_name):
         mod_entry = """
 :mod:`%s`
--- a/entities/schemaobjs.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/entities/schemaobjs.py	Thu Apr 04 13:49:34 2019 +0200
@@ -20,7 +20,7 @@
 
     def dc_title(self):
         return self.req._(self.name)
-    
+
     def dc_long_title(self):
         stereotypes = []
         _ = self.req._
@@ -40,10 +40,10 @@
 class CWRType(AnyEntity):
     id = 'CWRType'
     fetch_attrs, fetch_order = fetch_config(['name'])
-    
+
     def dc_title(self):
         return self.req._(self.name)
-    
+
     def dc_long_title(self):
         stereotypes = []
         _ = self.req._
@@ -61,7 +61,7 @@
 
     def inlined_changed(self, inlined):
         """check inlining is necessary and possible:
-        
+
         * return False if nothing has changed
         * raise ValidationError if inlining is'nt possible
         * eventually return True
@@ -88,13 +88,13 @@
 class CWRelation(AnyEntity):
     id = 'CWRelation'
     fetch_attrs = fetch_config(['cardinality'])[0]
-    
+
     def dc_title(self):
         return u'%s %s %s' % (
             self.from_entity[0].name,
-            self.relation_type[0].name, 
+            self.relation_type[0].name,
             self.to_entity[0].name)
-    
+
     def dc_long_title(self):
         card = self.cardinality
         scard, ocard = u'', u''
@@ -118,7 +118,7 @@
 
 class CWAttribute(CWRelation):
     id = 'CWAttribute'
-    
+
     def dc_long_title(self):
         card = self.cardinality
         scard = u''
@@ -126,7 +126,7 @@
             scard = '+'
         return u'%s %s%s %s' % (
             self.from_entity[0].name,
-            scard, self.relation_type[0].name, 
+            scard, self.relation_type[0].name,
             self.to_entity[0].name)
 
 
@@ -136,7 +136,7 @@
 
     def dc_title(self):
         return '%s(%s)' % (self.cstrtype[0].name, self.value or u'')
-        
+
     def after_deletion_path(self):
         """return (path, parameters) which should be used as redirect
         information when this entity is being deleted
@@ -149,7 +149,7 @@
     def type(self):
         return self.cstrtype[0].name
 
-        
+
 class RQLExpression(AnyEntity):
     id = 'RQLExpression'
     fetch_attrs, fetch_order = fetch_config(['exprtype', 'mainvars', 'expression'])
@@ -164,17 +164,17 @@
             values = getattr(self, 'reverse_%s' % rel)
             if values:
                 return values[0]
-            
+
     @cached
     def _rqlexpr(self):
         if self.exprtype == 'ERQLExpression':
             return ERQLExpression(self.expression, self.mainvars, self.eid)
         #if self.exprtype == 'RRQLExpression':
         return RRQLExpression(self.expression, self.mainvars, self.eid)
-    
+
     def check_expression(self, *args, **kwargs):
         return self._rqlexpr().check(*args, **kwargs)
-    
+
     def after_deletion_path(self):
         """return (path, parameters) which should be used as redirect
         information when this entity is being deleted
@@ -192,7 +192,7 @@
         if self.label:
             return '%s (%s)' % (self.req._(self.name), self.label)
         return self.req._(self.name)
-    
+
     def after_deletion_path(self):
         """return (path, parameters) which should be used as redirect
         information when this entity is being deleted
--- a/entity.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/entity.py	Thu Apr 04 13:49:34 2019 +0200
@@ -123,7 +123,7 @@
             for name, widgets in _get_defs('widgets', name, bases, classdict):
                 warn('%s: widgets is deprecated' % name, DeprecationWarning)
                 for rtype, wdgname in widgets.iteritems():
-                    if wdgname in ('URLWidget', 'EmbededURLWidget'):
+                    if wdgname in ('URLWidget', 'EmbededURLWidget', 'RawDynamicComboBoxWidget'):
                         warn('%s widget is deprecated' % wdgname, DeprecationWarning)
                         continue
                     if wdgname == 'StringWidget':
--- a/etwist/request.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/etwist/request.py	Thu Apr 04 13:49:34 2019 +0200
@@ -39,11 +39,11 @@
     def base_url(self):
         """return the root url of the application"""
         return self._base_url
-    
+
     def http_method(self):
         """returns 'POST', 'GET', 'HEAD', etc."""
         return self._twreq.method
-    
+
     def relative_path(self, includeparams=True):
         """return the normalized path of the request (ie at least relative
         to the application's root, but some other normalization may be needed
--- a/etwist/twconfig.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/etwist/twconfig.py	Thu Apr 04 13:49:34 2019 +0200
@@ -2,13 +2,13 @@
 
 * the "twisted" configuration to get a web application running in a standalone
   twisted web server which talk to a repository server using Pyro
-  
+
 * the "all-in-one" configuration to get a web application running in a twisted
   web server integrating a repository server in the same process (only available
   if the repository part of the software is installed
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -63,12 +63,12 @@
         ('pyro-server',
          {'type' : 'yn',
           # pyro is only a recommends by default, so don't activate it here
-          'default': False, 
+          'default': False,
           'help': 'run a pyro server',
           'group': 'main', 'inputlevel': 1,
           }),
         ) + WebConfiguration.options)
-    
+
     def server_file(self):
         return join(self.apphome, '%s-%s.py' % (self.appid, self.name))
 
@@ -91,6 +91,6 @@
         def pyro_enabled(self):
             """tell if pyro is activated for the in memory repository"""
             return self['pyro-server']
-        
+
 except ImportError:
     pass
--- a/etwist/twctl.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/etwist/twctl.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,4 +1,8 @@
 """cubicweb-clt handlers for twisted
+
+:organization: Logilab
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 
 import sys
@@ -52,8 +56,8 @@
 class TWStopHandler(CommandHandler):
     cmdname = 'stop'
     cfgname = 'twisted'
-    
-    
+
+
 try:
     from cubicweb.server import serverctl
 
@@ -67,7 +71,7 @@
             """bootstrap this configuration"""
             serverctl.RepositoryCreateHandler.bootstrap(self, cubes, inputlevel)
             TWCreateHandler.bootstrap(self, cubes, inputlevel)
-            
+
     class AllInOneStartHandler(TWStartHandler):
         cmdname = 'start'
         cfgname = 'all-in-one'
@@ -80,4 +84,3 @@
 
 except ImportError:
     pass
-    
--- a/ext/html4zope.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/ext/html4zope.py	Thu Apr 04 13:49:34 2019 +0200
@@ -40,19 +40,19 @@
     def __init__(self, url, klass):
         self.base_url = url
         self.translator_class = HTMLTranslator
-        
+
     def __call__(self, document):
         translator = self.translator_class(document)
         translator.base_url = self.base_url
         return translator
-    
+
 class HTMLTranslator(CSS1HTMLTranslator):
     """ReST tree to html translator"""
 
     def astext(self):
         """return the extracted html"""
         return ''.join(self.body)
-    
+
     def visit_title(self, node):
         """Only 6 section levels are supported by HTML."""
         if isinstance(node.parent, nodes.topic):
@@ -124,7 +124,7 @@
 
     def depart_problematic(self, node):
         pass
-    
+
     def visit_system_message(self, node):
         backref_text = ''
         if len(node['backrefs']):
--- a/ext/tal.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/ext/tal.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,7 +1,7 @@
 """provides simpleTAL extensions for CubicWeb
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 
@@ -12,7 +12,7 @@
 from os.path import exists, isdir, join
 from logging import getLogger
 from StringIO import StringIO
-        
+
 from simpletal import simpleTAL, simpleTALES
 
 from logilab.common.decorators import cached
@@ -23,7 +23,7 @@
 class LoggerAdapter(object):
     def __init__(self, tal_logger):
         self.tal_logger = tal_logger
-        
+
     def debug(self, msg):
         LOGGER.debug(msg)
 
@@ -49,7 +49,7 @@
         simpleTALES.Context.addRepeat(self, name, var, initialValue)
 
 # XXX FIXME need to find a clean to define OPCODE values for extensions
-I18N_CONTENT = 18  
+I18N_CONTENT = 18
 I18N_REPLACE = 19
 RQL_EXECUTE  = 20
 # simpleTAL uses the OPCODE values to define priority over commands.
@@ -113,7 +113,7 @@
         """
         # Compile tal:attributes into attribute command
         # Argument: [(attributeName, expression)]
-        
+
         # Break up the list of attribute settings first
         commandArgs = []
         # We only want to match semi-colons that are not escaped
@@ -187,7 +187,7 @@
 def compile_template_file(filepath):
     """compiles a TAL template file
     :type filepath: str
-    :param template: path of the file to compile 
+    :param template: path of the file to compile
     """
     fp = file(filepath)
     file_content = unicode(fp.read()) # template file should be pure ASCII
@@ -253,4 +253,3 @@
                 return compile_template_file(filepath)
         raise Exception('no such template %s' % self.filename)
     _compiled_template = cached(_compiled_template, 0)
-    
--- a/goa/__init__.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/__init__.py	Thu Apr 04 13:49:34 2019 +0200
@@ -17,7 +17,7 @@
     pass
 else:
 
-    import os    
+    import os
     _SS = os.environ.get('SERVER_SOFTWARE')
     if _SS is None:
         MODE = 'test'
@@ -30,7 +30,7 @@
     from cubicweb.goa.gaesource import GAESource
     SOURCE_TYPES['gae'] = GAESource
 
-    
+
     def do_monkey_patch():
 
         # monkey patch yams Bytes validator since it should take a bytes string with gae
@@ -56,16 +56,16 @@
 
         # XXX monkey patch cubicweb.schema.CubicWebSchema to have string eid with
         #     optional cardinality (since eid is set after the validation)
-        
+
         import re
         from yams import buildobjs as ybo
-        
+
         def add_entity_type(self, edef):
             edef.name = edef.name.encode()
             assert re.match(r'[A-Z][A-Za-z0-9]*[a-z]+[0-9]*$', edef.name), repr(edef.name)
             eschema = super(CubicWebSchema, self).add_entity_type(edef)
             if not eschema.is_final():
-                # automatically add the eid relation to non final entity types 
+                # automatically add the eid relation to non final entity types
                 rdef = ybo.RelationDefinition(eschema.type, 'eid', 'Bytes',
                                               cardinality='?1', uid=True)
                 self.add_relation_def(rdef)
@@ -73,7 +73,7 @@
                 self.add_relation_def(rdef)
             self._eid_index[eschema.eid] = eschema
             return eschema
-        
+
         from cubicweb.schema import CubicWebSchema
         CubicWebSchema.add_entity_type = add_entity_type
 
@@ -93,7 +93,7 @@
             cubes = config['included-cubes'] + config['included-yams-cubes']
             return config.expand_cubes(cubes)
         repository.Repository.get_cubes = get_cubes
-        
+
         from rql import RQLHelper
         RQLHelper.simplify = lambda x, r: None
 
--- a/goa/appobjects/components.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/appobjects/components.py	Thu Apr 04 13:49:34 2019 +0200
@@ -23,7 +23,7 @@
     to search for something to link to the edited eid
     """
     id = 'search-associate'
-    
+
     __select__ = one_line_rset() & match_search_state('linksearch') & accept
 
     def cell_call(self, row, col):
@@ -43,7 +43,7 @@
     binary = True
     content_type = 'image/png'
     def call(self):
-        """display global schema information"""        
+        """display global schema information"""
         skipmeta = not int(self.req.form.get('withmeta', 0))
         if skipmeta:
             url = self.build_url('data/schema.png')
--- a/goa/appobjects/dbmgmt.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/appobjects/dbmgmt.py	Thu Apr 04 13:49:34 2019 +0200
@@ -54,8 +54,8 @@
         values.append('__session=%s' % cookie['__session'].value)
         self.w(u"<p>pass this flag to the client: --cookie='%s'</p>"
                % html_escape('; '.join(values)))
-        
-        
+
+
 
 class ContentInit(StartupView):
     """special management view to initialize content of a repository,
@@ -74,7 +74,7 @@
         status['stepid'] = stepid
         Put(status)
         self.msg(msg)
-        
+
     def call(self):
         status = _get_status('creation')
         if status.get('finished'):
@@ -149,7 +149,7 @@
                        '<b>delete all datastore content</b> so process can be '
                        'reinitialized</div>' % html_escape(self.req.base_url()))
         Put(status)
-        
+
     @property
     @cached
     def _migrhandler(self):
@@ -164,12 +164,12 @@
     def continue_link(self):
         self.w(u'<a href="%s">continue</a><br/>' % html_escape(self.req.url()))
 
-        
+
 class ContentClear(StartupView):
     id = 'contentclear'
     __select__ = none_rset() & match_user_groups('managers')
     skip_etypes = ('CWGroup', 'CWUser')
-    
+
     def call(self):
         # XXX should use unsafe_execute with all hooks deactivated
         # XXX step by catching datastore errors?
--- a/goa/appobjects/gauthservice.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/appobjects/gauthservice.py	Thu Apr 04 13:49:34 2019 +0200
@@ -23,7 +23,7 @@
 
     def url(self):
         return users.create_logout_url(self.req.build_url('logout') )
-    
+
 def registration_callback(vreg):
     if hasattr(vreg.config, 'has_resource'):
         vreg.register(GACWUserLink, clear=True)
--- a/goa/appobjects/sessions.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/appobjects/sessions.py	Thu Apr 04 13:49:34 2019 +0200
@@ -41,10 +41,10 @@
     def __init__(self, *args, **kwargs):
         super(GAEAuthenticationManager, self).__init__(*args, **kwargs)
         self._repo = self.config.repository(vreg=self.vreg)
-        
+
     def authenticate(self, req, _login=None, _password=None):
         """authenticate user and return an established connection for this user
-        
+
         :raise ExplicitLogin: if authentication is required (no authentication
         info found or wrong user/password)
         """
@@ -75,7 +75,7 @@
     def __init__(self, *args, **kwargs):
         super(GAEPersistentSessionManager, self).__init__(*args, **kwargs)
         self._repo = self.config.repository(vreg=self.vreg)
-        
+
     def get_session(self, req, sessionid):
         """return existing session for the given session identifier"""
         # search a record for the given session
@@ -126,7 +126,7 @@
         record['anonymous_connection'] = cnx.anonymous_connection
         Put(record)
         return self._get_proxy(req, record, cnx, user)
-    
+
     def close_session(self, proxy):
         """close session on logout or on invalid session detected (expired out,
         corrupted...)
@@ -136,7 +136,7 @@
     def current_sessions(self):
         for record in Query('CubicWebSession').Run():
             yield ConnectionProxy(record)
-            
+
     def _get_proxy(self, req, record, cnx, user):
         proxy = ConnectionProxy(record, cnx, user)
         user.req = req
@@ -145,7 +145,7 @@
 
 
 class ConnectionProxy(object):
-    
+
     def __init__(self, record, cnx=None, user=None):
         self.__record = record
         self.__cnx = cnx
@@ -153,7 +153,7 @@
         self.__data = None
         self.__is_dirty = False
         self.sessionid = record.key().name()[4:] # remove 'key_' prefix
-        
+
     def __repr__(self):
         sstr = '<ConnectionProxy %s' % self.sessionid
         if self.anonymous_connection:
@@ -162,7 +162,7 @@
             sstr += ' for %s' % self.__user.login
         sstr += ', last used %s>' % strftime('%T', localtime(self.last_usage_time))
         return sstr
-        
+
     def __getattribute__(self, name):
         try:
             return super(ConnectionProxy, self).__getattribute__(name)
@@ -174,7 +174,7 @@
         self.__record['last_usage_time'] = value
     def _get_last_usage_time(self):
         return self.__record['last_usage_time']
-    
+
     last_usage_time = property(_get_last_usage_time, _set_last_usage_time)
 
     @property
@@ -182,7 +182,7 @@
         # use get() for bw compat if sessions without anonymous information are
         # found. Set default to True to limit lifetime of those sessions.
         return self.__record.get('anonymous_connection', True)
-        
+
     @property
     @cached
     def data(self):
@@ -194,7 +194,7 @@
                 self.exception('corrupted session data for session %s',
                                self.__cnx)
         return {}
-        
+
     def get_session_data(self, key, default=None, pop=False):
         """return value associated to `key` in session data"""
         if pop:
@@ -206,20 +206,20 @@
                 return default
         else:
             return self.data.get(key, default)
-        
+
     def set_session_data(self, key, value):
         """set value associated to `key` in session data"""
         self.data[key] = value
         self.__is_dirty = True
-        
+
     def del_session_data(self, key):
         """remove value associated to `key` in session data"""
         try:
             del self.data[key]
             self.__is_dirty = True
         except KeyError:
-            pass    
-            
+            pass
+
     def commit(self):
         if self.__is_dirty:
             self.__save()
@@ -233,7 +233,7 @@
         if self.__cnx is not None:
             self.__cnx.close()
         Delete(self.__record)
-        
+
     def __save(self):
         if self.__is_dirty:
             self.__record['data'] = Blob(dumps(self.data))
@@ -243,7 +243,7 @@
     def user(self, req=None, props=None):
         """return the User object associated to this connection"""
         return self.__user
-        
+
 
 import logging
 from cubicweb import set_log_methods
@@ -256,7 +256,7 @@
 class SessionsCleaner(StartupView):
     id = 'cleansessions'
     __select__ = none_rset() & match_user_groups('managers')
-    
+
     def call(self):
         # clean web session
         session_manager = application.SESSION_MANAGER
@@ -270,7 +270,7 @@
         self.w(u'%s remaining sessions<br/>\n' % remaining)
         self.w(u'</div>')
 
-        
+
 def registration_callback(vreg):
     vreg.register(SessionsCleaner)
     vreg.register(GAEAuthenticationManager, clear=True)
--- a/goa/db.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/db.py	Thu Apr 04 13:49:34 2019 +0200
@@ -13,11 +13,11 @@
 * all methods returning `google.appengine.ext.db.Model` instance(s) will return
   `cubicweb.goa.db.Model` instance instead (though you should see almost no
   difference since those instances have the same api)
-  
+
 * class methods returning model instance take a `req` as first argument, unless
   they are called through an instance, representing the current request
   (accessible through `self.req` on almost all objects)
-  
+
 * XXX no instance.<modelname>_set attributes, use instance.reverse_<attr name>
       instead
 * XXX reference property always return a list of objects, not the instance
@@ -47,7 +47,7 @@
 from google.appengine.api.datastore_errors import BadKeyError
 
 # XXX remove this dependancy
-from google.appengine.ext import db 
+from google.appengine.ext import db
 
 
 def rset_from_objs(req, objs, attrs=('eid',), rql=None, args=None):
@@ -76,15 +76,15 @@
                 value = obj[attr]
                 descr = str(eschema.destination(attr))
             line.append(value)
-            linedescr.append(descr)            
+            linedescr.append(descr)
         rows.append(line)
         description.append(linedescr)
         for j, attr in enumerate(attrs):
             if attr == 'eid':
                 entity = vreg.etype_class(eschema.type)(req, rset, i, j)
-                rset._get_entity_cache_ = {(i, j): entity}        
+                rset._get_entity_cache_ = {(i, j): entity}
     rset.rowcount = len(rows)
-    req.decorate_rset(rset)    
+    req.decorate_rset(rset)
     return rset
 
 
@@ -102,7 +102,7 @@
         return wrapped(cls, req, *args, **kwargs)
     return iclassmethod(wrapper)
 
-    
+
 class gaedbmetaentity(metaentity):
     """metaclass for goa.db.Model classes: filter entity / db model part,
     put aside the db model part for later creation of db model class.
@@ -139,15 +139,15 @@
 class Model(entities.AnyEntity):
     id = 'Any'
     __metaclass__ = gaedbmetaentity
-    
+
     row = col = 0
-    
+
     @classmethod
     def __initialize__(cls):
         super(Model, cls).__initialize__()
         cls._attributes = frozenset(rschema for rschema in cls.e_schema.subject_relations()
                                     if rschema.is_final())
-    
+
     def __init__(self, *args, **kwargs):
         # db.Model prototype:
         #   __init__(self, parent=None, key_name=None, **kw)
@@ -168,7 +168,7 @@
                         val = val._dbmodel
                     kwargs[key] = val.key()
             self._gaeinitargs = (args, kwargs)
-            
+
     def __repr__(self):
         return '<ModelEntity %s %s %s at %s>' % (
             self.e_schema, self.eid, self.keys(), id(self))
@@ -179,7 +179,7 @@
             tschema = self.e_schema.destination(attr)
             if tschema == 'String':
                 if len(value) > 500:
-                    value = Text(value)                
+                    value = Text(value)
             elif tschema == 'Password':
                 # if value is a Binary instance, this mean we got it
                 # from a query result and so it is already encrypted
@@ -203,7 +203,7 @@
                 value = self._cubicweb_to_datastore(attr, value)
             gaedict[attr] = value
         return gaedict
-    
+
     def to_gae_model(self):
         dbmodel = self._dbmodel
         dbmodel.update(self._to_gae_dict())
@@ -211,7 +211,7 @@
 
     @property
     @cached
-    def _dbmodel(self): 
+    def _dbmodel(self):
         if self.has_eid():
             assert self._gaeinitargs is None
             try:
@@ -240,7 +240,7 @@
             if '_app' in kwargs:
                 assert _app is None
                 _app = kwargs.pop('_app')
-            
+
             for key, value in kwargs.iteritems():
                 if key in self._attributes:
                     values['s_'+key] = value
@@ -267,10 +267,10 @@
         value will be prefixed by 'key_' to build the actual key name.
         """
         return None
-    
+
     def metainformation(self):
         return {'type': self.id, 'source': {'uri': 'system'}, 'extid': None}
-       
+
     def view(self, vid, __registry='views', **kwargs):
         """shortcut to apply a view on this entity"""
         return self.vreg.render(__registry, vid, self.req, rset=self.rset,
@@ -282,7 +282,7 @@
         if needcheck:
             return 'eid', False
         return mainattr, needcheck
-    
+
     def get_value(self, name):
         try:
             value = self[name]
@@ -306,7 +306,7 @@
             return True
         except BadKeyError:
             return False
-        
+
     def complete(self, skip_bytes=True):
         pass
 
@@ -319,7 +319,7 @@
             objs = Query(str(targettype)).Run()
         return rset_from_objs(self.req, objs, ('eid',),
                               'Any X WHERE X is %s' % targettype)
-    
+
     def key(self):
         return Key(self.eid)
 
@@ -334,7 +334,7 @@
                                        'Any X WHERE X eid %(x)s', {'x': self.eid})
             self.row = self.col = 0
         return dbmodel
-    
+
     @needrequest
     def get(cls, req, keys):
         # if check if this is a dict.key call
@@ -393,7 +393,7 @@
 
     def dynamic_properties(self):
         raise NotImplementedError('use eschema')
-        
+
     def is_saved(self):
         return self.has_eid()
 
@@ -425,7 +425,7 @@
 IntegerProperty = db.IntegerProperty
 FloatProperty = db.FloatProperty
 ListProperty = db.ListProperty
-SelfReferenceProperty = db.SelfReferenceProperty 
+SelfReferenceProperty = db.SelfReferenceProperty
 UserProperty = db.UserProperty
 
 
--- a/goa/dbinit.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/dbinit.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,7 +1,7 @@
 """some utility functions for datastore initialization.
 
 :organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -72,7 +72,7 @@
         dsrelation = 'o_' + rschema.type
         if not dsrelation in gaeentity:
             gaeentity[dsrelation] = None
-    
+
 def fix_entities(schema):
     for etype in ('CWUser', 'CWGroup'):
         eschema = schema.eschema(etype)
@@ -81,7 +81,7 @@
             # XXX o_is on CWEType entity
             gaeentity['s_is'] = Key.from_path('CWEType', 'key_' + etype, parent=None)
             Put(gaeentity)
-    
+
 def init_persistent_schema(ssession, schema):
     execute = ssession.unsafe_execute
     rql = ('INSERT CWEType X: X name %(name)s, X description %(descr)s,'
@@ -105,4 +105,3 @@
         execute('INSERT CWProperty X: X pkey %(pk)s, X value%(v)s',
                 {'pk': u'system.version.%s' % cube,
                  'v': unicode(config.cube_version(cube))})
-    
--- a/goa/dbmyams.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/dbmyams.py	Thu Apr 04 13:49:34 2019 +0200
@@ -5,6 +5,9 @@
  - ReferenceProperty.verbose_name, collection_name, etc. (XXX)
 
 XXX proprify this knowing we'll use goa.db
+:organization: Logilab
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 
 from os.path import join
@@ -68,7 +71,7 @@
     # XXX no equivalent to Django's `auto_now`
     return dbm2y_default_factory(prop, **kwargs)
 
-    
+
 def dbm2y_relation_factory(etype, prop, multiple=False):
     """called if `prop` is a `db.ReferenceProperty`"""
     if multiple:
@@ -83,8 +86,8 @@
     except AttributeError, ex:
         # hack, data_type is still _SELF_REFERENCE_MARKER
         return SubjectRelation(etype, cardinality=cardinality)
-    
-    
+
+
 DBM2Y_FACTORY = {
     basestring: dbm2y_string_factory,
     datastore_types.Text: dbm2y_string_factory,
@@ -107,7 +110,7 @@
         self.created = []
         self.loaded_files = []
         self._instantiate_handlers()
-        
+
     def finalize(self, register_base_types=False):
         return self._build_schema('google-appengine', register_base_types)
 
@@ -148,11 +151,11 @@
     def import_yams_cube_schema(self, templpath):
         for filepath in self.get_schema_files(templpath):
             self.handle_file(filepath)
-        
+
     @property
     def pyreader(self):
         return self._live_handlers['.py']
-        
+
 import os
 from cubicweb import CW_SOFTWARE_ROOT
 
@@ -183,7 +186,7 @@
                      'is_', 'is_instance_of',
                      'read_permission', 'add_permission',
                      'delete_permission', 'update_permission'):
-        loader.import_yams_schema(erschema, 'bootstrap')  
+        loader.import_yams_schema(erschema, 'bootstrap')
     loader.handle_file(join(SCHEMAS_LIB_DIRECTORY, 'base.py'))
     cubes = config['included-yams-cubes']
     for cube in reversed(config.expand_cubes(cubes)):
@@ -211,4 +214,3 @@
         if getattr(ertype, 'inlined', False):
             ertype.inlined = False
     return loader.finalize()
-
--- a/goa/gaesource.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/gaesource.py	Thu Apr 04 13:49:34 2019 +0200
@@ -15,7 +15,7 @@
 
 from google.appengine.api.datastore import Key, Entity, Put, Delete
 from google.appengine.api import datastore_errors, users
-    
+
 def _init_groups(guser, euser):
     # set default groups
     if guser is None:
@@ -82,13 +82,13 @@
             gaeentity[relation] = related or None
     _mark_modified(session, gaeentity)
 
-    
+
 class DatastorePutOp(SingleOperation):
     """delayed put of entities to have less datastore write api calls
 
     * save all modified entities at precommit (should be the first operation
       processed, hence the 0 returned by insert_index())
-      
+
     * in case others precommit operations modify some entities, resave modified
       entities at commit. This suppose that no db changes will occurs during
       commit event but it should be the case.
@@ -103,10 +103,10 @@
             assert not eid in pending
             Put(gaeentity)
         modified.clear()
-        
+
     def commit_event(self):
         self._put_entities()
-        
+
     def precommit_event(self):
         self._put_entities()
 
@@ -117,9 +117,9 @@
     passwd_rql = "Any P WHERE X is CWUser, X login %(login)s, X upassword P"
     auth_rql = "Any X WHERE X is CWUser, X login %(login)s, X upassword %(pwd)s"
     _sols = ({'X': 'CWUser', 'P': 'Password'},)
-    
+
     options = ()
-    
+
     def __init__(self, repo, appschema, source_config, *args, **kwargs):
         AbstractSource.__init__(self, repo, appschema, source_config,
                                 *args, **kwargs)
@@ -128,11 +128,11 @@
             self.authenticate = self.authenticate_gauth
         else:
             self.authenticate = self.authenticate_local
-            
+
     def reset_caches(self):
         """method called during test to reset potential source caches"""
         pass
-    
+
     def init_creating(self):
         pass
 
@@ -144,7 +144,7 @@
 
     def get_connection(self):
         return ConnectionWrapper()
-    
+
     # ISource interface #######################################################
 
     def compile_rql(self, rql):
@@ -152,7 +152,7 @@
         rqlst.restricted_vars = ()
         rqlst.children[0].solutions = self._sols
         return rqlst
-    
+
     def set_schema(self, schema):
         """set the application'schema"""
         self.interpreter = RQLInterpreter(schema)
@@ -161,13 +161,13 @@
             # rql syntax trees used to authenticate users
             self._passwd_rqlst = self.compile_rql(self.passwd_rql)
             self._auth_rqlst = self.compile_rql(self.auth_rql)
-                
+
     def support_entity(self, etype, write=False):
         """return true if the given entity's type is handled by this adapter
         if write is true, return true only if it's a RW support
         """
         return True
-    
+
     def support_relation(self, rtype, write=False):
         """return true if the given relation's type is handled by this adapter
         if write is true, return true only if it's a RW support
@@ -200,7 +200,7 @@
             _init_groups(guser, euser)
             Put(euser)
             return str(euser.key())
-        
+
     def authenticate_local(self, session, login, password):
         """return CWUser eid for the given login/password if this account is
         defined in this source, else raise `AuthenticationError`
@@ -224,8 +224,8 @@
             return rset[0][0]
         except IndexError:
             raise AuthenticationError('bad password')
-    
-    def syntax_tree_search(self, session, union, args=None, cachekey=None, 
+
+    def syntax_tree_search(self, session, union, args=None, cachekey=None,
                            varmap=None):
         """return result from this source for a rql query (actually from a rql
         syntax tree and a solution dictionary mapping each used variable to a
@@ -235,16 +235,16 @@
         results, description = self.interpreter.interpret(union, args,
                                                           session.datastore_get)
         return results # XXX description
-                
+
     def flying_insert(self, table, session, union, args=None, varmap=None):
         raise NotImplementedError
-    
+
     def add_entity(self, session, entity):
         """add a new entity to the source"""
         # do not delay add_entity as other modifications, new created entity
         # needs an eid
         entity.put()
-        
+
     def update_entity(self, session, entity):
         """replace an entity in the source"""
         gaeentity = entity.to_gae_model()
@@ -253,7 +253,7 @@
             for asession in self.repo._sessions.itervalues():
                 if asession.user.eid == entity.eid:
                     asession.user.update(dict(gaeentity))
-                
+
     def delete_entity(self, session, etype, eid):
         """delete an entity from the source"""
         # do not delay delete_entity as other modifications to ensure
@@ -270,7 +270,7 @@
         _radd(session, gaesubj, gaeobj.key(), 's_' + rtype, cards[0])
         _radd(session, gaeobj, gaesubj.key(), 'o_' + rtype, cards[1])
         _clear_related_cache(session, gaesubj, rtype, gaeobj)
-            
+
     def delete_relation(self, session, subject, rtype, object):
         """delete a relation from the source"""
         gaesubj, gaeobj, cards = _rinfo(session, subject, rtype, object)
@@ -280,7 +280,7 @@
         if not object in pending:
             _rdel(session, gaeobj, gaesubj.key(), 'o_' + rtype, cards[1])
         _clear_related_cache(session, gaesubj, rtype, gaeobj)
-        
+
     # system source interface #################################################
 
     def eid_type_source(self, session, eid):
@@ -290,7 +290,7 @@
         except datastore_errors.BadKeyError:
             raise UnknownEid(eid)
         return key.kind(), 'system', None
-    
+
     def create_eid(self, session):
         return None # let the datastore generating key
 
@@ -303,15 +303,14 @@
         record from the entities table to the deleted_entities table
         """
         pass
-        
+
     def fti_unindex_entity(self, session, eid):
         """remove text content for entity with the given eid from the full text
         index
         """
         pass
-        
+
     def fti_index_entity(self, session, entity):
         """add text content of a created/modified entity to the full text index
         """
         pass
-
--- a/goa/goaconfig.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/goaconfig.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,7 +1,7 @@
 """google appengine configuration
 
 :organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -32,7 +32,7 @@
     """repository and web application in the same twisted process"""
     name = 'app'
     repo_method = 'inmemory'
-    options = merge_options(( 
+    options = merge_options((
         ('included-cubes',
          {'type' : 'csv',
           'default': [],
@@ -75,7 +75,7 @@
           'anonymous access using the app.yaml file)',
           'group': 'main', 'inputlevel': 1,
           }),
-        
+
         ) + WebConfiguration.options + ServerConfiguration.options)
     options = [(optname, optdict) for optname, optdict in options
                if not optname in UNSUPPORTED_OPTIONS]
@@ -94,10 +94,10 @@
     # deactivate some hooks during [pre|post]create scripts execution
     # (unique values check, owned_by/created_by relations setup)
     free_wheel = True
-    
+
     if not os.environ.get('APYCOT_ROOT'):
         CUBES_DIR = join(CW_SOFTWARE_ROOT, '../cubes')
-    
+
     def __init__(self, appid, apphome=None):
         if apphome is None:
             apphome = 'data'
@@ -111,7 +111,7 @@
         if key == 'base-url':
             return self._base_url
         return super(GAEConfiguration, self).__getitem__(key)
-    
+
     # overriden from cubicweb base configuration
 
     @property
@@ -136,15 +136,15 @@
 
     def instance_md5_version(self):
         return ''
-    
+
     def _init_base_url(self):
         pass
-    
+
     # overriden from cubicweb server configuration
-    
+
     def sources(self):
         return {'system': {'adapter': 'gae'}}
-    
+
     def load_schema(self, schemaclasses=None, extrahook=None):
         try:
             return self._schema
@@ -155,10 +155,11 @@
     # goa specific
     def repo_session(self, sessionid):
         return self.repository()._sessions[sessionid]
-    
+
     def is_anonymous_user(self, login):
         if self['use-google-auth']:
             from google.appengine.api import users
             return users.get_current_user() is None
         else:
             return login == self.anonymous_user()[0]
+
--- a/goa/goactl.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/goactl.py	Thu Apr 04 13:49:34 2019 +0200
@@ -36,7 +36,7 @@
     (join(CW_SOFTWARE_ROOT, 'embedded', 'mx'), 'mx'),
     ('/usr/share/fckeditor/', 'fckeditor'),
 
-    (join(CW_SOFTWARE_ROOT, 'web', 'data'), join('cubes', 'shared', 'data')), 
+    (join(CW_SOFTWARE_ROOT, 'web', 'data'), join('cubes', 'shared', 'data')),
     (join(CW_SOFTWARE_ROOT, 'web', 'wdoc'), join('cubes', 'shared', 'wdoc')),
     (join(CW_SOFTWARE_ROOT, 'i18n'), join('cubes', 'shared', 'i18n')),
     (join(CW_SOFTWARE_ROOT, 'goa', 'tools'), 'tools'),
@@ -60,7 +60,7 @@
     'utils.py',
     'vregistry.py',
     'view.py',
-    
+
     'common/mail.py',
     'common/migration.py',
     'common/mixins.py',
@@ -93,12 +93,12 @@
 
     'sobjects/__init__.py',
     'sobjects/notification.py',
-    
+
 # XXX would be necessary for goa.testlib but require more stuff to be added
 #     such as server.serverconfig and so on (check devtools.__init__)
 #    'devtools/__init__.py',
 #    'devtools/fake.py',
-    
+
     'web/__init__.py',
     'web/_exceptions.py',
     'web/action.py',
@@ -139,7 +139,7 @@
     'wsgi/__init__.py',
     'wsgi/handler.py',
     'wsgi/request.py',
-    
+
     'goa/__init__.py',
     'goa/db.py',
     'goa/dbinit.py',
@@ -149,9 +149,9 @@
     'goa/gaesource.py',
     'goa/rqlinterpreter.py',
     'goa/appobjects/__init__.py',
-    'goa/appobjects/components.py', 
-    'goa/appobjects/dbmgmt.py', 
-    'goa/appobjects/gauthservice.py', 
+    'goa/appobjects/components.py',
+    'goa/appobjects/dbmgmt.py',
+    'goa/appobjects/gauthservice.py',
     'goa/appobjects/sessions.py',
 
     'schemas/bootstrap.py',
@@ -178,7 +178,7 @@
     """
     name = 'newgapp'
     arguments = '<application directory>'
-    
+
     def run(self, args):
         if len(args) != 1:
             raise BadCommandUsage("exactly one argument is expected")
@@ -196,7 +196,7 @@
                 create_dir(split(subdirectory)[0])
             create_symlink(directory, join(appldir, subdirectory))
         create_init_file(join(appldir, 'logilab'), 'logilab')
-        # copy supported part of cubicweb 
+        # copy supported part of cubicweb
         create_dir(join(appldir, 'cubicweb'))
         for fpath in COPY_CW_FILES:
             target = join(appldir, 'cubicweb', fpath)
--- a/goa/goavreg.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/goavreg.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,7 +1,7 @@
 """goa specific registry
 
 :organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -19,7 +19,7 @@
     return 'cubes.%s.%s' % (cube, module)
 
 class GAERegistry(CubicWebRegistry):
-    
+
     def set_schema(self, schema):
         """disable reload hooks of cubicweb registry set_schema method"""
         self.schema = schema
@@ -37,7 +37,7 @@
         for cube in reversed(self.config.cubes()):
             self.load_cube(cube)
         self.load_application(applroot)
-        
+
     def load_directory(self, directory, cube, skip=()):
         for filename in listdir(directory):
             if filename[-3:] == '.py' and not filename in skip:
@@ -70,6 +70,3 @@
             # when using db.Model defined schema, the defined class is used as
             # entity class as well and so have to be registered
             self._import(_pkg_name(cube, 'schema'))
-
-
-    
--- a/goa/overrides/mttransforms.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/overrides/mttransforms.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,7 +1,7 @@
 """mime type transformation engine for cubicweb, based on mtconverter
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -38,7 +38,7 @@
 
 HAS_PIL_TRANSFORMS = False
 HAS_PYGMENTS_TRANSFORMS = False
-    
+
 class html_to_text(Transform):
     inputs = HTML_MIMETYPES
     output = 'text/plain'
--- a/goa/overrides/rqlannotation.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/overrides/rqlannotation.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,6 +1,13 @@
+"""
+:organization: Logilab
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+__docformat__ = "restructuredtext en"
+
 def set_qdata(getrschema, union, noinvariant):
     pass
-        
+
 class SQLGenAnnotator(object):
     def __init__(self, schema):
         self.schema = schema
@@ -9,5 +16,5 @@
     def annotate(self, rqlst):
         rqlst.has_text_query = False
         rqlst.need_distinct = False
-        
-   
+
+
--- a/goa/overrides/server_utils.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/overrides/server_utils.py	Thu Apr 04 13:49:34 2019 +0200
@@ -6,7 +6,7 @@
         pass
     def join(self):
         pass
-    
+
 class LoopTask(RepoThread):
     def cancel(self):
         pass
--- a/goa/rqlinterpreter.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/rqlinterpreter.py	Thu Apr 04 13:49:34 2019 +0200
@@ -23,7 +23,7 @@
     return Key(key).kind()
 
 def poss_var_types(myvar, ovar, kind, solutions):
-    return frozenset(etypes[myvar] for etypes in solutions 
+    return frozenset(etypes[myvar] for etypes in solutions
                      if etypes[ovar] == kind)
 
 def expand_result(results, result, myvar, values, dsget=None):
@@ -84,7 +84,7 @@
             string.append('%s: %s' % (k, v))
     return '{%s}' % ', '.join(string)
 
-                         
+
 class EidMismatch(Exception):
     def __init__(self, varname, value):
         self.varname = varname
@@ -101,45 +101,45 @@
         self.operator = operator
         self.rtype = rel.r_type
         self.var = rel.children[0]
-        
+
     def __repr__(self):
         return '<%s for %s>' % (self.__class__.__name__, self.rel)
-    
+
     @property
     def rhs(self):
         return self.rel.children[1].children[0]
 
-        
+
 class MultipleRestriction(object):
     def __init__(self, restrictions):
         self.restrictions = restrictions
-        
+
     def resolve(self, solutions, fixed):
         return _resolve(self.restrictions, solutions, fixed)
 
-    
+
 class VariableSelection(Restriction):
     def __init__(self, rel, dsget, prefix='s'):
         Restriction.__init__(self, rel)
         self._dsget = dsget
         self._not = self.rel.neged(strict=True)
         self._prefix = prefix + '_'
-        
+
     def __repr__(self):
         return '<%s%s for %s>' % (self._prefix[0], self.__class__.__name__, self.rel)
-        
+
     @property
     def searched_var(self):
         if self._prefix == 's_':
             return self.var.name
         return self.rhs.name
-        
+
     @property
     def constraint_var(self):
         if self._prefix == 's_':
             return self.rhs.name
         return self.var.name
-        
+
     def _possible_values(self, myvar, ovar, entity, solutions, dsprefix):
         if self.rtype == 'identity':
             return (entity.key(),)
@@ -150,7 +150,7 @@
             value = [value]
         vartypes = poss_var_types(myvar, ovar, entity.kind(), solutions)
         return (v for v in value if v.kind() in vartypes)
-        
+
     def complete_and_filter(self, solutions, results):
         myvar = self.rhs.name
         ovar = self.var.name
@@ -173,8 +173,8 @@
                     expand_result(results, result, myvar, values, self._dsget)
         else:
             assert self.rhs.name in results[0]
-            self.object_complete_and_filter(solutions, results)           
-            
+            self.object_complete_and_filter(solutions, results)
+
     def filter(self, solutions, results):
         myvar = self.rhs.name
         ovar = self.var.name
@@ -187,10 +187,10 @@
                 newsols[key] = frozenset(v for v in values)
             if self._not:
                 if result[myvar].key() in newsols[key]:
-                    results.remove(result)                
+                    results.remove(result)
             elif not result[myvar].key() in newsols[key]:
                 results.remove(result)
-    
+
     def object_complete_and_filter(self, solutions, results):
         if self._not:
             raise NotImplementedError()
@@ -201,7 +201,7 @@
                                            solutions, 'o_')
             expand_result(results, result, myvar, values, self._dsget)
 
-    
+
 class EidRestriction(Restriction):
     def __init__(self, rel, dsget):
         Restriction.__init__(self, rel)
@@ -216,7 +216,7 @@
 
     def _get_value(self, fixed):
         return fixed[self.constraint_var].key()
-    
+
     def fill_query(self, fixed, query, operator=None):
         restr = '%s%s %s' % (self._prefix, self.rtype, operator or self.operator)
         query[restr] = self._get_value(fixed)
@@ -235,7 +235,7 @@
 
     def _get_value(self, fixed):
         return None
-    
+
     def resolve(self, solutions, fixed):
         if self.rtype == 'identity':
             raise NotImplementedError()
@@ -255,7 +255,7 @@
                 raise NotImplementedError('LIKE is only supported for prefix search')
             self.operator = '>'
             self.value = value[:-1]
-            
+
     def complete_and_filter(self, solutions, results):
         # check lhs var first in case this is a restriction
         assert self._not
@@ -263,7 +263,7 @@
         for result in results[:]:
             if result[myvar].get('s_'+rtype) == value:
                 results.remove(result)
-            
+
     def _get_value(self, fixed):
         return self.value
 
@@ -294,7 +294,7 @@
     @property
     def operator(self):
         return 'in'
-            
+
 
 class TypeRestriction(AttributeRestriction):
     def __init__(self, var):
@@ -302,7 +302,7 @@
 
     def __repr__(self):
         return '<%s for %s>' % (self.__class__.__name__, self.var)
-    
+
     def resolve(self, solutions, fixed):
         objs = []
         for etype in frozenset(etypes[self.var.name] for etypes in solutions):
@@ -330,7 +330,7 @@
         self.args = args
         self.term = term
         self._solution = self.term.stmt.solutions[0]
-        
+
     def compute(self, result):
         """return (entity type, value) to which self.term is evaluated according
         to the given result dictionnary and to query arguments (self.args)
@@ -341,7 +341,7 @@
         args = tuple(n.accept(self, result)[1] for n in node.children)
         value = self.functions[node.name](*args)
         return node.get_type(self._solution, self.args), value
-    
+
     def visit_variableref(self, node, result):
         value = result[node.name]
         try:
@@ -350,11 +350,11 @@
         except AttributeError:
             etype = self._solution[node.name]
         return etype, value
-    
+
     def visit_constant(self, node, result):
         return node.get_type(kwargs=self.args), node.eval(self.args)
-    
-        
+
+
 class RQLInterpreter(object):
     """algorithm:
     1. visit the restriction clauses and collect restriction for each subject
@@ -369,7 +369,7 @@
            for each solution in select'solutions:
                1. resolve variables which have attribute restriction
                2. resolve relation restriction
-               3. resolve selection and add to global results 
+               3. resolve selection and add to global results
     """
     def __init__(self, schema):
         self.schema = schema
@@ -379,15 +379,15 @@
                              'UPPER': lambda x: x.upper()}
         for cb in SQL_CONNECT_HOOKS.get('sqlite', []):
             cb(self)
-            
+
     # emulate sqlite connection interface so we can reuse stored procedures
     def create_function(self, name, nbargs, func):
         self._stored_proc[name] = func
-        
+
     def create_aggregate(self, name, nbargs, func):
         self._stored_proc[name] = func
 
-        
+
     def execute(self, operation, parameters=None, eid_key=None, build_descr=True):
         rqlst = self.rqlhelper.parse(operation, annotate=True)
         try:
@@ -397,7 +397,7 @@
         else:
             results, description = self.interpret(rqlst, parameters)
         return ResultSet(results, operation, parameters, description, rqlst=rqlst)
-        
+
     def interpret(self, node, kwargs, dsget=None):
         if dsget is None:
             self._dsget = Get
@@ -417,7 +417,7 @@
             results += pres
             description += pdescr
         return results, description
-    
+
     def visit_select(self, node, extra):
         constraints = {}
         if node.where is not None:
@@ -441,7 +441,7 @@
         for varname, restrictions in constraints.iteritems():
             for restr in restrictions[:]:
                 if isinstance(restr, EidRestriction):
-                    assert not varname in fixed    
+                    assert not varname in fixed
                     try:
                         value = restr.resolve(kwargs)
                         fixed[varname] = value
@@ -455,7 +455,7 @@
                 if isinstance(restr, AttributeRestriction):
                     toresolve.setdefault(varname, []).append(restr)
                 elif isinstance(restr, NotRelationRestriction) or (
-                    isinstance(restr, RelationRestriction) and 
+                    isinstance(restr, RelationRestriction) and
                     not restr.searched_var in fixed and restr.constraint_var in fixed):
                     toresolve.setdefault(varname, []).append(restr)
                 else:
@@ -495,7 +495,7 @@
                     partres.append({varname: value})
             elif not varname in partres[0]:
                 # cartesian product
-                for res in partres:                    
+                for res in partres:
                     res[varname] = values[0]
                 for res in partres[:]:
                     for value in values[1:]:
@@ -503,14 +503,14 @@
                         res[varname] = value
                         partres.append(res)
             else:
-                # union 
+                # union
                 for res in varpartres:
                     for value in values:
                         res = res.copy()
                         res[varname] = value
                         partres.append(res)
         #print 'partres', len(partres)
-        #print partres                        
+        #print partres
         # Note: don't check for empty partres since constant selection may still
         # produce result at this point
         # sort to get RelationRestriction before AttributeSelection
@@ -569,14 +569,14 @@
                     append_result(res, descr, i, j, value, etype)
         #print '--------->', res
         return res, descr
-    
-    def visit_and(self, node, constraints, extra): 
+
+    def visit_and(self, node, constraints, extra):
         for child in node.children:
             child.accept(self, constraints, extra)
     def visit_exists(self, node, constraints, extra):
         extra['has_exists'] = True
         self.visit_and(node, constraints, extra)
-    
+
     def visit_not(self, node, constraints, extra):
         for child in node.children:
             child.accept(self, constraints, extra)
@@ -584,7 +584,7 @@
             extra.pop(node)
         except KeyError:
             raise NotImplementedError()
-        
+
     def visit_relation(self, node, constraints, extra):
         if node.is_types_restriction():
             return
@@ -600,7 +600,7 @@
             self._visit_non_final_neged_relation(rschema, node, constraints)
         else:
             self._visit_non_final_relation(rschema, node, constraints)
-                
+
     def _visit_non_final_relation(self, rschema, node, constraints, not_=False):
         lhs, rhs = node.get_variable_parts()
         for v1, v2, prefix in ((lhs, rhs, 's'), (rhs, lhs, 'o')):
@@ -611,14 +611,14 @@
             if nbrels > 1:
                 constraints.setdefault(v1.name, []).append(
                     RelationRestriction(node, self._dsget, prefix))
-                # just init an empty list for v2 variable to avoid a 
+                # just init an empty list for v2 variable to avoid a
                 # TypeRestriction being added for it
                 constraints.setdefault(v2.name, [])
                 break
         else:
             constraints.setdefault(rhs.name, []).append(
                 VariableSelection(node, self._dsget, 's'))
-                
+
     def _visit_non_final_neged_relation(self, rschema, node, constraints):
         lhs, rhs = node.get_variable_parts()
         for v1, v2, prefix in ((lhs, rhs, 's'), (rhs, lhs, 'o')):
@@ -653,16 +653,16 @@
                     AttributeInRestriction(node, extra['kwargs']))
             else:
                 raise NotImplementedError()
-        
+
     def _not_implemented(self, *args, **kwargs):
         raise NotImplementedError()
-    
+
     visit_or = _not_implemented
     # shouldn't occurs
     visit_set = _not_implemented
     visit_insert = _not_implemented
     visit_delete = _not_implemented
-        
+
 
 from logging import getLogger
 from cubicweb import set_log_methods
--- a/goa/skel/loader.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/skel/loader.py	Thu Apr 04 13:49:34 2019 +0200
@@ -4,7 +4,7 @@
     from cubicweb import goa
     from cubicweb.goa.goaconfig import GAEConfiguration
     from cubicweb.goa.dbinit import create_user, create_groups
-    
+
     # compute application's root directory
     APPLROOT = dirname(abspath(__file__))
     # apply monkey patches first
--- a/goa/skel/main.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/skel/main.py	Thu Apr 04 13:49:34 2019 +0200
@@ -2,7 +2,7 @@
 to change anything here.
 
 :organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
--- a/goa/test/data/views.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/test/data/views.py	Thu Apr 04 13:49:34 2019 +0200
@@ -21,7 +21,7 @@
 
 class MyIndex(StartupView):
     id = 'index'
-    
+
     def call(self):
         ctx = template.Context({'user': self.req.user})
         return INDEX_TEMPLATE.render(ctx)
--- a/goa/test/unittest_db.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/test/unittest_db.py	Thu Apr 04 13:49:34 2019 +0200
@@ -10,11 +10,11 @@
 
 class Blog(db.Model):
     data = db.BlobProperty()
-    
+
 class DBTest(GAEBasedTC):
     config = GAEConfiguration('toto')
     config.global_set_option('use-google-auth', False)
-    
+
     MODEL_CLASSES = (Blog,)
 
     def test_set_none_relation(self):
@@ -25,7 +25,7 @@
     def test_euser_key(self):
         euser = self.add_entity('CWUser', login=u'toto', upassword='toto')
         self.assertEquals(euser.key().name(), 'key_toto')
-        
+
     def test_egroup_key(self):
         egroup = self.add_entity('CWGroup', name=u'toto')
         self.assertEquals(egroup.key().name(), 'key_toto')
@@ -40,7 +40,7 @@
         text = u'e'*501
         entity = self.add_entity('State', name=u'test', description=text)
         self.assertIsInstance(entity.description, unicode)
-        self.failIf(isinstance(entity.description, Text)) 
+        self.failIf(isinstance(entity.description, Text))
         self.assertEquals(entity.description, text)
 
     def test_long_accentued_text(self):
@@ -48,7 +48,7 @@
         text = u'é'*500
         entity = self.add_entity('State', name=u'test', description=text)
         self.assertIsInstance(entity.description, unicode)
-        self.failIf(isinstance(entity.description, Text)) 
+        self.failIf(isinstance(entity.description, Text))
         self.assertEquals(entity.description, text)
 
     def test_blob(self):
@@ -56,10 +56,10 @@
         entity = self.add_entity('Blog', data=data)
         self.assertIsInstance(entity.data, Binary)
         value = entity.data.getvalue()
-        self.failIf(isinstance(value, Blob)) 
+        self.failIf(isinstance(value, Blob))
         self.assertEquals(value, data)
-        
-        
+
+
 if __name__ == '__main__':
     from logilab.common.testlib import unittest_main
     unittest_main()
--- a/goa/test/unittest_editcontroller.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/test/unittest_editcontroller.py	Thu Apr 04 13:49:34 2019 +0200
@@ -12,23 +12,23 @@
 
 
 class EditControllerTC(GAEBasedTC):
-    
+
     config = GAEConfiguration('toto')
     config.global_set_option('use-google-auth', False)
     config.global_set_option('schema-type', 'yams')
     config.global_set_option('included-cubes', ())
     config.global_set_option('included-yams-cubes', ('blog',))
-    
+
     MODEL_CLASSES = ()
     from cubicweb.web.views import editcontroller
     from cubicweb.entities import lib
     LOAD_APP_MODULES = (editcontroller, lib)
-    
+
     def setUp(self):
         GAEBasedTC.setUp(self)
         self.req = self.request()
         self.ctrl = self.get_ctrl(self.req)
-        
+
     def get_ctrl(self, req):
         return self.vreg.select(self.vreg.registry_objects('controllers', 'edit'),
                                 req=req, appli=self)
@@ -69,13 +69,13 @@
         """check behaviour of this controller without any form parameter"""
         self.req.form = {}
         self.assertRaises(ValidationError, self.publish, self.req)
-        
+
     def test_validation_unique(self):
-        """test creation of two linked entities"""        
+        """test creation of two linked entities"""
         user = self.user
         self.req.form = {'eid': 'X', '__type:X': 'CWUser',
-                         'login:X': self.user.login, 'edits-login:X': u'', 
-                         'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'', 
+                         'login:X': self.user.login, 'edits-login:X': u'',
+                         'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'',
                          }
         self.assertRaises(ValidationError, self.publish, self.req)
 
@@ -155,23 +155,23 @@
         self.assertUnorderedIterableEquals([g.eid for g in e.in_group], groupeids)
         #stateeids = [eid for eid, in self.req.execute('State S WHERE S name "activated"')]
         #self.assertEquals([s.eid for s in e.in_state], stateeids)
-        
-        
+
+
     def test_create_multiple_linked(self):
         gueid = self.req.execute('CWGroup G WHERE G name "users"')[0][0]
         self.req.form = {'eid': ['X', 'Y'],
-                         
+
                          '__type:X': 'CWUser',
                          '__maineid' : 'X',
-                         'login:X': u'adim', 'edits-login:X': u'', 
-                         'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'', 
+                         'login:X': u'adim', 'edits-login:X': u'',
+                         'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'',
                          'surname:X': u'Di Mascio', 'edits-surname:X': '',
 
-                         'in_group:X': gueid, 'edits-in_group:X': INTERNAL_FIELD_VALUE, 
-                         
+                         'in_group:X': gueid, 'edits-in_group:X': INTERNAL_FIELD_VALUE,
+
                          '__type:Y': 'EmailAddress',
                          'address:Y': u'dima@logilab.fr', 'edits-address:Y': '',
-                         'use_email:X': 'Y', 'edits-use_email:X': INTERNAL_FIELD_VALUE, 
+                         'use_email:X': 'Y', 'edits-use_email:X': INTERNAL_FIELD_VALUE,
                          }
         path, params = self.expect_redirect_publish()
         # should be redirected on the created person
@@ -180,17 +180,17 @@
         self.assertEquals(e.surname, 'Di Mascio')
         email = e.use_email[0]
         self.assertEquals(email.address, 'dima@logilab.fr')
-        
+
     def test_edit_multiple_linked(self):
         peid = self.create_user('adim').eid
         self.req.form = {'eid': [peid, 'Y'],
                          '__type:%s'%peid: 'CWUser',
                          'surname:%s'%peid: u'Di Masci', 'edits-surname:%s'%peid: '',
-                         
+
                          '__type:Y': 'EmailAddress',
                          'address:Y': u'dima@logilab.fr', 'edits-address:Y': '',
                          'use_email:%s'%peid: 'Y', 'edits-use_email:%s'%peid: INTERNAL_FIELD_VALUE,
-                         
+
                          '__redirectrql': 'Any X WHERE X eid %s'%peid,
                          }
         path, params = self.expect_redirect_publish()
@@ -200,14 +200,14 @@
         self.assertEquals(e.surname, 'Di Masci')
         email = e.use_email[0]
         self.assertEquals(email.address, 'dima@logilab.fr')
-        
+
         emaileid = email.eid
         self.req.form = {'eid': [peid, emaileid],
                          '__type:%s'%peid: 'CWUser',
                          'surname:%s'%peid: u'Di Masci', 'edits-surname:%s'%peid: 'Di Masci',
                          '__type:%s'%emaileid: 'EmailAddress',
                          'address:%s'%emaileid: u'adim@logilab.fr', 'edits-address:%s'%emaileid: 'dima@logilab.fr',
-                         'use_email:%s'%peid: emaileid, 'edits-use_email:%s'%peid: emaileid, 
+                         'use_email:%s'%peid: emaileid, 'edits-use_email:%s'%peid: emaileid,
                          '__redirectrql': 'Any X WHERE X eid %s'%peid,
                          }
         path, params = self.expect_redirect_publish()
@@ -220,21 +220,21 @@
         email = e.use_email[0]
         self.assertEquals(email.address, 'adim@logilab.fr')
 
-        
+
     def test_password_confirm(self):
         """test creation of two linked entities
-        """        
+        """
         user = self.user
         self.req.form = {'__cloned_eid:X': user.eid,
                          'eid': 'X', '__type:X': 'CWUser',
-                         'login:X': u'toto', 'edits-login:X': u'', 
-                         'upassword:X': u'toto', 'edits-upassword:X': u'', 
+                         'login:X': u'toto', 'edits-login:X': u'',
+                         'upassword:X': u'toto', 'edits-upassword:X': u'',
                          }
         self.assertRaises(ValidationError, self.publish, self.req)
         self.req.form = {'__cloned_eid:X': user.eid,
                          'eid': 'X', '__type:X': 'CWUser',
-                         'login:X': u'toto', 'edits-login:X': u'', 
-                         'upassword:X': u'toto', 'upassword-confirm:X': u'tutu', 'edits-upassword:X': u'', 
+                         'login:X': u'toto', 'edits-login:X': u'',
+                         'upassword:X': u'toto', 'upassword-confirm:X': u'tutu', 'edits-upassword:X': u'',
                          }
         self.assertRaises(ValidationError, self.publish, self.req)
 
@@ -288,7 +288,7 @@
             self.assertEquals(rset[0][0], 'FOO')
         finally:
             del CWUser.custom_login_edit
-        
+
     def test_redirect_apply_button(self):
         redirectrql = rql_for_eid(4012) # whatever
         self.req.form = {
@@ -355,21 +355,21 @@
         path, params = self.expect_redirect_publish()
         self.assertEquals(path, 'view')
         self.assertEquals(params, {u'__message': u'entities deleted'})
-        
+
 
     def test_nonregr_multiple_empty_email_addr(self):
         gueid = self.req.execute('CWGroup G WHERE G name "users"')[0][0]
         self.req.form = {'eid': ['X', 'Y'],
-                         
+
                          '__type:X': 'CWUser',
-                         'login:X': u'adim', 'edits-login:X': u'', 
-                         'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'', 
-                         'in_group:X': gueid, 'edits-in_group:X': INTERNAL_FIELD_VALUE, 
-                         
+                         'login:X': u'adim', 'edits-login:X': u'',
+                         'upassword:X': u'toto', 'upassword-confirm:X': u'toto', 'edits-upassword:X': u'',
+                         'in_group:X': gueid, 'edits-in_group:X': INTERNAL_FIELD_VALUE,
+
                          '__type:Y': 'EmailAddress',
                          'address:Y': u'', 'edits-address:Y': '',
                          'alias:Y': u'', 'edits-alias:Y': '',
-                         'use_email:X': 'Y', 'edits-use_email:X': INTERNAL_FIELD_VALUE, 
+                         'use_email:X': 'Y', 'edits-use_email:X': INTERNAL_FIELD_VALUE,
                          }
         self.assertRaises(ValidationError, self.publish, self.req)
 
@@ -386,7 +386,7 @@
                          {'p' : p.eid, 'e' : e.eid})
             self.req.form = {'__cloned_eid:X': p.eid,
                              'eid': 'X', '__type:X': 'CWUser',
-                             'login': u'dodo', 'edits-login': u'dodo', 
+                             'login': u'dodo', 'edits-login': u'dodo',
                              'surname:X': u'Boom', 'edits-surname:X': u'',
                              '__errorurl' : "whatever but required",
                              }
@@ -405,7 +405,7 @@
         finally:
             p.__class__.skip_copy_for = old_skips
 
-        
+
 if __name__ == '__main__':
     from logilab.common.testlib import unittest_main
     unittest_main()
--- a/goa/test/unittest_metadata.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/test/unittest_metadata.py	Thu Apr 04 13:49:34 2019 +0200
@@ -7,7 +7,7 @@
 
 from google.appengine.api import datastore
 
-class Article(db.Model):        
+class Article(db.Model):
     content = db.TextProperty()
     synopsis = db.StringProperty(default='hello')
 
@@ -15,20 +15,20 @@
     diem = db.DateProperty(required=True, auto_now_add=True)
     title = db.StringProperty(required=True)
     content = db.TextProperty()
-    talks_about = db.ReferenceProperty(Article) 
-    cites = db.SelfReferenceProperty() 
+    talks_about = db.ReferenceProperty(Article)
+    cites = db.SelfReferenceProperty()
 
-  
+
 class MetaDataTC(GAEBasedTC):
     MODEL_CLASSES = (Article, Blog)
-    
+
     def setUp(self):
         GAEBasedTC.setUp(self)
         self.req = self.request()
         self.a = self.add_entity('Article')
         self.p = self.add_entity('CWProperty', pkey=u'ui.language', value=u'en')
         self.session.commit()
-        
+
     def _test_timestamp(self, entity, attr, sleep=0.1):
         timestamp = getattr(entity, attr)
         self.failUnless(timestamp)
@@ -41,20 +41,20 @@
             entity.set_attributes(value=u'en')
         self.session.commit()
         return timestamp
-    
+
     def test_creation_date_dbmodel(self):
         cdate = self._test_timestamp(self.a, 'creation_date')
         self.assertEquals(cdate, self.a.creation_date)
-        
+
     def test_creation_date_yams(self):
         cdate = self._test_timestamp(self.p, 'creation_date')
         self.assertEquals(cdate, self.p.creation_date)
-        
+
     def test_modification_date_dbmodel(self):
         mdate = self._test_timestamp(self.a, 'modification_date', sleep=1)
         a = self.execute('Any X WHERE X eid %(x)s', {'x': self.a.eid}, 'x').get_entity(0, 0)
         self.failUnless(mdate < a.modification_date, (mdate, a.modification_date))
-        
+
     def test_modification_date_yams(self):
         mdate = self._test_timestamp(self.p, 'modification_date', sleep=1)
         p = self.execute('Any X WHERE X eid %(x)s', {'x': self.p.eid}, 'x').get_entity(0, 0)
@@ -67,10 +67,10 @@
         dbmodel = entity.to_gae_model()
         self.assertEquals(len(dbmodel['s_owned_by']), 1)
         self.assertIsInstance(dbmodel['s_owned_by'][0], datastore.Key)
-        
+
     def test_owned_by_dbmodel(self):
         self._test_owned_by(self.a)
-        
+
     def test_owned_by_yams(self):
         self._test_owned_by(self.p)
 
@@ -79,16 +79,16 @@
         creator = entity.created_by[0]
         self.assertIsInstance(creator, db.Model)
         self.assertIsInstance(entity.to_gae_model()['s_created_by'], datastore.Key)
-        
+
     def test_created_by_dbmodel(self):
         self._test_created_by(self.a)
-        
+
     def test_created_by_dbmodel(self):
         self._test_created_by(self.p)
-        
+
     def test_user_owns_dbmodel(self):
         self.failUnless(self.req.user.owns(self.a.eid))
-        
+
     def test_user_owns_yams(self):
         self.failUnless(self.req.user.owns(self.p.eid))
 
@@ -96,11 +96,11 @@
         en = self.execute('Any EN WHERE E name EN, X is E, X eid %(x)s', {'x': self.a.eid}, 'x')[0][0]
         self.assertEquals(en, 'Article')
         en = self.execute('Any EN WHERE E name EN, X is E, X eid %(x)s', {'x': self.p.eid}, 'x')[0][0]
-        self.assertEquals(en, 'CWProperty') 
+        self.assertEquals(en, 'CWProperty')
         en = self.execute('Any EN WHERE E name EN, X is E, X eid %(x)s', {'x': self.req.user.eid}, 'x')[0][0]
         self.assertEquals(en, 'CWUser')
 
-        
+
 if __name__ == '__main__':
     from logilab.common.testlib import unittest_main
     unittest_main()
--- a/goa/test/unittest_rql.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/test/unittest_rql.py	Thu Apr 04 13:49:34 2019 +0200
@@ -32,7 +32,7 @@
 
 # end stored procedure definition #############################################
 
-class Article(db.Model):        
+class Article(db.Model):
     content = db.TextProperty()
     synopsis = db.StringProperty(default=u'hello')
 
@@ -40,14 +40,14 @@
     diem = db.DateProperty(required=True, auto_now_add=True)
     content = db.TextProperty()
     itemtype = db.StringProperty(required=True, choices=(u'personal', u'business'))
-    talks_about = db.ReferenceProperty(Article) 
-    cites = db.SelfReferenceProperty() 
+    talks_about = db.ReferenceProperty(Article)
+    cites = db.SelfReferenceProperty()
     data = db.BlobProperty()
 
-    
+
 class RQLTest(GAEBasedTC):
     MODEL_CLASSES = (Article, Blog)
-    
+
     def setUp(self):
         GAEBasedTC.setUp(self)
         # hack to make talks_about cardinality to ** instead of ?*
@@ -59,13 +59,13 @@
         self.execute('SET X talks_about Y WHERE X eid %(x)s, Y eid %(y)s',
                      {'x': self.blog.eid, 'y': self.article.eid})
         self.commit()
-        
+
     def _check_rset_size(self, rset, row, col):
         self.assertEquals(len(rset), row)
         self.assertEquals(len(rset[0]), col)
         self.assertEquals(len(rset.description), row)
         self.assertEquals(len(rset.description[0]), col)
-        
+
     def _check_blog_rset(self, rset):
         self._check_rset_size(rset, 1, 1)
         self.assertEquals(rset.description[0][0], 'Blog')
@@ -121,20 +121,20 @@
         self.assertEquals(len(rset), 2)
         self.assertEquals(rset.description, [('Blog',), ('Blog',)])
 
-        
+
     def test_2_attribute_selection_1(self):
         rset = self.req.execute('Any X,D,C WHERE X is Blog, X diem D, X content C')
         self._check_rset_size(rset, 1, 3)
         self.assertEquals(rset[0], [self.blog.eid, today(), u'hop'])
         self.assertEquals(rset.description[0], ('Blog', 'Date', 'String'))
         self.assertIsInstance(rset[0][1], DateTimeType)
-        
+
     def test_2_attribute_selection_2(self):
         rset = self.req.execute('Any D,C WHERE X is Blog, X diem D, X content C')
         self._check_rset_size(rset, 1, 2)
         self.assertEquals(rset[0], [today(), u'hop'])
         self.assertEquals(rset.description[0], ('Date', 'String'))
-        
+
     def test_2_attribute_selection_binary(self):
         rset = self.req.execute('Any D WHERE X is Blog, X data D')
         self._check_rset_size(rset, 1, 1)
@@ -147,19 +147,19 @@
         self.assertIsInstance(rset[0][0], Binary)
         value = rset[0][0].getvalue()
         self.assertIsInstance(value, str)
-        self.failIf(isinstance(value, Blob)) 
+        self.failIf(isinstance(value, Blob))
         self.assertEquals(value, 'raw data')
         self.assertEquals(rset.description[0], ('Bytes',))
-        
+
     def test_2_attribute_selection_long_text(self):
         self.blog['content'] = text = 'a'*501
         self.blog.put()
         rset = self.req.execute('Any C WHERE X is Blog, X content C')
         self._check_rset_size(rset, 1, 1)
         self.assertIsInstance(rset[0][0], unicode)
-        self.failIf(isinstance(rset[0][0], Text)) 
+        self.failIf(isinstance(rset[0][0], Text))
         self.assertEquals(rset[0][0], text)
-        
+
     def test_2_attribute_selection_transformation(self):
         rset = self.req.execute('Any X,UPPER(C) WHERE X is Blog, X content C')
         self._check_rset_size(rset, 1, 2)
@@ -172,15 +172,15 @@
         self._check_blog_rset(rset)
         rset = self.req.execute('Any X WHERE X itemtype "business"')
         self.assertEquals(len(rset), 0)
-        
+
     def test_3_ambigous_attribute_restriction_1(self):
         rset = self.req.execute('Any X WHERE X content "hello"')
         self.assertEquals(len(rset), 0)
-        
+
     def test_3_ambigous_attribute_restriction_2(self):
         rset = self.req.execute('Any X WHERE X content "hop"')
         self._check_blog_rset(rset)
-        
+
     def test_3_ambigous_attribute_restriction_3(self):
         article = Article(content=u'hop')
         article.put()
@@ -193,11 +193,11 @@
         rset = self.req.execute('Any X WHERE X eid %(x)s, X content "hola"',
                                 {'x': self.blog.eid})
         self.assertEquals(len(rset), 0)
-        
+
     def test_3_multiple_attribute_restriction(self):
         rset = self.req.execute('Any X WHERE X content "hop", X itemtype "personal"')
         self._check_blog_rset(rset)
-        
+
     def test_3_incoherant_multiple_attribute_restriction(self):
         rset = self.req.execute('Any X WHERE X content "hip", X itemtype "personal"')
         self.assertEquals(len(rset), 0)
@@ -234,7 +234,7 @@
         repo = self.config.repository()
         versions = repo.get_versions()
         self.assertEquals(versions.keys(), ['cubicweb'])
-    
+
     def _setup_relation_description(self):
         self.article2 = self.add_entity('Article', content=u'hop')
         self.blog2 = self.add_entity('Blog', itemtype=u'personal', content=u'hip')
@@ -242,7 +242,7 @@
                      {'x': self.blog2.eid, 'y': self.article2.eid})
         self.blog3 = self.add_entity('Blog', itemtype=u'business', content=u'hep')
         self.commit()
-        
+
     def test_4_relation_restriction_1(self):
         self._setup_relation_description()
         rset = self.req.execute('Any X WHERE X talks_about Y')
@@ -250,7 +250,7 @@
         self.assertUnorderedIterableEquals([r[0] for r in rset],
                              [self.blog.eid, self.blog2.eid])
         self.assertUnorderedIterableEquals([r[0] for r in rset.description], ['Blog', 'Blog'])
-        
+
     def test_4_relation_restriction_2(self):
         self._setup_relation_description()
         rset = self.req.execute('Any Y WHERE X talks_about Y')
@@ -259,7 +259,7 @@
                              [self.article.eid, self.article2.eid])
         self.assertUnorderedIterableEquals([r[0] for r in rset.description],
                              ['Article', 'Article'])
-        
+
     def test_4_relation_restriction_3(self):
         self._setup_relation_description()
         rset = self.req.execute('Any X,Y WHERE X talks_about Y')
@@ -270,7 +270,7 @@
         self.assertUnorderedIterableEquals([tuple(r) for r in rset.description],
                              [('Blog', 'Article'),
                               ('Blog', 'Article')])
-        
+
     def test_4_relation_restriction_4(self):
         self._setup_relation_description()
         rset = self.req.execute('Any X,Y WHERE X talks_about Y, X eid %(x)s',
@@ -278,7 +278,7 @@
         self._check_rset_size(rset, 1, 2)
         self.assertEquals(rset[0], [self.blog.eid, self.article.eid])
         self.assertUnorderedIterableEquals(rset.description[0], ['Blog', 'Article'])
-        
+
     def test_4_relation_restriction_5(self):
         self._setup_relation_description()
         rset = self.req.execute('Any X,Y WHERE X talks_about Y, Y eid %(x)s',
@@ -286,7 +286,7 @@
         self._check_rset_size(rset, 1, 2)
         self.assertEquals(rset[0], [self.blog.eid, self.article.eid])
         self.assertUnorderedIterableEquals(rset.description[0], ['Blog', 'Article'])
-        
+
     def test_4_relation_subject_restriction(self):
         self._setup_relation_description()
         rset = self.req.execute('Any X,Y WHERE X talks_about Y, X content %(c)s',
@@ -294,7 +294,7 @@
         self._check_rset_size(rset, 1, 2)
         self.assertEquals(rset[0], [self.blog.eid, self.article.eid])
         self.assertUnorderedIterableEquals(rset.description[0], ['Blog', 'Article'])
-        
+
     def test_4_relation_object_restriction(self):
         self._setup_relation_description()
         rset = self.req.execute('Any X WHERE X is Blog, X talks_about Y, Y content %(c)s',
@@ -302,7 +302,7 @@
         self._check_rset_size(rset, 1, 1)
         self.assertEquals(rset[0], [self.blog.eid])
         self.assertUnorderedIterableEquals(rset.description[0], ['Blog'])
-        
+
     def test_4_relation_subject_object_restriction(self):
         article2 = self.add_entity('Article', content=u'very interesting')
         rset = self.req.execute('Any X,XC WHERE X is Blog, X content XC, X content %(xc)s, '
@@ -311,20 +311,20 @@
         self._check_rset_size(rset, 1, 2)
         self.assertEquals(rset[0], [self.blog.eid, self.blog.content])
         self.assertUnorderedIterableEquals(rset.description[0], ['Blog', 'String'])
-        
+
     def test_4_relation_subject_object_restriction_no_res(self):
         article2 = self.add_entity('Article', content=u'very interesting')
         rset = self.req.execute('Any X,XC WHERE X is Blog, X content XC, X content %(xc)s, '
                                 'X talks_about Y, Y content %(c)s',
                                 {'xc': 'hip', 'c': 'very interesting'})
         self.assertEquals(len(rset), 0)
-        
+
     def test_4_relation_subject_object_restriction_no_res_2(self):
         rset = self.req.execute('Any X,XC WHERE X is Blog, X content XC, X content %(xc)s, '
                                 'X talks_about Y, Y content %(c)s',
                                 {'xc': 'hop', 'c': 'not interesting'})
         self.assertEquals(len(rset), 0)
-        
+
     def test_4_relation_restriction_7(self):
         self._setup_relation_description()
         rset = self.req.execute('Any XC,XD,YC WHERE X talks_about Y, Y eid %(x)s,'
@@ -333,7 +333,7 @@
         self._check_rset_size(rset, 1, 3)
         self.assertEquals(rset[0], [self.blog.content, self.blog.diem, self.article.content])
         self.assertUnorderedIterableEquals(rset.description[0], ['String', 'Date', 'String'])
-        
+
     def test_4_relation_restriction_8(self):
         self._setup_relation_description()
         rset = self.req.execute('Any X,Y WHERE X cites Y, Y eid %(x)s', {'x': self.blog.eid})
@@ -346,7 +346,7 @@
         rset = self.req.execute('Any X,Y WHERE X talks_about Y, X eid %(x)s, Y eid %(y)s',
                                 {'x': self.blog.eid, 'y': article2.eid})
         self._check_rset_size(rset, 1, 2)
-        
+
     def test_4_ambiguous_subject_relation(self):
         ye = self.add_entity('YamsEntity')
         self.req.execute('SET X ambiguous_relation Y WHERE X eid %(x)s, Y eid %(y)s',
@@ -365,7 +365,7 @@
         self._check_rset_size(rset, 2, 1)
         self.assertUnorderedIterableEquals([r[0] for r in rset], [self.blog.eid, self.article.eid])
         self.assertUnorderedIterableEquals([r[0] for r in rset.description], ['Blog', 'Article'])
-        
+
     def test_4_relation_selection(self):
         req = self.request()
         rset = req.execute('Any N WHERE G content N, U talks_about G, U eid %(u)s', {'u': self.blog.eid})
@@ -381,7 +381,7 @@
                           [[self.blog3.eid, 'hep'],
                            [self.blog2.eid, 'hip'],
                            [self.blog.eid, 'hop']])
-                           
+
     def test_5_orderby_desc(self):
         self._setup_relation_description()
         rset = self.req.execute('Any X,XC ORDERBY XC DESC WHERE X is Blog, X content XC')
@@ -417,7 +417,7 @@
                           [[self.blog.eid, 'hop', 'personal'],
                            [self.blog2.eid, 'hip', 'personal'],
                            [self.blog3.eid, 'hep', 'business']])
-        
+
     def test_5_orderby_several_terms_mixed_order(self):
         self._setup_relation_description()
         rset = self.req.execute('Any X,XC,XI ORDERBY XI ASC,XC DESC WHERE X is Blog, X content XC, X itemtype XI')
@@ -449,25 +449,25 @@
                                 'WHERE X is Blog, X itemtype XIT')
         self._check_rset_size(rset, 2, 1)
         self.assertEquals(rset.rows, [[self.blog.eid], [blog2.eid]])
-                          
-        
+
+
     def test_6_limit(self):
         self._setup_relation_description()
         rset = self.req.execute('Any X LIMIT 2 WHERE X is Blog')
         self._check_rset_size(rset, 2, 1)
-        
+
     def test_6_offset(self):
         self._setup_relation_description()
         rset = self.req.execute('Any XC ORDERBY XC DESC OFFSET 1 WHERE X is Blog, X content XC')
         self._check_rset_size(rset, 2, 1)
         self.assertEquals(rset.rows, [['hip'], ['hep']])
-        
+
     def test_6_limit_and_orderby(self):
         self._setup_relation_description()
         rset = self.req.execute('Any XC ORDERBY XC LIMIT 2 WHERE X is Blog, X content XC')
         self._check_rset_size(rset, 2, 1)
         self.assertEquals(rset.rows, [['hep'], ['hip']])
-        
+
     def test_6_limit_offset_and_orderby(self):
         self._setup_relation_description()
         rset = self.req.execute('Any XC ORDERBY XC LIMIT 2 OFFSET 0 WHERE X is Blog, X content XC')
@@ -481,7 +481,7 @@
         self.assertEquals(rset.rows, [['hop']])
         rset = self.req.execute('Any XC ORDERBY XC LIMIT 2 OFFSET 3 WHERE X is Blog, X content XC')
         self.failIf(rset)
-        
+
 
     def test_7_simple_datetimecast(self):
         self._setup_relation_description()
@@ -496,7 +496,7 @@
         rset = self.req.execute('Any X WHERE X is Blog, X creation_date <= "%s"'
                                 % _tomorrow.strftime('%Y-%m-%d'))
         self._check_rset_size(rset, 3, 1)
-        
+
     def test_7_identity_relation(self):
         rset = self.req.execute('Any X WHERE X identity Y, X eid %(x)s, Y eid %(y)s',
                                 {'x': self.user.eid, 'y': self.user.eid})
@@ -509,13 +509,13 @@
         rset = self.req.execute('Any X WHERE X identity Y, X eid %(x)s, Y eid %(y)s',
                                 {'x': self.blog.eid, 'y': blog2.eid})
         self.failIf(rset)
-        
+
     def test_8_not_relation_1(self):
         rset = self.req.execute('Any X WHERE X identity U, NOT U in_group G, '
                                 'G name "guests", X eid %(x)s, U eid %(u)s',
                                 {'x': self.user.eid, 'u': self.user.eid})
         self._check_rset_size(rset, 1, 1)
-        self.assertEquals(rset.rows, [[self.user.eid]])        
+        self.assertEquals(rset.rows, [[self.user.eid]])
 
     def test_8_not_relation_linked_subject(self):
         rset = self.req.execute('Any X WHERE NOT X talks_about Y, Y eid %(y)s',
@@ -524,7 +524,7 @@
         blog2 = self.add_entity('Blog', content=u'hop', itemtype=u'personal')
         self.commit()
         rset = self.req.execute('Any X WHERE NOT X talks_about Y, Y eid %(y)s',
-                                {'y': self.article.eid})        
+                                {'y': self.article.eid})
         self._check_rset_size(rset, 1, 1)
         self.assertEquals(rset.rows, [[blog2.eid]])
 
@@ -541,7 +541,7 @@
 
     def test_8_not_relation_linked_attr(self):
         self.skip('not yet implemented')
-        # TODO: this should generated 
+        # TODO: this should generated
         # Query(X)[s_talks_about] > "hop" || Query(X)[s_talks_about] < "hop"
         article2 = self.add_entity('Article', content=u'hop')
         self.req.execute('SET X talks_about Y WHERE X eid %(x)s, Y eid %(y)s',
@@ -564,13 +564,13 @@
         rset = self.req.execute('Any Y WHERE NOT X talks_about Y')
         self._check_rset_size(rset, 1, 1)
         self.assertEquals(rset.rows, [[article2.eid]])
-        
+
     def test_8_not_relation_final_1(self):
         rset = self.req.execute('Any G WHERE G is CWGroup, NOT G name "guests"')
         self._check_rset_size(rset, 2, 1)
         self.assertUnorderedIterableEquals([g.name for g in rset.entities()],
-                                           ['users', 'managers'])        
-        
+                                           ['users', 'managers'])
+
     def test_8_not_relation_final_2(self):
         rset = self.req.execute('Any GN WHERE G is CWGroup, NOT G name "guests", G name GN')
         self._check_rset_size(rset, 2, 1)
@@ -587,8 +587,8 @@
         rset = self.req.execute('Any X WHERE X is Blog, EXISTS(X talks_about Y)')
         self._check_rset_size(rset, 1, 1)
         self.assertEquals(rset.rows, [[self.blog.eid]])
-        
-        
+
+
     def test_error_unknown_eid(self):
         rset = self.req.execute('Any X WHERE X eid %(x)s', {'x': '1234'})
         self.assertEquals(len(rset), 0)
@@ -603,6 +603,6 @@
         rset = self.execute('Any X WHERE Y inlined_relation X, Y eid %(y)s', {'y': eid})
         self._check_rset_size(rset, 1, 1)
         self.assertEquals(rset[0][0], self.blog.eid)
-        
+
 if __name__ == '__main__':
     unittest_main()
--- a/goa/test/unittest_schema.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/test/unittest_schema.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,6 +1,6 @@
 from cubicweb.goa.testlib import *
 
-class Article(db.Model):        
+class Article(db.Model):
     content = db.TextProperty()
     synopsis = db.StringProperty(default='hello')
 
@@ -8,10 +8,10 @@
     diem = db.DateProperty(required=True, auto_now_add=True)
     title = db.StringProperty(required=True)
     content = db.TextProperty()
-    talks_about = db.ReferenceProperty(Article) 
-    cites = db.SelfReferenceProperty() 
+    talks_about = db.ReferenceProperty(Article)
+    cites = db.SelfReferenceProperty()
 
-  
+
 class SomeViewsTC(GAEBasedTC):
     MODEL_CLASSES = (Article, Blog)
 
@@ -77,7 +77,7 @@
                            'is', 'is_instance_of', 'modification_date', 'owned_by'])
         self.assertUnorderedIterableEquals((str(e) for e in eschema.object_relations()),
                              ('identity',))
-    
+
     def test_yams_ambiguous_relation(self):
         rschema = self.schema['ambiguous_relation']
         # only relations defined in the class are actually ordered
@@ -103,7 +103,7 @@
         self.assertEquals(rschema.objects(), ('Bytes',))
         self.assertEquals(rschema.rproperty('Blog', 'Bytes', 'cardinality'), '?1')
 
-        
+
 if __name__ == '__main__':
     from logilab.common.testlib import unittest_main
     unittest_main()
--- a/goa/test/unittest_views.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/test/unittest_views.py	Thu Apr 04 13:49:34 2019 +0200
@@ -25,28 +25,28 @@
             return [mydate]
         return []
 
-  
+
 class SomeViewsTC(GAEBasedTC):
     MODEL_CLASSES = (Blog, )
     from cubicweb.web.views import basecontrollers, baseviews, navigation, boxes, calendar
     from data import views
     LOAD_APP_MODULES = (basecontrollers, baseviews, navigation, boxes, calendar, views)
-    
+
     def setUp(self):
         GAEBasedTC.setUp(self)
         self.req = self.request()
         self.blog = Blog(title=u'a blog', content=u'hop')
         self.blog.put(self.req)
-        
+
     def test_hcal(self):
         self.vreg.render('views', 'hcal', self.req, rset=self.blog.rset)
-        
+
     def test_django_index(self):
         self.vreg.render('views', 'index', self.req, rset=None)
 
 for vid in ('primary', 'secondary', 'oneline', 'incontext', 'outofcontext', 'text'):
     setattr(SomeViewsTC, 'test_%s'%vid, lambda self, vid=vid: self.blog.view(vid))
-        
+
 if __name__ == '__main__':
     from logilab.common.testlib import unittest_main
     unittest_main()
--- a/goa/testlib.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/testlib.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,3 +1,10 @@
+"""
+:organization: Logilab
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+__docformat__ = "restructuredtext en"
+
 from logilab.common.testlib import TestCase
 
 import os, os.path as osp
@@ -18,7 +25,7 @@
     import_appengine_failed = None
 except ImportError, exc:
     # XXX necessary ?
-    class db: 
+    class db:
         class Model:
             pass
         class DummyProperty:
@@ -31,7 +38,7 @@
         ReferenceProperty = DummyProperty
         SelfReferenceProperty = DummyProperty
     import_appengine_failed = 'cannot import appengine: %s' % exc
-    
+
 
 from cubicweb.devtools.fake import FakeRequest
 from cubicweb.goa.goavreg import GAERegistry
@@ -56,11 +63,11 @@
 
     def load_schema_hook(self, loader):
         loader.import_yams_cube_schema('data')
-    
+
     @property
     def DS_FILE(self):
         return self.DS_TEMPL_FILE.replace('-template', '')
-    
+
     @property
     def DS_TEMPL_FILE(self):
         return self._DS_TEMPL_FILE + '_'.join(sorted(cls.__name__ for cls in self.MODEL_CLASSES))
@@ -72,7 +79,7 @@
         stub = datastore_file_stub.DatastoreFileStub(self.APP_ID, dsfile,
                                                      dsfile+'.history')
         apiproxy_stub_map.apiproxy.RegisterStub('datastore_v3', stub)
-        
+
     def setUp(self):
         if import_appengine_failed:
             self.skip(import_appengine_failed)
@@ -88,7 +95,7 @@
             self._set_ds_file(self.DS_TEMPL_FILE)
 #         from google.appengine.api import mail_stub
 #         from google3.apphosting.api import urlfetch_stub
-#         from google3.apphosting.api import user_service_stub        
+#         from google3.apphosting.api import user_service_stub
 #         # Use a fresh stub UserService.
 #         apiproxy_stub_map.apiproxy.RegisterStub(
 #             'user', user_service_stub.UserServiceStub())
@@ -149,15 +156,15 @@
                 req = FakeRequest(vreg=self.vreg)
                 self.session = self.session_manager.open_session(req)
             self.user = self.session.user()
-            
+
     def tearDown(self):
         self.session.close()
-        
+
     def request(self):
         req = FakeRequest(vreg=self.vreg)
         req.set_connection(self.session, self.user)
         return req
-    
+
     def add_entity(self, etype, **kwargs):
         cu = self.session.cursor()
         rql = 'INSERT %s X' % etype
@@ -174,7 +181,7 @@
 
     def rollback(self):
         self.session.rollback()
-        
+
     def create_user(self, login, groups=('users',), req=None):
         assert not self.config['use-google-auth']
         user = self.add_entity('CWUser', upassword=str(login), login=unicode(login))
@@ -190,4 +197,3 @@
         req.form['__login'] = login
         req.form['__password'] = password or login
         return self.session_manager.open_session(req)
-        
--- a/goa/tools/generate_schema_img.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/tools/generate_schema_img.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,6 +1,6 @@
 import sys
 from os.path import dirname, abspath, join
-from yams import schema2dot 
+from yams import schema2dot
 
 APPLROOT = abspath(join(dirname(abspath(__file__)), '..'))
 
@@ -9,7 +9,7 @@
 except ImportError:
     sys.path.insert(0, APPLROOT)
     import custom
-    
+
 
 schema = custom.SCHEMA
 skip_rels = ('owned_by', 'created_by', 'identity', 'is', 'is_instance_of')
--- a/goa/tools/laxctl.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/goa/tools/laxctl.py	Thu Apr 04 13:49:34 2019 +0200
@@ -23,7 +23,7 @@
 
 def initialize_vregistry(applroot):
     # apply monkey patches first
-    from cubicweb.goa import do_monkey_patch    
+    from cubicweb.goa import do_monkey_patch
     do_monkey_patch()
     from cubicweb.goa.goavreg import GAERegistry
     from cubicweb.goa.goaconfig import GAEConfiguration
@@ -32,21 +32,21 @@
     vreg = GAERegistry(config)
     vreg.set_schema(config.load_schema())
     return vreg
-        
+
 def alistdir(directory):
     return [osp.join(directory, f) for f in os.listdir(directory)]
 
 
 class LaxCommand(Command):
     """base command class for all lax commands
-    creates vreg, schema and calls 
+    creates vreg, schema and calls
     """
     min_args = max_args = 0
 
     def run(self, args):
         self.vreg = initialize_vregistry(APPLROOT)
         self._run(args)
-        
+
 
 class GenerateSchemaCommand(LaxCommand):
     """generates the schema's png file"""
@@ -54,7 +54,7 @@
 
     def _run(self, args):
         assert not args, 'no argument expected'
-        from yams import schema2dot        
+        from yams import schema2dot
         schema = self.vreg.schema
         skip_rels = ('owned_by', 'created_by', 'identity', 'is', 'is_instance_of')
         path = osp.join(APPLROOT, 'data', 'schema.png')
@@ -107,7 +107,7 @@
 class GetSessionIdHandler(urllib2.HTTPRedirectHandler):
     def __init__(self, config):
         self.config = config
-        
+
     def http_error_303(self, req, fp, code, msg, headers):
         cookie = SimpleCookie(headers['Set-Cookie'])
         sessionid = cookie['__session'].value
@@ -115,7 +115,7 @@
         setattr(self.config, 'cookie', '__session=' + sessionid)
         return 1 # on exception should be raised
 
-    
+
 class URLCommand(LaxCommand):
     """abstract class for commands doing stuff by accessing the web application
     """
@@ -138,7 +138,7 @@
           'help': 'user password instead of giving raw cookie string (require '
           'lax based authentication).'}),
         )
-    
+
     def _run(self, args):
         baseurl = args[0]
         if not baseurl.startswith('http'):
@@ -154,9 +154,9 @@
             urllib2.install_opener(opener)
             data = urlencode(dict(__login=self.config.user,
                                   __password=self.config.password))
-            self.open_url(urllib2.Request(baseurl, data))            
+            self.open_url(urllib2.Request(baseurl, data))
         opener = urllib2.build_opener(NoRedirectHandler())
-        urllib2.install_opener(opener)        
+        urllib2.install_opener(opener)
         self.do_base_url(baseurl)
 
     def build_req(self, url):
@@ -164,7 +164,7 @@
         if self.config.cookie:
             req.headers['Cookie'] = self.config.cookie
         return req
-    
+
     def open_url(self, req):
         try:
             return urllib2.urlopen(req)
@@ -194,11 +194,11 @@
             msg = remove_html_tags(match.group(1))
             print msg
             return msg
-        
+
     def do_base_url(self, baseurl):
         raise NotImplementedError()
 
-        
+
 class DSInitCommand(URLCommand):
     """initialize the datastore"""
     name = 'db-init'
@@ -210,7 +210,7 @@
           'help': 'number of seconds to wait between each request to avoid '
           'going out of quota.'}),
         )
-        
+
     def do_base_url(self, baseurl):
         req = self.build_req(baseurl + '?vid=contentinit')
         while True:
@@ -240,8 +240,8 @@
         req = self.build_req(baseurl + '?vid=cleansessions')
         data = self.open_url(req)
         self.extract_message(data)
-            
-    
+
+
 register_commands([GenerateSchemaCommand,
                    PopulateDataDirCommand,
                    DSInitCommand,
@@ -250,6 +250,6 @@
 
 def run():
     main_run(sys.argv[1:])
-    
+
 if __name__ == '__main__':
     run()
--- a/hercule.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/hercule.py	Thu Apr 04 13:49:34 2019 +0200
@@ -13,11 +13,11 @@
 from logilab.common.cli import CLIHelper
 from logilab.common.clcommands import BadCommandUsage, pop_arg, register_commands
 from cubicweb.toolsutils import CONNECT_OPTIONS, Command
- 
+
 # result formatter ############################################################
 
 PAGER = os.environ.get('PAGER', 'less')
-            
+
 def pager_format_results(writer, layout):
     """pipe results to a pager like more or less"""
     (r, w) = os.pipe()
@@ -42,8 +42,8 @@
 def izip2(list1, list2):
     for i in xrange(len(list1)):
         yield list1[i] + tuple(list2[i])
-        
-def format_results(writer, layout, stream=sys.stdout): 
+
+def format_results(writer, layout, stream=sys.stdout):
     """format result as text into the given file like object"""
     writer.format(layout, stream)
 
@@ -60,7 +60,7 @@
     return str(value)
 
 # command line querier ########################################################
-    
+
 class RQLCli(CLIHelper):
     """Interactive command line client for CubicWeb, allowing user to execute
     arbitrary RQL queries and to fetch schema information
@@ -74,10 +74,10 @@
         'description'  : "CubicWeb",
         'commit' :       "CubicWeb",
         'rollback' :     "CubicWeb",
-        'autocommit'  :  "Others", 
+        'autocommit'  :  "Others",
         'debug' :        "Others",
         })
-    
+
     def __init__(self, application=None, user=None, password=None,
                  host=None, debug=0):
         CLIHelper.__init__(self, os.path.join(os.environ["HOME"], ".erqlhist"))
@@ -94,7 +94,7 @@
         if application is not None:
             self.do_connect(application, user, password, host)
         self.do_debug(debug)
-        
+
     def do_connect(self, application, user=None, password=None, host=None):
         """connect to an cubicweb application"""
         from cubicweb.dbapi import connect
@@ -113,7 +113,7 @@
         self._completer.list = (self.commands.keys() +
                                 self.schema.entities() + ['Any'])
         print _('You are now connected to %s') % application
-        
+
 
     help_do_connect = ('connect', "connect <application> [<user> [<password> [<host>]]]",
                        _(do_connect.__doc__))
@@ -127,9 +127,9 @@
             self._format = pager_format_results
         if self._debug:
             print _('Debug level set to %s'%debug)
-        
+
     help_do_debug = ('debug', "debug [debug_level]", _(do_debug.__doc__))
-    
+
     def do_description(self):
         """display the description of the latest result"""
         if self.rset.description is None:
@@ -139,7 +139,7 @@
                              for line_desc in self.rset.description])
 
     help_do_description = ('description', "description", _(do_description.__doc__))
-    
+
     def do_schema(self, name=None):
         """display information about the application schema """
         if self.cnx is None:
@@ -159,28 +159,28 @@
                 done = 1
         if done is None:
             print _('Unable to find anything named "%s" in the schema !') % name
-            
+
     help_do_schema = ('schema', "schema [keyword]", _(do_schema.__doc__))
 
-    
+
     def do_commit(self):
         """commit the current transaction"""
         self.cnx.commit()
 
     help_do_commit = ('commit', "commit", _(do_commit.__doc__))
-    
+
     def do_rollback(self):
         """rollback the current transaction"""
         self.cnx.rollback()
 
     help_do_rollback = ('rollback', "rollback", _(do_rollback.__doc__))
-    
+
     def do_autocommit(self):
         """toggle autocommit mode"""
         self.autocommit = not self.autocommit
 
     help_do_autocommit = ('autocommit', "autocommit", _(do_autocommit.__doc__))
-    
+
 
     def handle_line(self, stripped_line):
         """handle non command line :
@@ -232,7 +232,7 @@
     """A command line querier for CubicWeb, using the Relation Query Language.
 
     <application>
-      identifier of the application to connect to 
+      identifier of the application to connect to
     """
     name = 'client'
     arguments = '<application>'
@@ -247,7 +247,7 @@
           'help': 'file containing a batch of RQL statements to execute.',
           }),
         )
-    
+
     def run(self, args):
         """run the command with its specific arguments"""
         appid = pop_arg(args, expected_size_after=None)
@@ -271,5 +271,5 @@
                 cli.handle_line(line)
         else:
             cli.run()
-        
+
 register_commands((CubicWebClientCommand,))
--- a/i18n/en.po	Wed Jun 03 09:09:33 2009 +0200
+++ b/i18n/en.po	Thu Apr 04 13:49:34 2019 +0200
@@ -118,10 +118,6 @@
 msgid "%s software version of the database"
 msgstr ""
 
-#, python-format
-msgid "%s_perm"
-msgstr ""
-
 msgid "**"
 msgstr "0..n 0..n"
 
@@ -200,30 +196,11 @@
 msgid "Bytes_plural"
 msgstr "Bytes"
 
-msgid "Date"
-msgstr "Date"
-
-msgid "Date_plural"
-msgstr "Dates"
-
-msgid "Datetime"
-msgstr "Date and time"
-
-msgid "Datetime_plural"
-msgstr "Dates and times"
-
-#, python-format
-msgid "Debug level set to %s"
-msgstr ""
-
-msgid "Decimal"
-msgstr "Decimal number"
-
-msgid "Decimal_plural"
-msgstr "Decimal numbers"
-
-msgid "Do you want to delete the following element(s) ?"
-msgstr ""
+msgid "CWAttribute"
+msgstr "Attribute"
+
+msgid "CWAttribute_plural"
+msgstr "Attributes"
 
 msgid "CWCache"
 msgstr ""
@@ -249,24 +226,12 @@
 msgid "CWEType_plural"
 msgstr "Entity types"
 
-msgid "CWAttribute"
-msgstr "Attribute"
-
-msgid "CWAttribute_plural"
-msgstr "Attributes"
-
 msgid "CWGroup"
 msgstr "Group"
 
 msgid "CWGroup_plural"
 msgstr "Groups"
 
-msgid "CWRelation"
-msgstr "Relation"
-
-msgid "CWRelation_plural"
-msgstr "Relations"
-
 msgid "CWPermission"
 msgstr "Permission"
 
@@ -285,13 +250,41 @@
 msgid "CWRType_plural"
 msgstr "Relation types"
 
+msgid "CWRelation"
+msgstr "Relation"
+
+msgid "CWRelation_plural"
+msgstr "Relations"
+
 msgid "CWUser"
 msgstr "User"
 
 msgid "CWUser_plural"
 msgstr "Users"
 
-msgid "Email body: "
+msgid "Date"
+msgstr "Date"
+
+msgid "Date_plural"
+msgstr "Dates"
+
+msgid "Datetime"
+msgstr "Date and time"
+
+msgid "Datetime_plural"
+msgstr "Dates and times"
+
+#, python-format
+msgid "Debug level set to %s"
+msgstr ""
+
+msgid "Decimal"
+msgstr "Decimal number"
+
+msgid "Decimal_plural"
+msgstr "Decimal numbers"
+
+msgid "Do you want to delete the following element(s) ?"
 msgstr ""
 
 msgid "EmailAddress"
@@ -312,7 +305,7 @@
 msgid "Float_plural"
 msgstr "Floats"
 
-msgid "From: "
+msgid "From:"
 msgstr ""
 
 msgid "Int"
@@ -330,6 +323,9 @@
 msgid "New Bookmark"
 msgstr "New bookmark"
 
+msgid "New CWAttribute"
+msgstr "New attribute"
+
 msgid "New CWCache"
 msgstr ""
 
@@ -342,15 +338,9 @@
 msgid "New CWEType"
 msgstr "New entity type"
 
-msgid "New CWAttribute"
-msgstr "New attribute"
-
 msgid "New CWGroup"
 msgstr "New group"
 
-msgid "New CWRelation"
-msgstr "New relation"
-
 msgid "New CWPermission"
 msgstr "New permission"
 
@@ -360,6 +350,9 @@
 msgid "New CWRType"
 msgstr "New relation type"
 
+msgid "New CWRelation"
+msgstr "New relation"
+
 msgid "New CWUser"
 msgstr "New user"
 
@@ -396,16 +389,13 @@
 msgid "Please note that this is only a shallow copy"
 msgstr ""
 
-msgid "Problem occured"
-msgstr ""
-
 msgid "RQLExpression"
 msgstr "RQL expression"
 
 msgid "RQLExpression_plural"
 msgstr "RQL expressions"
 
-msgid "Recipients: "
+msgid "Recipients:"
 msgstr ""
 
 msgid "Relations"
@@ -439,7 +429,7 @@
 msgid "String_plural"
 msgstr "Strings"
 
-msgid "Subject: "
+msgid "Subject:"
 msgstr ""
 
 msgid "Submit bug report"
@@ -466,6 +456,9 @@
 msgid "This Bookmark"
 msgstr "This bookmark"
 
+msgid "This CWAttribute"
+msgstr "This attribute"
+
 msgid "This CWCache"
 msgstr ""
 
@@ -478,15 +471,9 @@
 msgid "This CWEType"
 msgstr "This entity type"
 
-msgid "This CWAttribute"
-msgstr "This attribute"
-
 msgid "This CWGroup"
 msgstr "This group"
 
-msgid "This CWRelation"
-msgstr "This relation"
-
 msgid "This CWPermission"
 msgstr "This permission"
 
@@ -496,6 +483,9 @@
 msgid "This CWRType"
 msgstr "This relation type"
 
+msgid "This CWRelation"
+msgstr "This relation"
+
 msgid "This CWUser"
 msgstr "This user"
 
@@ -669,6 +659,12 @@
 msgid "actions_manage_description"
 msgstr ""
 
+msgid "actions_managepermission"
+msgstr ""
+
+msgid "actions_managepermission_description"
+msgstr ""
+
 msgid "actions_muledit"
 msgstr "modify all"
 
@@ -741,6 +737,12 @@
 msgid "add Bookmark bookmarked_by CWUser object"
 msgstr "bookmark"
 
+msgid "add CWAttribute constrained_by CWConstraint subject"
+msgstr "constraint"
+
+msgid "add CWAttribute relation_type CWRType object"
+msgstr "attribute definition"
+
 msgid "add CWEType add_permission RQLExpression subject"
 msgstr "rql expression for the add permission"
 
@@ -753,18 +755,6 @@
 msgid "add CWEType update_permission RQLExpression subject"
 msgstr "rql expression for the update permission"
 
-msgid "add CWAttribute constrained_by CWConstraint subject"
-msgstr "constraint"
-
-msgid "add CWAttribute relation_type CWRType object"
-msgstr "attribute definition"
-
-msgid "add CWRelation constrained_by CWConstraint subject"
-msgstr "constraint"
-
-msgid "add CWRelation relation_type CWRType object"
-msgstr "relation definition"
-
 msgid "add CWProperty for_user CWUser object"
 msgstr "property"
 
@@ -777,6 +767,12 @@
 msgid "add CWRType read_permission RQLExpression subject"
 msgstr "rql expression for the read permission"
 
+msgid "add CWRelation constrained_by CWConstraint subject"
+msgstr "constraint"
+
+msgid "add CWRelation relation_type CWRType object"
+msgstr "relation definition"
+
 msgid "add CWUser in_group CWGroup object"
 msgstr "user"
 
@@ -807,6 +803,9 @@
 msgid "add a Bookmark"
 msgstr "add a bookmark"
 
+msgid "add a CWAttribute"
+msgstr "add an attribute"
+
 msgid "add a CWCache"
 msgstr ""
 
@@ -819,15 +818,9 @@
 msgid "add a CWEType"
 msgstr "add an entity type"
 
-msgid "add a CWAttribute"
-msgstr "add an attribute"
-
 msgid "add a CWGroup"
 msgstr "add a group"
 
-msgid "add a CWRelation"
-msgstr "add a relation"
-
 msgid "add a CWPermission"
 msgstr "add a permission"
 
@@ -837,6 +830,9 @@
 msgid "add a CWRType"
 msgstr "add a relation type"
 
+msgid "add a CWRelation"
+msgstr "add a relation"
+
 msgid "add a CWUser"
 msgstr "add a user"
 
@@ -1118,9 +1114,6 @@
 msgid "click on the box to cancel the deletion"
 msgstr ""
 
-msgid "close all"
-msgstr ""
-
 msgid "comment"
 msgstr ""
 
@@ -1190,12 +1183,6 @@
 msgid "components_rqlinput_description"
 msgstr "the rql box in the page's header"
 
-msgid "components_rss_feed_url"
-msgstr ""
-
-msgid "components_rss_feed_url_description"
-msgstr ""
-
 msgid "composite"
 msgstr ""
 
@@ -1335,28 +1322,31 @@
 msgid "creating Bookmark (Bookmark bookmarked_by CWUser %(linkto)s)"
 msgstr "creating bookmark for %(linkto)s"
 
-msgid "creating CWConstraint (CWAttribute %(linkto)s constrained_by CWConstraint)"
-msgstr "creating constraint for attribute %(linkto)s"
-
-msgid "creating CWConstraint (CWRelation %(linkto)s constrained_by CWConstraint)"
-msgstr "creating constraint for relation %(linkto)s"
-
 msgid "creating CWAttribute (CWAttribute relation_type CWRType %(linkto)s)"
 msgstr "creating attribute %(linkto)s"
 
+msgid ""
+"creating CWConstraint (CWAttribute %(linkto)s constrained_by CWConstraint)"
+msgstr "creating constraint for attribute %(linkto)s"
+
+msgid ""
+"creating CWConstraint (CWRelation %(linkto)s constrained_by CWConstraint)"
+msgstr "creating constraint for relation %(linkto)s"
+
+msgid "creating CWProperty (CWProperty for_user CWUser %(linkto)s)"
+msgstr "creating property for user %(linkto)s"
+
 msgid "creating CWRelation (CWRelation relation_type CWRType %(linkto)s)"
 msgstr "creating relation %(linkto)s"
 
-msgid "creating CWProperty (CWProperty for_user CWUser %(linkto)s)"
-msgstr "creating property for user %(linkto)s"
-
 msgid "creating CWUser (CWUser in_group CWGroup %(linkto)s)"
 msgstr "creating a new user in group %(linkto)s"
 
 msgid "creating EmailAddress (CWUser %(linkto)s use_email EmailAddress)"
 msgstr "creating email address for user %(linkto)s"
 
-msgid "creating RQLExpression (CWEType %(linkto)s add_permission RQLExpression)"
+msgid ""
+"creating RQLExpression (CWEType %(linkto)s add_permission RQLExpression)"
 msgstr "creating rql expression for add permission on %(linkto)s"
 
 msgid ""
@@ -1371,7 +1361,8 @@
 "creating RQLExpression (CWEType %(linkto)s update_permission RQLExpression)"
 msgstr "creating rql expression for update permission on %(linkto)s"
 
-msgid "creating RQLExpression (CWRType %(linkto)s add_permission RQLExpression)"
+msgid ""
+"creating RQLExpression (CWRType %(linkto)s add_permission RQLExpression)"
 msgstr "creating rql expression for add permission on relations %(linkto)s"
 
 msgid ""
@@ -1540,6 +1531,9 @@
 msgid "destination_state_object"
 msgstr "destination of"
 
+msgid "detach attached file"
+msgstr ""
+
 #, python-format
 msgid "detach attached file %s"
 msgstr ""
@@ -1618,9 +1612,18 @@
 msgid "entities deleted"
 msgstr ""
 
+msgid "entity copied"
+msgstr ""
+
+msgid "entity created"
+msgstr ""
+
 msgid "entity deleted"
 msgstr ""
 
+msgid "entity edited"
+msgstr ""
+
 msgid "entity type"
 msgstr ""
 
@@ -1727,6 +1730,10 @@
 msgid "from"
 msgstr ""
 
+#, python-format
+msgid "from %(date)s"
+msgstr ""
+
 msgid "from_entity"
 msgstr "from entity"
 
@@ -1751,6 +1758,9 @@
 msgid "generic plot"
 msgstr ""
 
+msgid "generic relation to link one entity to another"
+msgstr ""
+
 msgid "go back to the index page"
 msgstr ""
 
@@ -2004,6 +2014,11 @@
 msgstr ""
 
 msgid ""
+"link a permission to the entity. This permission should be used in the "
+"security definition of the entity's type to be useful."
+msgstr ""
+
+msgid ""
 "link a property to the user which want this property customization. Unless "
 "you're a site manager, this relation will be handled automatically."
 msgstr ""
@@ -2026,11 +2041,6 @@
 msgid "link a transition to one or more entity type"
 msgstr ""
 
-msgid ""
-"link a transition to one or more rql expression allowing to go through this "
-"transition"
-msgstr ""
-
 msgid "link to each item in"
 msgstr ""
 
@@ -2046,6 +2056,9 @@
 msgid "login"
 msgstr ""
 
+msgid "login or email"
+msgstr ""
+
 msgid "login_action"
 msgstr "log in"
 
@@ -2173,7 +2186,7 @@
 msgid "no"
 msgstr ""
 
-msgid "no associated epermissions"
+msgid "no associated permissions"
 msgstr ""
 
 msgid "no possible transition"
@@ -2362,6 +2375,9 @@
 msgid "remove this Bookmark"
 msgstr "remove this bookmark"
 
+msgid "remove this CWAttribute"
+msgstr "remove this attribute"
+
 msgid "remove this CWCache"
 msgstr ""
 
@@ -2374,15 +2390,9 @@
 msgid "remove this CWEType"
 msgstr "remove this entity type"
 
-msgid "remove this CWAttribute"
-msgstr "remove this attribute"
-
 msgid "remove this CWGroup"
 msgstr "remove this group"
 
-msgid "remove this CWRelation"
-msgstr "remove this relation"
-
 msgid "remove this CWPermission"
 msgstr "remove this permission"
 
@@ -2392,6 +2402,9 @@
 msgid "remove this CWRType"
 msgstr "remove this relation type"
 
+msgid "remove this CWRelation"
+msgstr "remove this relation"
+
 msgid "remove this CWUser"
 msgstr "remove this user"
 
@@ -2416,6 +2429,12 @@
 msgid "require_group_object"
 msgstr "required by"
 
+msgid "require_permission"
+msgstr ""
+
+msgid "require_permission_object"
+msgstr ""
+
 msgid "required attribute"
 msgstr ""
 
@@ -2483,12 +2502,18 @@
 msgid "see them all"
 msgstr ""
 
+msgid "see_also"
+msgstr ""
+
 msgid "select"
 msgstr ""
 
 msgid "select a"
 msgstr ""
 
+msgid "select a key first"
+msgstr ""
+
 msgid "select a relation"
 msgstr ""
 
@@ -2547,6 +2572,9 @@
 msgid "show meta-data"
 msgstr "show the complete schema"
 
+msgid "sioc"
+msgstr ""
+
 msgid "site configuration"
 msgstr ""
 
@@ -2672,6 +2700,10 @@
 msgid "to"
 msgstr ""
 
+#, python-format
+msgid "to %(date)s"
+msgstr ""
+
 msgid "to associate with"
 msgstr ""
 
@@ -2690,6 +2722,9 @@
 msgid "todo_by"
 msgstr "to do by"
 
+msgid "toggle check boxes"
+msgstr ""
+
 msgid "transition is not allowed"
 msgstr ""
 
@@ -2904,6 +2939,9 @@
 msgid "you have been logged out"
 msgstr ""
 
+msgid "you should probably delete that property"
+msgstr ""
+
 #~ msgid "Card"
 #~ msgstr "Card"
 
--- a/i18n/es.po	Wed Jun 03 09:09:33 2009 +0200
+++ b/i18n/es.po	Thu Apr 04 13:49:34 2019 +0200
@@ -123,10 +123,6 @@
 msgid "%s software version of the database"
 msgstr "versión sistema de la base para %s"
 
-#, python-format
-msgid "%s_perm"
-msgstr ""
-
 msgid "**"
 msgstr "0..n 0..n"
 
@@ -205,30 +201,11 @@
 msgid "Bytes_plural"
 msgstr "Bytes"
 
-msgid "Date"
-msgstr "Fecha"
-
-msgid "Date_plural"
-msgstr "Fechas"
-
-msgid "Datetime"
-msgstr "Fecha y hora"
-
-msgid "Datetime_plural"
-msgstr "Fechas y horas"
-
-#, python-format
-msgid "Debug level set to %s"
-msgstr "Nivel de debug puesto a %s"
-
-msgid "Decimal"
-msgstr "Decimal"
-
-msgid "Decimal_plural"
-msgstr "Decimales"
-
-msgid "Do you want to delete the following element(s) ?"
-msgstr "Desea suprimir el(los) elemento(s) siguiente(s)"
+msgid "CWAttribute"
+msgstr "Atributo"
+
+msgid "CWAttribute_plural"
+msgstr "Atributos"
 
 msgid "CWCache"
 msgstr "Cache"
@@ -254,24 +231,12 @@
 msgid "CWEType_plural"
 msgstr "Tipos de entidades"
 
-msgid "CWAttribute"
-msgstr "Atributo"
-
-msgid "CWAttribute_plural"
-msgstr "Atributos"
-
 msgid "CWGroup"
 msgstr "Groupo"
 
 msgid "CWGroup_plural"
 msgstr "Groupos"
 
-msgid "CWRelation"
-msgstr "Relación"
-
-msgid "CWRelation_plural"
-msgstr "Relaciones"
-
 msgid "CWPermission"
 msgstr "Autorización"
 
@@ -290,14 +255,42 @@
 msgid "CWRType_plural"
 msgstr "Tipos de relación"
 
+msgid "CWRelation"
+msgstr "Relación"
+
+msgid "CWRelation_plural"
+msgstr "Relaciones"
+
 msgid "CWUser"
 msgstr "Usuario"
 
 msgid "CWUser_plural"
 msgstr "Usuarios"
 
-msgid "Email body: "
-msgstr "Contenido del correo electrónico : "
+msgid "Date"
+msgstr "Fecha"
+
+msgid "Date_plural"
+msgstr "Fechas"
+
+msgid "Datetime"
+msgstr "Fecha y hora"
+
+msgid "Datetime_plural"
+msgstr "Fechas y horas"
+
+#, python-format
+msgid "Debug level set to %s"
+msgstr "Nivel de debug puesto a %s"
+
+msgid "Decimal"
+msgstr "Decimal"
+
+msgid "Decimal_plural"
+msgstr "Decimales"
+
+msgid "Do you want to delete the following element(s) ?"
+msgstr "Desea suprimir el(los) elemento(s) siguiente(s)"
 
 msgid "EmailAddress"
 msgstr "Correo Electrónico"
@@ -317,8 +310,8 @@
 msgid "Float_plural"
 msgstr "Números flotantes"
 
-msgid "From: "
-msgstr "De : "
+msgid "From:"
+msgstr ""
 
 msgid "Int"
 msgstr "Número entero"
@@ -335,6 +328,9 @@
 msgid "New Bookmark"
 msgstr "Agregar a Favoritos"
 
+msgid "New CWAttribute"
+msgstr "Nueva definición de relación final"
+
 msgid "New CWCache"
 msgstr "Agregar Cache"
 
@@ -347,15 +343,9 @@
 msgid "New CWEType"
 msgstr "Agregar tipo de entidad"
 
-msgid "New CWAttribute"
-msgstr "Nueva definición de relación final"
-
 msgid "New CWGroup"
 msgstr "Nuevo grupo"
 
-msgid "New CWRelation"
-msgstr "Nueva definición de relación final"
-
 msgid "New CWPermission"
 msgstr "Agregar autorización"
 
@@ -365,6 +355,9 @@
 msgid "New CWRType"
 msgstr "Agregar tipo de relación"
 
+msgid "New CWRelation"
+msgstr "Nueva definición de relación final"
+
 msgid "New CWUser"
 msgstr "Agregar usuario"
 
@@ -401,17 +394,14 @@
 msgid "Please note that this is only a shallow copy"
 msgstr "Recuerde que no es más que una copia superficial"
 
-msgid "Problem occured"
-msgstr "Ha ocurrido un error"
-
 msgid "RQLExpression"
 msgstr "Expresión RQL"
 
 msgid "RQLExpression_plural"
 msgstr "Expresiones RQL"
 
-msgid "Recipients: "
-msgstr "Destinatarios : "
+msgid "Recipients:"
+msgstr ""
 
 msgid "Relations"
 msgstr "Relaciones"
@@ -444,8 +434,8 @@
 msgid "String_plural"
 msgstr "Cadenas de caracteres"
 
-msgid "Subject: "
-msgstr "Objeto : "
+msgid "Subject:"
+msgstr ""
 
 msgid "Submit bug report"
 msgstr "Enviar un reporte de error (bug)"
@@ -471,6 +461,9 @@
 msgid "This Bookmark"
 msgstr "Este favorito"
 
+msgid "This CWAttribute"
+msgstr "Esta definición de relación final"
+
 msgid "This CWCache"
 msgstr "Este Cache"
 
@@ -483,15 +476,9 @@
 msgid "This CWEType"
 msgstr "Este tipo de Entidad"
 
-msgid "This CWAttribute"
-msgstr "Esta definición de relación final"
-
 msgid "This CWGroup"
 msgstr "Este grupo"
 
-msgid "This CWRelation"
-msgstr "Esta definición de relación no final"
-
 msgid "This CWPermission"
 msgstr "Esta autorización"
 
@@ -501,6 +488,9 @@
 msgid "This CWRType"
 msgstr "Este tipo de relación"
 
+msgid "This CWRelation"
+msgstr "Esta definición de relación no final"
+
 msgid "This CWUser"
 msgstr "Este usuario"
 
@@ -692,6 +682,12 @@
 msgid "actions_manage_description"
 msgstr ""
 
+msgid "actions_managepermission"
+msgstr ""
+
+msgid "actions_managepermission_description"
+msgstr ""
+
 msgid "actions_muledit"
 msgstr "Edición múltiple"
 
@@ -764,6 +760,12 @@
 msgid "add Bookmark bookmarked_by CWUser object"
 msgstr "Agregar a los favoritos "
 
+msgid "add CWAttribute constrained_by CWConstraint subject"
+msgstr "Restricción"
+
+msgid "add CWAttribute relation_type CWRType object"
+msgstr "Definición de atributo"
+
 msgid "add CWEType add_permission RQLExpression subject"
 msgstr "Agregar una autorización"
 
@@ -776,18 +778,6 @@
 msgid "add CWEType update_permission RQLExpression subject"
 msgstr "Definir una expresión RQL de actualización"
 
-msgid "add CWAttribute constrained_by CWConstraint subject"
-msgstr "Restricción"
-
-msgid "add CWAttribute relation_type CWRType object"
-msgstr "Definición de atributo"
-
-msgid "add CWRelation constrained_by CWConstraint subject"
-msgstr "Restricción"
-
-msgid "add CWRelation relation_type CWRType object"
-msgstr "Definición de relación"
-
 msgid "add CWProperty for_user CWUser object"
 msgstr "Agregar Propiedad"
 
@@ -800,6 +790,12 @@
 msgid "add CWRType read_permission RQLExpression subject"
 msgstr "Agregar expresión RQL de lectura"
 
+msgid "add CWRelation constrained_by CWConstraint subject"
+msgstr "Restricción"
+
+msgid "add CWRelation relation_type CWRType object"
+msgstr "Definición de relación"
+
 msgid "add CWUser in_group CWGroup object"
 msgstr "Agregar usuario"
 
@@ -830,6 +826,9 @@
 msgid "add a Bookmark"
 msgstr "Agregar un Favorito"
 
+msgid "add a CWAttribute"
+msgstr "Agregar un tipo de relación"
+
 msgid "add a CWCache"
 msgstr "Agregar un cache"
 
@@ -842,15 +841,9 @@
 msgid "add a CWEType"
 msgstr "Agregar un tipo de entidad"
 
-msgid "add a CWAttribute"
-msgstr "Agregar un tipo de relación"
-
 msgid "add a CWGroup"
 msgstr "Agregar un grupo de usuarios"
 
-msgid "add a CWRelation"
-msgstr "Agregar una relación"
-
 msgid "add a CWPermission"
 msgstr "Agregar una autorización"
 
@@ -860,6 +853,9 @@
 msgid "add a CWRType"
 msgstr "Agregar un tipo de relación"
 
+msgid "add a CWRelation"
+msgstr "Agregar una relación"
+
 msgid "add a CWUser"
 msgstr "Agregar un usuario"
 
@@ -1148,9 +1144,6 @@
 msgid "click on the box to cancel the deletion"
 msgstr "Seleccione la zona de edición para cancelar la eliminación"
 
-msgid "close all"
-msgstr ""
-
 msgid "comment"
 msgstr "Comentario"
 
@@ -1223,12 +1216,6 @@
 msgid "components_rqlinput_description"
 msgstr "La barra de demanda rql, en el encabezado de página"
 
-msgid "components_rss_feed_url"
-msgstr "RSS FEED URL"
-
-msgid "components_rss_feed_url_description"
-msgstr "El espacio para administrar RSS"
-
 msgid "composite"
 msgstr "composite"
 
@@ -1384,28 +1371,31 @@
 msgid "creating Bookmark (Bookmark bookmarked_by CWUser %(linkto)s)"
 msgstr "Creando Favorito"
 
-msgid "creating CWConstraint (CWAttribute %(linkto)s constrained_by CWConstraint)"
-msgstr "Creación condicionada por el atributo %(linkto)s"
-
-msgid "creating CWConstraint (CWRelation %(linkto)s constrained_by CWConstraint)"
-msgstr "Creación condicionada por la relación %(linkto)s"
-
 msgid "creating CWAttribute (CWAttribute relation_type CWRType %(linkto)s)"
 msgstr "Creación del atributo %(linkto)s"
 
+msgid ""
+"creating CWConstraint (CWAttribute %(linkto)s constrained_by CWConstraint)"
+msgstr "Creación condicionada por el atributo %(linkto)s"
+
+msgid ""
+"creating CWConstraint (CWRelation %(linkto)s constrained_by CWConstraint)"
+msgstr "Creación condicionada por la relación %(linkto)s"
+
+msgid "creating CWProperty (CWProperty for_user CWUser %(linkto)s)"
+msgstr "Creación de una propiedad por el usuario %(linkto)s"
+
 msgid "creating CWRelation (CWRelation relation_type CWRType %(linkto)s)"
 msgstr "Creación de la relación %(linkto)s"
 
-msgid "creating CWProperty (CWProperty for_user CWUser %(linkto)s)"
-msgstr "Creación de una propiedad por el usuario %(linkto)s"
-
 msgid "creating CWUser (CWUser in_group CWGroup %(linkto)s)"
 msgstr "Creación de un usuario para agregar al grupo %(linkto)s"
 
 msgid "creating EmailAddress (CWUser %(linkto)s use_email EmailAddress)"
 msgstr "Creación de una dirección electrónica para el usuario %(linkto)s"
 
-msgid "creating RQLExpression (CWEType %(linkto)s add_permission RQLExpression)"
+msgid ""
+"creating RQLExpression (CWEType %(linkto)s add_permission RQLExpression)"
 msgstr ""
 "Creación de una expresión RQL para la autorización de agregar %(linkto)s"
 
@@ -1422,7 +1412,8 @@
 "creating RQLExpression (CWEType %(linkto)s update_permission RQLExpression)"
 msgstr "Creación de una expresión RQL para autorizar actualizar %(linkto)s"
 
-msgid "creating RQLExpression (CWRType %(linkto)s add_permission RQLExpression)"
+msgid ""
+"creating RQLExpression (CWRType %(linkto)s add_permission RQLExpression)"
 msgstr ""
 "Creación de una expresión RQL para la autorización de agregar relaciones %"
 "(linkto)s"
@@ -1610,6 +1601,9 @@
 msgid "destination_state_object"
 msgstr "Destino de"
 
+msgid "detach attached file"
+msgstr "soltar el archivo existente"
+
 #, python-format
 msgid "detach attached file %s"
 msgstr "Quitar archivo adjunto %s"
@@ -1690,9 +1684,18 @@
 msgid "entities deleted"
 msgstr "Entidades eliminadas"
 
+msgid "entity copied"
+msgstr ""
+
+msgid "entity created"
+msgstr ""
+
 msgid "entity deleted"
 msgstr "Entidad eliminada"
 
+msgid "entity edited"
+msgstr ""
+
 msgid "entity type"
 msgstr "Tipo de entidad"
 
@@ -1804,6 +1807,10 @@
 msgid "from"
 msgstr "De"
 
+#, python-format
+msgid "from %(date)s"
+msgstr ""
+
 msgid "from_entity"
 msgstr "De la entidad"
 
@@ -1828,6 +1835,9 @@
 msgid "generic plot"
 msgstr "Trazado de curbas estándares"
 
+msgid "generic relation to link one entity to another"
+msgstr ""
+
 msgid "go back to the index page"
 msgstr "Regresar a la página de inicio"
 
@@ -2094,6 +2104,11 @@
 msgstr "izquierda"
 
 msgid ""
+"link a permission to the entity. This permission should be used in the "
+"security definition of the entity's type to be useful."
+msgstr ""
+
+msgid ""
 "link a property to the user which want this property customization. Unless "
 "you're a site manager, this relation will be handled automatically."
 msgstr ""
@@ -2119,12 +2134,6 @@
 msgid "link a transition to one or more entity type"
 msgstr "liga una transición a una o mas tipos de entidad"
 
-msgid ""
-"link a transition to one or more rql expression allowing to go through this "
-"transition"
-msgstr ""
-"liga una transición a una o mas expresiones RQL permitiendo que funcione"
-
 msgid "link to each item in"
 msgstr "ligar hacia cada elemento en"
 
@@ -2140,6 +2149,9 @@
 msgid "login"
 msgstr "Clave de acesso"
 
+msgid "login or email"
+msgstr ""
+
 msgid "login_action"
 msgstr "Ingresa tus datos"
 
@@ -2269,8 +2281,8 @@
 msgid "no"
 msgstr "no"
 
-msgid "no associated epermissions"
-msgstr "permisos no asociados"
+msgid "no associated permissions"
+msgstr ""
 
 msgid "no possible transition"
 msgstr "transición no posible"
@@ -2457,6 +2469,9 @@
 msgid "remove this Bookmark"
 msgstr "Eliminar este Favorito"
 
+msgid "remove this CWAttribute"
+msgstr "Eliminar este atributo"
+
 msgid "remove this CWCache"
 msgstr "Eliminar esta cache de aplicación"
 
@@ -2469,15 +2484,9 @@
 msgid "remove this CWEType"
 msgstr "Eliminar este tipo de entidad"
 
-msgid "remove this CWAttribute"
-msgstr "Eliminar este atributo"
-
 msgid "remove this CWGroup"
 msgstr "Eliminar este grupo"
 
-msgid "remove this CWRelation"
-msgstr "Eliminar esta relación"
-
 msgid "remove this CWPermission"
 msgstr "Eliminar este permiso"
 
@@ -2487,6 +2496,9 @@
 msgid "remove this CWRType"
 msgstr "Eliminar esta definición de relación"
 
+msgid "remove this CWRelation"
+msgstr "Eliminar esta relación"
+
 msgid "remove this CWUser"
 msgstr "Eliminar este usuario"
 
@@ -2511,6 +2523,12 @@
 msgid "require_group_object"
 msgstr "Objeto_grupo_requerido"
 
+msgid "require_permission"
+msgstr ""
+
+msgid "require_permission_object"
+msgstr ""
+
 msgid "required attribute"
 msgstr "Atributo requerido"
 
@@ -2582,12 +2600,18 @@
 msgid "see them all"
 msgstr "Ver todos"
 
+msgid "see_also"
+msgstr ""
+
 msgid "select"
 msgstr "Seleccionar"
 
 msgid "select a"
 msgstr "seleccione un"
 
+msgid "select a key first"
+msgstr ""
+
 msgid "select a relation"
 msgstr "seleccione una relación"
 
@@ -2649,6 +2673,9 @@
 msgid "show meta-data"
 msgstr "mostrar meta-data"
 
+msgid "sioc"
+msgstr ""
+
 msgid "site configuration"
 msgstr "configuracion del sitio"
 
@@ -2775,6 +2802,10 @@
 msgid "to"
 msgstr "a"
 
+#, python-format
+msgid "to %(date)s"
+msgstr ""
+
 msgid "to associate with"
 msgstr "a asociar con"
 
@@ -2793,6 +2824,9 @@
 msgid "todo_by"
 msgstr "a hacer por"
 
+msgid "toggle check boxes"
+msgstr ""
+
 msgid "transition is not allowed"
 msgstr "transition no permitida"
 
@@ -3020,6 +3054,9 @@
 msgid "you have been logged out"
 msgstr "ha terminado la sesion"
 
+msgid "you should probably delete that property"
+msgstr ""
+
 #~ msgid "%s constraint failed"
 #~ msgstr "La contrainte %s n'est pas satisfaite"
 
@@ -3035,15 +3072,30 @@
 #~ msgid "Card_plural"
 #~ msgstr "Fichas"
 
+#~ msgid "Email body: "
+#~ msgstr "Contenido del correo electrónico : "
+
+#~ msgid "From: "
+#~ msgstr "De : "
+
 #~ msgid "Loading"
 #~ msgstr "chargement"
 
 #~ msgid "New Card"
 #~ msgstr "Agregar Ficha"
 
+#~ msgid "Problem occured"
+#~ msgstr "Ha ocurrido un error"
+
 #~ msgid "Problem occured while setting new value"
 #~ msgstr "Un problËme est survenu lors de la mise ‡ jour"
 
+#~ msgid "Recipients: "
+#~ msgstr "Destinatarios : "
+
+#~ msgid "Subject: "
+#~ msgstr "Objeto : "
+
 #~ msgid "This Card"
 #~ msgstr "Esta Ficha"
 
@@ -3069,6 +3121,12 @@
 #~ msgid "cancel edition"
 #~ msgstr "annuler l'Èdition"
 
+#~ msgid "components_rss_feed_url"
+#~ msgstr "RSS FEED URL"
+
+#~ msgid "components_rss_feed_url_description"
+#~ msgstr "El espacio para administrar RSS"
+
 #~ msgid "content"
 #~ msgstr "Contenido"
 
@@ -3082,9 +3140,6 @@
 #~ "langue par dÈfaut (regarder le rÈpertoire i18n de l'application pour voir "
 #~ "les langues disponibles)"
 
-#~ msgid "detach attached file"
-#~ msgstr "soltar el archivo existente"
-
 #~ msgid "filter"
 #~ msgstr "filtrer"
 
@@ -3103,6 +3158,12 @@
 #~ msgid "inlined view"
 #~ msgstr "Vista incluída (en línea)"
 
+#~ msgid ""
+#~ "link a transition to one or more rql expression allowing to go through "
+#~ "this transition"
+#~ msgstr ""
+#~ "liga una transición a una o mas expresiones RQL permitiendo que funcione"
+
 #~ msgid "linked"
 #~ msgstr "liÈ"
 
@@ -3114,6 +3175,9 @@
 #~ msgstr ""
 #~ "nombre maximum d'entitÈs liÈes ‡ afficher dans la vue de restriction"
 
+#~ msgid "no associated epermissions"
+#~ msgstr "permisos no asociados"
+
 #~ msgid "owned by"
 #~ msgstr "appartient ‡"
 
--- a/i18n/fr.po	Wed Jun 03 09:09:33 2009 +0200
+++ b/i18n/fr.po	Thu Apr 04 13:49:34 2019 +0200
@@ -123,10 +123,6 @@
 msgid "%s software version of the database"
 msgstr "version logicielle de la base pour %s"
 
-#, python-format
-msgid "%s_perm"
-msgstr ""
-
 msgid "**"
 msgstr "0..n 0..n"
 
@@ -205,30 +201,11 @@
 msgid "Bytes_plural"
 msgstr "Données binaires"
 
-msgid "Date"
-msgstr "Date"
-
-msgid "Date_plural"
-msgstr "Dates"
-
-msgid "Datetime"
-msgstr "Date et heure"
-
-msgid "Datetime_plural"
-msgstr "Date et heure"
-
-#, python-format
-msgid "Debug level set to %s"
-msgstr "Niveau de debug mis à %s"
-
-msgid "Decimal"
-msgstr "Nombre décimal"
-
-msgid "Decimal_plural"
-msgstr "Nombres décimaux"
-
-msgid "Do you want to delete the following element(s) ?"
-msgstr "Voulez vous supprimer le(s) élément(s) suivant(s)"
+msgid "CWAttribute"
+msgstr "Attribut"
+
+msgid "CWAttribute_plural"
+msgstr "Attributs"
 
 msgid "CWCache"
 msgstr "Cache applicatif"
@@ -254,24 +231,12 @@
 msgid "CWEType_plural"
 msgstr "Types d'entité"
 
-msgid "CWAttribute"
-msgstr "Attribut"
-
-msgid "CWAttribute_plural"
-msgstr "Attributs"
-
 msgid "CWGroup"
 msgstr "Groupe"
 
 msgid "CWGroup_plural"
 msgstr "Groupes"
 
-msgid "CWRelation"
-msgstr "Relation"
-
-msgid "CWRelation_plural"
-msgstr "Relations"
-
 msgid "CWPermission"
 msgstr "Permission"
 
@@ -290,14 +255,42 @@
 msgid "CWRType_plural"
 msgstr "Types de relation"
 
+msgid "CWRelation"
+msgstr "Relation"
+
+msgid "CWRelation_plural"
+msgstr "Relations"
+
 msgid "CWUser"
 msgstr "Utilisateur"
 
 msgid "CWUser_plural"
 msgstr "Utilisateurs"
 
-msgid "Email body: "
-msgstr "Contenu du courriel : "
+msgid "Date"
+msgstr "Date"
+
+msgid "Date_plural"
+msgstr "Dates"
+
+msgid "Datetime"
+msgstr "Date et heure"
+
+msgid "Datetime_plural"
+msgstr "Date et heure"
+
+#, python-format
+msgid "Debug level set to %s"
+msgstr "Niveau de debug mis à %s"
+
+msgid "Decimal"
+msgstr "Nombre décimal"
+
+msgid "Decimal_plural"
+msgstr "Nombres décimaux"
+
+msgid "Do you want to delete the following element(s) ?"
+msgstr "Voulez vous supprimer le(s) élément(s) suivant(s)"
 
 msgid "EmailAddress"
 msgstr "Adresse électronique"
@@ -317,8 +310,8 @@
 msgid "Float_plural"
 msgstr "Nombres flottants"
 
-msgid "From: "
-msgstr "De : "
+msgid "From:"
+msgstr "De :"
 
 msgid "Int"
 msgstr "Nombre entier"
@@ -335,6 +328,9 @@
 msgid "New Bookmark"
 msgstr "Nouveau signet"
 
+msgid "New CWAttribute"
+msgstr "Nouvelle définition de relation finale"
+
 msgid "New CWCache"
 msgstr "Nouveau cache applicatif"
 
@@ -347,15 +343,9 @@
 msgid "New CWEType"
 msgstr "Nouveau type d'entité"
 
-msgid "New CWAttribute"
-msgstr "Nouvelle définition de relation finale"
-
 msgid "New CWGroup"
 msgstr "Nouveau groupe"
 
-msgid "New CWRelation"
-msgstr "Nouvelle définition de relation non finale"
-
 msgid "New CWPermission"
 msgstr "Nouvelle permission"
 
@@ -365,6 +355,9 @@
 msgid "New CWRType"
 msgstr "Nouveau type de relation"
 
+msgid "New CWRelation"
+msgstr "Nouvelle définition de relation non finale"
+
 msgid "New CWUser"
 msgstr "Nouvel utilisateur"
 
@@ -401,17 +394,14 @@
 msgid "Please note that this is only a shallow copy"
 msgstr "Attention, cela n'effectue qu'une copie de surface"
 
-msgid "Problem occured"
-msgstr "Une erreur est survenue"
-
 msgid "RQLExpression"
 msgstr "Expression RQL"
 
 msgid "RQLExpression_plural"
 msgstr "Expressions RQL"
 
-msgid "Recipients: "
-msgstr "Destinataires : "
+msgid "Recipients:"
+msgstr "Destinataires :"
 
 msgid "Relations"
 msgstr "Relations"
@@ -444,8 +434,8 @@
 msgid "String_plural"
 msgstr "Chaînes de caractères"
 
-msgid "Subject: "
-msgstr "Sujet : "
+msgid "Subject:"
+msgstr "Sujet :"
 
 msgid "Submit bug report"
 msgstr "Soumettre un rapport de bug"
@@ -471,6 +461,9 @@
 msgid "This Bookmark"
 msgstr "Ce signet"
 
+msgid "This CWAttribute"
+msgstr "Cette définition de relation finale"
+
 msgid "This CWCache"
 msgstr "Ce cache applicatif"
 
@@ -483,15 +476,9 @@
 msgid "This CWEType"
 msgstr "Ce type d'entité"
 
-msgid "This CWAttribute"
-msgstr "Cette définition de relation finale"
-
 msgid "This CWGroup"
 msgstr "Ce groupe"
 
-msgid "This CWRelation"
-msgstr "Cette définition de relation non finale"
-
 msgid "This CWPermission"
 msgstr "Cette permission"
 
@@ -501,6 +488,9 @@
 msgid "This CWRType"
 msgstr "Ce type de relation"
 
+msgid "This CWRelation"
+msgstr "Cette définition de relation non finale"
+
 msgid "This CWUser"
 msgstr "Cet utilisateur"
 
@@ -690,6 +680,12 @@
 msgid "actions_manage_description"
 msgstr ""
 
+msgid "actions_managepermission"
+msgstr ""
+
+msgid "actions_managepermission_description"
+msgstr ""
+
 msgid "actions_muledit"
 msgstr "édition multiple"
 
@@ -762,6 +758,12 @@
 msgid "add Bookmark bookmarked_by CWUser object"
 msgstr "signet"
 
+msgid "add CWAttribute constrained_by CWConstraint subject"
+msgstr "contrainte"
+
+msgid "add CWAttribute relation_type CWRType object"
+msgstr "définition d'attribut"
+
 msgid "add CWEType add_permission RQLExpression subject"
 msgstr "définir une expression RQL d'ajout"
 
@@ -774,18 +776,6 @@
 msgid "add CWEType update_permission RQLExpression subject"
 msgstr "définir une expression RQL de mise à jour"
 
-msgid "add CWAttribute constrained_by CWConstraint subject"
-msgstr "contrainte"
-
-msgid "add CWAttribute relation_type CWRType object"
-msgstr "définition d'attribut"
-
-msgid "add CWRelation constrained_by CWConstraint subject"
-msgstr "contrainte"
-
-msgid "add CWRelation relation_type CWRType object"
-msgstr "définition de relation"
-
 msgid "add CWProperty for_user CWUser object"
 msgstr "propriété"
 
@@ -798,6 +788,12 @@
 msgid "add CWRType read_permission RQLExpression subject"
 msgstr "expression RQL de lecture"
 
+msgid "add CWRelation constrained_by CWConstraint subject"
+msgstr "contrainte"
+
+msgid "add CWRelation relation_type CWRType object"
+msgstr "définition de relation"
+
 msgid "add CWUser in_group CWGroup object"
 msgstr "utilisateur"
 
@@ -828,6 +824,9 @@
 msgid "add a Bookmark"
 msgstr "ajouter un signet"
 
+msgid "add a CWAttribute"
+msgstr "ajouter un type de relation"
+
 msgid "add a CWCache"
 msgstr "ajouter un cache applicatif"
 
@@ -840,15 +839,9 @@
 msgid "add a CWEType"
 msgstr "ajouter un type d'entité"
 
-msgid "add a CWAttribute"
-msgstr "ajouter un type de relation"
-
 msgid "add a CWGroup"
 msgstr "ajouter un groupe d'utilisateurs"
 
-msgid "add a CWRelation"
-msgstr "ajouter une relation"
-
 msgid "add a CWPermission"
 msgstr "ajouter une permission"
 
@@ -858,6 +851,9 @@
 msgid "add a CWRType"
 msgstr "ajouter un type de relation"
 
+msgid "add a CWRelation"
+msgstr "ajouter une relation"
+
 msgid "add a CWUser"
 msgstr "ajouter un utilisateur"
 
@@ -1146,9 +1142,6 @@
 msgid "click on the box to cancel the deletion"
 msgstr "cliquer dans la zone d'édition pour annuler la suppression"
 
-msgid "close all"
-msgstr "tout fermer"
-
 msgid "comment"
 msgstr "commentaire"
 
@@ -1221,12 +1214,6 @@
 msgid "components_rqlinput_description"
 msgstr "la barre de requête rql, dans l'en-tête de page"
 
-msgid "components_rss_feed_url"
-msgstr "syndication rss"
-
-msgid "components_rss_feed_url_description"
-msgstr ""
-
 msgid "composite"
 msgstr "composite"
 
@@ -1383,28 +1370,31 @@
 msgid "creating Bookmark (Bookmark bookmarked_by CWUser %(linkto)s)"
 msgstr "création d'un signet pour %(linkto)s"
 
-msgid "creating CWConstraint (CWAttribute %(linkto)s constrained_by CWConstraint)"
-msgstr "création d'une contrainte pour l'attribut %(linkto)s"
-
-msgid "creating CWConstraint (CWRelation %(linkto)s constrained_by CWConstraint)"
-msgstr "création d'une contrainte pour la relation %(linkto)s"
-
 msgid "creating CWAttribute (CWAttribute relation_type CWRType %(linkto)s)"
 msgstr "création d'un attribut %(linkto)s"
 
+msgid ""
+"creating CWConstraint (CWAttribute %(linkto)s constrained_by CWConstraint)"
+msgstr "création d'une contrainte pour l'attribut %(linkto)s"
+
+msgid ""
+"creating CWConstraint (CWRelation %(linkto)s constrained_by CWConstraint)"
+msgstr "création d'une contrainte pour la relation %(linkto)s"
+
+msgid "creating CWProperty (CWProperty for_user CWUser %(linkto)s)"
+msgstr "création d'une propriété pour l'utilisateur %(linkto)s"
+
 msgid "creating CWRelation (CWRelation relation_type CWRType %(linkto)s)"
 msgstr "création relation %(linkto)s"
 
-msgid "creating CWProperty (CWProperty for_user CWUser %(linkto)s)"
-msgstr "création d'une propriété pour l'utilisateur %(linkto)s"
-
 msgid "creating CWUser (CWUser in_group CWGroup %(linkto)s)"
 msgstr "création d'un utilisateur à rajouter au groupe %(linkto)s"
 
 msgid "creating EmailAddress (CWUser %(linkto)s use_email EmailAddress)"
 msgstr "création d'une adresse électronique pour l'utilisateur %(linkto)s"
 
-msgid "creating RQLExpression (CWEType %(linkto)s add_permission RQLExpression)"
+msgid ""
+"creating RQLExpression (CWEType %(linkto)s add_permission RQLExpression)"
 msgstr "création d'une expression RQL pour la permission d'ajout de %(linkto)s"
 
 msgid ""
@@ -1421,7 +1411,8 @@
 msgstr ""
 "création d'une expression RQL pour la permission de mise à jour de %(linkto)s"
 
-msgid "creating RQLExpression (CWRType %(linkto)s add_permission RQLExpression)"
+msgid ""
+"creating RQLExpression (CWRType %(linkto)s add_permission RQLExpression)"
 msgstr ""
 "création d'une expression RQL pour la permission d'ajout des relations %"
 "(linkto)s"
@@ -1608,6 +1599,9 @@
 msgid "destination_state_object"
 msgstr "destination de"
 
+msgid "detach attached file"
+msgstr "détacher le fichier existant"
+
 #, python-format
 msgid "detach attached file %s"
 msgstr "détacher le fichier existant %s"
@@ -1647,7 +1641,7 @@
 msgstr "icône de téléchargement"
 
 msgid "download schema as owl"
-msgstr ""
+msgstr "télécharger le schéma OWL"
 
 msgid "edit bookmarks"
 msgstr "éditer les signets"
@@ -1688,9 +1682,18 @@
 msgid "entities deleted"
 msgstr "entités supprimées"
 
+msgid "entity copied"
+msgstr "entité copiée"
+
+msgid "entity created"
+msgstr "entité créée"
+
 msgid "entity deleted"
 msgstr "entité supprimée"
 
+msgid "entity edited"
+msgstr "entité éditée"
+
 msgid "entity type"
 msgstr "type d'entité"
 
@@ -1801,6 +1804,10 @@
 msgid "from"
 msgstr "de"
 
+#, python-format
+msgid "from %(date)s"
+msgstr "du %(date)s"
+
 msgid "from_entity"
 msgstr "de l'entité"
 
@@ -1825,6 +1832,9 @@
 msgid "generic plot"
 msgstr "tracé de courbes standard"
 
+msgid "generic relation to link one entity to another"
+msgstr "relation générique pour lier une entité à une autre"
+
 msgid "go back to the index page"
 msgstr "retourner sur la page d'accueil"
 
@@ -2093,6 +2103,13 @@
 msgstr "gauche"
 
 msgid ""
+"link a permission to the entity. This permission should be used in the "
+"security definition of the entity's type to be useful."
+msgstr ""
+"lie une permission à une entité. Cette permission doit généralement être utilisée "
+"dans la définition de sécurité du type d'entité pour être utile."
+
+msgid ""
 "link a property to the user which want this property customization. Unless "
 "you're a site manager, this relation will be handled automatically."
 msgstr ""
@@ -2118,11 +2135,6 @@
 msgid "link a transition to one or more entity type"
 msgstr "lie une transition à un ou plusieurs types d'entités"
 
-msgid ""
-"link a transition to one or more rql expression allowing to go through this "
-"transition"
-msgstr ""
-
 msgid "link to each item in"
 msgstr "lier vers chaque élément dans"
 
@@ -2138,6 +2150,9 @@
 msgid "login"
 msgstr "identifiant"
 
+msgid "login or email"
+msgstr "identifiant ou email"
+
 msgid "login_action"
 msgstr "identifiez vous"
 
@@ -2267,8 +2282,8 @@
 msgid "no"
 msgstr "non"
 
-msgid "no associated epermissions"
-msgstr "aucune permission spécifique n'est définie"
+msgid "no associated permissions"
+msgstr "aucune permission associée"
 
 msgid "no possible transition"
 msgstr "aucune transition possible"
@@ -2335,10 +2350,10 @@
 msgstr "ordre"
 
 msgid "owl"
-msgstr ""
+msgstr "owl"
 
 msgid "owlabox"
-msgstr ""
+msgstr "owl ABox"
 
 msgid "owned_by"
 msgstr "appartient à"
@@ -2446,7 +2461,7 @@
 msgstr "définition"
 
 msgid "relations"
-msgstr ""
+msgstr "relations"
 
 msgid "relations deleted"
 msgstr "relations supprimées"
@@ -2457,6 +2472,9 @@
 msgid "remove this Bookmark"
 msgstr "supprimer ce signet"
 
+msgid "remove this CWAttribute"
+msgstr "supprimer cet attribut"
+
 msgid "remove this CWCache"
 msgstr "supprimer ce cache applicatif"
 
@@ -2469,15 +2487,9 @@
 msgid "remove this CWEType"
 msgstr "supprimer ce type d'entité"
 
-msgid "remove this CWAttribute"
-msgstr "supprimer cet attribut"
-
 msgid "remove this CWGroup"
 msgstr "supprimer ce groupe"
 
-msgid "remove this CWRelation"
-msgstr "supprimer cette relation"
-
 msgid "remove this CWPermission"
 msgstr "supprimer cette permission"
 
@@ -2487,6 +2499,9 @@
 msgid "remove this CWRType"
 msgstr "supprimer cette définition de relation"
 
+msgid "remove this CWRelation"
+msgstr "supprimer cette relation"
+
 msgid "remove this CWUser"
 msgstr "supprimer cet utilisateur"
 
@@ -2511,6 +2526,12 @@
 msgid "require_group_object"
 msgstr "à les droits"
 
+msgid "require_permission"
+msgstr "require permission"
+
+msgid "require_permission_object"
+msgstr "permission of"
+
 msgid "required attribute"
 msgstr "attribut requis"
 
@@ -2587,12 +2608,18 @@
 msgid "see them all"
 msgstr "les voir toutes"
 
+msgid "see_also"
+msgstr "see also"
+
 msgid "select"
 msgstr "sélectionner"
 
 msgid "select a"
 msgstr "sélectionner un"
 
+msgid "select a key first"
+msgstr "sélectionnez d'abord une clé"
+
 msgid "select a relation"
 msgstr "sélectionner une relation"
 
@@ -2654,6 +2681,9 @@
 msgid "show meta-data"
 msgstr "afficher le schéma complet"
 
+msgid "sioc"
+msgstr "sioc"
+
 msgid "site configuration"
 msgstr "configuration du site"
 
@@ -2780,6 +2810,10 @@
 msgid "to"
 msgstr "à"
 
+#, python-format
+msgid "to %(date)s"
+msgstr "au %(date)s"
+
 msgid "to associate with"
 msgstr "pour associer à"
 
@@ -2798,6 +2832,9 @@
 msgid "todo_by"
 msgstr "à faire par"
 
+msgid "toggle check boxes"
+msgstr "inverser les cases à cocher"
+
 msgid "transition is not allowed"
 msgstr "transition non permise"
 
@@ -2865,7 +2902,7 @@
 msgstr "clé de propriété inconnue"
 
 msgid "up"
-msgstr ""
+msgstr "haut"
 
 msgid "upassword"
 msgstr "mot de passe"
@@ -3023,6 +3060,9 @@
 msgid "you have been logged out"
 msgstr "vous avez été déconnecté"
 
+msgid "you should probably delete that property"
+msgstr "vous devriez probablement supprimer cette propriété"
+
 #~ msgid "%s constraint failed"
 #~ msgstr "La contrainte %s n'est pas satisfaite"
 
@@ -3038,15 +3078,30 @@
 #~ msgid "Card_plural"
 #~ msgstr "Fiches"
 
+#~ msgid "Email body: "
+#~ msgstr "Contenu du courriel : "
+
+#~ msgid "From: "
+#~ msgstr "De : "
+
 #~ msgid "Loading"
 #~ msgstr "chargement"
 
 #~ msgid "New Card"
 #~ msgstr "Nouvelle fiche"
 
+#~ msgid "Problem occured"
+#~ msgstr "Une erreur est survenue"
+
 #~ msgid "Problem occured while setting new value"
 #~ msgstr "Un problème est survenu lors de la mise à jour"
 
+#~ msgid "Recipients: "
+#~ msgstr "Destinataires : "
+
+#~ msgid "Subject: "
+#~ msgstr "Sujet : "
+
 #~ msgid "This Card"
 #~ msgstr "Cette fiche"
 
@@ -3075,6 +3130,12 @@
 #~ msgid "cancel edition"
 #~ msgstr "annuler l'édition"
 
+#~ msgid "close all"
+#~ msgstr "tout fermer"
+
+#~ msgid "components_rss_feed_url"
+#~ msgstr "syndication rss"
+
 #~ msgid "content"
 #~ msgstr "contenu"
 
@@ -3088,9 +3149,6 @@
 #~ "langue par défaut (regarder le répertoire i18n de l'application pour voir "
 #~ "les langues disponibles)"
 
-#~ msgid "detach attached file"
-#~ msgstr "détacher le fichier existant"
-
 #~ msgid "filter"
 #~ msgstr "filtrer"
 
@@ -3120,6 +3178,9 @@
 #~ msgstr ""
 #~ "nombre maximum d'entités liées à afficher dans la vue de restriction"
 
+#~ msgid "no associated epermissions"
+#~ msgstr "aucune permission spécifique n'est définie"
+
 #~ msgid "owned by"
 #~ msgstr "appartient à"
 
--- a/interfaces.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/interfaces.py	Thu Apr 04 13:49:34 2019 +0200
@@ -267,6 +267,3 @@
 
     def isioc_items(self):
         """return contained items"""
-
-
-
--- a/misc/cwdesklets/rqlsensor/__init__.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/misc/cwdesklets/rqlsensor/__init__.py	Thu Apr 04 13:49:34 2019 +0200
@@ -52,7 +52,7 @@
             output.set('resultbg[%s]' % index, 'black')
             webbrowser.open(self._urls[index])
         self._send_output(output)
-        
+
     def __get_connection(self):
         try:
             return self._v_cnx
@@ -73,8 +73,8 @@
             del self._v_cnx
             raise
         self._urls = []
-        output.set('layout', 'vertical, 14')        
-        output.set('length', rset.rowcount)        
+        output.set('layout', 'vertical, 14')
+        output.set('length', rset.rowcount)
         i = 0
         for line in rset:
             output.set('result[%s]' % i, ', '.join([str(v) for v in line[1:]]))
@@ -84,7 +84,7 @@
             except:
                 self._urls.append('')
             i += 1
-    
+
     def __update(self):
         output = self._new_output()
         try:
@@ -92,12 +92,12 @@
         except Exception, ex:
             import traceback
             traceback.print_exc()
-            output.set('layout', 'vertical, 10')        
-            output.set('length', 1)        
+            output.set('layout', 'vertical, 10')
+            output.set('length', 1)
             output.set('result[0]', str(ex))
         self._send_output(output)
         self._add_timer(int(self._get_config('delay'))*1000, self.__update)
 
-        
+
 def new_sensor(args):
     return RQLSensor(*args)
--- a/misc/cwfs/cwfs.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/misc/cwfs/cwfs.py	Thu Apr 04 13:49:34 2019 +0200
@@ -24,7 +24,7 @@
                                ] ),
                  })
 
-    
+
 
 DATA = { 'societe': [ ('CETIAD', 'Dijon'),
                       ('EDF_R&D', 'Clamart'),
@@ -58,7 +58,7 @@
         self._attr = None
         self._rel = None
         self._restrictions = []
-        
+
     def parse(self) :
         self._entity = self._components.next()
         try:
@@ -97,7 +97,7 @@
             for nom, entity in self.schema.get_relations(self._entity) :
                 yield nom+'/'
                 yield entity+'/'
-    
+
 def ls(path) :
     p = PathParser(SCHEMA,path)
     p.parse()
@@ -113,7 +113,7 @@
         self._e_type = None
         self._restrictions = []
         self._alphabet = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
-        
+
     def parse(self):
         self._var = self._alphabet.pop(0)
         self._e_type = self._components.next()
@@ -124,7 +124,7 @@
         except StopIteration :
             pass
         return 'Any %s WHERE %s' % (self._var, ', '.join(self._restrictions))
-    
+
     def process_entity(self) :
         _next = self._components.next()
         if _next in self.schema.get_attrs(self._e_type) :
@@ -147,9 +147,9 @@
                 self._restrictions.append('%s is %s' % (r_var, _next.capitalize()))
             except StopIteration:
                 raise
-        self.process_entity()            
+        self.process_entity()
 
-        
+
 def to_rql(path) :
     p = SytPathParser(SCHEMA,path)
     return p.parse()
--- a/misc/migration/2.42.1_Any.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/misc/migration/2.42.1_Any.py	Thu Apr 04 13:49:34 2019 +0200
@@ -15,4 +15,4 @@
 if 'inline_view' in schema:
     # inline_view attribute should have been deleted for a while now....
     drop_attribute('CWRelation', 'inline_view')
-    
+
--- a/rset.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/rset.py	Thu Apr 04 13:49:34 2019 +0200
@@ -11,7 +11,7 @@
 from rql import nodes
 
 from cubicweb import NotAnEntity
-    
+
 
 class ResultSet(object):
     """a result set wrap a RQL query result. This object implements a partial
@@ -53,12 +53,12 @@
         self.req = None
         # actions cache
         self._rsetactions = None
-        
+
     def __str__(self):
         if not self.rows:
             return '<empty resultset %s>' % self.rql
         return '<resultset %s (%s rows)>' % (self.rql, len(self.rows))
-    
+
     def __repr__(self):
         if not self.rows:
             return '<empty resultset for %r>' % self.rql
@@ -85,22 +85,22 @@
             actions = self.vreg.possible_vobjects('actions', self.req, self, **kwargs)
             self._rsetactions[key] = actions
             return actions
-    
+
     def __len__(self):
         """returns the result set's size"""
         return self.rowcount
 
     def __nonzero__(self):
         return self.rowcount
-    
+
     def __getitem__(self, i):
         """returns the ith element of the result set"""
         return self.rows[i] #ResultSetRow(self.rows[i])
-    
+
     def __getslice__(self, i, j):
         """returns slice [i:j] of the result set"""
         return self.rows[i:j]
-        
+
     def __iter__(self):
         """Returns an iterator over rows"""
         return iter(self.rows)
@@ -126,7 +126,7 @@
         :param transformcb:
           a callable which should take a row and its type description as
           parameters, and return the transformed row and type description.
-          
+
 
         :type col: int
         :param col: the column index
@@ -199,7 +199,7 @@
 
     def split_rset(self, keyfunc=None, col=0, return_dict=False):
         """Splits the result set in multiple result set according to a given key
-    
+
         :type keyfunc: callable(entity or FinalType)
         :param keyfunc:
           a callable which should take a value of the rset in argument and
@@ -256,7 +256,7 @@
 
         :type offset: int
         :param offset: the offset index
-        
+
         :type inplace: bool
         :param inplace:
           if true, the result set is modified in place, else a new result set
@@ -289,7 +289,7 @@
                 copy_cache(rset, 'get_entity', self)
         rset.limited = (limit, offset)
         return rset
-    
+
     def printable_rql(self, encoded=False):
         """return the result set's origin rql as a string, with arguments
         substitued
@@ -301,11 +301,11 @@
             if isinstance(rqlstr, unicode):
                 return rqlstr
             return unicode(rqlstr, encoding)
-        else: 
+        else:
             if isinstance(rqlstr, unicode):
                 return rqlstr.encode(encoding)
             return rqlstr
-       
+
     # client helper methods ###################################################
 
     def entities(self, col=0):
@@ -320,7 +320,7 @@
     def get_entity(self, row, col=None):
         """special method for query retreiving a single entity, returns a
         partially initialized Entity instance.
-        
+
         WARNING: due to the cache wrapping this function, you should NEVER
                  give row as a named parameter (i.e. rset.get_entity(req, 0)
                  is OK but rset.get_entity(row=0, req=req) isn't
@@ -351,7 +351,7 @@
 
         partially means that only attributes selected in the RQL
         query will be directly assigned to the entity.
-        
+
         :type row,col: int, int
         :param row,col:
           row and col numbers localizing the entity among the result's table
@@ -427,7 +427,7 @@
 
     @cached
     def syntax_tree(self):
-        """get the syntax tree for the source query. 
+        """get the syntax tree for the source query.
 
         :rtype: rql.stmts.Statement
         :return: the RQL syntax tree of the originating query
@@ -441,12 +441,12 @@
         else:
             rqlst = self.vreg.parse(self.req, self.rql, self.args)
         return rqlst
-        
+
     @cached
     def column_types(self, col):
         """return the list of different types in the column with the given col
         index default to 0 (ie the first column)
-        
+
         :type col: int
         :param col: the index of the desired column
 
@@ -483,7 +483,7 @@
         etype = self.description[row][col]
         if self.vreg.schema.eschema(etype).is_final():
             # final type, find a better one to locate the correct subquery
-            # (ambiguous if possible) 
+            # (ambiguous if possible)
             for i in xrange(len(rqlst.children[0].selection)):
                 if i == col:
                     continue
@@ -522,7 +522,7 @@
                 __, rhs = rel.get_variable_parts()
                 return rhs.eval(self.args)
         return None
-        
+
 
 def attr_desc_iterator(rqlst, index=0):
     """return an iterator on a list of 2-uple (index, attr_relation)
--- a/schemas/Bookmark.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/schemas/Bookmark.py	Thu Apr 04 13:49:34 2019 +0200
@@ -4,10 +4,10 @@
     title = String(required=True, maxsize=128)
     path  = String(maxsize=512, required=True,
                    description=_("relative url of the bookmarked page"))
-    
+
     bookmarked_by = SubjectRelation('CWUser',
                                     description=_("users using this bookmark"))
-    
+
 
 class bookmarked_by(MetaUserRelationType):
     permissions = {'read':   ('managers', 'users', 'guests',),
--- a/schemaviewer.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/schemaviewer.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,7 +1,7 @@
 """an helper class to display CubicWeb schema using ureports
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
--- a/server/__init__.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/__init__.py	Thu Apr 04 13:49:34 2019 +0200
@@ -4,7 +4,7 @@
 This module contains functions to initialize a new repository.
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
--- a/server/checkintegrity.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/checkintegrity.py	Thu Apr 04 13:49:34 2019 +0200
@@ -61,7 +61,7 @@
                     yield container
     else:
         yield eschema
-    
+
 def reindex_entities(schema, session):
     """reindex all entities in the repository"""
     # deactivate modification_date hook since we don't want them
@@ -103,7 +103,7 @@
     # restore Entity.check
     Entity.check = _check
 
-    
+
 def check_schema(schema, session, eids, fix=1):
     """check serialized schema"""
     print 'Checking serialized schema'
@@ -122,7 +122,7 @@
                 count, cstrname, en, rn)
 
 
-    
+
 def check_text_index(schema, session, eids, fix=1):
     """check all entities registered in the text index"""
     print 'Checking text index'
@@ -172,8 +172,8 @@
                     print >> sys.stderr, ' [FIXED]'
                 else:
                     print >> sys.stderr
-                
-            
+
+
 def bad_related_msg(rtype, target, eid, fix):
     msg = '  A relation %s with %s eid %s exists but no such entity in sources'
     print >> sys.stderr, msg % (rtype, target, eid),
@@ -181,8 +181,8 @@
         print >> sys.stderr, ' [FIXED]'
     else:
         print >> sys.stderr
-    
-    
+
+
 def check_relations(schema, session, eids, fix=1):
     """check all relations registered in the repo system table"""
     print 'Checking relations'
--- a/server/hookhelper.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/hookhelper.py	Thu Apr 04 13:49:34 2019 +0200
@@ -42,7 +42,7 @@
     for session in repo._sessions.values():
         if ueid == session.user.eid:
             yield session
-        
+
 
 # mail related ################################################################
 
@@ -58,17 +58,17 @@
         else:
             assert recipients is None
             self.to_send = []
-        super(SendMailOp, self).__init__(session, **kwargs) 
-       
+        super(SendMailOp, self).__init__(session, **kwargs)
+
     def register(self, session):
         previous = super(SendMailOp, self).register(session)
         if previous:
             self.to_send = previous.to_send + self.to_send
-        
+
     def commit_event(self):
         self.repo.threaded_task(self.sendmails)
 
-    def sendmails(self):        
+    def sendmails(self):
         server, port = self.config['smtp-host'], self.config['smtp-port']
         SMTP_LOCK.acquire()
         try:
@@ -89,7 +89,7 @@
             smtp.close()
         finally:
             SMTP_LOCK.release()
-            
+
 
 # state related ###############################################################
 
--- a/server/hooks.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/hooks.py	Thu Apr 04 13:49:34 2019 +0200
@@ -18,13 +18,13 @@
 
 def relation_deleted(session, eidfrom, rtype, eidto):
     session.add_query_data('pendingrelations', (eidfrom, rtype, eidto))
-    
+
 
 # base meta-data handling #####################################################
 
 def setctime_before_add_entity(session, entity):
     """before create a new entity -> set creation and modification date
- 
+
     this is a conveniency hook, you shouldn't have to disable it
     """
     if not 'creation_date' in entity:
@@ -36,9 +36,9 @@
     """update an entity -> set modification date"""
     if not 'modification_date' in entity:
         entity['modification_date'] = datetime.now()
-        
+
 class SetCreatorOp(PreCommitOperation):
-        
+
     def precommit_event(self):
         if self.eid in self.session.query_data('pendingeids', ()):
             # entity have been created and deleted in the same transaction
@@ -46,7 +46,7 @@
         ueid = self.session.user.eid
         execute = self.session.unsafe_execute
         if not execute('Any X WHERE X created_by U, X eid %(x)s',
-                       {'x': self.eid}, 'x'): 
+                       {'x': self.eid}, 'x'):
             execute('SET X created_by U WHERE X eid %(x)s, U eid %(u)s',
                     {'x': self.eid, 'u': ueid}, 'x')
 
@@ -93,15 +93,15 @@
     if session.repo.schema.rschema(rtype).fulltext_container:
         FTIndexEntityOp(session, entity=session.entity(eidto))
         FTIndexEntityOp(session, entity=session.entity(eidfrom))
-    
+
 class SyncOwnersOp(PreCommitOperation):
-        
+
     def precommit_event(self):
         self.session.unsafe_execute('SET X owned_by U WHERE C owned_by U, C eid %(c)s,'
                                     'NOT EXISTS(X owned_by U, X eid %(x)s)',
                                     {'c': self.compositeeid, 'x': self.composedeid},
                                     ('c', 'x'))
-        
+
 def sync_owner_after_add_composite_relation(session, eidfrom, rtype, eidto):
     """when adding composite relation, the composed should have the same owners
     has the composite
@@ -114,7 +114,7 @@
         SyncOwnersOp(session, compositeeid=eidfrom, composedeid=eidto)
     elif composite == 'object':
         SyncOwnersOp(session, compositeeid=eidto, composedeid=eidfrom)
-    
+
 def _register_metadata_hooks(hm):
     """register meta-data related hooks on the hooks manager"""
     hm.register_hook(setctime_before_add_entity, 'before_add_entity', '')
@@ -127,14 +127,14 @@
         hm.register_hook(setis_after_add_entity, 'after_add_entity', '')
     if 'CWUser' in hm.schema:
         hm.register_hook(setowner_after_add_user, 'after_add_entity', 'CWUser')
-            
+
 # core hooks ##################################################################
-    
+
 class DelayedDeleteOp(PreCommitOperation):
     """delete the object of composite relation except if the relation
     has actually been redirected to another composite
     """
-        
+
     def precommit_event(self):
         session = self.session
         if not self.eid in session.query_data('pendingeids', ()):
@@ -142,7 +142,7 @@
             session.unsafe_execute('DELETE %s X WHERE X eid %%(x)s, NOT %s'
                                    % (etype, self.relation),
                                    {'x': self.eid}, 'x')
-    
+
 def handle_composite_before_del_relation(session, eidfrom, rtype, eidto):
     """delete the object of composite relation"""
     composite = rproperty(session, rtype, eidfrom, eidto, 'composite')
@@ -157,7 +157,7 @@
 
 
 # schema validation hooks #####################################################
-        
+
 class CheckConstraintsOperation(LateOperation):
     """check a new relation satisfy its constraints
     """
@@ -176,10 +176,10 @@
             except NotImplementedError:
                 self.critical('can\'t check constraint %s, not supported',
                               constraint)
-    
+
     def commit_event(self):
         pass
-    
+
 def cstrcheck_after_add_relation(session, eidfrom, rtype, eidto):
     """check the relation satisfy its constraints
 
@@ -213,7 +213,7 @@
     case the relation is being replaced
     """
     eid, rtype = None, None
-    
+
     def precommit_event(self):
         # recheck pending eids
         if self.eid in self.session.query_data('pendingeids', ()):
@@ -224,18 +224,18 @@
             raise ValidationError(self.eid, {self.rtype: msg % {'rtype': self.rtype,
                                                                 'etype': etype,
                                                                 'eid': self.eid}})
-    
+
     def commit_event(self):
         pass
-        
+
     def _rql(self):
         raise NotImplementedError()
-    
+
 class CheckSRelationOp(CheckRequiredRelationOperation):
     """check required subject relation"""
     def _rql(self):
         return 'Any O WHERE S eid %%(x)s, S %s O' % self.rtype, {'x': self.eid}, 'x'
-    
+
 class CheckORelationOp(CheckRequiredRelationOperation):
     """check required object relation"""
     def _rql(self):
@@ -248,7 +248,7 @@
             break
     else:
         opcls(session, rtype=rtype, eid=eid)
-    
+
 def cardinalitycheck_after_add_entity(session, entity):
     """check cardinalities are satisfied"""
     eid = entity.eid
@@ -283,7 +283,7 @@
 def _register_core_hooks(hm):
     hm.register_hook(handle_composite_before_del_relation, 'before_delete_relation', '')
     hm.register_hook(before_del_group, 'before_delete_entity', 'CWGroup')
-    
+
     #hm.register_hook(cstrcheck_before_update_entity, 'before_update_entity', '')
     hm.register_hook(cardinalitycheck_after_add_entity, 'after_add_entity', '')
     hm.register_hook(cardinalitycheck_before_del_relation, 'before_delete_relation', '')
@@ -293,13 +293,13 @@
 
 
 # user/groups synchronisation #################################################
-            
+
 class GroupOperation(Operation):
     """base class for group operation"""
     geid = None
     def __init__(self, session, *args, **kwargs):
         """override to get the group name before actual groups manipulation:
-        
+
         we may temporarily loose right access during a commit event, so
         no query should be emitted while comitting
         """
@@ -318,13 +318,13 @@
         except KeyError:
             self.error('user %s not in group %s',  self.cnxuser, self.group)
             return
-    
+
 def after_del_in_group(session, fromeid, rtype, toeid):
     """modify user permission, need to update users"""
     for session_ in get_user_sessions(session.repo, fromeid):
         DeleteGroupOp(session, cnxuser=session_.user, geid=toeid)
 
-        
+
 class AddGroupOp(GroupOperation):
     """synchronize user when a in_group relation has been added"""
     def commit_event(self):
@@ -347,7 +347,7 @@
     def __init__(self, session, cnxid):
         self.cnxid = cnxid
         Operation.__init__(self, session)
-        
+
     def commit_event(self):
         """the observed connections pool has been commited"""
         try:
@@ -359,7 +359,7 @@
     """modify user permission, need to update users"""
     for session_ in get_user_sessions(session.repo, eid):
         DelUserOp(session, session_.id)
-    
+
 def _register_usergroup_hooks(hm):
     """register user/group related hooks on the hooks manager"""
     hm.register_hook(after_del_user, 'after_delete_entity', 'CWUser')
@@ -430,7 +430,7 @@
 
 def set_initial_state_after_add(session, entity):
     SetInitialStateOp(session, entity=entity)
-    
+
 def _register_wf_hooks(hm):
     """register workflow related hooks on the hooks manager"""
     if 'in_state' in hm.schema:
@@ -447,7 +447,7 @@
 
 class DelCWPropertyOp(Operation):
     """a user's custom properties has been deleted"""
-    
+
     def commit_event(self):
         """the observed connections pool has been commited"""
         try:
@@ -457,14 +457,14 @@
 
 class ChangeCWPropertyOp(Operation):
     """a user's custom properties has been added/changed"""
-        
+
     def commit_event(self):
         """the observed connections pool has been commited"""
         self.epropdict[self.key] = self.value
 
 class AddCWPropertyOp(Operation):
     """a user's custom properties has been added/changed"""
-        
+
     def commit_event(self):
         """the observed connections pool has been commited"""
         eprop = self.eprop
@@ -485,7 +485,7 @@
                                {'x': entity.eid, 'u': session.user.eid}, 'x')
     else:
         AddCWPropertyOp(session, eprop=entity)
-        
+
 def after_update_eproperty(session, entity):
     key, value = entity.pkey, entity.value
     try:
@@ -502,7 +502,7 @@
         # site wide properties
         ChangeCWPropertyOp(session, epropdict=session.vreg.eprop_values,
                           key=key, value=value)
-        
+
 def before_del_eproperty(session, eid):
     for eidfrom, rtype, eidto in session.query_data('pendingrelations', ()):
         if rtype == 'for_user' and eidfrom == eid:
@@ -524,7 +524,7 @@
     for session_ in get_user_sessions(session.repo, toeid):
         ChangeCWPropertyOp(session, epropdict=session_.user.properties,
                           key=key, value=value)
-        
+
 def before_del_for_user(session, fromeid, rtype, toeid):
     key = session.execute('Any K WHERE P eid %(x)s, P pkey K',
                           {'x': fromeid}, 'x')[0][0]
--- a/server/hooksmanager.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/hooksmanager.py	Thu Apr 04 13:49:34 2019 +0200
@@ -28,7 +28,7 @@
 """
 __docformat__ = "restructuredtext en"
 
-ENTITIES_HOOKS = ('before_add_entity',    'after_add_entity', 
+ENTITIES_HOOKS = ('before_add_entity',    'after_add_entity',
                   'before_update_entity', 'after_update_entity',
                   'before_delete_entity', 'after_delete_entity')
 RELATIONS_HOOKS = ('before_add_relation',   'after_add_relation' ,
@@ -42,7 +42,7 @@
     """handle hooks registration and calls
     """
     verification_hooks_activated = True
-    
+
     def __init__(self, schema):
         self.set_schema(schema)
 
@@ -50,20 +50,20 @@
         self._hooks = {}
         self.schema = schema
         self._init_hooks(schema)
-        
+
     def register_hooks(self, hooks):
         """register a dictionary of hooks :
-        
+
              {'event': {'entity or relation type': [callbacks list]}}
         """
         for event, subevents in hooks.items():
             for subevent, callbacks in subevents.items():
                 for callback in callbacks:
                     self.register_hook(callback, event, subevent)
-                    
+
     def register_hook(self, function, event, etype=''):
         """register a function to call when <event> occurs
-        
+
          <etype> is an entity/relation type or an empty string.
          If etype is the empty string, the function will be called at each
          event, else the function will be called only when event occurs on an
@@ -76,14 +76,14 @@
             self._hooks[event][etype].append(function)
             self.debug('registered hook %s on %s (%s)', event, etype or 'any',
                        function.func_name)
-            
+
         except KeyError:
             self.error('can\'t register hook %s on %s (%s)',
                        event, etype or 'any', function.func_name)
-            
+
     def unregister_hook(self, function, event, etype=''):
         """register a function to call when <event> occurs
-        
+
         <etype> is an entity/relation type or an empty string.
         If etype is the empty string, the function will be called at each
         event, else the function will be called only when event occurs on an
@@ -109,7 +109,7 @@
             for hook in self._hooks[__event][__type]:
                 #print '[%s]'%__type, hook.__name__
                 hook(*args, **kwargs)
-    
+
     def _init_hooks(self, schema):
         """initialize the hooks map"""
         for hook_event in ENTITIES_HOOKS:
@@ -164,7 +164,7 @@
         self.unregister_hook(uniquecstrcheck_before_modification, 'before_update_entity', '')
 #         self.unregister_hook(tidy_html_fields('before_add_entity'), 'before_add_entity', '')
 #         self.unregister_hook(tidy_html_fields('before_update_entity'), 'before_update_entity', '')
-        
+
     def reactivate_verification_hooks(self):
         from cubicweb.server.hooks import (cardinalitycheck_after_add_entity,
                                         cardinalitycheck_before_del_relation,
@@ -179,7 +179,7 @@
         self.register_hook(uniquecstrcheck_before_modification, 'before_update_entity', '')
 #         self.register_hook(tidy_html_fields('before_add_entity'), 'before_add_entity', '')
 #         self.register_hook(tidy_html_fields('before_update_entity'), 'before_update_entity', '')
-            
+
 from cubicweb.selectors import yes
 from cubicweb.appobject import AppObject
 
@@ -199,16 +199,16 @@
     events = None
     accepts = None
     enabled = True
-    
+
     def __init__(self, event=None):
         super(Hook, self).__init__()
         self.event = event
-        
+
     @classmethod
     def registered(cls, vreg):
         super(Hook, cls).registered(vreg)
         return cls()
-    
+
     @classmethod
     def register_to(cls):
         if not cls.enabled:
@@ -232,7 +232,7 @@
                             continue
                         yield event, str(eetype)
                         done.add((event, eetype))
-                        
+
 
     def make_callback(self, event):
         if len(self.events) == 1:
@@ -241,7 +241,7 @@
 
     def call(self):
         raise NotImplementedError
-    
+
 class SystemHook(Hook):
     accepts = ('',)
 
--- a/server/mssteps.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/mssteps.py	Thu Apr 04 13:49:34 2019 +0200
@@ -16,7 +16,7 @@
 from cubicweb.server.ssplanner import (LimitOffsetMixIn, Step, OneFetchStep,
                                     varmap_test_repr, offset_result)
 
-AGGR_TRANSFORMS = {'COUNT':'SUM', 'MIN':'MIN', 'MAX':'MAX', 'SUM': 'SUM'} 
+AGGR_TRANSFORMS = {'COUNT':'SUM', 'MIN':'MIN', 'MAX':'MAX', 'SUM': 'SUM'}
 
 def remove_clauses(union, keepgroup):
     clauses = []
@@ -73,7 +73,7 @@
                         if lhsvar.name in srqlst.defined_vars:
                             key = '%s.%s' % (lhsvar.name, rel.r_type)
                             self.outputmap[key] = self.outputmap[var.name]
-                
+
     def execute(self):
         """execute this step"""
         self.execute_children()
@@ -86,7 +86,7 @@
             source.flying_insert(self.table, plan.session, union, plan.args,
                                  self.inputmap)
         restore_clauses(union, self.keepgroup, clauses)
-            
+
     def mytest_repr(self):
         """return a representation of this step suitable for test"""
         clauses = remove_clauses(self.union, self.keepgroup)
@@ -104,7 +104,7 @@
         finally:
             restore_clauses(self.union, self.keepgroup, clauses)
 
-    
+
 class AggrStep(LimitOffsetMixIn, Step):
     """step consisting in making aggregat from temporary data in the system
     source
@@ -123,7 +123,7 @@
             plan.init_temp_table(outputtable, selection, select.solutions[0])
 
         #self.inputmap = inputmap
-        
+
     def mytest_repr(self):
         """return a representation of this step suitable for test"""
         sel = self.select.selection
@@ -167,7 +167,7 @@
                     clause.append(term.accept(self))
                     # restaure the tree XXX necessary?
                     term.name = orig_name
-                    term.children = orig_children                
+                    term.children = orig_children
                 except KeyError:
                     clause.append(var_name)
             else:
@@ -215,28 +215,28 @@
             self.plan.create_temp_table(self.outputtable)
             sql = 'INSERT INTO %s %s' % (self.outputtable, sql)
         return self.plan.sqlexec(sql, self.plan.args)
-    
+
     def visit_function(self, function):
         """generate SQL name for a function"""
         return '%s(%s)' % (function.name,
                            ','.join(c.accept(self) for c in function.children))
-        
+
     def visit_variableref(self, variableref):
         """get the sql name for a variable reference"""
         try:
             return self.inputmap[variableref.name]
         except KeyError: # XXX duh? explain
             return variableref.variable.name
-        
+
     def visit_constant(self, constant):
         """generate SQL name for a constant"""
         assert constant.type == 'Int'
         return str(constant.value)
-    
+
 
 class UnionStep(LimitOffsetMixIn, Step):
     """union results of child in-memory steps (e.g. OneFetchStep / AggrStep)"""
-        
+
     def execute(self):
         """execute this step"""
         result = []
@@ -258,7 +258,7 @@
                 if len(result) >= olimit:
                     return result[:olimit]
         return result
-        
+
     def mytest_repr(self):
         """return a representation of this step suitable for test"""
         return (self.__class__.__name__, self.limit, self.offset)
@@ -266,7 +266,7 @@
 
 class IntersectStep(UnionStep):
     """return intersection of results of child in-memory steps (e.g. OneFetchStep / AggrStep)"""
-        
+
     def execute(self):
         """execute this step"""
         result = set()
--- a/server/pool.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/pool.py	Thu Apr 04 13:49:34 2019 +0200
@@ -2,7 +2,7 @@
 
 * the rql repository has a limited number of connections pools, each of them
   dealing with a set of connections on each source used by the repository
-  
+
 * operation may be registered by hooks during a transaction, which will  be
   fired when the pool is commited or rollbacked
 
@@ -17,7 +17,7 @@
 __docformat__ = "restructuredtext en"
 
 import sys
-    
+
 class ConnectionsPool(object):
     """handle connections on a set of sources, at some point associated to a
     user session
@@ -40,7 +40,7 @@
         for source, cnx in self.source_cnxs.values():
             # let exception propagates
             cnx.commit()
-        
+
     def rollback(self):
         """rollback the current transaction for this user"""
         for source, cnx in self.source_cnxs.values():
@@ -64,7 +64,7 @@
                 cnx.close()
             except:
                 continue
-            
+
     # internals ###############################################################
 
     def pool_set(self, session):
@@ -75,7 +75,7 @@
         """pool is being reseted"""
         for source, cnx in self.source_cnxs.values():
             source.pool_reset(cnx)
-        
+
     def __getitem__(self, uri):
         """subscription notation provide access to sources'cursors"""
         try:
@@ -86,7 +86,7 @@
                 # None possible on sources without cursor support such as ldap
                 self._cursors[uri] = cursor
         return cursor
-    
+
     def sources(self):
         """return the source objects handled by this pool"""
         # implementation details of flying insert requires the system source
@@ -97,11 +97,11 @@
                 continue
             yield source
         #return [source_cnx[0] for source_cnx in self.source_cnxs.values()]
-    
+
     def source(self, uid):
         """return the source object with the given uri"""
         return self.source_cnxs[uid][0]
-    
+
     def connection(self, uid):
         """return the connection on the source object with the given uri"""
         return self.source_cnxs[uid][1]
@@ -109,7 +109,7 @@
     def reconnect(self, source):
         """reopen a connection for this source"""
         source.info('trying to reconnect')
-        self.source_cnxs[source.uri] = (source, source.get_connection())        
+        self.source_cnxs[source.uri] = (source, source.get_connection())
         del self._cursors[source.uri]
 
     def check_connections(self):
@@ -133,11 +133,11 @@
       do any heavy computation or raise an exception if the commit can't go.
       You can add some new operation during this phase but their precommit
       event won't be triggered
-      
+
     commit:
       the pool is preparing to commit. You should avoid to do to expensive
       stuff or something that may cause an exception in this event
-      
+
     revertcommit:
       if an operation failed while commited, this event is triggered for
       all operations which had their commit event already to let them
@@ -153,7 +153,7 @@
     order of operations may be important, and is controlled according to:
     * operation's class
     """
-    
+
     def __init__(self, session, **kwargs):
         self.session = session
         self.user = session.user
@@ -165,10 +165,10 @@
         # execution information
         self.processed = None # 'precommit', 'commit'
         self.failed = False
-        
+
     def register(self, session):
         session.add_operation(self, self.insert_index())
-        
+
     def insert_index(self):
         """return the index of  the lastest instance which is not a
         LateOperation instance
@@ -177,17 +177,17 @@
             if isinstance(op, (LateOperation, SingleLastOperation)):
                 return i
         return None
-    
+
     def handle_event(self, event):
         """delegate event handling to the opertaion"""
         getattr(self, event)()
 
     def precommit_event(self):
         """the observed connections pool is preparing a commit"""
-    
+
     def revertprecommit_event(self):
         """an error went when pre-commiting this operation or a later one
-        
+
         should revert pre-commit's changes but take care, they may have not
         been all considered if it's this operation which failed
         """
@@ -195,17 +195,17 @@
     def commit_event(self):
         """the observed connections pool is commiting"""
         raise NotImplementedError()
-    
+
     def revertcommit_event(self):
         """an error went when commiting this operation or a later one
-        
+
         should revert commit's changes but take care, they may have not
         been all considered if it's this operation which failed
         """
-    
+
     def rollback_event(self):
         """the observed connections pool has been rollbacked
-        
+
         do nothing by default, the operation will just be removed from the pool
         operation list
         """
@@ -226,7 +226,7 @@
 class LateOperation(Operation):
     """special operation which should be called after all possible (ie non late)
     operations
-    """    
+    """
     def insert_index(self):
         """return the index of  the lastest instance which is not a
         SingleLastOperation instance
@@ -238,7 +238,7 @@
 
 
 class SingleOperation(Operation):
-    """special operation which should be called once"""    
+    """special operation which should be called once"""
     def register(self, session):
         """override register to handle cases where this operation has already
         been added
@@ -251,7 +251,7 @@
             equivalent = None
         session.add_operation(self, self.insert_index())
         return equivalent
-    
+
     def equivalent_index(self, operations):
         """return the index of the equivalent operation if any"""
         equivalents = [i for i, op in enumerate(operations)
@@ -264,7 +264,7 @@
 class SingleLastOperation(SingleOperation):
     """special operation which should be called once and after all other
     operations
-    """    
+    """
     def insert_index(self):
         return None
 
--- a/server/querier.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/querier.py	Thu Apr 04 13:49:34 2019 +0200
@@ -2,7 +2,7 @@
 security checking and data aggregation.
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -84,7 +84,7 @@
             #assert len(erqlexprs) == 1
             localchecks[varname] = tuple(erqlexprs)
     return localchecks
-                    
+
 def noinvariant_vars(restricted, select, nbtrees):
     # a variable can actually be invariant if it has not been restricted for
     # security reason or if security assertion hasn't modified the possible
@@ -114,12 +114,12 @@
                 colalias = newselect.get_variable(vref.name, len(aliases))
                 aliases.append(VariableRef(colalias))
                 selected.add(vref.name)
-                
+
 # Plans #######################################################################
 
 class ExecutionPlan(object):
     """the execution model of a rql query, composed of querier steps"""
-    
+
     def __init__(self, querier, rqlst, args, session):
         # original rql syntax tree
         self.rqlst = rqlst
@@ -137,11 +137,11 @@
         self.schema = querier.schema
         self.rqlhelper = querier._rqlhelper
         self.sqlannotate = querier.sqlgen_annotate
-        
+
     def annotate_rqlst(self):
         if not self.rqlst.annotated:
             self.rqlhelper.annotate(self.rqlst)
-            
+
     def add_step(self, step):
         """add a step to the plan"""
         self.steps.append(step)
@@ -149,10 +149,10 @@
     def clean(self):
         """remove temporary tables"""
         self.syssource.clean_temp_data(self.session, self.temp_tables)
-        
+
     def sqlexec(self, sql, args=None):
         return self.syssource.sqlexec(self.session, sql, args)
-            
+
     def execute(self):
         """execute a plan and return resulting rows"""
         try:
@@ -162,7 +162,7 @@
             return result
         finally:
             self.clean()
-            
+
     def init_temp_table(self, table, selected, sol):
         """initialize sql schema and variable map for a temporary table which
         will be used to store result for the given rqlst
@@ -175,17 +175,17 @@
                                                                  table)
             self.temp_tables[table] = [outputmap, sqlschema, False]
         return outputmap
-        
+
     def create_temp_table(self, table):
         """create a temporary table to store result for the given rqlst"""
         if not self.temp_tables[table][-1]:
             sqlschema = self.temp_tables[table][1]
             self.syssource.create_temp_table(self.session, table, sqlschema)
             self.temp_tables[table][-1] = True
-        
+
     def preprocess(self, union, security=True):
         """insert security when necessary then annotate rql st for sql generation
-        
+
         return rqlst to actually execute
         """
         #if server.DEBUG:
@@ -279,7 +279,7 @@
         are removed, else if the user may read it (eg if an rql expression is
         defined for the "read" permission of the related type), the local checks
         dict for the solution is updated
-        
+
         return a dict with entries for each different local check necessary,
         with associated solutions as value. A local check is defined by a list
         of 2-uple, with variable name as first item and the necessary rql
@@ -346,11 +346,11 @@
         self.rqlhelper.annotate(rqlst)
         self.preprocess(rqlst, security=False)
         return rqlst
-       
+
 class InsertPlan(ExecutionPlan):
     """an execution model specific to the INSERT rql query
     """
-    
+
     def __init__(self, querier, rqlst, args, session):
         ExecutionPlan.__init__(self, querier, rqlst, args, session)
         # save originaly selected variable, we may modify this
@@ -387,7 +387,7 @@
                     value = rhs.eval(self.args)
                     eschema = edef.e_schema
                     attrtype = eschema.subject_relation(rtype).objects(eschema)[0]
-                    if attrtype == 'Password' and isinstance(value, unicode): 
+                    if attrtype == 'Password' and isinstance(value, unicode):
                         value = value.encode('UTF8')
                     edef[rtype] = value
                 elif to_build.has_key(str(rhs)):
@@ -397,12 +397,12 @@
                     to_select.setdefault(edef, []).append( (rtype, rhs, 0) )
         return to_select
 
-        
+
     def add_entity_def(self, edef):
         """add an entity definition to build"""
         edef.querier_pending_relations = {}
         self.e_defs[-1].append(edef)
-        
+
     def add_relation_def(self, rdef):
         """add an relation definition to build"""
         self.r_defs.append(rdef)
@@ -410,11 +410,11 @@
             self._r_subj_index.setdefault(rdef[0], []).append(rdef)
         if not isinstance(rdef[2], int):
             self._r_obj_index.setdefault(rdef[2], []).append(rdef)
-        
+
     def substitute_entity_def(self, edef, edefs):
         """substitute an incomplete entity definition by a list of complete
         equivalents
-        
+
         e.g. on queries such as ::
           INSERT Personne X, Societe Y: X nom N, Y nom 'toto', X travaille Y
           WHERE U login 'admin', U login N
@@ -455,7 +455,7 @@
                     for edef in edefs:
                         result.append( (exp_rdef[0], exp_rdef[1], edef) )
                 self._expanded_r_defs[rdef] = result
-        
+
     def _expanded(self, rdef):
         """return expanded value for the given relation definition"""
         try:
@@ -463,7 +463,7 @@
         except KeyError:
             self.r_defs.remove(rdef)
             return [rdef]
-        
+
     def relation_defs(self):
         """return the list for relation definitions to insert"""
         for rdefs in self._expanded_r_defs.values():
@@ -471,11 +471,11 @@
                 yield rdef
         for rdef in self.r_defs:
             yield rdef
-            
+
     def insert_entity_defs(self):
         """return eids of inserted entities in a suitable form for the resulting
         result set, e.g.:
-        
+
         e.g. on queries such as ::
           INSERT Personne X, Societe Y: X nom N, Y nom 'toto', X travaille Y
           WHERE U login 'admin', U login N
@@ -490,7 +490,7 @@
             results.append([repo.glob_add_entity(session, edef)
                             for edef in row])
         return results
-        
+
     def insert_relation_defs(self):
         session = self.session
         repo = session.repo
@@ -514,18 +514,18 @@
 
 class QuerierHelper(object):
     """helper class to execute rql queries, putting all things together"""
-    
+
     def __init__(self, repo, schema):
         # system info helper
         self._repo = repo
         # application schema
         self.set_schema(schema)
-        
+
     def set_schema(self, schema):
         self.schema = schema
         # rql parsing / analysing helper
         self._rqlhelper = RQLHelper(schema, special_relations={'eid': 'uid',
-                                                               'has_text': 'fti'})        
+                                                               'has_text': 'fti'})
         self._rql_cache = Cache(self._repo.config['rql-cache-size'])
         self.cache_hit, self.cache_miss = 0, 0
         # rql planner
@@ -535,11 +535,11 @@
             from cubicweb.server.ssplanner import SSPlanner
             self._planner = SSPlanner(schema, self._rqlhelper)
         else:
-            from cubicweb.server.msplanner import MSPlanner            
+            from cubicweb.server.msplanner import MSPlanner
             self._planner = MSPlanner(schema, self._rqlhelper)
         # sql generation annotator
         self.sqlgen_annotate = SQLGenAnnotator(schema).annotate
-        
+
     def parse(self, rql, annotate=False):
         """return a rql syntax tree for the given rql"""
         try:
@@ -559,7 +559,7 @@
         if rqlst.TYPE == 'insert':
             return InsertPlan(self, rqlst, args, session)
         return ExecutionPlan(self, rqlst, args, session)
-        
+
     def execute(self, session, rql, args=None, eid_key=None, build_descr=True):
         """execute a rql query, return resulting rows and their description in
         a `ResultSet` object
@@ -578,7 +578,7 @@
 
         on INSERT queries, there will be on row with the eid of each inserted
         entity
-        
+
         result for DELETE and SET queries is undefined yet
 
         to maximize the rql parsing/analyzing cache performance, you should
--- a/server/rqlannotation.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/rqlannotation.py	Thu Apr 04 13:49:34 2019 +0200
@@ -69,7 +69,7 @@
             # "Any X", "Any X, Y WHERE X attr Y"
             stinfo['invariant'] = False
             continue
-        joins = set()            
+        joins = set()
         invariant = False
         for ref in var.references():
             rel = ref.relation()
@@ -78,7 +78,7 @@
             lhs, rhs = rel.get_parts()
             onlhs = ref is lhs
             if rel.r_type == 'eid':
-                if not (onlhs and len(stinfo['relations']) > 1): 
+                if not (onlhs and len(stinfo['relations']) > 1):
                     break
                 if not stinfo['constnode']:
                     joins.add(rel)
@@ -110,9 +110,9 @@
                 continue
             if not stinfo['constnode']:
                 if rschema.inlined and rel.neged(strict=True):
-                    # if relation is inlined, can't be invariant if that 
+                    # if relation is inlined, can't be invariant if that
                     # variable is used anywhere else.
-                    # see 'Any P WHERE NOT N ecrit_par P, N eid 512':                    
+                    # see 'Any P WHERE NOT N ecrit_par P, N eid 512':
                     # sql for 'NOT N ecrit_par P' is 'N.ecrit_par is NULL' so P
                     # can use N.ecrit_par as principal
                     if (stinfo['selected'] or len(stinfo['relations']) > 1):
@@ -184,7 +184,7 @@
         return iter(_sort(diffscope_rels)).next()
     # XXX  could use a relation for a different scope if it can't generate
     # duplicates, so we would have to check cardinality
-    raise CantSelectPrincipal()    
+    raise CantSelectPrincipal()
 
 def _select_main_var(relations):
     """given a list of rqlst relations, select one which will be used as main
@@ -265,12 +265,12 @@
             return False
         try:
             data = var.stmt._deamb_data
-        except AttributeError: 
+        except AttributeError:
             data = var.stmt._deamb_data = IsAmbData(self.schema, self.nfdomain)
             data.compute(var.stmt)
         return data.is_ambiguous(var)
 
-        
+
 class IsAmbData(object):
     def __init__(self, schema, nfdomain):
         self.schema = schema
@@ -288,7 +288,7 @@
         self.deambification_map = {}
         # not invariant variables (access to final.inlined relation)
         self.not_invariants = set()
-        
+
     def is_ambiguous(self, var):
         return var in self.ambiguousvars
 
@@ -296,7 +296,7 @@
         self.varsols[var] &= restricted_domain
         if var in self.ambiguousvars and self.varsols[var] == var.stinfo['possibletypes']:
             self.ambiguousvars.remove(var)
-    
+
     def compute(self, rqlst):
         # set domains for each variable
         for varname, var in rqlst.defined_vars.iteritems():
@@ -334,7 +334,7 @@
                 except KeyError:
                     # no relation to deambiguify
                     continue
-        
+
     def _debug_print(self):
         print 'varsols', dict((x, sorted(str(v) for v in values))
                                for x, values in self.varsols.iteritems())
@@ -350,7 +350,7 @@
                     self.maydeambrels[var].add(rel)
                 except KeyError:
                     self.maydeambrels[var] = set((rel,))
-        
+
     def deambiguifying_relation(self, var, rel):
         lhs, rhs = rel.get_variable_parts()
         onlhs = var is getattr(lhs, 'variable', None)
--- a/server/rqlrewrite.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/rqlrewrite.py	Thu Apr 04 13:49:34 2019 +0200
@@ -34,7 +34,7 @@
     return newsolutions
 
 class Unsupported(Exception): pass
-        
+
 class RQLRewriter(object):
     """insert some rql snippets into another rql syntax tree"""
     def __init__(self, querier, session):
@@ -51,7 +51,7 @@
             raise Unsupported()
         if len(self.select.solutions) < len(self.solutions):
             raise Unsupported()
-        
+
     def rewrite(self, select, snippets, solutions, kwargs):
         if server.DEBUG:
             print '---- rewrite', select, snippets, solutions
@@ -112,7 +112,7 @@
         add_types_restriction(self.schema, select)
         if server.DEBUG:
             print '---- rewriten', select
-            
+
     def build_variantes(self, newsolutions):
         variantes = set()
         for sol in newsolutions:
@@ -133,7 +133,7 @@
                 for variante in variantes:
                     del variante[(erqlexpr, mainvar, oldvar)]
         return variantes
-    
+
     def insert_snippets(self, snippets, varexistsmap=None):
         self.rewritten = {}
         for varname, erqlexprs in snippets:
@@ -175,7 +175,7 @@
             if varexistsmap is None and not inserted:
                 # no rql expression found matching rql solutions. User has no access right
                 raise Unauthorized()
-            
+
     def insert_snippet(self, varname, snippetrqlst, parent=None):
         new = snippetrqlst.where.accept(self)
         if new is not None:
@@ -240,7 +240,7 @@
                     else:
                         parent.parent.replace(or_, or_.children[0])
                         self._cleanup_inserted(new)
-                    raise 
+                    raise
             return new
 
     def _cleanup_inserted(self, node):
@@ -250,7 +250,7 @@
             if not vref.variable.stinfo['references']:
                 # no more references, undefine the variable
                 del self.select.defined_vars[vref.name]
-        
+
     def _visit_binary(self, node, cls):
         newnode = cls()
         for c in node.children:
@@ -270,20 +270,20 @@
             return None
         newnode = cls()
         newnode.append(newc)
-        return newnode 
-        
+        return newnode
+
     def visit_and(self, et):
         return self._visit_binary(et, nodes.And)
 
     def visit_or(self, ou):
         return self._visit_binary(ou, nodes.Or)
-        
+
     def visit_not(self, node):
         return self._visit_unary(node, nodes.Not)
 
     def visit_exists(self, node):
         return self._visit_unary(node, nodes.Exists)
-   
+
     def visit_relation(self, relation):
         lhs, rhs = relation.get_variable_parts()
         if lhs.name == 'X':
@@ -301,7 +301,7 @@
             if relation.r_type in self.rhs_rels and self._may_be_shared(relation, 'subject'):
                 # ok, can share variable
                 term = self.rhs_rels[relation.r_type].children[0]
-                self._use_outer_term(lhs.name, term)            
+                self._use_outer_term(lhs.name, term)
                 return
         rel = nodes.Relation(relation.r_type, relation.optional)
         for c in relation.children:
@@ -319,7 +319,7 @@
         for c in cmp.children:
             cmp_.append(c.accept(self))
         return cmp_
-        
+
     def visit_function(self, function):
         """generate filter name for a function"""
         function_ = nodes.Function(function.name)
@@ -371,7 +371,7 @@
             for inserted_vref in insertedvar.references():
                 inserted_vref.parent.replace(inserted_vref, term.copy(self.select))
         self.rewritten[key] = term
-        
+
     def _get_varname_or_term(self, vname):
         if vname == 'U':
             if self.u_varname is None:
--- a/server/schemahooks.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/schemahooks.py	Thu Apr 04 13:49:34 2019 +0200
@@ -21,7 +21,7 @@
 from cubicweb.server.pool import Operation, SingleLastOperation, PreCommitOperation
 from cubicweb.server.hookhelper import (entity_attr, entity_name,
                                      check_internal_entity)
-    
+
 # core entity and relation types which can't be removed
 CORE_ETYPES = list(BASE_TYPES) + ['CWEType', 'CWRType', 'CWUser', 'CWGroup',
                                   'CWConstraint', 'CWAttribute', 'CWRelation']
@@ -52,7 +52,7 @@
                                % (table, column)))
         session.info('added column %s to table %s', column, table)
     except:
-        # silent exception here, if this error has not been raised because the 
+        # silent exception here, if this error has not been raised because the
         # column already exists, index creation will fail anyway
         session.exception('error while adding column %s to table %s',
                           table, column)
@@ -74,7 +74,7 @@
         Operation.__init__(self, session, **kwargs)
         # every schema operation is triggering a schema update
         UpdateSchemaOp(session)
-        
+
 class EarlySchemaOperation(SchemaOperation):
     def insert_index(self):
         """schema operation which are inserted at the begining of the queue
@@ -85,7 +85,7 @@
             if not isinstance(op, EarlySchemaOperation):
                 return i
         return i + 1
-    
+
 class UpdateSchemaOp(SingleLastOperation):
     """the update schema operation:
 
@@ -93,15 +93,15 @@
     operations. It will trigger internal structures rebuilding to consider
     schema changes
     """
-    
+
     def __init__(self, session):
         self.repo = session.repo
         SingleLastOperation.__init__(self, session)
-        
+
     def commit_event(self):
         self.repo.set_schema(self.repo.schema)
 
-        
+
 class DropTableOp(PreCommitOperation):
     """actually remove a database from the application's schema"""
     table = None # make pylint happy
@@ -113,7 +113,7 @@
         dropped.add(self.table)
         self.session.system_sql('DROP TABLE %s' % self.table)
         self.info('dropped table %s', self.table)
-        
+
 class DropColumnOp(PreCommitOperation):
     """actually remove the attribut's column from entity table in the system
     database
@@ -130,12 +130,12 @@
         except Exception, ex:
             # not supported by sqlite for instance
             self.error('error while altering table %s: %s', table, ex)
-            
+
 
 # deletion ####################################################################
 
 class DeleteCWETypeOp(SchemaOperation):
-    """actually remove the entity type from the application's schema"""    
+    """actually remove the entity type from the application's schema"""
     def commit_event(self):
         try:
             # del_entity_type also removes entity's relations
@@ -162,9 +162,9 @@
     session.execute('DELETE State X WHERE NOT X state_of Y')
     session.execute('DELETE Transition X WHERE NOT X transition_of Y')
 
-        
+
 class DeleteCWRTypeOp(SchemaOperation):
-    """actually remove the relation type from the application's schema"""    
+    """actually remove the relation type from the application's schema"""
     def commit_event(self):
         try:
             self.schema.del_relation_type(self.kobj)
@@ -186,7 +186,7 @@
                     {'x': eid})
     DeleteCWRTypeOp(session, name)
 
-    
+
 class DelErdefOp(SchemaOperation):
     """actually remove the relation definition from the application's schema"""
     def commit_event(self):
@@ -196,7 +196,7 @@
         except KeyError:
             # relation type may have been already deleted
             pass
-        
+
 def after_del_relation_type(session, rdefeid, rtype, rteid):
     """before deleting a CWAttribute or CWRelation entity:
     * if this is a final or inlined relation definition, instantiate an
@@ -223,7 +223,7 @@
     # we have to update physical schema systematically for final and inlined
     # relations, but only if it's the last instance for this relation type
     # for other relations
-    
+
     if (rschema.is_final() or rschema.inlined):
         rset = execute('Any COUNT(X) WHERE X is %s, X relation_type R, '
                        'R eid %%(x)s, X from_entity E, E name %%(name)s'
@@ -238,16 +238,16 @@
         execute('DELETE CWRType X WHERE X eid %(x)s', {'x': rteid}, 'x')
     DelErdefOp(session, (subjschema, rschema, objschema))
 
-        
+
 # addition ####################################################################
 
 class AddCWETypeOp(EarlySchemaOperation):
-    """actually add the entity type to the application's schema"""    
+    """actually add the entity type to the application's schema"""
     eid = None # make pylint happy
     def commit_event(self):
         eschema = self.schema.add_entity_type(self.kobj)
         eschema.eid = self.eid
-        
+
 def before_add_eetype(session, entity):
     """before adding a CWEType entity:
     * check that we are not using an existing entity type,
@@ -304,25 +304,25 @@
 
 
 class AddCWRTypeOp(EarlySchemaOperation):
-    """actually add the relation type to the application's schema"""    
+    """actually add the relation type to the application's schema"""
     eid = None # make pylint happy
     def commit_event(self):
         rschema = self.schema.add_relation_type(self.kobj)
         rschema.set_default_groups()
         rschema.eid = self.eid
-        
+
 def before_add_ertype(session, entity):
     """before adding a CWRType entity:
     * check that we are not using an existing relation type,
     * register an operation to add the relation type to the application's
       schema on commit
-      
+
     We don't know yeat this point if a table is necessary
     """
     name = entity['name']
     if name in session.repo.schema.relations():
         raise RepositoryError('a relation type %s already exists' % name)
-    
+
 def after_add_ertype(session, entity):
     """after a CWRType entity has been added:
     * register an operation to add the relation type to the application's
@@ -340,7 +340,7 @@
 class AddErdefOp(EarlySchemaOperation):
     """actually add the attribute relation definition to the application's
     schema
-    """    
+    """
     def commit_event(self):
         self.schema.add_relation_def(self.kobj)
 
@@ -350,7 +350,7 @@
     'Float': float,
     'Password': str,
     'String': unicode,
-    'Date' : unicode, 
+    'Date' : unicode,
     'Datetime' : unicode,
     'Time' : unicode,
     }
@@ -362,7 +362,7 @@
     * set default on this column if any and possible
     * register an operation to add the relation definition to the
       application's schema on commit
-      
+
     constraints are handled by specific hooks
     """
     entity = None # make pylint happy
@@ -457,7 +457,7 @@
         session = self.session
         entity = self.entity
         fromentity = entity.from_entity[0]
-        relationtype = entity.relation_type[0] 
+        relationtype = entity.relation_type[0]
         session.execute('SET X ordernum Y+1 WHERE X from_entity SE, SE eid %(se)s, X ordernum Y, X ordernum >= %(order)s, NOT X eid %(x)s',
                         {'x': entity.eid, 'se': fromentity.eid, 'order': entity.ordernum or 0})
         subj, rtype = str(fromentity.name), str(relationtype.name)
@@ -508,7 +508,7 @@
                     if sql.strip():
                         self.session.system_sql(sql)
                 session.add_query_data('createdtables', rtype)
-                
+
 def after_add_enfrdef(session, entity):
     AddCWRelationPreCommitOp(session, entity=entity)
 
@@ -556,7 +556,7 @@
                 (self.newname, self.oldname))
         sqlexec('UPDATE deleted_entities SET type=%s WHERE type=%s',
                 (self.newname, self.oldname))
-        
+
     def commit_event(self):
         self.session.repo.schema.rename_entity_type(self.oldname, self.newname)
 
@@ -575,13 +575,13 @@
                 sysource.create_index(self.session, table, column)
             else:
                 sysource.drop_index(self.session, table, column)
-                
+
     def commit_event(self):
         # structure should be clean, not need to remove entity's relations
         # at this point
         self.rschema._rproperties[self.kobj].update(self.values)
 
-    
+
 def after_update_erdef(session, entity):
     desttype = entity.to_entity[0].name
     rschema = session.repo.schema[entity.relation_type[0].name]
@@ -600,7 +600,7 @@
 
 
 class UpdateRtypeOp(SchemaOperation):
-    """actually update some properties of a relation definition"""    
+    """actually update some properties of a relation definition"""
     rschema = values = entity = None # make pylint happy
 
     def precommit_event(self):
@@ -639,13 +639,13 @@
         else:
             for etype in rschema.subjects():
                 try:
-                    add_inline_relation_column(session, str(etype), rtype)                    
+                    add_inline_relation_column(session, str(etype), rtype)
                 except Exception, ex:
                     # the column probably already exists. this occurs when
                     # the entity's type has just been added or if the column
                     # has not been previously dropped
                     self.error('error while altering table %s: %s', etype, ex)
-                # copy existant data. 
+                # copy existant data.
                 # XXX don't use, it's not supported by sqlite (at least at when i tried it)
                 #sqlexec('UPDATE %(etype)s SET %(rtype)s=eid_to '
                 #        'FROM %(rtype)s_relation '
@@ -667,7 +667,7 @@
         # structure should be clean, not need to remove entity's relations
         # at this point
         self.rschema.__dict__.update(self.values)
-    
+
 def after_update_ertype(session, entity):
     rschema = session.repo.schema.rschema(entity.name)
     newvalues = {}
@@ -684,13 +684,13 @@
 class ConstraintOp(SchemaOperation):
     """actually update constraint of a relation definition"""
     entity = None # make pylint happy
-    
+
     def prepare_constraints(self, rtype, subjtype, objtype):
         constraints = rtype.rproperty(subjtype, objtype, 'constraints')
         self.constraints = list(constraints)
         rtype.set_rproperty(subjtype, objtype, 'constraints', self.constraints)
         return self.constraints
-    
+
     def precommit_event(self):
         rdef = self.entity.reverse_constrained_by[0]
         session = self.session
@@ -698,7 +698,7 @@
         # is created by AddEN?FRDefPreCommitOp, there is nothing to do here
         if rdef.eid in session.query_data('neweids', ()):
             self.cancelled = True
-            return 
+            return
         self.cancelled = False
         schema = session.repo.schema
         subjtype, rtype, objtype = schema.schema_by_eid(rdef.eid)
@@ -723,7 +723,7 @@
         elif cstrtype == 'UniqueConstraint':
             session.pool.source('system').create_index(
                 self.session, table, column, unique=True)
-        
+
     def commit_event(self):
         if self.cancelled:
             return
@@ -743,7 +743,7 @@
 class DelConstraintOp(ConstraintOp):
     """actually remove a constraint of a relation definition"""
     rtype = subjtype = objtype = None # make pylint happy
-    
+
     def precommit_event(self):
         self.prepare_constraints(self.rtype, self.subjtype, self.objtype)
         cstrtype = self.cstr.type()
@@ -754,7 +754,7 @@
             try:
                 self.session.system_sql('ALTER TABLE %s ALTER COLUMN %s TYPE TEXT'
                                         % (table, column))
-                self.info('altered column %s of table %s: now TEXT', 
+                self.info('altered column %s of table %s: now TEXT',
                           column, table)
             except Exception, ex:
                 # not supported by sqlite for instance
@@ -762,7 +762,7 @@
         elif cstrtype == 'UniqueConstraint':
             self.session.pool.source('system').drop_index(
                 self.session, table, column, unique=True)
-                
+
     def commit_event(self):
         self.constraints.remove(self.cstr)
 
@@ -784,7 +784,7 @@
     if fromeid in session.query_data('neweids', ()):
         session.add_query_data(fromeid, toeid)
 
-    
+
 # schema permissions synchronization ##########################################
 
 class PermissionOp(Operation):
@@ -805,7 +805,7 @@
     def __init__(self, session, perm, etype_eid, group_eid):
         self.group = entity_name(session, group_eid)
         PermissionOp.__init__(self, session, perm, etype_eid)
-        
+
     def commit_event(self):
         """the observed connections pool has been commited"""
         try:
@@ -815,7 +815,7 @@
             self.error('no schema for %s', self.name)
             return
         groups = list(erschema.get_groups(self.perm))
-        try:            
+        try:
             groups.index(self.group)
             self.warning('group %s already have permission %s on %s',
                          self.group, self.perm, erschema.type)
@@ -830,7 +830,7 @@
     def __init__(self, session, perm, etype_eid, expression):
         self.expr = expression
         PermissionOp.__init__(self, session, perm, etype_eid)
-        
+
     def commit_event(self):
         """the observed connections pool has been commited"""
         try:
@@ -852,12 +852,12 @@
         expr = session.execute('Any EXPR WHERE X eid %(x)s, X expression EXPR',
                                {'x': object}, 'x')[0][0]
         AddRQLExpressionPermissionOp(session, perm, subject, expr)
-    
+
 
-        
+
 class DelGroupPermissionOp(AddGroupPermissionOp):
     """synchronize schema when a *_permission relation has been deleted from a group"""
-        
+
     def commit_event(self):
         """the observed connections pool has been commited"""
         try:
@@ -867,17 +867,17 @@
             self.error('no schema for %s', self.name)
             return
         groups = list(erschema.get_groups(self.perm))
-        try:            
+        try:
             groups.remove(self.group)
             erschema.set_groups(self.perm, groups)
         except ValueError:
             self.error('can\'t remove permission %s on %s to group %s',
                 self.perm, erschema.type, self.group)
 
-        
+
 class DelRQLExpressionPermissionOp(AddRQLExpressionPermissionOp):
     """synchronize schema when a *_permission relation has been deleted from an rql expression"""
-        
+
     def commit_event(self):
         """the observed connections pool has been commited"""
         try:
@@ -897,7 +897,7 @@
             return
         erschema.set_rqlexprs(self.perm, rqlexprs)
 
-                
+
 def before_del_permission(session, subject, rtype, object):
     """delete entity/relation *_permission, need to update schema
 
@@ -943,7 +943,7 @@
     hm.register_hook(before_del_ertype, 'before_delete_entity', 'CWRType')
     hm.register_hook(after_del_relation_type, 'after_delete_relation', 'relation_type')
     hm.register_hook(rebuild_infered_relations, 'after_add_relation', 'specializes')
-    hm.register_hook(rebuild_infered_relations, 'after_delete_relation', 'specializes')    
+    hm.register_hook(rebuild_infered_relations, 'after_delete_relation', 'specializes')
     # constraints synchronization hooks
     hm.register_hook(after_add_econstraint, 'after_add_entity', 'CWConstraint')
     hm.register_hook(after_update_econstraint, 'after_update_entity', 'CWConstraint')
--- a/server/securityhooks.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/securityhooks.py	Thu Apr 04 13:49:34 2019 +0200
@@ -24,25 +24,25 @@
         if rschema.is_final(): # non final relation are checked by other hooks
             # add/delete should be equivalent (XXX: unify them into 'update' ?)
             rschema.check_perm(session, 'add', eid)
-            
-    
+
+
 class CheckEntityPermissionOp(LateOperation):
     def precommit_event(self):
         #print 'CheckEntityPermissionOp', self.session.user, self.entity, self.action
         self.entity.check_perm(self.action)
         check_entity_attributes(self.session, self.entity)
-        
+
     def commit_event(self):
         pass
-            
-    
+
+
 class CheckRelationPermissionOp(LateOperation):
     def precommit_event(self):
         self.rschema.check_perm(self.session, self.action, self.fromeid, self.toeid)
-        
+
     def commit_event(self):
         pass
-    
+
 def after_add_entity(session, entity):
     if not session.is_super_session:
         CheckEntityPermissionOp(session, entity=entity, action='add')
@@ -56,7 +56,7 @@
         except Unauthorized:
             entity.clear_local_perm_cache('update')
             CheckEntityPermissionOp(session, entity=entity, action='update')
-        
+
 def before_del_entity(session, eid):
     if not session.is_super_session:
         eschema = session.repo.schema[session.describe(eid)[0]]
@@ -67,7 +67,7 @@
     if rtype in BEFORE_ADD_RELATIONS and not session.is_super_session:
         rschema = session.repo.schema[rtype]
         rschema.check_perm(session, 'add', fromeid, toeid)
-        
+
 def after_add_relation(session, fromeid, rtype, toeid):
     if not rtype in BEFORE_ADD_RELATIONS and not session.is_super_session:
         rschema = session.repo.schema[rtype]
@@ -89,4 +89,4 @@
     hm.register_hook(before_add_relation, 'before_add_relation', '')
     hm.register_hook(after_add_relation, 'after_add_relation', '')
     hm.register_hook(before_del_relation, 'before_delete_relation', '')
-    
+
--- a/server/server.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/server.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,7 +1,7 @@
 """Pyro RQL server
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -22,7 +22,7 @@
     """base event"""
     # timefunc = staticmethod(localtime)
     timefunc = localtime
-    
+
     def __init__(self, absolute=None, period=None):
         # local time tuple
         if absolute is None:
@@ -57,10 +57,10 @@
     def fire(self, server):
         server.repo.shutdown()
         server.quiting = True
-        
+
 
 class RepositoryServer(object):
-    
+
     def __init__(self, config, debug=False):
         """make the repository available as a PyRO object"""
         self.config = config
@@ -86,7 +86,7 @@
                     event.update()
                 except Finished:
                     self.events.remove(event)
-            
+
     def run(self, req_timeout=5.0):
         """enter the service loop"""
         while self.quiting is None:
@@ -95,7 +95,7 @@
             except select.error:
                 continue
             self.trigger_events()
-    
+
     def quit(self):
         """stop the server"""
         self.add_event(QuitEvent())
@@ -105,16 +105,16 @@
         necessary
         """
         self.daemon = self.repo.pyro_register(host)
-            
+
     # server utilitities ######################################################
-    
+
     def install_sig_handlers(self):
         """install signal handlers"""
         import signal
         self.info('installing signal handlers')
         signal.signal(signal.SIGINT, lambda x, y, s=self: s.quit())
         signal.signal(signal.SIGTERM, lambda x, y, s=self: s.quit())
-        
+
     def daemonize(self, pid_file=None):
         """daemonize the process"""
         # fork so the parent can exist
--- a/server/sources/ldapuser.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/sources/ldapuser.py	Thu Apr 04 13:49:34 2019 +0200
@@ -52,14 +52,14 @@
 
 class LDAPUserSource(AbstractSource):
     """LDAP read-only CWUser source"""
-    support_entities = {'CWUser': False} 
+    support_entities = {'CWUser': False}
 
     port = None
-    
+
     cnx_mode = 0
     cnx_dn = ''
     cnx_pwd = ''
-    
+
     options = (
         ('host',
          {'type' : 'string',
@@ -119,9 +119,9 @@
           'help': 'life time of query cache in minutes (default to two hours).',
           'group': 'ldap-source', 'inputlevel': 2,
           }),
-        
+
     )
-            
+
     def __init__(self, repo, appschema, source_config, *args, **kwargs):
         AbstractSource.__init__(self, repo, appschema, source_config,
                                 *args, **kwargs)
@@ -150,8 +150,8 @@
 
     def init(self):
         """method called by the repository once ready to handle request"""
-        self.repo.looping_task(self._interval, self.synchronize) 
-        self.repo.looping_task(self._query_cache.ttl.seconds/10, self._query_cache.clear_expired) 
+        self.repo.looping_task(self._interval, self.synchronize)
+        self.repo.looping_task(self._query_cache.ttl.seconds/10, self._query_cache.clear_expired)
 
     def synchronize(self):
         """synchronize content known by this repository with content in the
@@ -169,7 +169,7 @@
             for eid, extid in cursor.fetchall():
                 # if no result found, _search automatically delete entity information
                 res = self._search(session, extid, BASE)
-                if res: 
+                if res:
                     ldapemailaddr = res[0].get(ldap_emailattr)
                     if ldapemailaddr:
                         rset = session.execute('EmailAddress X,A WHERE '
@@ -192,13 +192,13 @@
         finally:
             session.commit()
             session.close()
-            
+
     def get_connection(self):
         """open and return a connection to the source"""
         if self._conn is None:
             self._connect()
         return ConnectionWrapper(self._conn)
-    
+
     def authenticate(self, session, login, password):
         """return CWUser eid for the given login/password if this account is
         defined in this source, else raise `AuthenticationError`
@@ -231,7 +231,7 @@
             relname = iter(var.stinfo['relations']).next().r_type
             return self.user_rev_attrs.get(relname)
         return None
-        
+
     def prepare_columns(self, mainvars, rqlst):
         """return two list describin how to build the final results
         from the result of an ldap search (ie a list of dictionnary)
@@ -270,11 +270,11 @@
             #    # probably a bug in rql splitting if we arrive here
             #    raise NotImplementedError
         return columns, global_transforms
-    
+
     def syntax_tree_search(self, session, union,
                            args=None, cachekey=None, varmap=None, debug=0):
-        """return result from this source for a rql query (actually from a rql 
-        syntax tree and a solution dictionary mapping each used variable to a 
+        """return result from this source for a rql query (actually from a rql
+        syntax tree and a solution dictionary mapping each used variable to a
         possible type). If cachekey is given, the query necessary to fetch the
         results (but not the results themselves) may be cached using this key.
         """
@@ -361,8 +361,8 @@
             result = trfunc.apply(result)
         #print '--> ldap result', result
         return result
-                
-    
+
+
     def _connect(self, userdn=None, userpwd=None):
         port, protocol = MODES[self.cnx_mode]
         if protocol == 'ldapi':
@@ -444,12 +444,12 @@
             result.append(rec_dict)
         #print '--->', result
         return result
-    
+
     def before_entity_insertion(self, session, lid, etype, eid):
         """called by the repository when an eid has been attributed for an
         entity stored here but the entity has not been inserted in the system
         table yet.
-        
+
         This method must return the an Entity instance representation of this
         entity.
         """
@@ -458,7 +458,7 @@
         for attr in entity.e_schema.indexable_attributes():
             entity[attr] = res[self.user_rev_attrs[attr]]
         return entity
-    
+
     def after_entity_insertion(self, session, dn, entity):
         """called by the repository after an entity stored here has been
         inserted in the system table.
@@ -492,13 +492,13 @@
 def _insert_email(session, emailaddr, ueid):
     session.execute('INSERT EmailAddress X: X address %(addr)s, U primary_email X '
                     'WHERE U eid %(x)s', {'addr': emailaddr, 'x': ueid}, 'x')
-    
+
 class GotDN(Exception):
     """exception used when a dn localizing the searched user has been found"""
     def __init__(self, dn):
         self.dn = dn
 
-        
+
 class RQL2LDAPFilter(object):
     """generate an LDAP filter for a rql query"""
     def __init__(self, source, session, args=None, mainvars=()):
@@ -510,7 +510,7 @@
             args = {}
         self._args = args
         self.mainvars = mainvars
-        
+
     def generate(self, selection, mainvarname):
         self._filters = res = self._base_filters[:]
         self._mainvarname = mainvarname
@@ -527,7 +527,7 @@
         if len(res) > 1:
             return self._eidfilters, '(&%s)' % ''.join(res)
         return self._eidfilters, res[0]
-    
+
     def visit_and(self, et):
         """generate filter for a AND subtree"""
         for c in et.children:
@@ -587,7 +587,7 @@
         else:
             raise NotImplementedError(relation)
         return res
-        
+
     def _visit_attribute_relation(self, relation):
         """generate filter for an attribute relation"""
         lhs, rhs = relation.get_parts()
@@ -623,18 +623,18 @@
 
     def visit_comparison(self, cmp):
         """generate filter for a comparaison"""
-        return '%s%s'% (cmp.operator, cmp.children[0].accept(self))            
+        return '%s%s'% (cmp.operator, cmp.children[0].accept(self))
 
     def visit_mathexpression(self, mexpr):
         """generate filter for a mathematic expression"""
         raise NotImplementedError
-        
+
     def visit_function(self, function):
         """generate filter name for a function"""
         if function.name == 'IN':
             return self.visit_in(function)
         raise NotImplementedError
-        
+
     def visit_in(self, function):
         grandpapa = function.parent.parent
         ldapattr = self._ldap_attrs[grandpapa.r_type]
@@ -649,7 +649,7 @@
             else:
                 part = '(%s=%s)' % (ldapattr, res[0])
         return part
-        
+
     def visit_constant(self, constant):
         """generate filter name for a constant"""
         value = constant.value
@@ -667,7 +667,7 @@
         else:
             value = str(value)
         return escape_filter_chars(value)
-        
+
     def visit_variableref(self, variableref):
         """get the sql name for a variable reference"""
         pass
--- a/server/sources/pyrorql.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/sources/pyrorql.py	Thu Apr 04 13:49:34 2019 +0200
@@ -342,12 +342,14 @@
         cu = session.pool[self.uri]
         cu.execute('SET %s WHERE X eid %%(x)s' % ','.join(relations),
                    kwargs, 'x')
+        self._query_cache.clear()
 
     def delete_entity(self, session, etype, eid):
         """delete an entity from the source"""
         cu = session.pool[self.uri]
         cu.execute('DELETE %s X WHERE X eid %%(x)s' % etype,
                    {'x': self.eid2extid(eid, session)}, 'x')
+        self._query_cache.clear()
 
     def add_relation(self, session, subject, rtype, object):
         """add a relation to the source"""
@@ -355,6 +357,7 @@
         cu.execute('SET X %s Y WHERE X eid %%(x)s, Y eid %%(y)s' % rtype,
                    {'x': self.eid2extid(subject, session),
                     'y': self.eid2extid(object, session)}, ('x', 'y'))
+        self._query_cache.clear()
 
     def delete_relation(self, session, subject, rtype, object):
         """delete a relation from the source"""
@@ -362,6 +365,7 @@
         cu.execute('DELETE X %s Y WHERE X eid %%(x)s, Y eid %%(y)s' % rtype,
                    {'x': self.eid2extid(subject, session),
                     'y': self.eid2extid(object, session)}, ('x', 'y'))
+        self._query_cache.clear()
 
 
 class RQL2RQL(object):
--- a/server/sources/rql2sql.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/sources/rql2sql.py	Thu Apr 04 13:49:34 2019 +0200
@@ -17,7 +17,7 @@
 
    -> direct join between nonfinal1 and nonfinal2, whatever X,Y, Z (unless
       inlined...)
-      
+
       NOT IMPLEMENTED (and quite hard to implement)
 
 Potential optimization information is collected by the querier, sql generation
@@ -41,7 +41,7 @@
 from cubicweb.server.sqlutils import SQL_PREFIX
 from cubicweb.server.utils import cleanup_solutions
 
-def _new_var(select, varname): 
+def _new_var(select, varname):
     newvar = select.get_variable(varname)
     if not 'relations' in newvar.stinfo:
         # not yet initialized
@@ -61,7 +61,7 @@
                 _fill_to_wrap_rel(vref.variable, newselect, towrap, schema)
         elif rschema.is_final():
             towrap.add( (var, rel) )
-   
+
 def rewrite_unstable_outer_join(select, solutions, unstable, schema):
     """if some optional variables are unstable, they should be selected in a
     subquery. This function check this and rewrite the rql syntax tree if
@@ -104,7 +104,7 @@
                 var.stinfo['relations'].add(newrel)
                 var.stinfo['rhsrelations'].add(newrel)
                 if rel.optional in ('right', 'both'):
-                    var.stinfo['optrelations'].add(newrel)                
+                    var.stinfo['optrelations'].add(newrel)
         # extract subquery solutions
         solutions = [sol.copy() for sol in solutions]
         cleanup_solutions(newselect, solutions)
@@ -205,7 +205,7 @@
                 for vref in term.iget_nodes(VariableRef):
                     if not vref in groups:
                         groups.append(vref)
-        
+
 def fix_selection(rqlst, selectedidx, needwrap, sorts, groups, having):
     if sorts:
         sort_term_selection(sorts, selectedidx, rqlst, not needwrap and groups)
@@ -230,7 +230,7 @@
         self.existssols = existssols
         self.unstablevars = unstablevars
         self.subtables = {}
-        
+
     def reset(self, solution):
         """reset some visit variables"""
         self.solution = solution
@@ -246,11 +246,11 @@
         self.aliases = {}
         self.restrictions = []
         self._restr_stack = []
-        
+
     def add_restriction(self, restr):
         if restr:
             self.restrictions.append(restr)
-            
+
     def iter_exists_sols(self, exists):
         if not exists in self.existssols:
             yield 1
@@ -286,8 +286,8 @@
         restrictions = self.restrictions
         self.restrictions = self._restr_stack.pop()
         return restrictions, self.actual_tables.pop()
-    
-    
+
+
 class SQLGenerator(object):
     """
     generation of SQL from the fully expanded RQL syntax tree
@@ -295,13 +295,13 @@
 
     Groups and sort are not handled here since they should not be handled at
     this level (see cubicweb.server.querier)
-    
+
     we should not have errors here !
 
     WARNING: a CubicWebSQLGenerator instance is not thread safe, but generate is
     protected by a lock
     """
-    
+
     def __init__(self, schema, dbms_helper, dbencoding='UTF-8'):
         self.schema = schema
         self.dbms_helper = dbms_helper
@@ -312,7 +312,7 @@
         if not self.dbms_helper.union_parentheses_support:
             self.union_sql = self.noparen_union_sql
         self._lock = threading.Lock()
-        
+
     def generate(self, union, args=None, varmap=None):
         """return SQL queries and a variable dictionnary from a RQL syntax tree
 
@@ -355,7 +355,7 @@
         sqls = (self.select_sql(select, needalias)
                 for i, select in enumerate(union.children))
         return '\nUNION ALL\n'.join(sqls)
-    
+
     def select_sql(self, select, needalias=False):
         """return SQL queries and a variable dictionnary from a RQL syntax tree
 
@@ -388,7 +388,7 @@
                 # query will be necessary
                 if groups or select.has_aggregat:
                     select.select_only_variables()
-                    needwrap = True                        
+                    needwrap = True
         else:
             existssols, unstable = {}, ()
         state = StateInfo(existssols, unstable)
@@ -441,7 +441,7 @@
                 sql += '\nHAVING %s' % having
             # sort
             if sorts:
-                sql += '\nORDER BY %s' % ','.join(self._sortterm_sql(sortterm, 
+                sql += '\nORDER BY %s' % ','.join(self._sortterm_sql(sortterm,
                                                                      fselectidx)
                                                   for sortterm in sorts)
                 if fneedwrap:
@@ -497,7 +497,7 @@
             return '\nUNION\n'.join(sqls)
         else:
             return '\nUNION ALL\n'.join(sqls)
-        
+
     def _selection_sql(self, selected, distinct, needaliasing=False):
         clause = []
         for term in selected:
@@ -546,7 +546,7 @@
                 return '(%s)' % ' OR '.join(res)
             return res[0]
         return ''
-    
+
     def visit_not(self, node):
         self._state.push_scope()
         csql = node.children[0].accept(self)
@@ -581,7 +581,7 @@
         if not sqls:
             return ''
         return 'EXISTS(%s)' % ' UNION '.join(sqls)
-            
+
     def _visit_exists(self, exists):
         self._state.push_scope()
         restriction = exists.children[0].accept(self)
@@ -593,12 +593,12 @@
             return ''
         if not tables:
             # XXX could leave surrounding EXISTS() in this case no?
-            sql = 'SELECT 1 WHERE %s' % restriction 
+            sql = 'SELECT 1 WHERE %s' % restriction
         else:
             sql = 'SELECT 1 FROM %s WHERE %s' % (', '.join(tables), restriction)
         return sql
 
-    
+
     def visit_relation(self, relation):
         """generate SQL for a relation"""
         rtype = relation.r_type
@@ -691,7 +691,7 @@
             extrajoin = self._extra_join_sql(relation, '%s.%s' % (rid, relfield), termvar)
             if extrajoin:
                 yield extrajoin
-        
+
     def _visit_relation(self, relation, rschema):
         """generate SQL for a relation
 
@@ -718,10 +718,10 @@
         """
         left outer join syntax (optional=='right'):
           X relation Y?
-          
+
         right outer join syntax (optional=='left'):
           X? relation Y
-          
+
         full outer join syntaxes (optional=='both'):
           X? relation Y?
 
@@ -834,7 +834,7 @@
         lhssql = self._inlined_var_sql(relation.children[0].variable,
                                        relation.r_type)
         return '%s%s' % (lhssql, relation.children[1].accept(self, contextrels))
-    
+
     def _visit_attribute_relation(self, relation):
         """generate SQL for an attribute relation"""
         lhs, rhs = relation.get_parts()
@@ -897,7 +897,7 @@
             not_ = False
         return self.dbms_helper.fti_restriction_sql(alias, const.eval(self._args),
                                                     jointo, not_) + restriction
-        
+
     def visit_comparison(self, cmp, contextrels=None):
         """generate SQL for a comparaison"""
         if len(cmp.children) == 2:
@@ -918,7 +918,7 @@
             return '%s%s'% (operator, rhs.accept(self, contextrels))
         return '%s%s%s'% (lhs.accept(self, contextrels), operator,
                           rhs.accept(self, contextrels))
-            
+
     def visit_mathexpression(self, mexpr, contextrels=None):
         """generate SQL for a mathematic expression"""
         lhs, rhs = mexpr.get_parts()
@@ -931,11 +931,11 @@
             pass
         return '(%s %s %s)'% (lhs.accept(self, contextrels), operator,
                               rhs.accept(self, contextrels))
-        
+
     def visit_function(self, func, contextrels=None):
         """generate SQL name for a function"""
         # function_description will check function is supported by the backend
-        sqlname = self.dbms_helper.func_sqlname(func.name) 
+        sqlname = self.dbms_helper.func_sqlname(func.name)
         return '%s(%s)' % (sqlname, ', '.join(c.accept(self, contextrels)
                                               for c in func.children))
 
@@ -963,7 +963,7 @@
                 value = value.encode(self.dbencoding)
             self._query_attrs[_id] = value
         return '%%(%s)s' % _id
-        
+
     def visit_variableref(self, variableref, contextrels=None):
         """get the sql name for a variable reference"""
         # use accept, .variable may be a variable or a columnalias
@@ -979,7 +979,7 @@
             self.add_table(table)
             return sql
         return colalias._q_sql
-    
+
     def visit_variable(self, variable, contextrels=None):
         """get the table name and sql string for a variable"""
         if contextrels is None and variable.name in self._state.done:
@@ -989,7 +989,7 @@
         self._state.done.add(variable.name)
         vtablename = None
         if contextrels is None and variable.name in self._varmap:
-            sql, vtablename = self._var_info(variable)            
+            sql, vtablename = self._var_info(variable)
         elif variable.stinfo['attrvar']:
             # attribute variable (systematically used in rhs of final
             # relation(s)), get table name and sql from any rhs relation
@@ -1043,7 +1043,7 @@
             # so nothing to return here
             pass
         return ''
-    
+
     def _var_info(self, var):
         # if current var or one of its attribute is selected , it *must*
         # appear in the toplevel's FROM even if we're currently visiting
@@ -1067,7 +1067,7 @@
             sql = '%s.%seid' % (table, SQL_PREFIX)
             self.add_table('%s%s AS %s' % (SQL_PREFIX, etype, table), table, scope=scope)
         return sql, table
-    
+
     def _inlined_var_sql(self, var, rtype):
         try:
             sql = self._varmap['%s.%s' % (var.name, rtype)]
@@ -1077,14 +1077,14 @@
             sql = '%s.%s%s' % (self._var_table(var), SQL_PREFIX, rtype)
             #self._state.done.add(var.name)
         return sql
-        
+
     def _linked_var_sql(self, variable, contextrels=None):
         if contextrels is None:
             try:
-                return self._varmap[variable.name]            
+                return self._varmap[variable.name]
             except KeyError:
                 pass
-        rel = (contextrels and contextrels.get(variable.name) or 
+        rel = (contextrels and contextrels.get(variable.name) or
                variable.stinfo.get('principal') or
                iter(variable.stinfo['rhsrelations']).next())
         linkedvar = rel.children[0].variable
@@ -1096,7 +1096,7 @@
         try:
             sql = self._varmap['%s.%s' % (linkedvar.name, rel.r_type)]
         except KeyError:
-            linkedvar.accept(self)            
+            linkedvar.accept(self)
             sql = '%s.%s%s' % (linkedvar._q_sqltable, SQL_PREFIX, rel.r_type)
         return sql
 
@@ -1107,7 +1107,7 @@
         self._state.count += 1
         self.add_table('%s AS %s' % (tablename, alias), alias)
         return alias
-        
+
     def add_table(self, table, key=None, scope=-1):
         if key is None:
             key = table
@@ -1115,7 +1115,7 @@
             return
         self._state.tables[key] = (len(self._state.actual_tables) - 1, table)
         self._state.actual_tables[scope].append(table)
-    
+
     def replace_tables_by_outer_join(self, substitute, lefttable, *tables):
         for table in tables:
             try:
@@ -1160,8 +1160,8 @@
         for table, outerexpr in self._state.outer_tables.iteritems():
             if outerexpr == oldalias:
                 self._state.outer_tables[table] = newalias
-        self._state.outer_tables[table] = newalias        
-        
+        self._state.outer_tables[table] = newalias
+
     def _var_table(self, var):
         var.accept(self)#.visit_variable(var)
         return var._q_sqltable
@@ -1173,7 +1173,7 @@
         assert not self.schema.rschema(relation.r_type).is_final(), relation.r_type
         rid = 'rel_%s%s' % (relation.r_type, self._state.count)
         # relation's table is belonging to the root scope if it is the principal
-        # table of one of it's variable and if that variable belong's to parent 
+        # table of one of it's variable and if that variable belong's to parent
         # scope
         for varref in relation.iget_nodes(VariableRef):
             var = varref.variable
@@ -1192,7 +1192,7 @@
         relation._q_sqltable = rid
         self._state.done.add(relation)
         return rid
-    
+
     def _fti_table(self, relation):
         if relation in self._state.done:
             try:
@@ -1203,7 +1203,7 @@
         alias = self.alias_and_add_table(self.dbms_helper.fti_table)
         relation._q_sqltable = alias
         return alias
-        
+
     def _varmap_table_scope(self, select, table):
         """since a varmap table may be used for multiple variable, its scope is
         the most outer scope of each variables
--- a/server/ssplanner.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/ssplanner.py	Thu Apr 04 13:49:34 2019 +0200
@@ -78,35 +78,35 @@
                 rel = newroot.add_type_restriction(var, possibletypes)
             stinfo['typerels'] = frozenset((rel,))
             stinfo['possibletypes'] = possibletypes
-        
+
 class SSPlanner(object):
     """SingleSourcePlanner: build execution plan for rql queries
 
     optimized for single source repositories
     """
-    
+
     def __init__(self, schema, rqlhelper):
         self.schema = schema
         self.rqlhelper = rqlhelper
 
     def build_plan(self, plan):
         """build an execution plan from a RQL query
-        
+
         do nothing here, dispatch according to the statement type
         """
         build_plan = getattr(self, 'build_%s_plan' % plan.rqlst.TYPE)
         for step in build_plan(plan, plan.rqlst):
             plan.add_step(step)
-    
+
     def build_select_plan(self, plan, rqlst):
         """build execution plan for a SELECT RQL query. Suppose only one source
         is available and so avoid work need for query decomposition among sources
-               
+
         the rqlst should not be tagged at this point.
         """
         plan.preprocess(rqlst)
         return (OneFetchStep(plan, rqlst, plan.session.repo.sources),)
-            
+
     def build_insert_plan(self, plan, rqlst):
         """get an execution plan from an INSERT RQL query"""
         # each variable in main variables is a new entity to insert
@@ -123,7 +123,7 @@
         step.children += self._compute_relation_steps(plan, rqlst.solutions,
                                                       rqlst.where, to_select)
         return (step,)
-        
+
     def _compute_relation_steps(self, plan, solutions, restriction, to_select):
         """handle the selection of relations for an insert query"""
         for edef, rdefs in to_select.items():
@@ -146,7 +146,7 @@
             step = RelationsStep(plan, edef, rdefs)
             step.children += self._select_plan(plan, select, solutions)
             yield step
-    
+
     def build_delete_plan(self, plan, rqlst):
         """get an execution plan from a DELETE RQL query"""
         # build a select query to fetch entities to delete
@@ -174,7 +174,7 @@
         if etype != 'Any':
             select.add_type_restriction(varref.variable, etype)
         return self._select_plan(plan, select, solutions)
-        
+
     def _sel_relation_steps(self, plan, solutions, restriction, relation):
         """handle the selection of relations for a delete query"""
         select = Select()
@@ -185,7 +185,7 @@
         if restriction is not None:
             select.add_restriction(restriction.copy(select))
         return self._select_plan(plan, select, solutions)
-    
+
     def build_set_plan(self, plan, rqlst):
         """get an execution plan from an SET RQL query"""
         select = Select()
@@ -222,12 +222,12 @@
         return (step,)
 
     # internal methods ########################################################
-    
+
     def _select_plan(self, plan, select, solutions):
         union = Union()
         union.append(select)
         select.clean_solutions(solutions)
-        add_types_restriction(self.schema, select)        
+        add_types_restriction(self.schema, select)
         self.rqlhelper.annotate(union)
         return self.build_select_plan(plan, union)
 
@@ -260,35 +260,35 @@
         self.limit = limit
         self.offset = offset or None
 
-        
+
 class Step(object):
     """base abstract class for execution step"""
     def __init__(self, plan):
         self.plan = plan
         self.children = []
-        
+
     def execute_child(self):
         assert len(self.children) == 1
         return self.children[0].execute()
-    
+
     def execute_children(self):
         for step in self.children:
             step.execute()
-        
+
     def execute(self):
         """execute this step and store partial (eg this step) results"""
         raise NotImplementedError()
-    
+
     def mytest_repr(self):
         """return a representation of this step suitable for test"""
         return (self.__class__.__name__,)
-    
+
     def test_repr(self):
         """return a representation of this step suitable for test"""
         return self.mytest_repr() + (
             [step.test_repr() for step in self.children],)
 
-        
+
 class OneFetchStep(LimitOffsetMixIn, Step):
     """step consisting in fetching data from sources and directly returning
     results
@@ -305,7 +305,7 @@
         for select in self.union.children:
             select.limit = limit
             select.offset = offset
-        
+
     def execute(self):
         """call .syntax_tree_search with the given syntax tree on each
         source for each solution
@@ -375,22 +375,22 @@
 
     relations values comes from the latest result, with one columns for
     each relation defined in self.r_defs
-    
+
     for one entity definition, we'll construct N entity, where N is the
     number of the latest result
     """
-    
+
     FINAL = 0
     RELATION = 1
     REVERSE_RELATION = 2
-    
+
     def __init__(self, plan, e_def, r_defs):
         Step.__init__(self, plan)
         # partial entity definition to expand
         self.e_def = e_def
         # definition of relations to complete
         self.r_defs = r_defs
-        
+
     def execute(self):
         """execute this step"""
         base_e_def = self.e_def
@@ -415,7 +415,7 @@
 
 class InsertStep(Step):
     """step consisting in inserting new entities / relations"""
-    
+
     def execute(self):
         """execute this step"""
         for step in self.children:
@@ -444,34 +444,34 @@
         pending |= actual
         for eid in actual:
             delete(session, eid)
-            
-    
+
+
 class DeleteRelationsStep(Step):
     """step consisting in deleting relations"""
 
     def __init__(self, plan, rtype):
         Step.__init__(self, plan)
         self.rtype = rtype
-        
+
     def execute(self):
         """execute this step"""
         session = self.plan.session
         delete = session.repo.glob_delete_relation
         for subj, obj in self.execute_child():
             delete(session, subj, self.rtype, obj)
-    
+
 
 class UpdateStep(Step):
     """step consisting in updating entities / adding relations from relations
     definitions and from results fetched in previous step
     """
-    
+
     def __init__(self, plan, attribute_relations, relations, selected_index):
         Step.__init__(self, plan)
         self.attribute_relations = attribute_relations
         self.relations = relations
         self.selected_index = selected_index
-        
+
     def execute(self):
         """execute this step"""
         plan = self.plan
--- a/server/test/data/migrschema/Affaire.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/data/migrschema/Affaire.py	Thu Apr 04 13:49:34 2019 +0200
@@ -6,7 +6,7 @@
         'update': ('managers', 'owners', ERQLExpression('X concerne S, S owned_by U')),
         'delete': ('managers', 'owners', ERQLExpression('X concerne S, S owned_by U')),
         }
-    
+
     ref = String(fulltextindexed=True, indexed=True,
                  constraints=[SizeConstraint(16)])
     sujet = String(fulltextindexed=True,
@@ -18,4 +18,4 @@
         'add':    ('managers', RRQLExpression('U has_update_permission S')),
         'delete': ('managers', RRQLExpression('O owned_by U')),
         }
-    
+
--- a/server/test/data/migrschema/Folder2.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/data/migrschema/Folder2.py	Thu Apr 04 13:49:34 2019 +0200
@@ -22,4 +22,4 @@
     # is_about has been renamed into filed_under
     #//* is_about Folder
     #* filed_under Folder
-    
+
--- a/server/test/data/migrschema/Note.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/data/migrschema/Note.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,13 +1,13 @@
 class Note(EntityType):
-    
+
     permissions = {'read':   ('managers', 'users', 'guests',),
                    'update': ('managers', 'owners',),
                    'delete': ('managers', ),
-                   'add':    ('managers', 
+                   'add':    ('managers',
                               ERQLExpression('X ecrit_part PE, U in_group G, '
                                              'PE require_permission P, P name "add_note", '
                                              'P require_group G'),)}
-    
+
     date = Datetime()
     type = String(maxsize=1)
     whatever = Int()
@@ -19,7 +19,7 @@
 class ecrit_par(RelationType):
     permissions = {'read':   ('managers', 'users', 'guests',),
                    'delete': ('managers', ),
-                   'add':    ('managers', 
+                   'add':    ('managers',
                               RRQLExpression('O require_permission P, P name "add_note", '
                                              'U in_group G, P require_group G'),)
                    }
--- a/server/test/data/schema/Affaire.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/data/schema/Affaire.py	Thu Apr 04 13:49:34 2019 +0200
@@ -2,13 +2,13 @@
 
 class Affaire(WorkflowableEntityType):
     permissions = {
-        'read':   ('managers', 
+        'read':   ('managers',
                    ERQLExpression('X owned_by U'), ERQLExpression('X concerne S?, S owned_by U')),
         'add':    ('managers', ERQLExpression('X concerne S, S owned_by U')),
         'update': ('managers', 'owners', ERQLExpression('X in_state S, S name in ("pitetre", "en cours")')),
         'delete': ('managers', 'owners', ERQLExpression('X concerne S, S owned_by U')),
         }
-    
+
     ref = String(fulltextindexed=True, indexed=True,
                  constraints=[SizeConstraint(16)])
     sujet = String(fulltextindexed=True,
@@ -23,12 +23,12 @@
 
     depends_on = SubjectRelation('Affaire')
     require_permission = SubjectRelation('CWPermission')
-    
+
 class concerne(RelationType):
     permissions = {
         'read':   ('managers', 'users', 'guests'),
         'add':    ('managers', RRQLExpression('U has_update_permission S')),
         'delete': ('managers', RRQLExpression('O owned_by U')),
         }
-    
 
+
--- a/server/test/data/schema/Societe.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/data/schema/Societe.py	Thu Apr 04 13:49:34 2019 +0200
@@ -5,10 +5,10 @@
         'delete': ('managers', 'owners', ERQLExpression('U login L, X nom L')),
         'add': ('managers', 'users',)
         }
-    
+
     nom  = String(maxsize=64, fulltextindexed=True)
     web  = String(maxsize=128)
-    type  = String(maxsize=128) # attribute in common with Note 
+    type  = String(maxsize=128) # attribute in common with Note
     tel  = Int()
     fax  = Int()
     rncs = String(maxsize=128)
--- a/server/test/data/schema/note.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/data/schema/note.py	Thu Apr 04 13:49:34 2019 +0200
@@ -11,7 +11,7 @@
     object = 'State'
     cardinality = '1*'
     constraints=[RQLConstraint('S is ET, O state_of ET')]
-    
+
 class wf_info_for(RelationDefinition):
     subject = 'TrInfo'
     object = 'Note'
--- a/server/test/unittest_checkintegrity.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/unittest_checkintegrity.py	Thu Apr 04 13:49:34 2019 +0200
@@ -17,6 +17,6 @@
         finally:
             sys.stderr = sys.__stderr__
             sys.stdout = sys.__stdout__
-        
+
 if __name__ == '__main__':
     unittest_main()
--- a/server/test/unittest_config.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/unittest_config.py	Thu Apr 04 13:49:34 2019 +0200
@@ -13,7 +13,7 @@
             @staticmethod
             def registry_objects(registry):
                 return []
-            
+
         cfg1 = TestServerConfiguration('data/config1')
         cfg1.bootstrap_cubes()
         cfg2 = TestServerConfiguration('data/config2')
@@ -21,7 +21,7 @@
         self.failIf(cfg1.load_hooks(vreg) is cfg2.load_hooks(vreg))
         self.failUnless('after_add_relation' in cfg1.load_hooks(vreg))
         self.failUnless('after_delete_relation' in cfg2.load_hooks(vreg))
-        
+
 
 if __name__ == '__main__':
     unittest_main()
--- a/server/test/unittest_hooksmanager.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/unittest_hooksmanager.py	Thu Apr 04 13:49:34 2019 +0200
@@ -16,7 +16,7 @@
 class HooksManagerTC(TestCase):
     args = (None,)
     kwargs = {'a': 1}
-    
+
     def setUp(self):
         """ called before each test from this class """
         self.o = HooksManager(schema)
@@ -32,22 +32,22 @@
                           self.o.register_hook, self._hook, 'server_startup', 'CWEType')
         self.assertRaises(AssertionError,
                           self.o.register_hook, self._hook, 'server_shutdown', 'CWEType')
-        
+
     def test_register_hook1(self):
         self.o.register_hook(self._hook, 'before_add_entity')
         self.o.register_hook(self._hook, 'before_delete_entity', 'Personne')
         self._test_called_hooks()
-        
+
     def test_register_hook2(self):
         self.o.register_hook(self._hook, 'before_add_entity', '')
         self.o.register_hook(self._hook, 'before_delete_entity', 'Personne')
         self._test_called_hooks()
-        
+
     def test_register_hook3(self):
         self.o.register_hook(self._hook, 'before_add_entity', None)
         self.o.register_hook(self._hook, 'before_delete_entity', 'Personne')
         self._test_called_hooks()
-        
+
     def test_register_hooks(self):
         self.o.register_hooks({'before_add_entity' : {'': [self._hook]},
                                'before_delete_entity' : {'Personne': [self._hook]},
@@ -62,7 +62,7 @@
         self.o.unregister_hook(self._hook, 'after_delete_entity', 'Personne')
         # no hook should be called there
         self.o.call_hooks('after_delete_entity', 'Personne')
-        
+
 
     def _test_called_hooks(self):
         self.assertRaises(HookCalled,
@@ -102,9 +102,9 @@
                              'before_add_relation', 'concerne')
         self.assertEquals(self.called, [])
         self.o.call_hooks('before_add_relation', 'concerne', 'USER',
-                          1, 'concerne', 2)        
+                          1, 'concerne', 2)
         self.assertEquals(self.called, [(1, 'concerne', 2)])
-        
+
     def test_after_add_relation(self):
         """make sure after_xxx_relation hooks are deferred"""
         self.o.register_hook(self._after_relation_hook,
@@ -115,14 +115,14 @@
         self.o.call_hooks('after_add_relation', 'concerne', 'USER',
                           3, 'concerne', 4)
         self.assertEquals(self.called, [(1, 'concerne', 2), (3, 'concerne', 4)])
-    
+
     def test_before_delete_relation(self):
         """make sure before_xxx_relation hooks are called directly"""
         self.o.register_hook(self._before_relation_hook,
                              'before_delete_relation', 'concerne')
         self.assertEquals(self.called, [])
         self.o.call_hooks('before_delete_relation', 'concerne', 'USER',
-                          1, 'concerne', 2)        
+                          1, 'concerne', 2)
         self.assertEquals(self.called, [(1, 'concerne', 2)])
 
     def test_after_delete_relation(self):
@@ -166,7 +166,7 @@
     schema = schema # set for actual hooks at registration time
     events = ('whatever', 'another')
     accepts = ('Societe', 'Division')
-    
+
 class HookTC(RepositoryBasedTC):
     def test_inheritance(self):
         self.assertEquals(list(MyHook.register_to()),
--- a/server/test/unittest_ldapuser.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/unittest_ldapuser.py	Thu Apr 04 13:49:34 2019 +0200
@@ -34,14 +34,14 @@
 
 class LDAPUserSourceTC(RepositoryBasedTC):
     repo, cnx = repo, cnx
-    
+
     def patch_authenticate(self):
         self._orig_authenticate = LDAPUserSource.authenticate
         LDAPUserSource.authenticate = nopwd_authenticate
 
     def setUp(self):
         self._prepare()
-        # XXX: need this first query else we get 'database is locked' from 
+        # XXX: need this first query else we get 'database is locked' from
         # sqlite since it doesn't support multiple connections on the same
         # database
         # so doing, ldap inserted users don't get removed between each test
@@ -50,21 +50,21 @@
         # check we get some users from ldap
         self.assert_(len(rset) > 1)
         self.maxeid = self.execute('Any MAX(X)')[0][0]
-        
+
     def tearDown(self):
         if hasattr(self, '_orig_authenticate'):
             LDAPUserSource.authenticate = self._orig_authenticate
         RepositoryBasedTC.tearDown(self)
-            
+
     def test_authenticate(self):
         source = self.repo.sources_by_uri['ldapuser']
         self.assertRaises(AuthenticationError,
                           source.authenticate, self.session, 'toto', 'toto')
-        
+
     def test_synchronize(self):
         source = self.repo.sources_by_uri['ldapuser']
         source.synchronize()
-        
+
     def test_base(self):
         # check a known one
         e = self.execute('CWUser X WHERE X login "syt"').get_entity(0, 0)
@@ -139,7 +139,7 @@
     def test_or(self):
         rset = self.execute('DISTINCT Any X WHERE X login "syt" OR (X in_group G, G name "managers")')
         self.assertEquals(len(rset), 2, rset.rows) # syt + admin
-        
+
     def test_nonregr_set_owned_by(self):
         # test that when a user coming from ldap is triggering a transition
         # the related TrInfo has correct owner information
@@ -175,7 +175,7 @@
     def test_multiple_entities_from_different_sources(self):
         self.create_user('cochon')
         self.failUnless(self.execute('Any X,Y WHERE X login "syt", Y login "cochon"'))
-        
+
     def test_exists1(self):
         self.add_entity('CWGroup', name=u'bougloup1')
         self.add_entity('CWGroup', name=u'bougloup2')
@@ -241,11 +241,11 @@
         self.assertEquals(sorted(rset.rows), [['guests', 'cochon'],
                                               ['users', 'cochon'],
                                               ['users', 'syt']])
-        
+
     def test_cd_restriction(self):
         rset = self.execute('CWUser X WHERE X creation_date > "2009-02-01"')
         self.assertEquals(len(rset), 2) # admin/anon but no ldap user since it doesn't support creation_date
-        
+
     def test_union(self):
         afeids = self.execute('State X')
         ueids = self.execute('CWUser X')
@@ -257,21 +257,21 @@
         self.create_user('iaminguestsgrouponly', groups=('guests',))
         cnx = self.login('iaminguestsgrouponly')
         return cnx.cursor()
-    
+
     def test_security1(self):
         cu = self._init_security_test()
         rset = cu.execute('Any X WHERE X login "syt"')
         self.assertEquals(rset.rows, [])
         rset = cu.execute('Any X WHERE X login "iaminguestsgrouponly"')
         self.assertEquals(len(rset.rows), 1)
-    
+
     def test_security2(self):
         cu = self._init_security_test()
         rset = cu.execute('Any X WHERE X has_text "syt"')
         self.assertEquals(rset.rows, [])
         rset = cu.execute('Any X WHERE X has_text "iaminguestsgrouponly"')
         self.assertEquals(len(rset.rows), 1)
-    
+
     def test_security3(self):
         cu = self._init_security_test()
         rset = cu.execute('Any F WHERE X has_text "syt", X firstname F')
@@ -298,13 +298,13 @@
         emaileid = self.execute('INSERT EmailAddress X: X address "toto@logilab.org"')[0][0]
         self.execute('Any X,AA WHERE X use_email Y, Y eid %(x)s, X modification_date AA',
                      {'x': emaileid})
-        
+
     def test_nonregr5(self):
         # original jpl query:
         # Any X, NOW - CD, P WHERE P is Project, U interested_in P, U is CWUser, U login "sthenault", X concerns P, X creation_date CD ORDERBY CD DESC LIMIT 5
         rql = 'Any X, NOW - CD, P ORDERBY CD DESC LIMIT 5 WHERE P bookmarked_by U, U login "%s", P is X, X creation_date CD' % self.session.user.login
         self.execute(rql, )#{'x': })
-        
+
     def test_nonregr6(self):
         self.execute('Any B,U,UL GROUPBY B,U,UL WHERE B created_by U?, B is File '
                      'WITH U,UL BEING (Any U,UL WHERE ME eid %(x)s, (EXISTS(U identity ME) '
@@ -350,33 +350,33 @@
 
 class RQL2LDAPFilterTC(RQLGeneratorTC):
     schema = repo.schema
-    
+
     def setUp(self):
         RQLGeneratorTC.setUp(self)
         ldapsource = repo.sources[-1]
         self.pool = repo._get_pool()
         session = mock_object(pool=self.pool)
         self.o = RQL2LDAPFilter(ldapsource, session)
-        
+
     def tearDown(self):
         repo._free_pool(self.pool)
         RQLGeneratorTC.tearDown(self)
-        
+
     def test_base(self):
         rqlst = self._prepare('CWUser X WHERE X login "toto"').children[0]
         self.assertEquals(self.o.generate(rqlst, 'X')[1],
                           '(&(objectClass=top)(objectClass=posixAccount)(uid=toto))')
-        
+
     def test_kwargs(self):
         rqlst = self._prepare('CWUser X WHERE X login %(x)s').children[0]
         self.o._args = {'x': "toto"}
         self.assertEquals(self.o.generate(rqlst, 'X')[1],
                           '(&(objectClass=top)(objectClass=posixAccount)(uid=toto))')
-        
+
     def test_get_attr(self):
         rqlst = self._prepare('Any X WHERE E firstname X, E eid 12').children[0]
         self.assertRaises(UnknownEid, self.o.generate, rqlst, 'E')
-        
-        
+
+
 if __name__ == '__main__':
     unittest_main()
--- a/server/test/unittest_rqlannotation.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/unittest_rqlannotation.py	Thu Apr 04 13:49:34 2019 +0200
@@ -9,15 +9,15 @@
 
 class SQLGenAnnotatorTC(BaseQuerierTC):
     repo = repo
-    
+
     def get_max_eid(self):
         # no need for cleanup here
         return None
     def cleanup(self):
         # no need for cleanup here
         pass
-                
-    def test_0_1(self):        
+
+    def test_0_1(self):
         rqlst = self._prepare('Any SEN,RN,OEN WHERE X from_entity SE, SE eid 44, X relation_type R, R eid 139, X to_entity OE, OE eid 42, R name RN, SE name SEN, OE name OEN')
         self.assertEquals(rqlst.defined_vars['SE']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['OE']._q_invariant, False)
@@ -25,13 +25,13 @@
         self.assertEquals(rqlst.defined_vars['SE'].stinfo['attrvar'], None)
         self.assertEquals(rqlst.defined_vars['OE'].stinfo['attrvar'], None)
         self.assertEquals(rqlst.defined_vars['R'].stinfo['attrvar'], None)
-        
-    def test_0_2(self):        
+
+    def test_0_2(self):
         rqlst = self._prepare('Any O WHERE NOT S ecrit_par O, S eid 1, S inline1 P, O inline2 P')
         self.assertEquals(rqlst.defined_vars['P']._q_invariant, True)
         self.assertEquals(rqlst.defined_vars['O'].stinfo['attrvar'], None)
 
-    def test_0_4(self):        
+    def test_0_4(self):
         rqlst = self._prepare('Any A,B,C WHERE A eid 12,A comment B, A ?wf_info_for C')
         self.assertEquals(rqlst.defined_vars['A']._q_invariant, False)
         self.assert_(rqlst.defined_vars['B'].stinfo['attrvar'])
@@ -40,28 +40,28 @@
                                       {'A': 'TrInfo', 'B': 'String', 'C': 'CWUser'},
                                       {'A': 'TrInfo', 'B': 'String', 'C': 'Note'}])
 
-    def test_0_5(self):        
+    def test_0_5(self):
         rqlst = self._prepare('Any P WHERE N ecrit_par P, N eid 0')
         self.assertEquals(rqlst.defined_vars['N']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['P']._q_invariant, True)
 
-    def test_0_6(self):        
+    def test_0_6(self):
         rqlst = self._prepare('Any P WHERE NOT N ecrit_par P, N eid 512')
         self.assertEquals(rqlst.defined_vars['P']._q_invariant, False)
 
-    def test_0_7(self):        
+    def test_0_7(self):
         rqlst = self._prepare('Personne X,Y where X nom NX, Y nom NX, X eid XE, not Y eid XE')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
         self.assert_(rqlst.defined_vars['XE'].stinfo['attrvar'])
 
-    def test_0_8(self):        
+    def test_0_8(self):
         rqlst = self._prepare('Any P WHERE X eid 0, NOT X connait P')
         self.assertEquals(rqlst.defined_vars['P']._q_invariant, False)
         #self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
         self.assertEquals(len(rqlst.solutions), 1, rqlst.solutions)
 
-    def test_0_10(self):        
+    def test_0_10(self):
         rqlst = self._prepare('Any X WHERE X concerne Y, Y is Note')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
         self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
@@ -71,78 +71,78 @@
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
 
-    def test_0_12(self):        
+    def test_0_12(self):
         rqlst = self._prepare('Personne P WHERE P concerne A, A concerne S, S nom "Logilab"')
         self.assertEquals(rqlst.defined_vars['P']._q_invariant, True)
         self.assertEquals(rqlst.defined_vars['A']._q_invariant, True)
         self.assertEquals(rqlst.defined_vars['S']._q_invariant, False)
-        
+
     def test_1_0(self):
         rqlst = self._prepare('Any X,Y WHERE X created_by Y, X eid 5, NOT Y eid 6')
         self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
-                
+
     def test_1_1(self):
         rqlst = self._prepare('Any X,Y WHERE X created_by Y, X eid 5, NOT Y eid IN (6,7)')
         self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
-                
+
     def test_2(self):
         rqlst = self._prepare('Any X WHERE X identity Y, Y eid 1')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
-        
+
     def test_7(self):
         rqlst = self._prepare('Personne X,Y where X nom NX, Y nom NX, X eid XE, not Y eid XE')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
-        
+
     def test_optional_inlined(self):
         rqlst = self._prepare('Any X,S where X from_state S?')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['S']._q_invariant, True)
-                
+
     def test_optional_inlined_2(self):
         rqlst = self._prepare('Any N,A WHERE N? inline1 A')
         self.assertEquals(rqlst.defined_vars['N']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['A']._q_invariant, False)
-        
+
     def test_optional_1(self):
         rqlst = self._prepare('Any X,S WHERE X travaille S?')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['S']._q_invariant, True)
-        
+
     def test_greater_eid(self):
         rqlst = self._prepare('Any X WHERE X eid > 5')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-        
+
     def test_greater_eid_typed(self):
         rqlst = self._prepare('Any X WHERE X eid > 5, X is Note')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-        
+
     def test_max_eid(self):
         rqlst = self._prepare('Any MAX(X)')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-        
+
     def test_max_eid_typed(self):
         rqlst = self._prepare('Any MAX(X) WHERE X is Note')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
-        
+
     def test_all_entities(self):
         rqlst = self._prepare('Any X')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-        
+
     def test_all_typed_entity(self):
         rqlst = self._prepare('Any X WHERE X is Note')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
-        
+
     def test_has_text_1(self):
         rqlst = self._prepare('Any X WHERE X has_text "toto tata"')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
         self.assertEquals(rqlst.defined_vars['X'].stinfo['principal'].r_type, 'has_text')
-        
+
     def test_has_text_2(self):
         rqlst = self._prepare('Any X WHERE X is Personne, X has_text "coucou"')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
         self.assertEquals(rqlst.defined_vars['X'].stinfo['principal'].r_type, 'has_text')
-        
+
     def test_not_relation_1(self):
         # P can't be invariant since deambiguification caused by "NOT X require_permission P"
         # is not considered by generated sql (NOT EXISTS(...))
@@ -150,31 +150,31 @@
         self.assertEquals(rqlst.defined_vars['P']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['G']._q_invariant, True)
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-        
+
     def test_not_relation_2(self):
         rqlst = self._prepare('TrInfo X WHERE X eid 2, NOT X from_state Y, Y is State')
         self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
-                
+
     def test_not_relation_3(self):
         rqlst = self._prepare('Any X, Y WHERE X eid 1, Y eid in (2, 3)')
         self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
-                
+
     def test_not_relation_4_1(self):
         rqlst = self._prepare('Note X WHERE NOT Y evaluee X')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
-        
+
     def test_not_relation_4_2(self):
         rqlst = self._prepare('Any X WHERE NOT Y evaluee X')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
-        
+
     def test_not_relation_4_3(self):
         rqlst = self._prepare('Any Y WHERE NOT Y evaluee X')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
         self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
-        
+
     def test_not_relation_4_4(self):
         rqlst = self._prepare('Any X WHERE NOT Y evaluee X, Y is CWUser')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
@@ -184,7 +184,7 @@
         rqlst = self._prepare('Any X WHERE NOT Y evaluee X, Y eid %s, X is Note' % self.ueid)
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
         self.assertEquals(rqlst.solutions, [{'X': 'Note'}])
-        
+
     def test_not_relation_5_1(self):
         rqlst = self._prepare('Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), NOT X read_permission Y')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
@@ -201,64 +201,64 @@
         self.assertEquals(rqlst.defined_vars['A']._q_invariant, True)
 
     def test_not_relation_7(self):
-        rqlst = self._prepare('Any K,V WHERE P is CWProperty, P pkey K, P value V, NOT P for_user U') 
+        rqlst = self._prepare('Any K,V WHERE P is CWProperty, P pkey K, P value V, NOT P for_user U')
         self.assertEquals(rqlst.defined_vars['P']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['U']._q_invariant, True)
-       
-    def test_exists_1(self):        
+
+    def test_exists_1(self):
         rqlst = self._prepare('Any U WHERE U eid IN (1,2), EXISTS(X owned_by U)')
         self.assertEquals(rqlst.defined_vars['U']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-       
-    def test_exists_2(self):        
+
+    def test_exists_2(self):
         rqlst = self._prepare('Any U WHERE EXISTS(U eid IN (1,2), X owned_by U)')
         self.assertEquals(rqlst.defined_vars['U']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
 
-    def test_exists_3(self):        
+    def test_exists_3(self):
         rqlst = self._prepare('Any U WHERE EXISTS(X owned_by U, X bookmarked_by U)')
         self.assertEquals(rqlst.defined_vars['U']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-        
+
     def test_exists_4(self):
         rqlst = self._prepare('Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), EXISTS(X read_permission Y)')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
-        
+
     def test_exists_5(self):
         rqlst = self._prepare('DISTINCT Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), EXISTS(X read_permission Y)')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
 
-    def test_not_exists_1(self):        
+    def test_not_exists_1(self):
         rqlst = self._prepare('Any U WHERE NOT EXISTS(X owned_by U, X bookmarked_by U)')
         self.assertEquals(rqlst.defined_vars['U']._q_invariant, False)
-        self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)        
+        self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
 
-    def test_not_exists_2(self):        
+    def test_not_exists_2(self):
         rqlst = self._prepare('Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), NOT EXISTS(X read_permission Y)')
         self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
 
-    def test_not_exists_distinct_1(self):        
+    def test_not_exists_distinct_1(self):
         rqlst = self._prepare('DISTINCT Any X,Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), NOT EXISTS(X read_permission Y)')
         self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
-        
-    def test_or_1(self):        
+
+    def test_or_1(self):
         rqlst = self._prepare('Any X WHERE X concerne B OR C concerne X, B eid 12, C eid 13')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
 
-    def test_or_2(self):        
+    def test_or_2(self):
         rqlst = self._prepare('Any X WHERE X created_by U, X concerne B OR C concerne X, B eid 12, C eid 13')
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-        self.assertEquals(rqlst.defined_vars['U']._q_invariant, True) 
+        self.assertEquals(rqlst.defined_vars['U']._q_invariant, True)
         self.assertEquals(rqlst.defined_vars['X'].stinfo['principal'].r_type, 'created_by')
 
-    def test_or_3(self):        
+    def test_or_3(self):
         rqlst = self._prepare('Any N WHERE A evaluee N or EXISTS(N todo_by U)')
         self.assertEquals(rqlst.defined_vars['N']._q_invariant, False)
-        self.assertEquals(rqlst.defined_vars['A']._q_invariant, True) 
-        self.assertEquals(rqlst.defined_vars['U']._q_invariant, True) 
-        
+        self.assertEquals(rqlst.defined_vars['A']._q_invariant, True)
+        self.assertEquals(rqlst.defined_vars['U']._q_invariant, True)
+
     def test_or_exists_1(self):
         # query generated by security rewriting
         rqlst = self._prepare('DISTINCT Any A,S WHERE A is Affaire, S nom "chouette", S is IN(Division, Societe, SubDivision),'
@@ -270,13 +270,13 @@
         self.assertEquals(rqlst.defined_vars['A']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['S']._q_invariant, False)
 
-    def test_or_exists_2(self):        
+    def test_or_exists_2(self):
         rqlst = self._prepare('Any U WHERE EXISTS(U in_group G, G name "managers") OR EXISTS(X owned_by U, X bookmarked_by U)')
         self.assertEquals(rqlst.defined_vars['U']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['G']._q_invariant, False)
         self.assertEquals(rqlst.defined_vars['X']._q_invariant, True)
-        
-    def test_or_exists_3(self):        
+
+    def test_or_exists_3(self):
         rqlst = self._prepare('Any COUNT(S),CS GROUPBY CS ORDERBY 1 DESC LIMIT 10 '
                               'WHERE C is Societe, S concerne C, C nom CS, '
                               '(EXISTS(S owned_by 1)) OR (EXISTS(S documented_by N, N title "published"))')
@@ -286,7 +286,7 @@
                               '(EXISTS(S owned_by 1)) OR (EXISTS(S documented_by N, N title "published"))')
         self.assertEquals(rqlst.defined_vars['S']._q_invariant, True)
 
-    def test_nonregr_ambiguity(self):        
+    def test_nonregr_ambiguity(self):
         rqlst = self._prepare('Note N WHERE N attachment F')
         # N may be an image as well, not invariant
         self.assertEquals(rqlst.defined_vars['N']._q_invariant, False)
--- a/server/test/unittest_security.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/unittest_security.py	Thu Apr 04 13:49:34 2019 +0200
@@ -15,15 +15,15 @@
         self.create_user('iaminusersgrouponly')
         self.readoriggroups = self.schema['Personne'].get_groups('read')
         self.addoriggroups = self.schema['Personne'].get_groups('add')
-        
+
     def tearDown(self):
         RepositoryBasedTC.tearDown(self)
         self.schema['Personne'].set_groups('read', self.readoriggroups)
         self.schema['Personne'].set_groups('add', self.addoriggroups)
 
-        
+
 class LowLevelSecurityFunctionTC(BaseSecurityTC):
-    
+
     def test_check_read_access(self):
         rql = u'Personne U where U nom "managers"'
         rqlst = self.repo.querier._rqlhelper.parse(rql).children[0]
@@ -38,7 +38,7 @@
                           check_read_access,
                           self.schema, cnx.user(self.current_session()), rqlst, solution)
         self.assertRaises(Unauthorized, cu.execute, rql)
-            
+
     def test_upassword_not_selectable(self):
         self.assertRaises(Unauthorized,
                           self.execute, 'Any X,P WHERE X is CWUser, X upassword P')
@@ -47,10 +47,10 @@
         cu = cnx.cursor()
         self.assertRaises(Unauthorized,
                           cu.execute, 'Any X,P WHERE X is CWUser, X upassword P')
-        
-    
+
+
 class SecurityTC(BaseSecurityTC):
-    
+
     def setUp(self):
         BaseSecurityTC.setUp(self)
         # implicitly test manager can add some entities
@@ -66,7 +66,7 @@
         cu.execute("INSERT Personne X: X nom 'bidule'")
         self.assertRaises(Unauthorized, cnx.commit)
         self.assertEquals(cu.execute('Personne X').rowcount, 1)
-        
+
     def test_insert_rql_permission(self):
         # test user can only add une affaire related to a societe he owns
         cnx = self.login('iaminusersgrouponly')
@@ -82,7 +82,7 @@
         cu.execute("INSERT Societe X: X nom 'chouette'")
         cu.execute("SET A concerne S WHERE A sujet 'cool', S nom 'chouette'")
         cnx.commit()
-        
+
     def test_update_security_1(self):
         cnx = self.login('anon')
         cu = cnx.cursor()
@@ -91,7 +91,7 @@
         self.assertRaises(Unauthorized, cnx.commit)
         self.restore_connection()
         self.assertEquals(self.execute('Personne X WHERE X nom "bidulechouette"').rowcount, 0)
-        
+
     def test_update_security_2(self):
         cnx = self.login('anon')
         cu = cnx.cursor()
@@ -109,7 +109,7 @@
         cu.execute("INSERT Personne X: X nom 'biduuule'")
         cu.execute("INSERT Societe X: X nom 'looogilab'")
         cu.execute("SET X travaille S WHERE X nom 'biduuule', S nom 'looogilab'")
-        
+
     def test_update_rql_permission(self):
         self.execute("SET A concerne S WHERE A is Affaire, S is Societe")
         self.commit()
@@ -121,13 +121,13 @@
         cnx.commit()
         # to actually get Unauthorized exception, try to update an entity we can read
         cu.execute("SET X nom 'toto' WHERE X is Societe")
-        self.assertRaises(Unauthorized, cnx.commit)        
+        self.assertRaises(Unauthorized, cnx.commit)
         cu.execute("INSERT Affaire X: X sujet 'pascool'")
         cu.execute("INSERT Societe X: X nom 'chouette'")
         cu.execute("SET A concerne S WHERE A sujet 'pascool', S nom 'chouette'")
         cu.execute("SET X sujet 'habahsicestcool' WHERE X sujet 'pascool'")
         cnx.commit()
-    
+
     def test_delete_security(self):
         # FIXME: sample below fails because we don't detect "owner" can't delete
         # user anyway, and since no user with login == 'bidule' exists, no
@@ -139,14 +139,14 @@
         cnx = self.login('iaminusersgrouponly')
         cu = cnx.cursor()
         self.assertRaises(Unauthorized, cu.execute, "DELETE CWGroup Y WHERE Y name 'staff'")
-        
+
     def test_delete_rql_permission(self):
         self.execute("SET A concerne S WHERE A is Affaire, S is Societe")
         self.commit()
         # test user can only dele une affaire related to a societe he owns
         cnx = self.login('iaminusersgrouponly')
         cu = cnx.cursor()
-        # this won't actually do anything since the selection query won't return anything        
+        # this won't actually do anything since the selection query won't return anything
         cu.execute("DELETE Affaire X")
         cnx.commit()
         # to actually get Unauthorized exception, try to delete an entity we can read
@@ -227,7 +227,7 @@
         self.assertRaises(Unauthorized, cnx.commit)
 
     # read security test
-    
+
     def test_read_base(self):
         self.schema['Personne'].set_groups('read', ('users', 'managers'))
         cnx = self.login('anon')
@@ -256,7 +256,7 @@
         self.assertEquals(rset.rows, [[aff2]])
         rset = cu.execute('Affaire X WHERE NOT X eid %(x)s', {'x': aff2}, 'x')
         self.assertEquals(rset.rows, [])
-        
+
     def test_read_erqlexpr_has_text1(self):
         aff1 = self.execute("INSERT Affaire X: X sujet 'cool'")[0][0]
         card1 = self.execute("INSERT Card X: X title 'cool'")[0][0]
@@ -286,7 +286,7 @@
         rset = cu.execute('Any N WHERE N has_text "bidule"')
         self.assertEquals(len(rset.rows), 1, rset.rows)
         rset = cu.execute('Any N WITH N BEING (Any N WHERE N has_text "bidule")')
-        self.assertEquals(len(rset.rows), 1, rset.rows)        
+        self.assertEquals(len(rset.rows), 1, rset.rows)
 
     def test_read_erqlexpr_optional_rel(self):
         self.execute("INSERT Personne X: X nom 'bidule'")
@@ -304,7 +304,7 @@
         cnx = self.login('iaminusersgrouponly')
         cu = cnx.cursor()
         rset = cu.execute('Any COUNT(X) WHERE X is Affaire')
-        self.assertEquals(rset.rows, [[0]])        
+        self.assertEquals(rset.rows, [[0]])
         aff2 = cu.execute("INSERT Affaire X: X sujet 'cool'")[0][0]
         soc1 = cu.execute("INSERT Societe X: X nom 'chouette'")[0][0]
         cu.execute("SET A concerne S WHERE A is Affaire, S is Societe")
@@ -320,7 +320,7 @@
         values = dict(rset)
         self.assertEquals(values['Affaire'], 1)
         self.assertEquals(values['Societe'], 2)
-        
+
 
     def test_attribute_security(self):
         # only managers should be able to edit the 'test' attribute of Personne entities
@@ -343,7 +343,7 @@
         cu.execute('SET X web "http://www.logilab.org" WHERE X eid %(x)s', {'x': eid}, 'x')
         cnx.commit()
         cnx.close()
-        
+
     def test_attribute_security_rqlexpr(self):
         # Note.para attribute editable by managers or if the note is in "todo" state
         eid = self.execute("INSERT Note X: X para 'bidule', X in_state S WHERE S name 'done'")[0][0]
@@ -384,10 +384,10 @@
         self.failUnless(x.creation_date)
         cnx.rollback()
 
-        
+
 class BaseSchemaSecurityTC(BaseSecurityTC):
     """tests related to the base schema permission configuration"""
-        
+
     def test_user_can_delete_object_he_created(self):
         # even if some other user have changed object'state
         cnx = self.login('iaminusersgrouponly')
@@ -400,7 +400,7 @@
         self.execute('SET X in_state S WHERE X ref "ARCT01", S name "ben non"')
         self.commit()
         self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01"')),
-                          2) 
+                          2)
         self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01",'
                                            'X owned_by U, U login "admin"')),
                           1) # TrInfo at the above state change
@@ -426,19 +426,19 @@
         self.assert_(cu.execute('CWGroup X'))
         # should only be able to read the anonymous user, not another one
         origuser = self.session.user
-        self.assertRaises(Unauthorized, 
+        self.assertRaises(Unauthorized,
                           cu.execute, 'CWUser X WHERE X eid %(x)s', {'x': origuser.eid}, 'x')
         # nothing selected, nothing updated, no exception raised
         #self.assertRaises(Unauthorized,
         #                  cu.execute, 'SET X login "toto" WHERE X eid %(x)s',
         #                  {'x': self.user.eid})
-        
+
         rset = cu.execute('CWUser X WHERE X eid %(x)s', {'x': anon.eid}, 'x')
         self.assertEquals(rset.rows, [[anon.eid]])
         # but can't modify it
         cu.execute('SET X login "toto" WHERE X eid %(x)s', {'x': anon.eid})
         self.assertRaises(Unauthorized, cnx.commit)
-    
+
     def test_in_group_relation(self):
         cnx = self.login('iaminusersgrouponly')
         cu = cnx.cursor()
@@ -454,7 +454,7 @@
         cu = cnx.cursor()
         rql = u"SET X owned_by U WHERE U login 'iaminusersgrouponly', X is Personne"
         self.assertRaises(Unauthorized, cu.execute, rql)
-        
+
     def test_bookmarked_by_guests_security(self):
         beid1 = self.execute('INSERT Bookmark B: B path "?vid=manage", B title "manage"')[0][0]
         beid2 = self.execute('INSERT Bookmark B: B path "?vid=index", B title "index", B bookmarked_by U WHERE U login "anon"')[0][0]
@@ -475,7 +475,7 @@
         self.assertRaises(Unauthorized,
                           cu.execute, 'SET B bookmarked_by U WHERE U eid %(x)s, B eid %(b)s',
                           {'x': anoneid, 'b': beid1}, 'x')
-        
+
 
     def test_ambigous_ordered(self):
         cnx = self.login('anon')
@@ -494,7 +494,7 @@
         # needed to avoid check_perm error
         session.set_pool()
         # needed to remove rql expr granting update perm to the user
-        self.schema['Affaire'].set_rqlexprs('update', ()) 
+        self.schema['Affaire'].set_rqlexprs('update', ())
         self.assertRaises(Unauthorized,
                           self.schema['Affaire'].check_perm, session, 'update', eid)
         cu = cnx.cursor()
@@ -506,6 +506,6 @@
         # the best would probably ValidationError if the transition doesn't exist
         # from the current state but Unauthorized if it exists but user can't pass it
         self.assertRaises(ValidationError, cu.execute, rql, {'x': cnx.user(self.current_session()).eid}, 'x')
-        
+
 if __name__ == '__main__':
     unittest_main()
--- a/server/test/unittest_session.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/unittest_session.py	Thu Apr 04 13:49:34 2019 +0200
@@ -6,12 +6,12 @@
     def __init__(self, name):
         self.name = name
         self.children = []
-        
+
     def get_type(self, solution, args=None):
         return solution[self.name]
     def as_string(self):
         return self.name
-    
+
 class Function:
     def __init__(self, name, varname):
         self.name = name
--- a/server/test/unittest_sqlutils.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/unittest_sqlutils.py	Thu Apr 04 13:49:34 2019 +0200
@@ -20,12 +20,12 @@
     def test_init(self):
         o = SQLAdapterMixIn(BASE_CONFIG)
         self.assertEquals(o.encoding, 'UTF-8')
-        
+
     def test_init_encoding(self):
         config = BASE_CONFIG.copy()
         config['db-encoding'] = 'ISO-8859-1'
         o = SQLAdapterMixIn(config)
         self.assertEquals(o.encoding, 'ISO-8859-1')
-        
+
 if __name__ == '__main__':
     unittest_main()
--- a/server/test/unittest_ssplanner.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/unittest_ssplanner.py	Thu Apr 04 13:49:34 2019 +0200
@@ -8,7 +8,7 @@
 class SSPlannerTC(BasePlannerTC):
     repo = repo
     _test = test_plan
-    
+
     def setUp(self):
         BasePlannerTC.setUp(self)
         self.planner = SSPlanner(self.o.schema, self.o._rqlhelper)
@@ -33,9 +33,9 @@
                                         {'X': 'State', 'XN': 'String'},
                                         {'X': 'Tag', u'XN': 'String'},
                                         {'X': 'Transition', 'XN': 'String'}])],
-                     None, None, 
+                     None, None,
                      [self.system], None, [])])
-    
+
     def test_groupeded_ambigous_sol(self):
         self._test('Any XN,COUNT(X) GROUPBY XN WHERE X name XN',
                    [('OneFetchStep', [('Any XN,COUNT(X) GROUPBY XN WHERE X name XN',
@@ -52,9 +52,9 @@
                                         {'X': 'State', 'XN': 'String'},
                                         {'X': 'Tag', u'XN': 'String'},
                                         {'X': 'Transition', 'XN': 'String'}])],
-                     None, None, 
+                     None, None,
                      [self.system], None, [])])
-        
+
 if __name__ == '__main__':
     from logilab.common.testlib import unittest_main
     unittest_main()
--- a/server/test/unittest_tools.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/test/unittest_tools.py	Thu Apr 04 13:49:34 2019 +0200
@@ -6,6 +6,6 @@
         import cubicweb.server.server
         import cubicweb.server.checkintegrity
         import cubicweb.server.serverctl
-        
+
 if __name__ == '__main__':
     unittest_main()
--- a/server/utils.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/server/utils.py	Thu Apr 04 13:49:34 2019 +0200
@@ -46,7 +46,7 @@
             for item in seqin[0]:
                 newcomb = comb + [item]     # add next item to current combination
                 # call rloop w/ remaining seqs, newcomb
-                for item in rloop(seqin[1:], newcomb):   
+                for item in rloop(seqin[1:], newcomb):
                     yield item          # seqs and newcomb
         else:                           # processing last sequence
             yield comb                  # comb finished, add to list
@@ -95,7 +95,7 @@
                 self.start()
         self.func = auto_restart_func
         self.name = func.__name__
-        
+
     def start(self):
         self._t = Timer(self.interval, self.func)
         self._t.start()
@@ -120,7 +120,7 @@
         Thread.__init__(self, target=auto_remove_func)
         self.running_threads = running_threads
         self._name = target.__name__
-        
+
     def start(self):
         self.running_threads.append(self)
         Thread.start(self)
--- a/setup.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/setup.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # pylint: disable-msg=W0142,W0403,W0404,W0613,W0622,W0622,W0704,R0904,C0103,E0611
 #
-# Copyright (c) 2003 LOGILAB S.A. (Paris, FRANCE).
+# Copyright (c) 2003-2009 LOGILAB S.A. (Paris, FRANCE).
 # http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This program is free software; you can redistribute it and/or modify it under
@@ -56,7 +56,7 @@
 
 BASE_BLACKLIST = ('CVS', 'debian', 'dist', 'build', '__buildlog')
 IGNORED_EXTENSIONS = ('.pyc', '.pyo', '.elc')
-    
+
 
 def ensure_scripts(linux_scripts):
     """
@@ -152,7 +152,7 @@
             for directory in include_dirs:
                 dest = join(self.install_dir, base, directory)
                 export(directory, dest)
-        
+
 def install(**kwargs):
     """setup entry point"""
     if subpackage_of:
@@ -177,6 +177,6 @@
                  cmdclass={'install_lib': MyInstallLib},
                  **kwargs
                  )
-            
+
 if __name__ == '__main__' :
     install()
--- a/skeleton/setup.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/skeleton/setup.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 # pylint: disable-msg=W0404,W0622,W0704,W0613,W0152
-# Copyright (c) 2003-2004 LOGILAB S.A. (Paris, FRANCE).
+# Copyright (c) 2003-2009 LOGILAB S.A. (Paris, FRANCE).
 # http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This program is free software; you can redistribute it and/or modify it under
@@ -45,6 +45,6 @@
                  url=web,
                  data_files=data_files,
                  **kwargs)
-            
+
 if __name__ == '__main__' :
     install()
--- a/skeleton/test/realdb_test_CUBENAME.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/skeleton/test/realdb_test_CUBENAME.py	Thu Apr 04 13:49:34 2019 +0200
@@ -18,7 +18,7 @@
     def test_all_primaries(self):
         for rset in self.iter_individual_rsets(limit=50):
             yield self.view, 'primary', rset, rset.req.reset_headers()
-    
+
     ## startup views
     def test_startup_views(self):
         for vid in self.list_startup_views():
--- a/sobjects/email.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/sobjects/email.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,7 +1,7 @@
 """hooks to ensure use_email / primary_email relations consistency
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -15,50 +15,50 @@
     """
     rtype = 'use_email'
     fromeid = toeid = None # make pylint happy
-    
+
     def condition(self):
         """check entity has use_email set for the email address"""
         return not self.session.unsafe_execute(
             'Any X WHERE X eid %(x)s, X use_email Y, Y eid %(y)s',
             {'x': self.fromeid, 'y': self.toeid}, 'x')
-    
+
     def precommit_event(self):
         session = self.session
         if self.condition():
             session.unsafe_execute(
                 'SET X %s Y WHERE X eid %%(x)s, Y eid %%(y)s' % self.rtype,
                 {'x': self.fromeid, 'y': self.toeid}, 'x')
-    
+
 class SetPrimaryEmailRelationOp(SetUseEmailRelationOp):
     rtype = 'primary_email'
-    
+
     def condition(self):
         """check entity has no primary_email set"""
         return not self.session.unsafe_execute(
             'Any X WHERE X eid %(x)s, X primary_email Y',
             {'x': self.fromeid}, 'x')
 
-    
+
 class SetPrimaryEmailHook(Hook):
     """notify when a bug or story or version has its state modified"""
     events = ('after_add_relation',)
     accepts = ('use_email',)
-    
+
     def call(self, session, fromeid, rtype, toeid):
         subjtype = session.describe(fromeid)[0]
         eschema = self.vreg.schema[subjtype]
         if 'primary_email' in eschema.subject_relations():
-            SetPrimaryEmailRelationOp(session, vreg=self.vreg, 
+            SetPrimaryEmailRelationOp(session, vreg=self.vreg,
                                       fromeid=fromeid, toeid=toeid)
 
 class SetUseEmailHook(Hook):
     """notify when a bug or story or version has its state modified"""
     events = ('after_add_relation',)
     accepts = ('primary_email',)
-    
+
     def call(self, session, fromeid, rtype, toeid):
         subjtype = session.describe(fromeid)[0]
         eschema = self.vreg.schema[subjtype]
         if 'use_email' in eschema.subject_relations():
-            SetUseEmailRelationOp(session, vreg=self.vreg, 
+            SetUseEmailRelationOp(session, vreg=self.vreg,
                                   fromeid=fromeid, toeid=toeid)
--- a/sobjects/hooks.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/sobjects/hooks.py	Thu Apr 04 13:49:34 2019 +0200
@@ -15,7 +15,7 @@
     """ensure user logins are stripped"""
     events = ('before_add_entity', 'before_update_entity',)
     accepts = ('CWUser',)
-    
+
     def call(self, session, entity):
         if 'login' in entity and entity['login']:
             entity['login'] = entity['login'].strip()
@@ -30,12 +30,12 @@
                                           {'x': self.beid}, 'x'):
                 session.unsafe_execute('DELETE Bookmark X WHERE X eid %(x)s',
                                        {'x': self.beid}, 'x')
-        
+
 class DelBookmarkedByHook(Hook):
     """ensure user logins are stripped"""
     events = ('after_delete_relation',)
     accepts = ('bookmarked_by',)
-    
+
     def call(self, session, subj, rtype, obj):
         AutoDeleteBookmark(session, beid=subj)
 
@@ -60,4 +60,3 @@
                         fmt = entity.get_value(metaattr)
                     if fmt == 'text/html':
                         entity[attr] = soup2xhtml(value, session.encoding)
-
--- a/sobjects/test/data/sobjects/__init__.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/sobjects/test/data/sobjects/__init__.py	Thu Apr 04 13:49:34 2019 +0200
@@ -2,5 +2,3 @@
 
 class UserStatusChangeView(StatusChangeMixIn, NotificationView):
     accepts = ('CWUser',)
-    
-    
--- a/sobjects/test/unittest_email.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/sobjects/test/unittest_email.py	Thu Apr 04 13:49:34 2019 +0200
@@ -22,7 +22,7 @@
         self.commit()
         self.assertEquals(self.execute('Any A WHERE U use_email X, U login "admin", X address A')[0][0],
                           'admin@logilab.fr')
-        
+
 
 if __name__ == '__main__':
     from logilab.common.testlib import unittest_main
--- a/sobjects/test/unittest_hooks.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/sobjects/test/unittest_hooks.py	Thu Apr 04 13:49:34 2019 +0200
@@ -13,7 +13,7 @@
                              {'e': u.eid})[0][0]
         self.assertEquals(tname, 'jijoe')
 
-    
+
     def test_auto_delete_bookmarks(self):
         beid = self.execute('INSERT Bookmark X: X title "hop", X path "view", X bookmarked_by U '
                             'WHERE U login "admin"')[0][0]
@@ -25,6 +25,6 @@
         self.execute('DELETE X bookmarked_by U WHERE U login "anon"')
         self.commit()
         self.failIf(self.execute('Any X WHERE X eid %(x)s', {'x': beid}, 'x'))
-        
+
 if __name__ == '__main__':
     unittest_main()
--- a/test/data/erqlexpr_on_ertype.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/test/data/erqlexpr_on_ertype.py	Thu Apr 04 13:49:34 2019 +0200
@@ -6,7 +6,7 @@
         'delete': ('managers',),
         }
     toto = SubjectRelation('TuTu')
-    
+
 class TuTu(EntityType):
     permissions = {
         'read': ('managers',),
--- a/test/data/rqlexpr_on_ertype_read.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/test/data/rqlexpr_on_ertype_read.py	Thu Apr 04 13:49:34 2019 +0200
@@ -6,7 +6,7 @@
         'delete': ('managers',),
         }
     toto = SubjectRelation('TuTu')
-    
+
 class TuTu(EntityType):
     permissions = {
         'read': ('managers',),
--- a/test/data/rrqlexpr_on_attr.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/test/data/rrqlexpr_on_attr.py	Thu Apr 04 13:49:34 2019 +0200
@@ -6,7 +6,7 @@
         'delete': ('managers',),
         }
     attr = String()
-    
+
 class attr(RelationType):
     permissions = {
         'read': ('managers', ),
--- a/test/unittest_cwctl.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/test/unittest_cwctl.py	Thu Apr 04 13:49:34 2019 +0200
@@ -19,10 +19,10 @@
         sys.stdout = self.stream
     def tearDown(self):
         sys.stdout = sys.__stdout__
-        
+
     def test_list(self):
         from cubicweb.cwctl import ListCommand
         ListCommand().run([])
-        
+
 if __name__ == '__main__':
     unittest_main()
--- a/test/unittest_schema.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/test/unittest_schema.py	Thu Apr 04 13:49:34 2019 +0200
@@ -96,7 +96,7 @@
                          ['Any X WHERE X travaille S, S owned_by U, X eid %(x)s, U eid %(u)s'])
         eperson.set_groups('read', ('managers',))
         self.assertEqual(eperson.get_groups('read'), set(('managers',)))
-        
+
     def test_relation_perms(self):
         rconcerne = schema.rschema('concerne')
         rconcerne.set_default_groups()
@@ -112,19 +112,19 @@
         self.assertRaises(RQLSyntaxError, ERQLExpression, '1')
         expr = ERQLExpression('X travaille S, S owned_by U')
         self.assertEquals(str(expr), 'Any X WHERE X travaille S, S owned_by U, X eid %(x)s, U eid %(u)s')
-        
+
     def test_rrqlexpression(self):
         self.assertRaises(Exception, RRQLExpression, '1')
         self.assertRaises(RQLSyntaxError, RRQLExpression, 'O X Y')
         expr = RRQLExpression('U has_update_permission O')
         self.assertEquals(str(expr), 'Any O WHERE U has_update_permission O, O eid %(o)s, U eid %(u)s')
-        
+
 
 loader = CubicWebSchemaLoader()
 config = TestConfiguration('data')
 config.bootstrap_cubes()
 loader.lib_directory = config.schemas_lib_dir()
-    
+
 class SQLSchemaReaderClassTest(TestCase):
 
     def test_knownValues_include_schema_files(self):
@@ -139,15 +139,15 @@
         self.assertEquals(schema.name, 'data')
         entities = [str(e) for e in schema.entities()]
         entities.sort()
-        expected_entities = ['Bookmark', 'Boolean', 'Bytes', 'Card', 
+        expected_entities = ['Bookmark', 'Boolean', 'Bytes', 'Card',
                              'Date', 'Datetime', 'Decimal',
                              'CWCache', 'CWConstraint', 'CWConstraintType', 'CWEType',
                              'CWAttribute', 'CWGroup', 'EmailAddress', 'CWRelation',
                              'CWPermission', 'CWProperty', 'CWRType', 'CWUser',
                              'File', 'Float', 'Image', 'Int', 'Interval', 'Note',
                              'Password', 'Personne',
-                             'RQLExpression', 
-                             'Societe', 'State', 'String', 'SubNote', 'Tag', 'Time', 
+                             'RQLExpression',
+                             'Societe', 'State', 'String', 'SubNote', 'Tag', 'Time',
                              'Transition', 'TrInfo']
         self.assertListEquals(entities, sorted(expected_entities))
         relations = [str(r) for r in schema.relations()]
@@ -155,7 +155,7 @@
         expected_relations = ['add_permission', 'address', 'alias',
                               'allowed_transition', 'bookmarked_by', 'canonical',
 
-                              'cardinality', 'comment', 'comment_format', 
+                              'cardinality', 'comment', 'comment_format',
                               'composite', 'condition', 'connait', 'constrained_by', 'content',
                               'content_format', 'created_by', 'creation_date', 'cstrtype',
 
@@ -167,7 +167,7 @@
                               'final', 'firstname', 'for_user',
                               'from_entity', 'from_state', 'fulltext_container', 'fulltextindexed',
 
-                              'has_text', 
+                              'has_text',
                               'identical_to', 'identity', 'in_group', 'in_state', 'indexed',
                               'initial_state', 'inlined', 'internationalizable', 'is', 'is_instance_of',
 
@@ -179,20 +179,20 @@
 
                               'ordernum', 'owned_by',
 
-                              'path', 'pkey', 'prenom', 'primary_email', 
+                              'path', 'pkey', 'prenom', 'primary_email',
 
                               'read_permission', 'relation_type', 'require_group',
-                              
+
                               'specializes', 'state_of', 'surname', 'symetric', 'synopsis',
 
                               'tags', 'timestamp', 'title', 'to_entity', 'to_state', 'transition_of', 'travaille', 'type',
 
                               'upassword', 'update_permission', 'use_email',
 
-                              'value', 
+                              'value',
 
                               'wf_info_for', 'wikiid']
-    
+
         self.assertListEquals(relations, expected_relations)
 
         eschema = schema.eschema('CWUser')
@@ -234,16 +234,16 @@
         ex = self.assertRaises(BadSchemaDefinition,
                                self.loader._build_schema, 'toto', False)
         self.assertEquals(str(ex), msg)
-        
+
     def test_rrqlexpr_on_etype(self):
         self._test('rrqlexpr_on_eetype.py', "can't use RRQLExpression on an entity type, use an ERQLExpression (ToTo)")
-        
+
     def test_erqlexpr_on_rtype(self):
         self._test('erqlexpr_on_ertype.py', "can't use ERQLExpression on a relation type, use a RRQLExpression (toto)")
-        
+
     def test_rqlexpr_on_rtype_read(self):
         self._test('rqlexpr_on_ertype_read.py', "can't use rql expression for read permission of a relation type (toto)")
-        
+
     def test_rrqlexpr_on_attr(self):
         self._test('rrqlexpr_on_attr.py', "can't use RRQLExpression on a final relation type (eg attribute relation), use an ERQLExpression (attr)")
 
--- a/test/unittest_utils.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/test/unittest_utils.py	Thu Apr 04 13:49:34 2019 +0200
@@ -9,7 +9,7 @@
     def test_1(self):
         self.assertNotEquals(make_uid('xyz'), make_uid('abcd'))
         self.assertNotEquals(make_uid('xyz'), make_uid('xyz'))
-        
+
     def test_2(self):
         d = {}
         while len(d)<10000:
@@ -18,7 +18,7 @@
                 self.fail(len(d))
             d[uid] = 1
 
-        
+
 class UStringIOTC(TestCase):
     def test_boolean_value(self):
         self.assert_(UStringIO())
@@ -31,7 +31,7 @@
         for i in xrange(12):
             l.append(i)
         self.assertEquals(l, range(2, 12))
-    
+
     def test_extend(self):
         testdata = [(range(5), range(5)),
                     (range(10), range(10)),
@@ -42,6 +42,6 @@
             l.extend(extension)
             yield self.assertEquals, l, expected
 
-   
+
 if __name__ == '__main__':
     unittest_main()
--- a/toolsutils.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/toolsutils.py	Thu Apr 04 13:49:34 2019 +0200
@@ -39,7 +39,7 @@
         if ex.errno != errno.EEXIST:
             raise
         print 'directory %s already exists' % directory
-                
+
 def create_symlink(source, target):
     """create a symbolic link"""
     if exists(target):
@@ -51,7 +51,7 @@
     import shutil
     print '[copy] %s <-- %s' % (target, source)
     shutil.copy2(source, target)
-    
+
 def rm(whatever):
     import shutil
     shutil.rmtree(whatever)
@@ -66,7 +66,7 @@
     diffs = p_output.read()
     if diffs:
         if askconfirm:
-            print 
+            print
             print diffs
             action = raw_input('replace (N/y/q) ? ').lower()
         else:
@@ -120,7 +120,7 @@
                 show_diffs(tfpath, fpath, askconfirm)
             else:
                 shutil.copyfile(fpath, tfpath)
-                
+
 def fill_templated_file(fpath, tfpath, context):
     fobj = file(tfpath, 'w')
     templated = file(fpath).read()
@@ -158,7 +158,7 @@
     :param config_file: path to the configuration file
 
     :rtype: dict
-    :return: a dictionary with specified values associated to option names 
+    :return: a dictionary with specified values associated to option names
     """
     from logilab.common.fileutils import lines
     config = current = {}
@@ -194,10 +194,10 @@
 
     :type default: str
     :param default: default value if the environment variable is not defined
-    
+
     :type name: str
     :param name: the informal name of the path, used for error message
-    
+
     :rtype: str
     :return: the value of the environment variable or the default value
 
@@ -243,12 +243,12 @@
             msg = 'No helper for command %s using %s configuration' % (
                 cmdname, config.name)
             raise ConfigurationError(msg)
-        
+
     def fail(self, reason):
         print "command failed:", reason
         sys.exit(1)
-    
-                    
+
+
 def main_run(args, doc):
     """command line tool"""
     try:
@@ -289,4 +289,4 @@
     if not password:
         password = getpass('password: ')
     return connect(user=user, password=password, host=optconfig.host, database=appid)
-    
+
--- a/web/__init__.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/__init__.py	Thu Apr 04 13:49:34 2019 +0200
@@ -13,6 +13,8 @@
 from datetime import datetime, date, timedelta
 from simplejson import dumps
 
+from logilab.common.deprecation import obsolete
+
 from cubicweb.common.uilib import urlquote
 from cubicweb.web._exceptions import *
 
@@ -62,6 +64,7 @@
         return json_dumps(function(*args, **kwargs))
     return newfunc
 
+@obsolete('use req.build_ajax_replace_url() instead')
 def ajax_replace_url(nodeid, rql, vid=None, swap=False, **extraparams):
     """builds a replacePageChunk-like url
     >>> ajax_replace_url('foo', 'Person P')
--- a/web/_exceptions.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/_exceptions.py	Thu Apr 04 13:49:34 2019 +0200
@@ -2,7 +2,7 @@
 """exceptions used in the core of the CubicWeb web application
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -11,13 +11,13 @@
 
 class PublishException(CubicWebException):
     """base class for publishing related exception"""
-    
+
 class RequestError(PublishException):
     """raised when a request can't be served because of a bad input"""
 
 class NothingToEdit(RequestError):
     """raised when an edit request doesn't specify any eid to edit"""
-    
+
 class NotFound(RequestError):
     """raised when a 404 error should be returned"""
 
@@ -34,7 +34,7 @@
     def __init__(self, status, content=''):
         self.status = int(status)
         self.content = content
-    
+
 class ExplicitLogin(AuthenticationError):
     """raised when a bad connection id is given or when an attempt to establish
     a connection failed"""
@@ -55,4 +55,3 @@
     def dumps(self):
         import simplejson
         return simplejson.dumps({'reason': self.reason})
-        
--- a/web/data/cubicweb.ajax.js	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/data/cubicweb.ajax.js	Thu Apr 04 13:49:34 2019 +0200
@@ -317,6 +317,18 @@
     }
 }
 
+/*
+ * fetches `url` and replaces `nodeid`'s content with the result
+ * @param replacemode how the replacement should be done (default is 'replace')
+ *  Possible values are :
+ *    - 'replace' to replace the node's content with the generated HTML
+ *    - 'swap' to replace the node itself with the generated HTML
+ *    - 'append' to append the generated HTML to the node's content
+ */
+function loadxhtml(nodeid, url, /* ... */ replacemode) {
+    jQuery('#' + nodeid).loadxhtml(url, null, 'post', replacemode);
+}
+
 /* XXX: this function should go in edition.js but as for now, htmlReplace
  * references it.
  *
--- a/web/formfields.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/formfields.py	Thu Apr 04 13:49:34 2019 +0200
@@ -473,9 +473,10 @@
                     if card in '?1':
                         kwargs['widget'].attrs.setdefault('size', 1)
                 if isinstance(cstr, SizeConstraint) and cstr.max is not None:
-                    if cstr.max > 257:
-                        kwargs.setdefault('widget', TextArea)
+                    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'):
--- a/web/httpcache.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/httpcache.py	Thu Apr 04 13:49:34 2019 +0200
@@ -42,14 +42,14 @@
 
     def etag(self):
         return self.view.id + '/' + ','.join(sorted(self.req.user.groups))
-    
+
     def max_age(self):
         # 0 to actually force revalidation
         return 0
-    
+
     def last_modified(self):
         return self.view.last_modified()
-    
+
     def set_headers(self):
         req = self.req
         try:
@@ -129,4 +129,4 @@
 viewmod.EntityView.http_cache_manager = EntityHTTPCacheManager
 
 viewmod.StartupView.http_cache_manager = MaxAgeHTTPCacheManager
-viewmod.StartupView.cache_max_age = 60*60*2 # stay in http cache for 2 hours by default 
+viewmod.StartupView.cache_max_age = 60*60*2 # stay in http cache for 2 hours by default
--- a/web/request.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/request.py	Thu Apr 04 13:49:34 2019 +0200
@@ -19,12 +19,14 @@
 from logilab.common.decorators import cached
 from logilab.common.deprecation import obsolete
 
+from logilab.mtconverter import html_escape
+
 from cubicweb.dbapi import DBAPIRequest
 from cubicweb.common.mail import header
 from cubicweb.common.uilib import remove_html_tags
 from cubicweb.utils import SizeConstrainedList, HTMLHead
-from cubicweb.web import (INTERNAL_FIELD_VALUE, LOGGER, NothingToEdit, RequestError,
-                          StatusResponse)
+from cubicweb.web import (INTERNAL_FIELD_VALUE, LOGGER, NothingToEdit,
+                          RequestError, StatusResponse)
 
 _MARKER = object()
 
@@ -478,6 +480,23 @@
                 cssfile = self.datadir_url + cssfile
             add_css(cssfile, media)
 
+    def build_ajax_replace_url(self, nodeid, rql, vid, replacemode='replace',
+                               **extraparams):
+        """builds an ajax url that will replace `nodeid`s content
+        :param nodeid: the dom id of the node to replace
+        :param rql: rql to execute
+        :param vid: the view to apply on the resultset
+        :param replacemode: defines how the replacement should be done.
+        Possible values are :
+         - 'replace' to replace the node's content with the generated HTML
+         - 'swap' to replace the node itself with the generated HTML
+         - 'append' to append the generated HTML to the node's content
+        """
+        url = self.build_url('view', rql=rql, vid=vid, __notemplate=1,
+                             **extraparams)
+        return "javascript: loadxhtml('%s', '%s', '%s')" % (
+            nodeid, html_escape(url), replacemode)
+
     # urls/path management ####################################################
 
     def url(self, includeparams=True):
--- a/web/test/data/schema/testschema.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/test/data/schema/testschema.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,7 +1,7 @@
 class Salesterm(EntityType):
     described_by_test = SubjectRelation('File', cardinality='1*', composite='subject')
     amount = Int(constraints=[IntervalBoundConstraint(0, 100)])
-    
+
 class tags(RelationDefinition):
     subject = 'Tag'
     object = ('BlogEntry', 'CWUser')
--- a/web/test/data/views.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/test/data/views.py	Thu Apr 04 13:49:34 2019 +0200
@@ -21,6 +21,6 @@
             pass
         assert req.user.login == login
     return orig_publish(self, path, req)
-    
+
 orig_publish = CubicWebPublisher.main_publish
 CubicWebPublisher.main_publish = auto_login_publish
--- a/web/test/test_views.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/test/test_views.py	Thu Apr 04 13:49:34 2019 +0200
@@ -22,7 +22,7 @@
 
 class SomeView(AnyRsetView):
     id = 'someview'
-    
+
     def call(self):
         self.req.add_js('spam.js')
         self.req.add_js('spam.js')
@@ -34,7 +34,7 @@
 
     def test_manual_tests(self):
         rset = self.execute('Any P,F,S WHERE P is CWUser, P firstname F, P surname S')
-        self.view('table', rset, template=None, displayfilter=True, displaycols=[0,2])        
+        self.view('table', rset, template=None, displayfilter=True, displaycols=[0,2])
 
     def test_sortable_js_added(self):
         rset = self.execute('CWUser X')
@@ -54,14 +54,13 @@
 
 
 class ExplicitViewsTest(WebTest):
-    
+
     def test_unrelateddivs(self):
         rset = self.execute('Any X WHERE X is CWUser, X login "admin"')
         group = self.add_entity('CWGroup', name=u'R&D')
         req = self.request(relation='in_group_subject')
         self.view('unrelateddivs', rset, req)
-        
-        
+
 
 if __name__ == '__main__':
     from logilab.common.testlib import unittest_main
--- a/web/test/unittest_application.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/test/unittest_application.py	Thu Apr 04 13:49:34 2019 +0200
@@ -44,7 +44,7 @@
 class RequestBaseTC(TestCase):
     def setUp(self):
         self.req = FakeRequest()
-        
+
 
     def test_list_arg(self):
         """tests the list_arg() function"""
@@ -73,13 +73,13 @@
         self.assertEquals(req.relative_path(False), 'login')
         self.assertEquals(req.from_controller(), 'login')
 
-        
+
 class UtilsTC(TestCase):
     """test suite for misc application utilities"""
 
     def setUp(self):
         self.ctrl = FakeController()
-    
+
     #def test_which_mapping(self):
     #    """tests which mapping is used (application or core)"""
     #    init_mapping()
@@ -95,7 +95,7 @@
         self.assertEquals(self.ctrl.execute_linkto(), None)
         self.assertEquals(self.ctrl._cursor.executed,
                           [])
-        
+
         self.ctrl.set_form({'__linkto' : 'works_for:12_13_14:object',
                               'eid': 8})
         self.ctrl.execute_linkto()
@@ -110,7 +110,7 @@
         self.assertEquals(self.ctrl._cursor.executed,
                           ['SET X works_for Y WHERE X eid 8, Y eid %s' % i
                            for i in (12, 13, 14)])
-        
+
 
         self.ctrl.new_cursor()
         self.ctrl.req.form = {'__linkto' : 'works_for:12_13_14:object'}
@@ -152,10 +152,10 @@
             return path, params
         else:
             self.fail('expected a Redirect exception')
-        
+
     def expect_redirect_publish(self, req, path='view'):
         return self.expect_redirect(lambda x: self.publish(x, path), req)
-    
+
     def test_cnx_user_groups_sync(self):
         user = self.user()
         self.assertEquals(user.groups, set(('managers',)))
@@ -168,16 +168,16 @@
         # cleanup
         self.execute('DELETE X in_group G WHERE X eid %s, G name "guests"' % user.eid)
         self.commit()
-    
+
     def test_nonregr_publish1(self):
         req = self.request(u'CWEType X WHERE X final FALSE, X meta FALSE')
         self.app.publish('view', req)
-        
+
     def test_nonregr_publish2(self):
         req = self.request(u'Any count(N) WHERE N todo_by U, N is Note, U eid %s'
                            % self.user().eid)
         self.app.publish('view', req)
-        
+
     def test_publish_validation_error(self):
         req = self.request()
         user = self.user()
@@ -204,12 +204,12 @@
 
     def test_validation_error_dont_loose_subentity_data(self):
         """test creation of two linked entities
-        """        
+        """
         req = self.request()
         form = {'eid': ['X', 'Y'],
                 '__type:X': 'CWUser',
                 # missing required field
-                'login:X': u'', 'edits-login:X': '', 
+                'login:X': u'', 'edits-login:X': '',
                 'surname:X': u'Mr Ouaoua', 'edits-surname:X': '',
                 '__type:Y': 'EmailAddress',
                 # but email address is set
@@ -229,13 +229,13 @@
         self.assertEquals(forminfo['errors'].errors, {'login': 'required attribute',
                                                       'upassword': 'required attribute'})
         self.assertEquals(forminfo['values'], form)
-        
+
     def _test_cleaned(self, kwargs, injected, cleaned):
         req = self.request(**kwargs)
         page = self.app.publish('view', req)
         self.failIf(injected in page, (kwargs, injected))
         self.failUnless(cleaned in page, (kwargs, cleaned))
-        
+
     def test_nonregr_script_kiddies(self):
         """test against current script injection"""
         injected = '<i>toto</i>'
@@ -245,7 +245,7 @@
                        {'vtitle': injected},
                        ):
             yield self._test_cleaned, kwargs, injected, cleaned
-        
+
     def test_site_wide_eproperties_sync(self):
         # XXX work in all-in-one configuration but not in twisted for instance
         # in which case we need a kindof repo -> http server notification
@@ -278,7 +278,7 @@
         self.failIf(req.cnx is origcnx)
         self.assertEquals(req.user.login, 'turlututu')
         self.failUnless('turlututu' in page, page)
-        
+
     # authentication tests ####################################################
 
     def _init_auth(self, authmode, anonuser=None):
@@ -289,7 +289,7 @@
         req.cnx = None
         sh = self.app.session_handler
         # not properly cleaned between tests
-        self.open_sessions = sh.session_manager._sessions = {} 
+        self.open_sessions = sh.session_manager._sessions = {}
         return req, origcnx
 
     def _test_auth_succeed(self, req, origcnx):
@@ -299,16 +299,16 @@
         self.assertEquals(len(self.open_sessions), 1, self.open_sessions)
         self.assertEquals(cnx.login, origcnx.login)
         self.assertEquals(cnx.password, origcnx.password)
-        self.assertEquals(cnx.anonymous_connection, False) 
+        self.assertEquals(cnx.anonymous_connection, False)
         self.assertEquals(path, 'view')
         self.assertEquals(params, {'__message': 'welcome %s !' % origcnx.login})
-    
+
     def _test_auth_fail(self, req):
         self.assertRaises(AuthenticationError, self.app.connect, req)
         self.assertEquals(req.cnx, None)
-        self.assertEquals(len(self.open_sessions), 0) 
+        self.assertEquals(len(self.open_sessions), 0)
         clear_cache(req, 'get_authorization')
-        
+
     def test_http_auth_no_anon(self):
         req, origcnx = self._init_auth('http')
         self._test_auth_fail(req)
@@ -318,7 +318,7 @@
         req._headers['Authorization'] = 'basic %s' % authstr
         self._test_auth_succeed(req, origcnx)
         self.assertRaises(AuthenticationError, self.publish, req, 'logout')
-        self.assertEquals(len(self.open_sessions), 0) 
+        self.assertEquals(len(self.open_sessions), 0)
 
     def test_cookie_auth_no_anon(self):
         req, origcnx = self._init_auth('cookie')
@@ -331,7 +331,7 @@
         req.form['__password'] = origcnx.password
         self._test_auth_succeed(req, origcnx)
         self.assertRaises(AuthenticationError, self.publish, req, 'logout')
-        self.assertEquals(len(self.open_sessions), 0) 
+        self.assertEquals(len(self.open_sessions), 0)
 
     def test_login_by_email(self):
         login = self.request().user.login
@@ -351,17 +351,17 @@
         req.form['__password'] = origcnx.password
         self._test_auth_succeed(req, origcnx)
         self.assertRaises(AuthenticationError, self.publish, req, 'logout')
-        self.assertEquals(len(self.open_sessions), 0) 
+        self.assertEquals(len(self.open_sessions), 0)
 
     def _test_auth_anon(self, req):
         self.app.connect(req)
         acnx = req.cnx
         self.assertEquals(len(self.open_sessions), 1)
-        self.assertEquals(acnx.login, 'anon') 
-        self.assertEquals(acnx.password, 'anon') 
+        self.assertEquals(acnx.login, 'anon')
+        self.assertEquals(acnx.password, 'anon')
         self.failUnless(acnx.anonymous_connection)
         self._reset_cookie(req)
-        
+
     def _reset_cookie(self, req):
         # preparing the suite of the test
         # set session id in cookie
@@ -371,15 +371,15 @@
         clear_cache(req, 'get_authorization')
         # reset cnx as if it was a new incoming request
         req.cnx = None
-        
+
     def _test_anon_auth_fail(self, req):
-        self.assertEquals(len(self.open_sessions), 1) 
+        self.assertEquals(len(self.open_sessions), 1)
         self.app.connect(req)
         self.assertEquals(req.message, 'authentication failure')
         self.assertEquals(req.cnx.anonymous_connection, True)
-        self.assertEquals(len(self.open_sessions), 1) 
+        self.assertEquals(len(self.open_sessions), 1)
         self._reset_cookie(req)
-        
+
     def test_http_auth_anon_allowed(self):
         req, origcnx = self._init_auth('http', 'anon')
         self._test_auth_anon(req)
@@ -390,8 +390,8 @@
         req._headers['Authorization'] = 'basic %s' % authstr
         self._test_auth_succeed(req, origcnx)
         self.assertRaises(AuthenticationError, self.publish, req, 'logout')
-        self.assertEquals(len(self.open_sessions), 0) 
-        
+        self.assertEquals(len(self.open_sessions), 0)
+
     def test_cookie_auth_anon_allowed(self):
         req, origcnx = self._init_auth('cookie', 'anon')
         self._test_auth_anon(req)
@@ -402,7 +402,7 @@
         req.form['__password'] = origcnx.password
         self._test_auth_succeed(req, origcnx)
         self.assertRaises(AuthenticationError, self.publish, req, 'logout')
-        self.assertEquals(len(self.open_sessions), 0) 
+        self.assertEquals(len(self.open_sessions), 0)
 
 
 if __name__ == '__main__':
--- a/web/test/unittest_urlrewrite.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/test/unittest_urlrewrite.py	Thu Apr 04 13:49:34 2019 +0200
@@ -35,7 +35,7 @@
             ('/doc/(.+?)/?$', dict(fid='\\1', vid='wdoc')),
             ('/changelog/?$', dict(vid='changelog')),
             # now in SchemaBasedRewriter
-            #('/search/(.+)$', dict(rql=r'Any X WHERE X has_text "\1"')), 
+            #('/search/(.+)$', dict(rql=r'Any X WHERE X has_text "\1"')),
             ])
 
 
@@ -94,8 +94,8 @@
         pmid, rset = rewriter.rewrite(req, u'/DaLToN/JoE')
         self.assertEquals(len(rset), 1)
         self.assertEquals(rset[0][0], self.p1.eid)
-        
-    
+
+
 
 if __name__ == '__main__':
     unittest_main()
--- a/web/test/unittest_views_actions.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/test/unittest_views_actions.py	Thu Apr 04 13:49:34 2019 +0200
@@ -20,6 +20,6 @@
         rset = self.execute('Any X WHERE X login "anon"', req=req)
         self.failIf([action for action in self.vreg.possible_vobjects('actions', req, rset)
                      if action.id == 'sendemail'])
-        
+
 if __name__ == '__main__':
     unittest_main()
--- a/web/test/unittest_views_baseforms.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/test/unittest_views_baseforms.py	Thu Apr 04 13:49:34 2019 +0200
@@ -31,7 +31,7 @@
 
     def setup_database(self):
         self.create_user('joe')
-        
+
     def _build_creation_form(self, etype):
         req = self.request()
         req.next_tabindex()
@@ -44,10 +44,10 @@
         view.w = buffer.write
         view.edit_form(entity, {})
         return buffer.getvalue()
-    
+
     def _test_view_for(self, etype, expected):
         self.assertTextEquals(expected, cleanup_text(self._build_creation_form(etype)))
-        
+
     def test_base(self):
         self._test_view_for('CWGroup', '''\
 <form id="entityForm" class="entityForm" cubicweb:target="eformframe"
@@ -198,7 +198,7 @@
         entity = vreg.etype_class('Salesterm')(req, None, None)
         view = vreg.select_view('creation', req, None)
         self.failUnless(view.need_multipart(entity))
-        
+
 
 
     def test_nonregr_check_add_permission_on_relation(self):
@@ -214,7 +214,7 @@
         self.login('joe')
         html = self._build_creation_form('BlogEntry')
         self.failIf('name="edits-checked_by:A"' in html)
-        
+
 from cubicweb.devtools.testlib import WebTest
 from cubicweb.devtools.htmlparser import DTDValidator
 
--- a/web/test/unittest_views_searchrestriction.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/test/unittest_views_searchrestriction.py	Thu Apr 04 13:49:34 2019 +0200
@@ -15,7 +15,7 @@
         mainvar = prepare_facets_rqlst(rqlst)[0]
         insert_attr_select_relation(rqlst.children[0], mainvar, rel, role, attr)
         return rqlst.as_string()
-        
+
     @property
     def select(self):
         return self.parse('Any B,(NOW - CD),S,V,U,GROUP_CONCAT(TN),VN,P,CD,BMD '
@@ -24,30 +24,30 @@
                           'B modification_date BMD, T? tags B, T name TN, '
                           'V? bookmarked_by B, V title VN, B created_by U?, '
                           'B in_group P, P name "managers"')
-    
+
     def test_1(self):
         self.assertEquals(self._generate(self.select, 'in_state', 'subject', 'name'),
                           "DISTINCT Any A,C ORDERBY C WHERE B in_group P, P name 'managers', "
                           "B in_state A, A name C, B is CWUser")
-        
+
     def test_2(self):
         self.assertEquals(self._generate(self.select, 'tags', 'object', 'name'),
                           "DISTINCT Any A,C ORDERBY C WHERE B in_group P, P name 'managers', "
                           "A tags B, A name C, B is CWUser")
-        
+
     def test_3(self):
         self.assertEquals(self._generate(self.select, 'created_by', 'subject', 'login'),
                           "DISTINCT Any A,C ORDERBY C WHERE B in_group P, P name 'managers', "
                           "B created_by A, A login C, B is CWUser")
-        
+
     def test_4(self):
         self.assertEquals(self._generate(self.parse('Any X WHERE X is CWUser'), 'created_by', 'subject', 'login'),
                           "DISTINCT Any A,B ORDERBY B WHERE X is CWUser, X created_by A, A login B")
-        
+
     def test_5(self):
         self.assertEquals(self._generate(self.parse('Any X,L WHERE X is CWUser, X login L'), 'created_by', 'subject', 'login'),
                           "DISTINCT Any A,B ORDERBY B WHERE X is CWUser, X created_by A, A login B")
-        
+
     def test_nonregr1(self):
         select = self.parse('Any T,V WHERE T bookmarked_by V?, '
                             'V in_state VS, VS name "published", T created_by U')
@@ -77,7 +77,7 @@
         self.assertEquals(self._generate(select, 'in_group', 'subject', 'name'),
                           "DISTINCT Any B,C ORDERBY C WHERE X is CWUser, X in_group B, B name C")
 
-        
+
 if __name__ == '__main__':
     from logilab.common.testlib import unittest_main
     unittest_main()
--- a/web/test/unittest_webconfig.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/test/unittest_webconfig.py	Thu Apr 04 13:49:34 2019 +0200
@@ -10,7 +10,7 @@
         self.config = ApptestConfiguration('data')
         self.config._cubes = ['file']
         self.config.load_configuration()
-        
+
     def test_nonregr_print_css_as_list(self):
         """make sure PRINT_CSS *must* is a list"""
         config = self.config
@@ -26,8 +26,8 @@
         self.failUnless('file' in self.config.locate_resource(rname).split(os.sep))
         cubicwebcsspath = self.config.locate_resource('cubicweb.css').split(os.sep)
         self.failUnless('web' in cubicwebcsspath or 'shared' in cubicwebcsspath) # 'shared' if tests under apycot
-        
+
 if __name__ == '__main__':
     unittest_main()
 
-    
+
--- a/web/test/unittest_widgets.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/test/unittest_widgets.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,6 +1,4 @@
-"""cubicweb.common.widget unit tests
-
-"""
+"""cubicweb.common.widget unit tests"""
 
 from datetime import datetime
 NOW = datetime.now()
@@ -13,11 +11,11 @@
 
 
 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')
@@ -187,7 +185,7 @@
     def test_datetime_widget(self):
         w = self.get_widget('Personne', 'datenaiss', 'Datetime')
         self.assertEquals(w.name, 'datenaiss')
-        example = '%s, or without time: %s' % (        
+        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)
@@ -231,8 +229,8 @@
         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')
@@ -314,7 +312,7 @@
             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']
 
@@ -337,7 +335,7 @@
             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']
 
@@ -365,7 +363,7 @@
         entity.autocomplete_initfuncs = {'nom' : 'getnames'}
         w = self.get_widget(entity, 'travaille', 'Societe')
         self.failUnless(isinstance(w, AutoCompletionWidget))
-        
-        
+
+
 if __name__ == '__main__':
     unittest_main()
--- a/web/views/apacherewrite.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/apacherewrite.py	Thu Apr 04 13:49:34 2019 +0200
@@ -28,7 +28,7 @@
     def match(self, **kwargs):
         self._match = self.condition.match(kwargs[self.match_part])
         return not self._match is None
-    
+
     def action_rewrite(self, path):
         for rgx, replace in self.rules:
             if not rgx.match(path) is None:
@@ -45,7 +45,7 @@
     def action_stop(self, path):
         return path
 
-    
+
 class ApacheURLRewrite(Component):
     """inherit from this class with actual rules to activate apache style rewriting
 
@@ -69,24 +69,24 @@
         RewriteRule ^/(data/.*) http://localhost:8080/$1 [L,P]
         RewriteRule ^/(json.*) http://localhost:8080/$1 [L,P]
         RewriteRule ^/(.*) http://localhost:8080/m_%1/$1 [L,P]
-    
+
     could be written (considering that no "host rewritting" is necessary):
 
-      class MyAppRules(ApacheURLRewrite): 
+      class MyAppRules(ApacheURLRewrite):
         rules = [
           RewriteCond('logilab\.fr', match='host',
                       rules=[('/(.*)', r'http://www.logilab.fr/\1')],
                       action='redirect'),
           RewriteCond('(www)\.logilab\.fr', match='host', action='stop'),
           RewriteCond('/(data|json)/', match='path', action='stop'),
-          RewriteCond('(?P<cat>.*)\.logilab\.fr', match='host', 
+          RewriteCond('(?P<cat>.*)\.logilab\.fr', match='host',
                       rules=[('/(.*)', r'/m_%(cat)s/\1')]),
         ]
     """
     __abstract__ = True
     id = 'urlrewriter'
     rules = []
-        
+
     def rewrite(self, host, path):
         for cond in self.rules:
             if cond.match(host=host, path=path):
--- a/web/views/baseforms.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/baseforms.py	Thu Apr 04 13:49:34 2019 +0200
@@ -24,8 +24,8 @@
 from cubicweb.web.views.autoform import AutomaticEntityForm
 
 _ = unicode
-    
-    
+
+
 class EditionForm(FormMixIn, EntityView):
     """primary entity edition form
 
@@ -34,14 +34,14 @@
     name of the attribute being edited. You may use this feature to compute
     dynamic default values such as the 'tomorrow' date or the user's login
     being connected
-    """    
+    """
     id = 'edition'
     __select__ = one_line_rset() & non_final_entity()
 
     title = _('edition')
     controller = 'edit'
     skip_relations = set()
-    
+
     EDITION_BODY = u'''\
  %(errormsg)s
 <form id="%(formid)s" class="entityForm" cubicweb:target="eformframe"
@@ -135,7 +135,7 @@
     @property
     def formid(self):
         return self.id
-    
+
     def action_title(self, entity):
         """form's title"""
         ptitle = self.req._(self.title)
@@ -155,7 +155,7 @@
                 output.append(u'<input type="hidden" name="%s" value="%s" />'
                               % (name, value))
         return u'\n'.join(output)
-                
+
     def add_hidden_web_behaviour_params(self, entity):
         """inserts hidden params controlling how errors and redirection
         should be handled
@@ -174,8 +174,8 @@
             self._hiddens.append( ('__linkto', linkto, '') )
             msg = '%s %s' % (msg, self.req._('and linked'))
         self._hiddens.append( ('__message', msg, '') )
-        
-    
+
+
     def attributes_form(self, entity, kwargs, include_eid=True):
         """create a form to edit entity's attributes"""
         html = []
@@ -208,7 +208,7 @@
         # XXX both (add, delete)
         return [(rschema, x) for rschema, _, x in entity.relations_by_category(('primary', 'secondary'), 'add')
                 if rschema != 'eid']
-    
+
     def relations_form(self, entity, kwargs):
         srels_by_cat = entity.srelations_by_category(('generic', 'metadata'), 'add')
         if not srels_by_cat:
@@ -267,7 +267,7 @@
         w(u'</table>')
         w(u'</fieldset>')
         return '\n'.join(html)
-        
+
     def inline_entities_form(self, entity, kwargs):
         """create a form to edit entity's inlined relations"""
         result = []
@@ -286,7 +286,7 @@
                 existant = entity.has_eid() and entity.related(rschema)
                 if existant:
                     # display inline-edition view for all existing related entities
-                    result.append(self.view('inline-edition', existant, 
+                    result.append(self.view('inline-edition', existant,
                                             ptype=entity.e_schema, peid=entity.eid,
                                             rtype=rschema, role=x, **kwargs))
                 if x == 'subject':
@@ -318,7 +318,7 @@
         return '\n'.join(result)
 
     # should_* method extracted to allow overriding
-    
+
     def should_inline_relation_form(self, entity, rschema, targettype, role):
         return AutomaticEntityForm.rinlined.etype_get(entity.id, rschema, role,
                                                       targettype)
@@ -328,10 +328,10 @@
 
     def should_display_add_inline_relation_link(self, rschema, existant, card):
         return not existant or card in '+*'
-    
+
     def reset_url(self, entity):
         return entity.absolute_url()
-    
+
     def on_submit(self, entity):
         return u'return freezeFormButtons(\'%s\')' % (self.domid)
 
@@ -339,7 +339,7 @@
         return self.req._('element edited')
 
 
-    
+
 class CreationForm(EditionForm):
     __select__ = specified_etype_implements('Any')
     # XXX bw compat, use View.registered since we don't want accept_compat
@@ -347,7 +347,7 @@
     registered = accepts_etype_compat(View.registered)
     id = 'creation'
     title = _('creation')
-    
+
     def call(self, **kwargs):
         """creation view for an entity"""
         self.req.add_js( ('cubicweb.ajax.js',) )
@@ -385,16 +385,16 @@
     @property
     def formid(self):
         return 'edition'
-    
+
     def relations_form(self, entity, kwargs):
         return u''
 
     def reset_url(self, entity=None):
         return self.build_url(self.req.form.get('etype', '').lower())
-    
+
     def submited_message(self):
         return self.req._('element created')
-    
+
     def url(self):
         """return the url associated with this view"""
         return self.create_url(self.req.form.get('etype'))
@@ -405,21 +405,21 @@
     @cached
     def card(self, etype):
         return self.rschema.rproperty(self.parent_schema, etype, 'cardinality')[0]
-    
+
     def action_title(self, entity):
         return self.rschema.display_name(self.req, self.role)
-        
+
     def add_hidden_web_behaviour_params(self, entity):
         pass
-    
+
     def edit_form(self, entity, ptype, peid, rtype,
                   role='subject', **kwargs):
         self.rschema = self.schema.rschema(rtype)
-        self.role = role        
+        self.role = role
         self.parent_schema = self.schema.eschema(ptype)
         self.parent_eid = peid
         super(InlineFormMixIn, self).edit_form(entity, kwargs)
-    
+
     def should_inline_relation_form(self, entity, rschema, targettype, role):
         if rschema == self.rschema:
             return False
@@ -455,7 +455,7 @@
                      }
         ctx.update(local_ctx)
         return ctx
-    
+
 
 class CopyEditionForm(EditionForm):
     id = 'copy'
@@ -465,7 +465,7 @@
         self.req.add_js(('cubicweb.ajax.js',))
         entity = self.complete_entity(row, col, skip_bytes=True)
         # make a copy of entity to avoid altering the entity in the
-        # request's cache. 
+        # request's cache.
         self.newentity = copy(entity)
         self.copying = self.newentity.eid
         self.newentity.eid = None
@@ -482,23 +482,23 @@
     @property
     def formid(self):
         return 'edition'
-        
+
     def relations_form(self, entity, kwargs):
         return u''
 
     def reset_url(self, entity):
         return self.build_url('view', rql='Any X WHERE X eid %s' % self.copying)
-    
+
     def attributes_form(self, entity, kwargs, include_eid=True):
         # we don't want __clone_eid on inlined edited entities
         if entity.eid == self.newentity.eid:
             self._hiddens.append((eid_param('__cloned_eid', entity.eid), self.copying, ''))
         return EditionForm.attributes_form(self, entity, kwargs, include_eid)
-    
+
     def submited_message(self):
         return self.req._('element copied')
-       
-    
+
+
 class TableEditForm(FormMixIn, EntityView):
     id = 'muledit'
     title = _('multiple edit')
@@ -526,7 +526,7 @@
       </td>
     </tr>
   </table>
-  </fieldset>    
+  </fieldset>
 </form>
 '''
 
@@ -535,7 +535,7 @@
   %(error)s
   <div>%(widget)s</div>
 </td>'''
-    
+
     def call(self, **kwargs):
         """a view to edit multiple entities of the same type
         the first column should be the eid
@@ -560,13 +560,13 @@
                'oktitle': _('validate modifications on selected items').capitalize(),
                'cancelvalue': _('button_reset').capitalize(),
                'canceltitle': _('revert changes').capitalize(),
-               }        
+               }
         self.w(self.EDITION_BODY % ctx)
-        
-        
+
+
     def reset_url(self, entity=None):
         self.build_url('view', rql=self.rset.printable_rql())
-        
+
     def edit_form(self, entity):
         html = []
         w = html.append
--- a/web/views/calendar.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/calendar.py	Thu Apr 04 13:49:34 2019 +0200
@@ -13,7 +13,6 @@
 from cubicweb.selectors import implements
 from cubicweb.utils import strptime, date_range, todate, todatetime
 from cubicweb.view import EntityView
-from cubicweb.web import ajax_replace_url
 
 _ = unicode
 
@@ -164,13 +163,15 @@
             else:
                 user = None
             the_dates = []
-            tstart = todate(task.start)
+            tstart = task.start
             if tstart:
+                tstart = todate(task.start)
                 if tstart > lastday:
                     continue
                 the_dates = [tstart]
-            tstop = todate(task.start)
+            tstop = task.stop
             if tstop:
+                tstop = todate(tstop)
                 if tstop < firstday:
                     continue
                 the_dates = [tstop]
@@ -260,10 +261,12 @@
         prevdate = curdate - timedelta(31)
         nextdate = curdate + timedelta(31)
         rql = self.rset.printable_rql()
-        prevlink = ajax_replace_url('onemonthcalid', rql, 'onemonthcal',
-                                    year=prevdate.year, month=prevdate.month)
-        nextlink = ajax_replace_url('onemonthcalid', rql, 'onemonthcal',
-                                    year=nextdate.year, month=nextdate.month)
+        prevlink = self.req.build_ajax_replace_url('onemonthcalid', rql, 'onemonthcal',
+                                                   year=prevdate.year,
+                                                   month=prevdate.month)
+        nextlink = self.req.build_ajax_replace_url('onemonthcalid', rql, 'onemonthcal',
+                                                   year=nextdate.year,
+                                                   month=nextdate.month)
         return prevlink, nextlink
 
     def _build_calendar_cell(self, celldate, rows, curdate):
@@ -348,13 +351,15 @@
                 continue
             done_tasks.append(task)
             the_dates = []
-            tstart = todate(task.start)
-            tstop = todate(task.stop)
+            tstart = task.start
+            tstop = task.stop
             if tstart:
+                tstart = todate(tstart)
                 if tstart > lastday:
                     continue
                 the_dates = [tstart]
             if tstop:
+                tstop = todate(tstop)
                 if tstop < firstday:
                     continue
                 the_dates = [tstop]
@@ -513,9 +518,11 @@
         prevdate = curdate - timedelta(7)
         nextdate = curdate + timedelta(7)
         rql = self.rset.printable_rql()
-        prevlink = ajax_replace_url('oneweekcalid', rql, 'oneweekcal',
-                                    year=prevdate.year, week=prevdate.isocalendar()[1])
-        nextlink = ajax_replace_url('oneweekcalid', rql, 'oneweekcal',
-                                    year=nextdate.year, week=nextdate.isocalendar()[1])
+        prevlink = self.req.build_ajax_replace_url('oneweekcalid', rql, 'oneweekcal',
+                                                   year=prevdate.year,
+                                                   week=prevdate.isocalendar()[1])
+        nextlink = self.req.build_ajax_replace_url('oneweekcalid', rql, 'oneweekcal',
+                                                   year=nextdate.year,
+                                                   week=nextdate.isocalendar()[1])
         return prevlink, nextlink
 
--- a/web/views/debug.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/debug.py	Thu Apr 04 13:49:34 2019 +0200
@@ -23,7 +23,7 @@
                 html_escape(str(key)), html_escape(repr(dict[key]))))
         w(u'</ul>')
 
-    
+
 class DebugView(StartupView):
     id = 'debug'
     __select__ = none_rset() & match_user_groups('managers')
--- a/web/views/editcontroller.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/editcontroller.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,7 +1,7 @@
 """The edit controller, handling form submitting.
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
--- a/web/views/embedding.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/embedding.py	Thu Apr 04 13:49:34 2019 +0200
@@ -29,7 +29,7 @@
     """template embeding an external web pages into CubicWeb web interface
     """
     id = 'external'
-    
+
     def call(self, body):
         # XXX fallback to HTML 4 mode when embeding ?
         self.set_request_content_type()
@@ -92,12 +92,12 @@
     """
     id = 'embed'
     __select__ = (one_line_rset() & match_search_state('normal')
-                  & implements(IEmbedable) 
+                  & implements(IEmbedable)
                   & score_entity(entity_has_embedable_url))
-    
+
     title = _('embed')
     controller = 'embed'
-    
+
     def url(self, row=0):
         entity = self.rset.get_entity(row, 0)
         url = urljoin(self.req.base_url(), entity.embeded_url())
@@ -119,7 +119,7 @@
     def __init__(self, prefix, custom_css=None):
         self.prefix = prefix
         self.custom_css = custom_css
-        
+
     def __call__(self, match):
         original_url = match.group(1)
         url = self.prefix + urlquote(original_url, safe='')
@@ -136,7 +136,7 @@
         self.embedded_url = embedded_url
         self.tag = tag
         self.custom_css = custom_css
-    
+
     def __call__(self, match):
         original_url = match.group(1)
         if '://' in original_url:
--- a/web/views/error.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/error.py	Thu Apr 04 13:49:34 2019 +0200
@@ -24,5 +24,3 @@
         _ = self.req._
         self.w(u"<h1>%s</h1>" %
                _('an error occured, the request cannot be fulfilled'))
-    
-
--- a/web/views/facets.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/facets.py	Thu Apr 04 13:49:34 2019 +0200
@@ -22,7 +22,7 @@
                          **kwargs):
     if view and getattr(view, 'filter_box_context_info', lambda: None)():
         return 1
-    return 0    
+    return 0
 
 
 class FilterBox(BoxTemplate):
@@ -42,7 +42,7 @@
         be used by the facet
         """
         return {}
-        
+
     def _get_context(self, view):
         context = getattr(view, 'filter_box_context_info', lambda: None)()
         if context:
@@ -52,7 +52,7 @@
             vid, divid = None, 'pageContent'
             paginate = view and view.need_navigation
         return rset, vid, divid, paginate
-        
+
     def call(self, view=None):
         req = self.req
         req.add_js( ('cubicweb.ajax.js', 'cubicweb.formfilter.js') )
@@ -109,7 +109,7 @@
         return self.vreg.possible_vobjects('facets', self.req, rset,
                                            context='facetbox',
                                            filtered_variable=mainvar)
-        
+
 # facets ######################################################################
 
 class CreatedByFacet(RelationFacet):
@@ -144,7 +144,7 @@
         """
         etypes = self.rset.column_types(0)
         return sorted((self.req._(etype), etype) for etype in etypes)
-    
+
     def add_rql_restrictions(self):
         """add restriction for this facet into the rql syntax tree"""
         value = self.req.form.get(self.id)
@@ -162,7 +162,7 @@
     @property
     def title(self):
         return self.req._('has_text')
-    
+
     def get_widget(self):
         """return the widget instance to use to display this facet
 
--- a/web/views/ibreadcrumbs.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/ibreadcrumbs.py	Thu Apr 04 13:49:34 2019 +0200
@@ -21,7 +21,7 @@
 def bc_title(entity):
     textsize = entity.req.property_value('navigation.short-line-size')
     return html_escape(cut(entity.dc_title(), textsize))
-    
+
 
 class BreadCrumbEntityVComponent(EntityVComponent):
     id = 'breadcrumbs'
@@ -52,7 +52,7 @@
                 self.w(u"\n")
                 self.wpath_part(parent, entity, i == len(path) - 1)
             self.w(u'</span>')
-            
+
     def wpath_part(self, part, contextentity, last=False):
         if isinstance(part, Entity):
             if last and part.eid == contextentity.eid:
@@ -67,7 +67,7 @@
         else:
             textsize = self.req.property_value('navigation.short-line-size')
             self.w(cut(unicode(part), textsize))
-        
+
 
 class BreadCrumbComponent(BreadCrumbEntityVComponent):
     __registry__ = 'components'
--- a/web/views/management.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/management.py	Thu Apr 04 13:49:34 2019 +0200
@@ -33,7 +33,7 @@
             _("permission"), _('granted to groups'), _('rql expressions')))
         for access_type in access_types:
             w(u'<tr>')
-            w(u'<td>%s</td>' % _('%s_perm' % access_type))
+            w(u'<td>%s</td>' % self.req.__('%s_perm' % access_type))
             groups = eschema.get_groups(access_type)
             l = []
             groups = [(_(group), group) for group in groups]
--- a/web/views/owl.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/owl.py	Thu Apr 04 13:49:34 2019 +0200
@@ -14,7 +14,7 @@
 
 _ = unicode
 
-OWL_CARD_MAP = {'1': '<rdf:type rdf:resource="&owl;FunctionalProperty"/>',                      
+OWL_CARD_MAP = {'1': '<rdf:type rdf:resource="&owl;FunctionalProperty"/>',
                 '?': '<owl:maxCardinality rdf:datatype="&xsd;int">1</owl:maxCardinality>',
                 '+': '<owl:minCardinality rdf:datatype="&xsd;int">1</owl:minCardinality>',
                 '*': ''
@@ -37,7 +37,7 @@
 <!DOCTYPE rdf:RDF [
         <!ENTITY owl "http://www.w3.org/2002/07/owl#" >
         <!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" >
-]>        
+]>
 <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
@@ -48,7 +48,7 @@
 
   <owl:Ontology rdf:about="">
     <rdfs:comment>
-    %(appid)s Cubicweb OWL Ontology                           
+    %(appid)s Cubicweb OWL Ontology
     </rdfs:comment>
   </owl:Ontology>'''
 
@@ -71,7 +71,7 @@
         self.visit_schema(skipmeta=skipmeta)
         if writeprefix:
             self.w(OWL_CLOSING_ROOT)
-        
+
     def visit_schema(self, skiprels=DEFAULT_SKIP_RELS, skipmeta=True):
         """get a layout for a whole schema"""
         entities = sorted([eschema for eschema in self.schema.entities()
@@ -89,8 +89,8 @@
 
     def visit_entityschema(self, eschema, skiprels=()):
         """get a layout for an entity OWL schema"""
-        self.w(u'<owl:Class rdf:ID="%s">'% eschema)         
-        self.w(u'<!-- relations -->')    
+        self.w(u'<owl:Class rdf:ID="%s">'% eschema)
+        self.w(u'<!-- relations -->')
         for rschema, targetschemas, role in eschema.relation_definitions():
             if rschema.type in skiprels:
                 continue
@@ -113,7 +113,7 @@
 ''' % (label, cardtag))
 
         self.w(u'<!-- attributes -->')
-              
+
         for rschema, aschema in eschema.attribute_definitions():
             if not (rschema.has_local_role('read') or rschema.has_perm(self.req, 'read')):
                 continue
@@ -125,10 +125,10 @@
    <owl:onProperty rdf:resource="#%s"/>
    <rdf:type rdf:resource="&owl;FunctionalProperty"/>
   </owl:Restriction>
-</rdfs:subClassOf>'''                         
+</rdfs:subClassOf>'''
                    % aname)
         self.w(u'</owl:Class>')
-    
+
     def visit_property_schema(self, eschema, skiprels=()):
         """get a layout for property entity OWL schema"""
         for rschema, targetschemas, role in eschema.relation_definitions():
@@ -141,7 +141,7 @@
                 self.w(u'''<owl:ObjectProperty rdf:ID="%s">
  <rdfs:domain rdf:resource="#%s"/>
  <rdfs:range rdf:resource="#%s"/>
-</owl:ObjectProperty>                                                
+</owl:ObjectProperty>
 ''' % (label, eschema, oeschema.type))
 
     def visit_property_object_schema(self, eschema):
@@ -157,15 +157,15 @@
 </owl:DatatypeProperty>'''
                    % (aname, eschema, OWL_TYPE_MAP[aschema.type]))
 
-            
+
 class OWLABOXView(EntityView):
     '''This view represents a part of the ABOX for a given entity.'''
-    
+
     id = 'owlabox'
     title = _('owlabox')
     templatable = False
     content_type = 'application/xml' # 'text/xml'
-    
+
     def call(self):
         self.w(OWL_OPENING_ROOT % {'appid': self.schema.name})
         for i in xrange(self.rset.rowcount):
@@ -175,9 +175,9 @@
     def cell_call(self, row, col, skiprels=DEFAULT_SKIP_RELS):
         self.wview('owlaboxitem', self.rset, row=row, col=col, skiprels=skiprels)
 
-        
+
 class OWLABOXItemView(EntityView):
-    '''This view represents a part of the ABOX for a given entity.'''    
+    '''This view represents a part of the ABOX for a given entity.'''
     id = 'owlaboxitem'
     templatable = False
     content_type = 'application/xml' # 'text/xml'
@@ -208,9 +208,9 @@
             if not (rschema.has_local_role('read') or rschema.has_perm(self.req, 'read')):
                 continue
             if role == 'object':
-                attr = 'reverse_%s' % rschema.type 
+                attr = 'reverse_%s' % rschema.type
             else:
-                attr = rschema.type        
+                attr = rschema.type
             for x in getattr(entity, attr):
                 self.w(u'<%s>%s %s</%s>' % (attr, x.id, x.eid, attr))
         self.w(u'</%s>'% eschema)
@@ -219,10 +219,9 @@
 class DownloadOWLSchemaAction(Action):
     id = 'download_as_owl'
     __select__ = none_rset() & match_view('schema')
-    
+
     category = 'mainactions'
     title = _('download schema as owl')
-   
+
     def url(self):
         return self.build_url('view', vid='owl')
-
--- a/web/views/searchrestriction.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/searchrestriction.py	Thu Apr 04 13:49:34 2019 +0200
@@ -2,7 +2,7 @@
 a search
 
 :organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
--- a/web/views/sessions.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/sessions.py	Thu Apr 04 13:49:34 2019 +0200
@@ -13,7 +13,7 @@
 
 class InMemoryRepositorySessionManager(AbstractSessionManager):
     """manage session data associated to a session identifier"""
-    
+
     def __init__(self):
         AbstractSessionManager.__init__(self)
         # XXX require a RepositoryAuthenticationManager which violates
@@ -23,7 +23,7 @@
 
     def current_sessions(self):
         return self._sessions.values()
-    
+
     def get_session(self, req, sessionid):
         """return existing session for the given session identifier"""
         if not sessionid in self._sessions:
@@ -47,13 +47,13 @@
 
     def open_session(self, req):
         """open and return a new session for the given request
-        
+
         :raise ExplicitLogin: if authentication is required
         """
         session = self.authmanager.authenticate(req)
         self._sessions[session.sessionid] = session
         return session
-    
+
     def close_session(self, session):
         """close session on logout or on invalid session detected (expired out,
         corrupted...)
@@ -66,4 +66,3 @@
             # already closed, may occurs if the repository session expired but
             # not the web session
             pass
-    
--- a/web/views/tabs.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/tabs.py	Thu Apr 04 13:49:34 2019 +0200
@@ -164,7 +164,7 @@
     """
     __select__ = EntityView.__select__ & partial_has_related_entities()
     vid = 'list'
-    
+
     def cell_call(self, row, col):
         rset = self.entity(row, col).related(self.rtype, role(self))
         self.w(u'<div class="mainInfo">')
--- a/web/views/treeview.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/treeview.py	Thu Apr 04 13:49:34 2019 +0200
@@ -45,7 +45,7 @@
             self.wview(self.itemvid, self.rset, row=rowidx, col=0,
                        vid=subvid, parentvid=self.id)
         self.w(u'</ul>')
-        
+
 
 class FileTreeView(TreeView):
     """specific version of the treeview to display file trees
@@ -79,7 +79,7 @@
 class DefaultTreeViewItemView(EntityView):
     """default treeitem view for entities which don't implement ITree"""
     id = 'treeitemview'
-    
+
     def cell_call(self, row, col, vid='oneline', parentvid='treeview'):
         entity = self.entity(row, col)
         itemview = self.view(vid, self.rset, row=row, col=col)
@@ -96,7 +96,7 @@
     """
     id = 'treeitemview'
     __select__ = implements(ITree)
-    
+
     def cell_call(self, row, col, vid='oneline', parentvid='treeview'):
         entity = self.entity(row, col)
         cssclasses = []
@@ -124,4 +124,3 @@
             self.w(u'<ul class="placeholder"><li>place holder</li></ul>')
         self.wview(vid, self.rset, row=row, col=col)
         self.w(u'</li>')
-
--- a/web/views/urlpublishing.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/urlpublishing.py	Thu Apr 04 13:49:34 2019 +0200
@@ -35,7 +35,7 @@
     """exception used by url evaluators to notify they can't evaluate
     a path
     """
-    
+
 class URLPublisherComponent(Component):
     """associate url's path to view identifier / rql queries,
     by applying a chain of urlpathevaluator components.
@@ -50,33 +50,33 @@
     something else than `PathDontMatch` will stop the handlers chain.
     """
     id = 'urlpublisher'
-    
+
     def __init__(self, default_method='view'):
         super(URLPublisherComponent, self).__init__()
         self.default_method = default_method
-        evaluators = []        
+        evaluators = []
         for evaluatorcls in self.vreg.registry_objects('components',
                                                        'urlpathevaluator'):
             # instantiation needed
             evaluator = evaluatorcls(self)
             evaluators.append(evaluator)
         self.evaluators = sorted(evaluators, key=lambda x: x.priority)
-        
+
     def process(self, req, path):
         """given an url (essentialy caracterized by a path on the server,
         but additional information may be found in the request object), return
         a publishing method identifier (eg controller) and an optional result
         set
-        
+
         :type req: `cubicweb.web.Request`
         :param req: the request object
-        
+
         :type path: str
         :param path: the path of the resource to publish
 
         :rtype: tuple(str, `cubicweb.common.utils.ResultSet` or None)
         :return: the publishing method identifier and an optional result set
-        
+
         :raise NotFound: if no handler is able to decode the given path
         """
         parts = [part for part in path.split('/')
@@ -97,7 +97,7 @@
             pmid = self.default_method
         return pmid, rset
 
-        
+
 class URLPathEvaluator(Component):
     __abstract__ = True
     id = 'urlpathevaluator'
@@ -136,7 +136,7 @@
             raise NotFound()
         return None, rset
 
-        
+
 class RestPathEvaluator(URLPathEvaluator):
     """handle path with the form::
 
@@ -149,7 +149,7 @@
         for etype in self.schema.entities():
             etype = str(etype)
             self.etype_map[etype.lower()] = etype
-            
+
     def evaluate_path(self, req, parts):
         if not (0 < len(parts) < 4):
             raise PathDontMatch()
@@ -177,7 +177,7 @@
 
     def cls_rset(self, req, cls):
         return req.execute(cls.fetch_rql(req.user))
-        
+
     def attr_rset(self, req, etype, attrname, value):
         rql = u'Any X WHERE X is %s, X %s %%(x)s' % (etype, attrname)
         if attrname == 'eid':
@@ -211,7 +211,7 @@
             except KeyError:
                 continue
         raise PathDontMatch()
-        
+
 
 class ActionPathEvaluator(URLPathEvaluator):
     """handle path with the form::
--- a/web/views/vcard.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/vcard.py	Thu Apr 04 13:49:34 2019 +0200
@@ -9,7 +9,7 @@
 from cubicweb.selectors import implements
 from cubicweb.view import EntityView
 
-_ = unicode 
+_ = unicode
 
 VCARD_PHONE_TYPES = {'home': 'HOME', 'office': 'WORK', 'mobile': 'CELL', 'fax': 'FAX'}
 
@@ -19,12 +19,12 @@
     title = _('vcard')
     templatable = False
     content_type = 'text/x-vcard'
-    __select__ = implements('CWUser')        
+    __select__ = implements('CWUser')
 
     def set_request_content_type(self):
         """overriden to set a .vcf filename"""
         self.req.set_content_type(self.content_type, filename='vcard.vcf')
-        
+
     def cell_call(self, row, col):
         self.vcard_header()
         self.vcard_content(self.complete_entity(row, col))
@@ -33,11 +33,11 @@
     def vcard_header(self):
         self.w(u'BEGIN:vcard\n')
         self.w(u'VERSION:3.0\n')
-        
+
     def vcard_footer(self):
         self.w(u'NOTE:this card has been generated by CubicWeb\n')
         self.w(u'END:vcard\n')
-        
+
     def vcard_content(self, entity):
         who = u'%s %s' % (entity.surname or '',
                           entity.firstname or '')
--- a/web/views/wdoc.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/views/wdoc.py	Thu Apr 04 13:49:34 2019 +0200
@@ -53,7 +53,7 @@
         node = index[section.attrib['appendto']]
         idx = None
     return node, idx
-                     
+
 def build_toc(config):
     alltocfiles = reversed(tuple(config.locate_all_files('toc.xml')))
     maintoc = parse(alltocfiles.next()).getroot()
@@ -61,7 +61,7 @@
     index = {}
     build_toc_index(maintoc, index)
     # insert component documentation into the tree according to their toc.xml
-    # file 
+    # file
     for fpath in alltocfiles:
         toc = parse(fpath).getroot()
         for section in toc:
@@ -73,7 +73,7 @@
             section.parent = node
             build_toc_index(section, index)
     return index
-    
+
 def title_for_lang(node, lang):
     for title in node.findall('title'):
         if title.attrib['{http://www.w3.org/XML/1998/namespace}lang'] == lang:
@@ -88,7 +88,7 @@
     __select__ = match_form_params('fid')
     id = 'wdoc'
     title = _('site documentation')
-    
+
     def call(self):
         fid = self.req.form['fid']
         for lang in chain((self.req.lang, self.vreg.property_value('ui.language')),
@@ -107,7 +107,7 @@
         else:
             self.navigation_links(node)
             self.w(u'<div class="hr"></div>')
-            self.w(u'<h1>%s</h1>' % (title_for_lang(node, self.req.lang)))            
+            self.w(u'<h1>%s</h1>' % (title_for_lang(node, self.req.lang)))
         data = open(join(resourcedir, rid)).read()
         self.w(rest_publish(self, data))
         if node is not None:
@@ -124,17 +124,17 @@
         self.w(u'<div class="docnav">\n')
         previousidx = brothers.index(node) - 1
         if previousidx >= 0:
-            self.navsection(brothers[previousidx], 'prev')            
-        self.navsection(parent, 'up')            
+            self.navsection(brothers[previousidx], 'prev')
+        self.navsection(parent, 'up')
         nextidx = brothers.index(node) + 1
         if nextidx < len(brothers):
-            self.navsection(brothers[nextidx], 'next')            
+            self.navsection(brothers[nextidx], 'next')
         self.w(u'</div>\n')
 
     navinfo = {'prev': ('', 'data/previous.png', _('i18nprevnext_previous')),
                'next': ('', 'data/next.png', _('i18nprevnext_next')),
                'up': ('', 'data/up.png', _('i18nprevnext_up'))}
-               
+
     def navsection(self, node, navtype):
         htmlclass, imgpath, msgid = self.navinfo[navtype]
         self.w(u'<span class="%s">' % htmlclass)
@@ -143,7 +143,7 @@
             self.req.build_url('doc/'+node.attrib['resource']),
             title_for_lang(node, self.req.lang)))
         self.w(u'</span>\n')
-        
+
     def subsections_links(self, node, first=True):
         sub = subsections(node)
         if not sub:
@@ -158,7 +158,7 @@
             self.subsections_links(child, False)
             self.w(u'</li>')
         self.w(u'</ul>\n')
-        
+
 
 
 class InlineHelpImageView(StartupView):
@@ -167,7 +167,7 @@
     binary = True
     templatable = False
     content_type = 'image/png'
-    
+
     def call(self):
         fid = self.req.form['fid']
         for lang in chain((self.req.lang, self.vreg.property_value('ui.language')),
@@ -185,7 +185,7 @@
     id = 'changelog'
     title = _('What\'s new?')
     maxentries = 25
-    
+
     def call(self):
         rid = 'ChangeLog_%s' % (self.req.lang)
         allentries = []
@@ -234,4 +234,3 @@
                     break
         w('') # blank line
         self.w(rest_publish(self, '\n'.join(restdata)))
-        
--- a/web/webconfig.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/webconfig.py	Thu Apr 04 13:49:34 2019 +0200
@@ -22,7 +22,7 @@
     ('site-title',
      {'type' : 'string', 'default': 'unset title',
       'help': _('site title'),
-      'sitewide': True, 'group': 'ui', 
+      'sitewide': True, 'group': 'ui',
       }),
     ('main-template',
      {'type' : 'string', 'default': 'main-template',
@@ -54,7 +54,7 @@
       'help': _('maximum number of entities to display in related combo box'),
       'group': 'navigation',
       }),
-    
+
     ))
 
 
@@ -64,7 +64,7 @@
     """
     cubicweb_vobject_path = CubicWebConfiguration.cubicweb_vobject_path | set(['web/views'])
     cube_vobject_path = CubicWebConfiguration.cube_vobject_path | set(['views'])
-    
+
     options = merge_options(CubicWebConfiguration.options + (
         ('anonymous-user',
          {'type' : 'string',
@@ -185,7 +185,7 @@
           'interface\'s language according to browser defined preferences',
           'group': 'web', 'inputlevel': 2,
           }),
-        
+
         ('print-traceback',
          {'type' : 'yn',
           'default': not CubicWebConfiguration.mode == 'installed',
@@ -206,17 +206,17 @@
 
     def fckeditor_installed(self):
         return exists(self.ext_resources['FCKEDITOR_PATH'])
-    
+
     def eproperty_definitions(self):
         for key, pdef in super(WebConfiguration, self).eproperty_definitions():
             if key == 'ui.fckeditor' and not self.fckeditor_installed():
                 continue
             yield key, pdef
-                
+
     # method used to connect to the repository: 'inmemory' / 'pyro'
     # Pyro repository by default
     repo_method = 'pyro'
-    
+
     # don't use @cached: we want to be able to disable it while this must still
     # be cached
     def repository(self, vreg=None):
@@ -235,7 +235,7 @@
 
     def vc_config(self):
         return self.repository().get_versions()
-    
+
     # mapping to external resources (id -> path) (`external_resources` file) ##
     ext_resources = {
         'FAVICON':  'DATADIR/favicon.ico',
@@ -244,13 +244,13 @@
         'HELP':     'DATADIR/help.png',
         'CALENDAR_ICON': 'DATADIR/calendar.gif',
         'SEARCH_GO':'DATADIR/go.png',
-        
+
         'FCKEDITOR_PATH':  '/usr/share/fckeditor/',
-        
+
         'IE_STYLESHEETS':    ['DATADIR/cubicweb.ie.css'],
         'STYLESHEETS':       ['DATADIR/cubicweb.css'],
         'STYLESHEETS_PRINT': ['DATADIR/cubicweb.print.css'],
-        
+
         'JAVASCRIPTS':       ['DATADIR/jquery.js',
                               'DATADIR/jquery.corner.js',
                               'DATADIR/jquery.json.js',
@@ -258,8 +258,8 @@
                               'DATADIR/cubicweb.python.js',
                               'DATADIR/cubicweb.htmlhelpers.js'],
         }
-        
-        
+
+
     def anonymous_user(self):
         """return a login and password to use for anonymous users. None
         may be returned for both if anonymous connections are not allowed
@@ -272,7 +272,7 @@
         if user is not None:
             user = unicode(user)
         return user, passwd
-    
+
     def has_resource(self, rid):
         """return true if an external resource is defined"""
         return bool(self.ext_resources.get(rid))
@@ -281,19 +281,19 @@
     def locate_resource(self, rid):
         """return the directory where the given resource may be found"""
         return self._fs_locate(rid, 'data')
-            
+
     @cached
     def locate_doc_file(self, fname):
         """return the directory where the given resource may be found"""
         return self._fs_locate(fname, 'wdoc')
-            
+
     def _fs_locate(self, rid, rdirectory):
         """return the directory where the given resource may be found"""
         path = [self.apphome] + self.cubes_path() + [join(self.shared_dir())]
         for directory in path:
             if exists(join(directory, rdirectory, rid)):
                 return join(directory, rdirectory)
-            
+
     def locate_all_files(self, rid, rdirectory='wdoc'):
         """return all files corresponding to the given resource"""
         path = [self.apphome] + self.cubes_path() + [join(self.shared_dir())]
@@ -308,7 +308,7 @@
         # load external resources definition
         self._build_ext_resources()
         self._init_base_url()
-        
+
     def _init_base_url(self):
         # normalize base url(s)
         baseurl = self['base-url']
@@ -341,11 +341,11 @@
 
 
     # static files handling ###################################################
-    
+
     @property
     def static_directory(self):
         return join(self.appdatahome, 'static')
-    
+
     def static_file_exists(self, rpath):
         return exists(join(self.static_directory, rpath))
 
@@ -365,4 +365,3 @@
     def static_file_del(self, rpath):
         if self.static_file_exists(rpath):
             os.remove(join(self.static_directory, rpath))
-        
--- a/web/webctl.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/web/webctl.py	Thu Apr 04 13:49:34 2019 +0200
@@ -12,7 +12,7 @@
 
 class WebCreateHandler(CommandHandler):
     cmdname = 'create'
-    
+
     def bootstrap(self, cubes, inputlevel=0):
         """bootstrap this configuration"""
         print '** generic web configuration'
@@ -23,9 +23,8 @@
             print '-' * 72
             config.input_config('pyro-client', inputlevel)
         if confirm('allow anonymous access', False):
-            config.global_set_option('anonymous-user', 'anon') 
-            config.global_set_option('anonymous-password', 'anon') 
-        
+            config.global_set_option('anonymous-user', 'anon')
+            config.global_set_option('anonymous-password', 'anon')
+
     def postcreate(self):
         """hooks called once application's initialization has been completed"""
-        
--- a/wsgi/__init__.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/wsgi/__init__.py	Thu Apr 04 13:49:34 2019 +0200
@@ -7,7 +7,7 @@
 WSGI corresponding PEP: http://www.python.org/dev/peps/pep-0333/
 
 :organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 __docformat__ = "restructuredtext en"
@@ -25,7 +25,7 @@
         return _pformat(obj)
     except:
         return u'<could not parse>'
-    
+
 def qs2dict(qs):
     """transforms a query string into a regular python dict"""
     result = {}
@@ -35,7 +35,7 @@
 
 def normalize_header(header):
     """returns a normalized header name
-    
+
     >>> normalize_header('User_Agent')
     'User-agent'
     """
@@ -84,4 +84,3 @@
         else:
             post.setdefault(key, []).append(submessage.get_payload())
     return post, files
-
--- a/wsgi/handler.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/wsgi/handler.py	Thu Apr 04 13:49:34 2019 +0200
@@ -1,7 +1,7 @@
 """WSGI request handler for cubicweb
 
 :organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 
@@ -74,7 +74,7 @@
 
     def __iter__(self):
         return iter(self.body)
-    
+
 
 
 class CubicWebWSGIApplication(object):
@@ -100,7 +100,7 @@
             self.url_rewriter = self.appli.vreg.select_component('urlrewriter')
         except ObjectNotFound:
             self.url_rewriter = None
-        
+
     def _render(self, req):
         """this function performs the actual rendering
         XXX missing: https handling, url rewriting, cache management,
@@ -156,8 +156,8 @@
             # 500 Internal server error
             return self.redirect(req, req.build_url('error'))
         return WSGIResponse(200, req, result)
-        
-    
+
+
     def __call__(self, environ, start_response):
         """WSGI protocol entry point"""
         req = CubicWebWsgiRequest(environ, self.appli.vreg, self.base_url)
@@ -170,7 +170,7 @@
         self.debug('redirecting to %s', location)
         req.set_header('location', str(location))
         return WSGIResponse(303, req)
-        
+
     def request_auth(self, req, loggedout=False):
         """returns the appropriate WSGIResponse to require the user to log in
         """
--- a/wsgi/request.py	Wed Jun 03 09:09:33 2009 +0200
+++ b/wsgi/request.py	Thu Apr 04 13:49:34 2019 +0200
@@ -5,7 +5,7 @@
   http://www.djangoproject.com/
 
 :organization: Logilab
-:copyright: 2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 """
 
@@ -25,7 +25,7 @@
 class CubicWebWsgiRequest(CubicWebRequestBase):
     """most of this code COMES FROM DJANO
     """
-    
+
     def __init__(self, environ, vreg, base_url=None):
         self.environ = environ
         self.path = environ['PATH_INFO']
@@ -42,7 +42,7 @@
             self.form.update(files)
         # prepare output headers
         self.headers_out = {}
-        
+
     def __repr__(self):
         # Since this is called as part of error handling, we need to be very
         # robust against potentially malformed input.
@@ -52,14 +52,14 @@
             (form, meta)
 
     ## cubicweb request interface ################################################
-    
+
     def base_url(self):
         return self._base_url
 
     def http_method(self):
         """returns 'POST', 'GET', 'HEAD', etc."""
         return self.method
-    
+
     def relative_path(self, includeparams=True):
         """return the normalized path of the request (ie at least relative
         to the application's root, but some other normalization may be needed
@@ -74,7 +74,7 @@
             qs = self.environ.get('QUERY_STRING')
             if qs:
                 return '%s?%s' % (path, qs)
-        
+
         return path
 
     def get_header(self, header, default=None):
@@ -82,7 +82,7 @@
         raise KeyError if the header is not set
         """
         return self._headers.get(normalize_header(header), default)
-    
+
     def set_header(self, header, value, raw=True):
         """set an output HTTP header"""
         assert raw, "don't know anything about non-raw headers for wsgi requests"
@@ -91,7 +91,7 @@
     def add_header(self, header, value):
         """add an output HTTP header"""
         self.headers_out[header] = value
-    
+
     def remove_header(self, header):
         """remove an output HTTP header"""
         self.headers_out.pop(header, None)
@@ -101,9 +101,9 @@
         mx date time value (GMT), else return None
         """
         return None
-        
+
     ## wsgi request helpers ###################################################
-    
+
     def application_uri(self):
         """Return the application's base URI (no PATH_INFO or QUERY_STRING)
 
@@ -123,7 +123,7 @@
                     url += ':' + environ['SERVER_PORT']
         url += quote(environ.get('SCRIPT_NAME') or '/')
         return url
-        
+
     def get_full_path(self):
         return '%s%s' % (self.path, self.environ.get('QUERY_STRING', '') and ('?' + self.environ.get('QUERY_STRING', '')) or '')