[test] update test to unittest2 api (still using lgc.testlib though) stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 24 Sep 2010 18:20:59 +0200
branchstable
changeset 6340 470d8e828fda
parent 6339 bdc3dc94d744
child 6341 ad5e08981153
[test] update test to unittest2 api (still using lgc.testlib though)
devtools/test/unittest_dbfill.py
devtools/test/unittest_httptest.py
devtools/test/unittest_qunit.py
devtools/test/unittest_testlib.py
entities/test/unittest_base.py
entities/test/unittest_wfobjs.py
ext/test/unittest_rest.py
goa/__init__.py
goa/appobjects/__init__.py
goa/appobjects/components.py
goa/appobjects/dbmgmt.py
goa/appobjects/gauthservice.py
goa/appobjects/sessions.py
goa/bin/laxctl
goa/db.py
goa/dbinit.py
goa/dbmyams.py
goa/doc/FAQ.en.txt
goa/doc/README_LAX.fr.txt
goa/doc/devmanual_fr/advanced_notes.txt
goa/doc/devmanual_fr/archi_globale.dia
goa/doc/devmanual_fr/archi_globale.png
goa/doc/devmanual_fr/chap_autres_composants_ui.txt
goa/doc/devmanual_fr/chap_bases_framework_erudi.txt
goa/doc/devmanual_fr/chap_configuration_instance.txt
goa/doc/devmanual_fr/chap_definition_schema.txt
goa/doc/devmanual_fr/chap_definition_workflows.txt
goa/doc/devmanual_fr/chap_fondements_erudi.txt
goa/doc/devmanual_fr/chap_i18n.txt
goa/doc/devmanual_fr/chap_manipulation_donnees.txt
goa/doc/devmanual_fr/chap_migration.txt
goa/doc/devmanual_fr/chap_mise_en_place_environnement.txt
goa/doc/devmanual_fr/chap_rql.txt
goa/doc/devmanual_fr/chap_serveur_crochets.txt
goa/doc/devmanual_fr/chap_serveur_notification.txt
goa/doc/devmanual_fr/chap_tests.txt
goa/doc/devmanual_fr/chap_ui_gestion_formulaire.txt
goa/doc/devmanual_fr/chap_ui_js_json.txt
goa/doc/devmanual_fr/chap_visualisation_donnees.txt
goa/doc/devmanual_fr/index.txt
goa/doc/devmanual_fr/main_template_layout.dia
goa/doc/devmanual_fr/main_template_layout.png
goa/doc/devmanual_fr/makefile
goa/doc/devmanual_fr/sect_definition_entites.txt
goa/doc/devmanual_fr/sect_definition_schema.txt
goa/doc/devmanual_fr/sect_erudi-ctl.txt
goa/doc/devmanual_fr/sect_installation.txt
goa/doc/devmanual_fr/sect_mercurial.txt
goa/doc/devmanual_fr/sect_stdlib_schemas.txt
goa/doc/devmanual_fr/sect_stdlib_vues.txt
goa/doc/quickstart.txt
goa/doc/tutorial-wine.txt
goa/doc/tutorial.en.txt
goa/gaesource.py
goa/goaconfig.py
goa/goactl.py
goa/goavreg.py
goa/overrides/__init__.py
goa/overrides/mttransforms.py
goa/overrides/rqlannotation.py
goa/overrides/server__init__.py
goa/overrides/server_utils.py
goa/overrides/toolsutils.py
goa/rqlinterpreter.py
goa/skel/app.yaml.tmpl
goa/skel/bootstrap_cubes
goa/skel/custom.py
goa/skel/cw-cubes/README.txt
goa/skel/i18n/en.po
goa/skel/i18n/fr.po
goa/skel/loader.py
goa/skel/main.py
goa/skel/schema.py
goa/skel/views.py
goa/test/data/__init__.py
goa/test/data/bootstrap_cubes
goa/test/data/schema.py
goa/test/data/settings.py
goa/test/data/views.py
goa/test/unittest_db.py
goa/test/unittest_editcontroller.py
goa/test/unittest_metadata.py
goa/test/unittest_rql.py
goa/test/unittest_schema.py
goa/test/unittest_views.py
goa/testlib.py
goa/tools/__init__.py
goa/tools/generate_schema_img.py
goa/tools/laxctl.py
hooks/test/unittest_hooks.py
hooks/test/unittest_syncschema.py
server/test/unittest_fti.py
server/test/unittest_hook.py
server/test/unittest_ldapuser.py
server/test/unittest_migractions.py
server/test/unittest_msplanner.py
server/test/unittest_multisources.py
server/test/unittest_querier.py
server/test/unittest_repository.py
server/test/unittest_rql2sql.py
server/test/unittest_rqlannotation.py
server/test/unittest_schemaserial.py
server/test/unittest_security.py
server/test/unittest_session.py
server/test/unittest_sqlutils.py
server/test/unittest_storage.py
server/test/unittest_undo.py
sobjects/test/unittest_email.py
sobjects/test/unittest_notification.py
sobjects/test/unittest_supervising.py
test/unittest_cwconfig.py
test/unittest_dbapi.py
test/unittest_entity.py
test/unittest_mail.py
test/unittest_migration.py
test/unittest_req.py
test/unittest_rqlrewrite.py
test/unittest_rset.py
test/unittest_rtags.py
test/unittest_schema.py
test/unittest_selectors.py
test/unittest_spa2rql.py
test/unittest_uilib.py
test/unittest_utils.py
test/unittest_vregistry.py
web/test/test_views.py
web/test/unittest_application.py
web/test/unittest_breadcrumbs.py
web/test/unittest_facet.py
web/test/unittest_form.py
web/test/unittest_formfields.py
web/test/unittest_magicsearch.py
web/test/unittest_propertysheet.py
web/test/unittest_reledit.py
web/test/unittest_session.py
web/test/unittest_uicfg.py
web/test/unittest_urlpublisher.py
web/test/unittest_urlrewrite.py
web/test/unittest_views_actions.py
web/test/unittest_views_apacherewrite.py
web/test/unittest_views_basecontrollers.py
web/test/unittest_views_basetemplates.py
web/test/unittest_views_baseviews.py
web/test/unittest_views_editforms.py
web/test/unittest_views_embeding.py
web/test/unittest_views_navigation.py
web/test/unittest_views_pyviews.py
web/test/unittest_views_searchrestriction.py
web/test/unittest_viewselector.py
web/test/unittest_web.py
--- a/devtools/test/unittest_dbfill.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/devtools/test/unittest_dbfill.py	Fri Sep 24 18:20:59 2010 +0200
@@ -68,7 +68,7 @@
     def test_string(self):
         """test string generation"""
         surname = self.person_valgen.generate_attribute_value({}, 'surname', 12)
-        self.assertEquals(surname, u'é&surname12')
+        self.assertEqual(surname, u'é&surname12')
 
     def test_domain_value(self):
         """test value generation from a given domain value"""
@@ -100,21 +100,21 @@
 
     def test_phone(self):
         """tests make_tel utility"""
-        self.assertEquals(make_tel(22030405), '22 03 04 05')
+        self.assertEqual(make_tel(22030405), '22 03 04 05')
 
     def test_customized_generation(self):
-        self.assertEquals(self.bug_valgen.generate_attribute_value({}, 'severity', 12),
+        self.assertEqual(self.bug_valgen.generate_attribute_value({}, 'severity', 12),
                           u'dangerous')
-        self.assertEquals(self.bug_valgen.generate_attribute_value({}, 'description', 12),
+        self.assertEqual(self.bug_valgen.generate_attribute_value({}, 'description', 12),
                           u'yo')
-        self.assertEquals(self.person_valgen.generate_attribute_value({}, 'description', 12),
+        self.assertEqual(self.person_valgen.generate_attribute_value({}, 'description', 12),
                           u'yo')
 
 
 class ConstraintInsertionTC(TestCase):
 
     def test_writeme(self):
-        self.skip('Test automatic insertion / Schema Constraints')
+        self.skipTest('Test automatic insertion / Schema Constraints')
 
 
 if __name__ == '__main__':
--- a/devtools/test/unittest_httptest.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/devtools/test/unittest_httptest.py	Fri Sep 24 18:20:59 2010 +0200
@@ -15,7 +15,7 @@
 
     def test_response_anon(self):
         response = self.web_get()
-        self.assertEquals(response.status, httplib.OK)
+        self.assertEqual(response.status, httplib.OK)
 
 
     def test_base_url(self):
@@ -29,20 +29,20 @@
 
     def test_response_denied(self):
         response = self.web_get()
-        self.assertEquals(response.status, httplib.FORBIDDEN)
+        self.assertEqual(response.status, httplib.FORBIDDEN)
 
     def test_login(self):
         response = self.web_get()
         if response.status != httplib.FORBIDDEN:
-             self.skip('Already authenticated')
+             self.skipTest('Already authenticated')
         # login
         self.web_login(self.admlogin, self.admpassword)
         response = self.web_get()
-        self.assertEquals(response.status, httplib.OK, response.body)
+        self.assertEqual(response.status, httplib.OK, response.body)
         # logout
         self.web_logout()
         response = self.web_get()
-        self.assertEquals(response.status, httplib.FORBIDDEN, response.body)
+        self.assertEqual(response.status, httplib.FORBIDDEN, response.body)
 
 
 
--- a/devtools/test/unittest_qunit.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/devtools/test/unittest_qunit.py	Fri Sep 24 18:20:59 2010 +0200
@@ -20,7 +20,7 @@
 
     def test_simple_failure(self):
         js_tests = list(self._test_qunit(js('test_simple_failure.js')))
-        self.assertEquals(len(js_tests), 3)
+        self.assertEqual(len(js_tests), 3)
         test_1, test_2, test_3 = js_tests
         self.assertRaises(self.failureException, test_1[0], *test_1[1:])
         self.assertRaises(self.failureException, test_2[0], *test_2[1:])
--- a/devtools/test/unittest_testlib.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/devtools/test/unittest_testlib.py	Fri Sep 24 18:20:59 2010 +0200
@@ -47,9 +47,9 @@
 
         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.failures), 1)
+        self.assertEqual(result.testsRun, 2)
+        self.assertEqual(len(result.errors), 0)
+        self.assertEqual(len(result.failures), 1)
         clean_repo_test_cls(MyWebTest)
 
 
@@ -104,7 +104,7 @@
 
     def test_source1(self):
         """make sure source is stored correctly"""
-        self.assertEquals(self.page_info.source, HTML_PAGE2)
+        self.assertEqual(self.page_info.source, HTML_PAGE2)
 
     def test_source2(self):
         """make sure source is stored correctly - raise exception"""
@@ -114,47 +114,47 @@
 
     def test_has_title_no_level(self):
         """tests h? tags information"""
-        self.assertEquals(self.page_info.has_title('Test'), True)
-        self.assertEquals(self.page_info.has_title('Test '), False)
-        self.assertEquals(self.page_info.has_title('Tes'), False)
-        self.assertEquals(self.page_info.has_title('Hello world !'), True)
+        self.assertEqual(self.page_info.has_title('Test'), True)
+        self.assertEqual(self.page_info.has_title('Test '), False)
+        self.assertEqual(self.page_info.has_title('Tes'), False)
+        self.assertEqual(self.page_info.has_title('Hello world !'), True)
 
     def test_has_title_level(self):
         """tests h? tags information"""
-        self.assertEquals(self.page_info.has_title('Test', level = 1), True)
-        self.assertEquals(self.page_info.has_title('Test', level = 2), False)
-        self.assertEquals(self.page_info.has_title('Test', level = 3), False)
-        self.assertEquals(self.page_info.has_title('Test', level = 4), False)
+        self.assertEqual(self.page_info.has_title('Test', level = 1), True)
+        self.assertEqual(self.page_info.has_title('Test', level = 2), False)
+        self.assertEqual(self.page_info.has_title('Test', level = 3), False)
+        self.assertEqual(self.page_info.has_title('Test', level = 4), False)
         self.assertRaises(IndexError, self.page_info.has_title, 'Test', level = 5)
 
     def test_has_title_regexp_no_level(self):
         """tests has_title_regexp() with no particular level specified"""
-        self.assertEquals(self.page_info.has_title_regexp('h[23] title'), True)
+        self.assertEqual(self.page_info.has_title_regexp('h[23] title'), True)
 
     def test_has_title_regexp_level(self):
         """tests has_title_regexp() with a particular level specified"""
-        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)
+        self.assertEqual(self.page_info.has_title_regexp('h[23] title', 2), True)
+        self.assertEqual(self.page_info.has_title_regexp('h[23] title', 3), True)
+        self.assertEqual(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)
-        self.assertEquals(self.page_info.appears('Logilab'), True)
-        self.assertEquals(self.page_info.appears('Logilab introduces'), True)
-        self.assertEquals(self.page_info.appears('H2 title'), False)
+        self.assertEqual(self.page_info.appears('CW'), True)
+        self.assertEqual(self.page_info.appears('Logilab'), True)
+        self.assertEqual(self.page_info.appears('Logilab introduces'), True)
+        self.assertEqual(self.page_info.appears('H2 title'), False)
 
     def test_has_link(self):
         """tests has_link()"""
-        self.assertEquals(self.page_info.has_link('Logilab'), True)
-        self.assertEquals(self.page_info.has_link('logilab'), False)
-        self.assertEquals(self.page_info.has_link('Logilab', 'http://www.logilab.org'), True)
-        self.assertEquals(self.page_info.has_link('Logilab', 'http://www.google.com'), False)
+        self.assertEqual(self.page_info.has_link('Logilab'), True)
+        self.assertEqual(self.page_info.has_link('logilab'), False)
+        self.assertEqual(self.page_info.has_link('Logilab', 'http://www.logilab.org'), True)
+        self.assertEqual(self.page_info.has_link('Logilab', 'http://www.google.com'), False)
 
     def test_has_link_regexp(self):
         """test has_link_regexp()"""
-        self.assertEquals(self.page_info.has_link_regexp('L[oi]gilab'), True)
-        self.assertEquals(self.page_info.has_link_regexp('L[ai]gilab'), False)
+        self.assertEqual(self.page_info.has_link_regexp('L[oi]gilab'), True)
+        self.assertEqual(self.page_info.has_link_regexp('L[ai]gilab'), False)
 
 
 if __name__ == '__main__':
--- a/entities/test/unittest_base.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/entities/test/unittest_base.py	Fri Sep 24 18:20:59 2010 +0200
@@ -44,16 +44,16 @@
         self.login(u'member')
         entity = self.request().create_entity('Bookmark', title=u"hello", path=u'project/cubicweb')
         self.commit()
-        self.assertEquals(entity.creator.eid, self.member.eid)
-        self.assertEquals(entity.dc_creator(), u'member')
+        self.assertEqual(entity.creator.eid, self.member.eid)
+        self.assertEqual(entity.dc_creator(), u'member')
 
     def test_type(self):
-        self.assertEquals(self.member.dc_type(), 'cwuser')
+        self.assertEqual(self.member.dc_type(), 'cwuser')
 
     def test_entity_meta_attributes(self):
         # XXX move to yams
-        self.assertEquals(self.schema['CWUser'].meta_attributes(), {})
-        self.assertEquals(dict((str(k), v) for k, v in self.schema['State'].meta_attributes().iteritems()),
+        self.assertEqual(self.schema['CWUser'].meta_attributes(), {})
+        self.assertEqual(dict((str(k), v) for k, v in self.schema['State'].meta_attributes().iteritems()),
                           {'description_format': ('format', 'description')})
 
 
@@ -63,20 +63,20 @@
         email2 = self.execute('INSERT EmailAddress X: X address "maarten@philips.com"').get_entity(0, 0)
         email3 = self.execute('INSERT EmailAddress X: X address "toto@logilab.fr"').get_entity(0, 0)
         email1.set_relations(prefered_form=email2)
-        self.assertEquals(email1.prefered.eid, email2.eid)
-        self.assertEquals(email2.prefered.eid, email2.eid)
-        self.assertEquals(email3.prefered.eid, email3.eid)
+        self.assertEqual(email1.prefered.eid, email2.eid)
+        self.assertEqual(email2.prefered.eid, email2.eid)
+        self.assertEqual(email3.prefered.eid, email3.eid)
 
     def test_mangling(self):
         email = self.execute('INSERT EmailAddress X: X address "maarten.ter.huurne@philips.com"').get_entity(0, 0)
-        self.assertEquals(email.display_address(), 'maarten.ter.huurne@philips.com')
-        self.assertEquals(email.printable_value('address'), 'maarten.ter.huurne@philips.com')
+        self.assertEqual(email.display_address(), 'maarten.ter.huurne@philips.com')
+        self.assertEqual(email.printable_value('address'), 'maarten.ter.huurne@philips.com')
         self.vreg.config.global_set_option('mangle-emails', True)
-        self.assertEquals(email.display_address(), 'maarten.ter.huurne at philips dot com')
-        self.assertEquals(email.printable_value('address'), 'maarten.ter.huurne at philips dot com')
+        self.assertEqual(email.display_address(), 'maarten.ter.huurne at philips dot com')
+        self.assertEqual(email.printable_value('address'), 'maarten.ter.huurne at philips dot com')
         email = self.execute('INSERT EmailAddress X: X address "syt"').get_entity(0, 0)
-        self.assertEquals(email.display_address(), 'syt')
-        self.assertEquals(email.printable_value('address'), 'syt')
+        self.assertEqual(email.display_address(), 'syt')
+        self.assertEqual(email.printable_value('address'), 'syt')
 
 
 class CWUserTC(BaseEntityTC):
@@ -94,19 +94,19 @@
 
     def test_dc_title_and_name(self):
         e = self.execute('CWUser U WHERE U login "member"').get_entity(0, 0)
-        self.assertEquals(e.dc_title(), 'member')
-        self.assertEquals(e.name(), 'member')
+        self.assertEqual(e.dc_title(), 'member')
+        self.assertEqual(e.name(), 'member')
         e.set_attributes(firstname=u'bouah')
-        self.assertEquals(e.dc_title(), 'member')
-        self.assertEquals(e.name(), u'bouah')
+        self.assertEqual(e.dc_title(), 'member')
+        self.assertEqual(e.name(), u'bouah')
         e.set_attributes(surname=u'lôt')
-        self.assertEquals(e.dc_title(), 'member')
-        self.assertEquals(e.name(), u'bouah lôt')
+        self.assertEqual(e.dc_title(), 'member')
+        self.assertEqual(e.name(), u'bouah lôt')
 
     def test_allowed_massmail_keys(self):
         e = self.execute('CWUser U WHERE U login "member"').get_entity(0, 0)
         # Bytes/Password attributes should be omited
-        self.assertEquals(e.cw_adapt_to('IEmailable').allowed_massmail_keys(),
+        self.assertEqual(e.cw_adapt_to('IEmailable').allowed_massmail_keys(),
                           set(('surname', 'firstname', 'login', 'last_login_time',
                                'creation_date', 'modification_date', 'cwuri', 'eid'))
                           )
@@ -144,7 +144,7 @@
         # no specific class for Subdivisions, the default one should be selected
         eclass = self.select_eclass('SubDivision')
         self.failUnless(eclass.__autogenerated__)
-        #self.assertEquals(eclass.__bases__, (AnyEntity,))
+        #self.assertEqual(eclass.__bases__, (AnyEntity,))
         # build class from most generic to most specific and make
         # sure the most specific is always selected
         self.vreg._loadedmods[__name__] = {}
@@ -156,12 +156,12 @@
             self.failUnless(eclass.__autogenerated__)
             self.failIf(eclass is Foo)
             if etype == 'SubDivision':
-                self.assertEquals(eclass.__bases__, (Foo,))
+                self.assertEqual(eclass.__bases__, (Foo,))
             else:
-                self.assertEquals(eclass.__bases__[0].__bases__, (Foo,))
+                self.assertEqual(eclass.__bases__[0].__bases__, (Foo,))
         # check Division eclass is still selected for plain Division entities
         eclass = self.select_eclass('Division')
-        self.assertEquals(eclass.__regid__, 'Division')
+        self.assertEqual(eclass.__regid__, 'Division')
 
 if __name__ == '__main__':
     unittest_main()
--- a/entities/test/unittest_wfobjs.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/entities/test/unittest_wfobjs.py	Fri Sep 24 18:20:59 2010 +0200
@@ -43,12 +43,12 @@
         wf = add_wf(self, 'Company')
         foo = wf.add_state(u'foo', initial=True)
         bar = wf.add_state(u'bar')
-        self.assertEquals(wf.state_by_name('bar').eid, bar.eid)
-        self.assertEquals(wf.state_by_name('barrr'), None)
+        self.assertEqual(wf.state_by_name('bar').eid, bar.eid)
+        self.assertEqual(wf.state_by_name('barrr'), None)
         baz = wf.add_transition(u'baz', (foo,), bar, ('managers',))
-        self.assertEquals(wf.transition_by_name('baz').eid, baz.eid)
-        self.assertEquals(len(baz.require_group), 1)
-        self.assertEquals(baz.require_group[0].name, 'managers')
+        self.assertEqual(wf.transition_by_name('baz').eid, baz.eid)
+        self.assertEqual(len(baz.require_group), 1)
+        self.assertEqual(baz.require_group[0].name, 'managers')
 
     def test_duplicated_state(self):
         wf = add_wf(self, 'Company')
@@ -56,7 +56,7 @@
         self.commit()
         wf.add_state(u'foo')
         ex = self.assertRaises(ValidationError, self.commit)
-        self.assertEquals(ex.errors, {'name-subject': 'workflow already have a state of that name'})
+        self.assertEqual(ex.errors, {'name-subject': 'workflow already have a state of that name'})
         # no pb if not in the same workflow
         wf2 = add_wf(self, 'Company')
         foo = wf2.add_state(u'foo', initial=True)
@@ -66,7 +66,7 @@
         self.commit()
         bar.set_attributes(name=u'foo')
         ex = self.assertRaises(ValidationError, self.commit)
-        self.assertEquals(ex.errors, {'name-subject': 'workflow already have a state of that name'})
+        self.assertEqual(ex.errors, {'name-subject': 'workflow already have a state of that name'})
 
     def test_duplicated_transition(self):
         wf = add_wf(self, 'Company')
@@ -75,7 +75,7 @@
         wf.add_transition(u'baz', (foo,), bar, ('managers',))
         wf.add_transition(u'baz', (bar,), foo)
         ex = self.assertRaises(ValidationError, self.commit)
-        self.assertEquals(ex.errors, {'name-subject': 'workflow already have a transition of that name'})
+        self.assertEqual(ex.errors, {'name-subject': 'workflow already have a transition of that name'})
         # no pb if not in the same workflow
         wf2 = add_wf(self, 'Company')
         foo = wf.add_state(u'foo', initial=True)
@@ -87,7 +87,7 @@
         self.commit()
         biz.set_attributes(name=u'baz')
         ex = self.assertRaises(ValidationError, self.commit)
-        self.assertEquals(ex.errors, {'name-subject': 'workflow already have a transition of that name'})
+        self.assertEqual(ex.errors, {'name-subject': 'workflow already have a transition of that name'})
 
 
 class WorkflowTC(CubicWebTC):
@@ -95,13 +95,13 @@
     def setup_database(self):
         rschema = self.schema['in_state']
         for rdef in rschema.rdefs.values():
-            self.assertEquals(rdef.cardinality, '1*')
+            self.assertEqual(rdef.cardinality, '1*')
         self.member = self.create_user('member')
 
     def test_workflow_base(self):
         e = self.create_user('toto')
         iworkflowable = e.cw_adapt_to('IWorkflowable')
-        self.assertEquals(iworkflowable.state, 'activated')
+        self.assertEqual(iworkflowable.state, 'activated')
         iworkflowable.change_state('deactivated', u'deactivate 1')
         self.commit()
         iworkflowable.change_state('activated', u'activate 1')
@@ -109,33 +109,33 @@
         iworkflowable.change_state('deactivated', u'deactivate 2')
         self.commit()
         e.cw_clear_relation_cache('wf_info_for', 'object')
-        self.assertEquals([tr.comment for tr in e.reverse_wf_info_for],
+        self.assertEqual([tr.comment for tr in e.reverse_wf_info_for],
                           ['deactivate 1', 'activate 1', 'deactivate 2'])
-        self.assertEquals(iworkflowable.latest_trinfo().comment, 'deactivate 2')
+        self.assertEqual(iworkflowable.latest_trinfo().comment, 'deactivate 2')
 
     def test_possible_transitions(self):
         user = self.execute('CWUser X').get_entity(0, 0)
         iworkflowable = user.cw_adapt_to('IWorkflowable')
         trs = list(iworkflowable.possible_transitions())
-        self.assertEquals(len(trs), 1)
-        self.assertEquals(trs[0].name, u'deactivate')
-        self.assertEquals(trs[0].destination(None).name, u'deactivated')
+        self.assertEqual(len(trs), 1)
+        self.assertEqual(trs[0].name, u'deactivate')
+        self.assertEqual(trs[0].destination(None).name, u'deactivated')
         # test a std user get no possible transition
         cnx = self.login('member')
         # fetch the entity using the new session
         trs = list(cnx.user().cw_adapt_to('IWorkflowable').possible_transitions())
-        self.assertEquals(len(trs), 0)
+        self.assertEqual(len(trs), 0)
 
     def _test_manager_deactivate(self, user):
         iworkflowable = user.cw_adapt_to('IWorkflowable')
         user.cw_clear_relation_cache('in_state', 'subject')
-        self.assertEquals(len(user.in_state), 1)
-        self.assertEquals(iworkflowable.state, 'deactivated')
+        self.assertEqual(len(user.in_state), 1)
+        self.assertEqual(iworkflowable.state, 'deactivated')
         trinfo = iworkflowable.latest_trinfo()
-        self.assertEquals(trinfo.previous_state.name, 'activated')
-        self.assertEquals(trinfo.new_state.name, 'deactivated')
-        self.assertEquals(trinfo.comment, 'deactivate user')
-        self.assertEquals(trinfo.comment_format, 'text/plain')
+        self.assertEqual(trinfo.previous_state.name, 'activated')
+        self.assertEqual(trinfo.new_state.name, 'deactivated')
+        self.assertEqual(trinfo.comment, 'deactivate user')
+        self.assertEqual(trinfo.comment_format, 'text/plain')
         return trinfo
 
     def test_change_state(self):
@@ -143,7 +143,7 @@
         iworkflowable = user.cw_adapt_to('IWorkflowable')
         iworkflowable.change_state('deactivated', comment=u'deactivate user')
         trinfo = self._test_manager_deactivate(user)
-        self.assertEquals(trinfo.transition, None)
+        self.assertEqual(trinfo.transition, None)
 
     def test_set_in_state_bad_wf(self):
         wf = add_wf(self, 'CWUser')
@@ -153,7 +153,7 @@
             ex = self.assertRaises(ValidationError, self.session.execute,
                                'SET X in_state S WHERE X eid %(x)s, S eid %(s)s',
                                {'x': self.user().eid, 's': s.eid})
-            self.assertEquals(ex.errors, {'in_state-subject': "state doesn't belong to entity's workflow. "
+            self.assertEqual(ex.errors, {'in_state-subject': "state doesn't belong to entity's workflow. "
                                       "You may want to set a custom workflow for this entity first."})
 
     def test_fire_transition(self):
@@ -161,10 +161,10 @@
         iworkflowable = user.cw_adapt_to('IWorkflowable')
         iworkflowable.fire_transition('deactivate', comment=u'deactivate user')
         user.clear_all_caches()
-        self.assertEquals(iworkflowable.state, 'deactivated')
+        self.assertEqual(iworkflowable.state, 'deactivated')
         self._test_manager_deactivate(user)
         trinfo = self._test_manager_deactivate(user)
-        self.assertEquals(trinfo.transition.name, 'deactivate')
+        self.assertEqual(trinfo.transition.name, 'deactivate')
 
     def test_goback_transition(self):
         wf = self.session.user.cw_adapt_to('IWorkflowable').current_workflow
@@ -179,7 +179,7 @@
         self.commit()
         iworkflowable.fire_transition('wake up')
         self.commit()
-        self.assertEquals(iworkflowable.state, 'activated')
+        self.assertEqual(iworkflowable.state, 'activated')
         iworkflowable.fire_transition('deactivate')
         self.commit()
         iworkflowable.fire_transition('rest')
@@ -187,7 +187,7 @@
         iworkflowable.fire_transition('wake up')
         self.commit()
         user.clear_all_caches()
-        self.assertEquals(iworkflowable.state, 'deactivated')
+        self.assertEqual(iworkflowable.state, 'deactivated')
 
     # XXX test managers can change state without matching transition
 
@@ -199,7 +199,7 @@
         iworkflowable = req.entity_from_eid(self.member.eid).cw_adapt_to('IWorkflowable')
         ex = self.assertRaises(ValidationError,
                                iworkflowable.fire_transition, 'deactivate')
-        self.assertEquals(ex.errors, {'by_transition-subject': "transition may not be fired"})
+        self.assertEqual(ex.errors, {'by_transition-subject': "transition may not be fired"})
         cnx.close()
         cnx = self.login('member')
         req = self.request()
@@ -208,7 +208,7 @@
         cnx.commit()
         ex = self.assertRaises(ValidationError,
                                iworkflowable.fire_transition, 'activate')
-        self.assertEquals(ex.errors, {'by_transition-subject': "transition may not be fired"})
+        self.assertEqual(ex.errors, {'by_transition-subject': "transition may not be fired"})
 
     def test_fire_transition_owned_by(self):
         self.execute('INSERT RQLExpression X: X exprtype "ERQLExpression", '
@@ -255,34 +255,34 @@
         state3 = mwf.add_state(u'state3')
         swftr1 = mwf.add_wftransition(u'swftr1', swf, state1,
                                       [(swfstate2, state2), (swfstate3, state3)])
-        self.assertEquals(swftr1.destination(None).eid, swfstate1.eid)
+        self.assertEqual(swftr1.destination(None).eid, swfstate1.eid)
         # workflows built, begin test
         group = self.request().create_entity('CWGroup', name=u'grp1')
         self.commit()
         iworkflowable = group.cw_adapt_to('IWorkflowable')
-        self.assertEquals(iworkflowable.current_state.eid, state1.eid)
-        self.assertEquals(iworkflowable.current_workflow.eid, mwf.eid)
-        self.assertEquals(iworkflowable.main_workflow.eid, mwf.eid)
-        self.assertEquals(iworkflowable.subworkflow_input_transition(), None)
+        self.assertEqual(iworkflowable.current_state.eid, state1.eid)
+        self.assertEqual(iworkflowable.current_workflow.eid, mwf.eid)
+        self.assertEqual(iworkflowable.main_workflow.eid, mwf.eid)
+        self.assertEqual(iworkflowable.subworkflow_input_transition(), None)
         iworkflowable.fire_transition('swftr1', u'go')
         self.commit()
         group.clear_all_caches()
-        self.assertEquals(iworkflowable.current_state.eid, swfstate1.eid)
-        self.assertEquals(iworkflowable.current_workflow.eid, swf.eid)
-        self.assertEquals(iworkflowable.main_workflow.eid, mwf.eid)
-        self.assertEquals(iworkflowable.subworkflow_input_transition().eid, swftr1.eid)
+        self.assertEqual(iworkflowable.current_state.eid, swfstate1.eid)
+        self.assertEqual(iworkflowable.current_workflow.eid, swf.eid)
+        self.assertEqual(iworkflowable.main_workflow.eid, mwf.eid)
+        self.assertEqual(iworkflowable.subworkflow_input_transition().eid, swftr1.eid)
         iworkflowable.fire_transition('tr1', u'go')
         self.commit()
         group.clear_all_caches()
-        self.assertEquals(iworkflowable.current_state.eid, state2.eid)
-        self.assertEquals(iworkflowable.current_workflow.eid, mwf.eid)
-        self.assertEquals(iworkflowable.main_workflow.eid, mwf.eid)
-        self.assertEquals(iworkflowable.subworkflow_input_transition(), None)
+        self.assertEqual(iworkflowable.current_state.eid, state2.eid)
+        self.assertEqual(iworkflowable.current_workflow.eid, mwf.eid)
+        self.assertEqual(iworkflowable.main_workflow.eid, mwf.eid)
+        self.assertEqual(iworkflowable.subworkflow_input_transition(), None)
         # force back to swfstate1 is impossible since we can't any more find
         # subworkflow input transition
         ex = self.assertRaises(ValidationError,
                                iworkflowable.change_state, swfstate1, u'gadget')
-        self.assertEquals(ex.errors, {'to_state-subject': "state doesn't belong to entity's workflow"})
+        self.assertEqual(ex.errors, {'to_state-subject': "state doesn't belong to entity's workflow"})
         self.rollback()
         # force back to state1
         iworkflowable.change_state('state1', u'gadget')
@@ -291,10 +291,10 @@
         iworkflowable.fire_transition('tr2', u'chapeau')
         self.commit()
         group.clear_all_caches()
-        self.assertEquals(iworkflowable.current_state.eid, state3.eid)
-        self.assertEquals(iworkflowable.current_workflow.eid, mwf.eid)
-        self.assertEquals(iworkflowable.main_workflow.eid, mwf.eid)
-        self.assertListEquals(parse_hist(iworkflowable.workflow_history),
+        self.assertEqual(iworkflowable.current_state.eid, state3.eid)
+        self.assertEqual(iworkflowable.current_workflow.eid, mwf.eid)
+        self.assertEqual(iworkflowable.main_workflow.eid, mwf.eid)
+        self.assertListEqual(parse_hist(iworkflowable.workflow_history),
                               [('state1', 'swfstate1', 'swftr1', 'go'),
                                ('swfstate1', 'swfstate2', 'tr1', 'go'),
                                ('swfstate2', 'state2', 'swftr1', 'exiting from subworkflow subworkflow'),
@@ -318,7 +318,7 @@
         mwf.add_wftransition(u'swftr1', swf, state1,
                              [(swfstate2, state2), (swfstate2, state3)])
         ex = self.assertRaises(ValidationError, self.commit)
-        self.assertEquals(ex.errors, {'subworkflow_exit-subject': u"can't have multiple exits on the same state"})
+        self.assertEqual(ex.errors, {'subworkflow_exit-subject': u"can't have multiple exits on the same state"})
 
     def test_swf_fire_in_a_row(self):
         # sub-workflow
@@ -382,7 +382,7 @@
             iworkflowable.fire_transition(trans)
             self.commit()
             group.clear_all_caches()
-            self.assertEquals(iworkflowable.state, nextstate)
+            self.assertEqual(iworkflowable.state, nextstate)
 
 
 class CustomWorkflowTC(CubicWebTC):
@@ -400,12 +400,12 @@
                      {'wf': wf.eid, 'x': self.member.eid})
         self.member.clear_all_caches()
         iworkflowable = self.member.cw_adapt_to('IWorkflowable')
-        self.assertEquals(iworkflowable.state, 'activated')# no change before commit
+        self.assertEqual(iworkflowable.state, 'activated')# no change before commit
         self.commit()
         self.member.clear_all_caches()
-        self.assertEquals(iworkflowable.current_workflow.eid, wf.eid)
-        self.assertEquals(iworkflowable.state, 'asleep')
-        self.assertEquals(iworkflowable.workflow_history, ())
+        self.assertEqual(iworkflowable.current_workflow.eid, wf.eid)
+        self.assertEqual(iworkflowable.state, 'asleep')
+        self.assertEqual(iworkflowable.workflow_history, ())
 
     def test_custom_wf_replace_state_keep_history(self):
         """member in inital state with some history, state is redirected and
@@ -420,9 +420,9 @@
                      {'wf': wf.eid, 'x': self.member.eid})
         self.commit()
         self.member.clear_all_caches()
-        self.assertEquals(iworkflowable.current_workflow.eid, wf.eid)
-        self.assertEquals(iworkflowable.state, 'asleep')
-        self.assertEquals(parse_hist(iworkflowable.workflow_history),
+        self.assertEqual(iworkflowable.current_workflow.eid, wf.eid)
+        self.assertEqual(iworkflowable.state, 'asleep')
+        self.assertEqual(parse_hist(iworkflowable.workflow_history),
                           [('activated', 'deactivated', 'deactivate', None),
                            ('deactivated', 'activated', 'activate', None),
                            ('activated', 'asleep', None, 'workflow changed to "CWUser"')])
@@ -436,7 +436,7 @@
         self.execute('SET X custom_workflow WF WHERE X eid %(x)s, WF eid %(wf)s',
                      {'wf': wf.eid, 'x': self.member.eid})
         ex = self.assertRaises(ValidationError, self.commit)
-        self.assertEquals(ex.errors, {'custom_workflow-subject': u'workflow has no initial state'})
+        self.assertEqual(ex.errors, {'custom_workflow-subject': u'workflow has no initial state'})
 
     def test_custom_wf_bad_etype(self):
         """try to set a custom workflow which doesn't apply to entity type"""
@@ -445,7 +445,7 @@
         self.execute('SET X custom_workflow WF WHERE X eid %(x)s, WF eid %(wf)s',
                      {'wf': wf.eid, 'x': self.member.eid})
         ex = self.assertRaises(ValidationError, self.commit)
-        self.assertEquals(ex.errors, {'custom_workflow-subject': u"workflow isn't a workflow for this type"})
+        self.assertEqual(ex.errors, {'custom_workflow-subject': u"workflow isn't a workflow for this type"})
 
     def test_del_custom_wf(self):
         """member in some state shared by the new workflow, nothing has to be
@@ -461,12 +461,12 @@
         self.execute('DELETE X custom_workflow WF WHERE X eid %(x)s, WF eid %(wf)s',
                      {'wf': wf.eid, 'x': self.member.eid})
         self.member.clear_all_caches()
-        self.assertEquals(iworkflowable.state, 'asleep')# no change before commit
+        self.assertEqual(iworkflowable.state, 'asleep')# no change before commit
         self.commit()
         self.member.clear_all_caches()
-        self.assertEquals(iworkflowable.current_workflow.name, "default user workflow")
-        self.assertEquals(iworkflowable.state, 'activated')
-        self.assertEquals(parse_hist(iworkflowable.workflow_history),
+        self.assertEqual(iworkflowable.current_workflow.name, "default user workflow")
+        self.assertEqual(iworkflowable.state, 'activated')
+        self.assertEqual(parse_hist(iworkflowable.workflow_history),
                           [('activated', 'deactivated', 'deactivate', None),
                            ('deactivated', 'asleep', None, 'workflow changed to "CWUser"'),
                            ('asleep', 'activated', None, 'workflow changed to "default user workflow"'),])
@@ -492,24 +492,24 @@
                      {'wf': wf.eid, 'x': user.eid})
         self.commit()
         user.clear_all_caches()
-        self.assertEquals(iworkflowable.state, 'asleep')
-        self.assertEquals([t.name for t in iworkflowable.possible_transitions()],
+        self.assertEqual(iworkflowable.state, 'asleep')
+        self.assertEqual([t.name for t in iworkflowable.possible_transitions()],
                           ['rest'])
         iworkflowable.fire_transition('rest')
         self.commit()
         user.clear_all_caches()
-        self.assertEquals(iworkflowable.state, 'asleep')
-        self.assertEquals([t.name for t in iworkflowable.possible_transitions()],
+        self.assertEqual(iworkflowable.state, 'asleep')
+        self.assertEqual([t.name for t in iworkflowable.possible_transitions()],
                           ['rest'])
-        self.assertEquals(parse_hist(iworkflowable.workflow_history),
+        self.assertEqual(parse_hist(iworkflowable.workflow_history),
                           [('asleep', 'asleep', 'rest', None)])
         user.set_attributes(surname=u'toto') # fulfill condition
         self.commit()
         iworkflowable.fire_transition('rest')
         self.commit()
         user.clear_all_caches()
-        self.assertEquals(iworkflowable.state, 'dead')
-        self.assertEquals(parse_hist(iworkflowable.workflow_history),
+        self.assertEqual(iworkflowable.state, 'dead')
+        self.assertEqual(parse_hist(iworkflowable.workflow_history),
                           [('asleep', 'asleep', 'rest', None),
                            ('asleep', 'asleep', 'rest', None),
                            ('asleep', 'dead', 'sick', None),])
@@ -521,7 +521,7 @@
                      {'wf': wf.eid, 'x': user.eid})
         self.commit()
         iworkflowable = user.cw_adapt_to('IWorkflowable')
-        self.assertEquals(iworkflowable.state, 'dead')
+        self.assertEqual(iworkflowable.state, 'dead')
 
     def test_auto_transition_initial_state_fired(self):
         wf = self.execute('Any WF WHERE ET default_workflow WF, '
@@ -534,7 +534,7 @@
         user = self.create_user('member', surname=u'toto')
         self.commit()
         iworkflowable = user.cw_adapt_to('IWorkflowable')
-        self.assertEquals(iworkflowable.state, 'dead')
+        self.assertEqual(iworkflowable.state, 'dead')
 
 
 class WorkflowHooksTC(CubicWebTC):
@@ -555,7 +555,7 @@
         self.commit()
         initialstate = self.execute('Any N WHERE S name N, X in_state S, X eid %(x)s',
                                     {'x' : ueid})[0][0]
-        self.assertEquals(initialstate, u'activated')
+        self.assertEqual(initialstate, u'activated')
         # give access to users group on the user's wf transitions
         # so we can test wf enforcing on euser (managers don't have anymore this
         # enforcement
@@ -592,7 +592,7 @@
         iworkflowable = user.cw_adapt_to('IWorkflowable')
         ex = self.assertRaises(ValidationError,
                                iworkflowable.fire_transition, 'activate')
-        self.assertEquals(self._cleanup_msg(ex.errors['by_transition-subject']),
+        self.assertEqual(self._cleanup_msg(ex.errors['by_transition-subject']),
                           u"transition isn't allowed from")
         cnx.close()
 
@@ -602,7 +602,7 @@
         iworkflowable = user.cw_adapt_to('IWorkflowable')
         ex = self.assertRaises(ValidationError,
                                iworkflowable.fire_transition, 'dummy')
-        self.assertEquals(self._cleanup_msg(ex.errors['by_transition-subject']),
+        self.assertEqual(self._cleanup_msg(ex.errors['by_transition-subject']),
                           u"transition isn't allowed from")
         cnx.close()
 
@@ -616,7 +616,7 @@
         session.set_pool()
         ex = self.assertRaises(ValidationError,
                                iworkflowable.fire_transition, 'deactivate')
-        self.assertEquals(self._cleanup_msg(ex.errors['by_transition-subject']),
+        self.assertEqual(self._cleanup_msg(ex.errors['by_transition-subject']),
                                             u"transition isn't allowed from")
         # get back now
         iworkflowable.fire_transition('activate')
--- a/ext/test/unittest_rest.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/ext/test/unittest_rest.py	Fri Sep 24 18:20:59 2010 +0200
@@ -29,9 +29,9 @@
 
     def test_eid_role(self):
         context = self.context()
-        self.assertEquals(rest_publish(context, ':eid:`%s`' % context.eid),
+        self.assertEqual(rest_publish(context, ':eid:`%s`' % context.eid),
                           '<p><a class="reference" href="http://testing.fr/cubicweb/cwuser/admin">#%s</a></p>\n' % context.eid)
-        self.assertEquals(rest_publish(context, ':eid:`%s:some text`' %  context.eid),
+        self.assertEqual(rest_publish(context, ':eid:`%s:some text`' %  context.eid),
                           '<p><a class="reference" href="http://testing.fr/cubicweb/cwuser/admin">some text</a></p>\n')
 
     def test_bad_rest_no_crash(self):
--- a/goa/__init__.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""cubicweb on google appengine
-
-"""
-__docformat__ = "restructuredtext en"
-
-
-try:
-    # WARNING: do not import the google's db module here since it will take
-    #          precedence over our own db submodule
-    from google.appengine.api.datastore import Key, Get, Query
-    from google.appengine.api.datastore_errors import BadKeyError
-except ImportError:
-    # not in google app environment
-    pass
-else:
-
-    import os
-    _SS = os.environ.get('SERVER_SOFTWARE')
-    if _SS is None:
-        MODE = 'test'
-    elif _SS.startswith('Dev'):
-        MODE = 'dev'
-    else:
-        MODE = 'prod'
-
-    from cubicweb.server import SOURCE_TYPES
-    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
-        # and not a StringIO
-        def check_bytes(eschema, value):
-            """check value is a bytes string"""
-            return isinstance(value, str)
-        from yams import constraints
-        constraints.BASE_CHECKERS['Bytes'] = check_bytes
-
-        def rql_for_eid(eid):
-            return 'Any X WHERE X eid "%s"' % eid
-        from cubicweb import uilib
-        uilib.rql_for_eid = rql_for_eid
-
-        def typed_eid(eid):
-            try:
-                return str(Key(eid))
-            except BadKeyError:
-                raise ValueError(eid)
-        import cubicweb
-        cubicweb.typed_eid = typed_eid
-
-        # 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.final:
-                # 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)
-                rdef = ybo.RelationDefinition(eschema.type, 'identity', eschema.type)
-                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
-
-
-        # don't reset vreg on repository set_schema
-        from cubicweb.server import repository
-        orig_set_schema = repository.Repository.set_schema
-        def set_schema(self, schema, resetvreg=True):
-            orig_set_schema(self, schema, False)
-        repository.Repository.set_schema = set_schema
-        # deactivate function ensuring relation cardinality consistency
-        repository.del_existing_rel_if_needed = lambda *args: None
-
-        def get_cubes(self):
-            """return the list of top level cubes used by this instance"""
-            config = self.config
-            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
-
-        # activate entity caching on the server side
-
-        def set_entity_cache(self, entity):
-            self.transaction_data.setdefault('_eid_cache', {})[entity.eid] = entity
-
-        def entity_cache(self, eid):
-            return self.transaction_data['_eid_cache'][eid]
-
-        def drop_entity_cache(self, eid=None):
-            if eid is None:
-                self.transaction_data['_eid_cache'] = {}
-            elif '_eid_cache' in self.transaction_data:
-                self.transaction_data['_eid_cache'].pop(eid, None)
-
-        def datastore_get(self, key):
-            if isinstance(key, basestring):
-                key = Key(key)
-            try:
-                gentity = self.transaction_data['_key_cache'][key]
-                #self.critical('cached %s', gentity)
-            except KeyError:
-                gentity = Get(key)
-                #self.critical('Get %s', gentity)
-                self.transaction_data.setdefault('_key_cache', {})[key] = gentity
-            return gentity
-
-        def clear_datastore_cache(self, key=None):
-            if key is None:
-                self.transaction_data['_key_cache'] = {}
-            else:
-                if isinstance(key, basestring):
-                    key = Key(key)
-                self.transaction_data['_key_cache'].pop(key, None)
-
-        from cubicweb.server.session import Session
-        Session.set_entity_cache = set_entity_cache
-        Session.entity_cache = entity_cache
-        Session.drop_entity_cache = drop_entity_cache
-        Session.datastore_get = datastore_get
-        Session.clear_datastore_cache = clear_datastore_cache
-
-        from docutils.frontend import OptionParser
-        # avoid a call to expanduser which is not available under gae
-        def get_standard_config_files(self):
-            return self.standard_config_files
-        OptionParser.get_standard_config_files = get_standard_config_files
--- a/goa/appobjects/__init__.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
--- a/goa/appobjects/components.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""overrides some base views for cubicweb on google appengine
-
-"""
-__docformat__ = "restructuredtext en"
-
-from logilab.mtconverter import xml_escape
-
-from cubicweb import typed_eid
-from cubicweb.selectors import one_line_rset, match_search_state, accept
-from cubicweb.schema import display_name
-from cubicweb.view import StartupView, EntityView
-from cubicweb.web import Redirect
-from cubicweb.web.views import vid_from_rset
-
-from google.appengine.api import mail
-
-
-class SearchForAssociationView(EntityView):
-    """view called by the edition view when the user asks
-    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):
-        entity = self.rset.get_entity(0, 0)
-        role, eid, rtype, etype = self.req.search_state[1]
-        assert entity.eid == typed_eid(eid)
-        rset = entity.unrelated(rtype, etype, role, ordermethod='fetch_order')
-        vid = vid_from_rset(self.req, rset, self.schema)
-        self.w(u'<div id="search-associate-content">')
-        self.pagination(self.req, rset, w=self.w)
-        self.wview(vid, rset)
-        self.w(u'</div>')
-
-
-class SchemaImageView(StartupView):
-    id = 'schemagraph'
-    binary = True
-    content_type = 'image/png'
-    def call(self):
-        """display global schema information"""
-        skipmeta = int(self.req.form.get('skipmeta', 1))
-        if skipmeta:
-            url = self.build_url('data/schema.png')
-        else:
-            url = self.build_url('data/metaschema.png')
-        raise Redirect(url)
-
-
-from cubicweb.web.views.baseviews import MetaDataView
-
-class GAEMetaDataView(MetaDataView):
-    show_eid = False
-
-
-from cubicweb.web.views.startup import ManageView
-
-def entity_types_no_count(self, eschemas):
-    """return a list of formatted links to get a list of entities of
-    a each entity's types
-    """
-    req = self.req
-    for eschema in eschemas:
-        if eschema.final or not (eschema.has_perm(req, 'read') or
-                                      eschema.has_local_role('read')):
-            continue
-        etype = eschema.type
-        label = display_name(req, etype, 'plural')
-        view = self.vreg.select('views', 'list', req, req.etype_rset(etype))
-        url = view.url()
-        etypelink = u'&#160;<a href="%s">%s</a>' % (xml_escape(url), label)
-        yield (label, etypelink, self.add_entity_link(eschema, req))
-
-ManageView.entity_types = entity_types_no_count
-
-
-from cubicweb.web.views.basecontrollers import SendMailController
-
-def sendmail(self, recipient, subject, body):
-    sender = '%s <%s>' % (
-        self.req.user.dc_title() or self.config['sender-name'],
-        self.req.user.cw_adapt_to('IEmailable').get_email() or self.config['sender-addr'])
-    mail.send_mail(sender=sender, to=recipient,
-                   subject=subject, body=body)
-
-SendMailController.sendmail = sendmail
--- a/goa/appobjects/dbmgmt.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""special management views to manage repository content (initialization and
-restoration).
-
-"""
-__docformat__ = "restructuredtext en"
-
-from os.path import exists, join, abspath
-from pickle import loads, dumps
-
-from logilab.common.decorators import cached
-from logilab.mtconverter import xml_escape
-
-from cubicweb.selectors import none_rset, match_user_groups
-from cubicweb.view import StartupView
-from cubicweb.web import Redirect
-from cubicweb.goa.dbinit import fix_entities, init_persistent_schema, insert_versions
-
-from google.appengine.api.datastore import Entity, Key, Get, Put, Delete
-from google.appengine.api.datastore_types import Blob
-from google.appengine.api.datastore_errors import EntityNotFoundError
-
-
-def _get_status(name, create=True):
-    key = Key.from_path('EApplicationStatus', name)
-    try:
-        status = Get(key)
-    except EntityNotFoundError:
-        if create:
-            status = Entity('EApplicationStatus', name=name)
-        else:
-            status = None
-    return status
-
-
-class AuthInfo(StartupView):
-    """special management view to get cookie values to give to laxctl commands
-    which are doing datastore administration requests
-    """
-    id = 'authinfo'
-    __select__ = none_rset() & match_user_groups('managers')
-
-    def call(self):
-        cookie = self.req.get_cookie()
-        values = []
-        if self.config['use-google-auth']:
-            for param in ('ACSID', 'dev_appserver_login'):
-                morsel = cookie.get(param)
-                if morsel:
-                    values.append('%s=%s' % (param, morsel.value))
-                    break
-        values.append('__session=%s' % cookie['__session'].value)
-        self.w(u"<p>pass this flag to the client: --cookie='%s'</p>"
-               % xml_escape('; '.join(values)))
-
-
-
-class ContentInit(StartupView):
-    """special management view to initialize content of a repository,
-    step by step to avoid depassing quotas
-    """
-    id = 'contentinit'
-    __select__ = none_rset() & match_user_groups('managers')
-
-    def server_session(self):
-        ssession = self.config.repo_session(self.req.cnx.sessionid)
-        ssession.set_pool()
-        return ssession
-
-    def end_core_step(self, msg, status, stepid):
-        status['cpath'] = ''
-        status['stepid'] = stepid
-        Put(status)
-        self.msg(msg)
-
-    def call(self):
-        status = _get_status('creation')
-        if status.get('finished'):
-            self.redirect('process already completed')
-        config = self.config
-        # execute cubicweb's post<event> script
-        #mhandler.exec_event_script('post%s' % event)
-        # execute cubes'post<event> script if any
-        paths = [p for p in config.cubes_path() + [config.apphome]
-                 if exists(join(p, 'migration'))]
-        paths = [abspath(p) for p in (reversed(paths))]
-        cpath = status.get('cpath')
-        if cpath is None and status.get('stepid') is None:
-            init_persistent_schema(self.server_session(), self.schema)
-            self.end_core_step(u'inserted schema entities', status, 0)
-            return
-        if cpath == '' and status.get('stepid') == 0:
-            fix_entities(self.schema)
-            self.end_core_step(u'fixed bootstrap groups and users', status, 1)
-            return
-        if cpath == '' and status.get('stepid') == 1:
-            insert_versions(self.server_session(), self.config)
-            self.end_core_step(u'inserted software versions', status, None)
-            return
-        for i, path in enumerate(paths):
-            if not cpath or cpath == path:
-                self.info('running %s', path)
-                stepid = status.get('stepid')
-                context = status.get('context')
-                if context is not None:
-                    context = loads(context)
-                else:
-                    context = {}
-                stepid = self._migrhandler.exec_event_script(
-                    'postcreate', path, 'stepable_postcreate', stepid, context)
-                if stepid is None: # finished for this script
-                    # reset script state
-                    context = stepid = None
-                    # next time, go to the next script
-                    self.msg(u'finished postcreate for %s' % path)
-                    try:
-                        path = paths[i+1]
-                        self.continue_link()
-                    except IndexError:
-                        status['finished'] = True
-                        path = None
-                        self.redirect('process completed')
-                else:
-                    if context.get('stepidx'):
-                        self.msg(u'created %s entities for step %s of %s' % (
-                            context['stepidx'], stepid, path))
-                    else:
-                        self.msg(u'finished postcreate step %s for %s' % (
-                            stepid, path))
-                    context = Blob(dumps(context))
-                    self.continue_link()
-                status['context'] = context
-                status['stepid'] = stepid
-                status['cpath'] = path
-                break
-        else:
-            if not cpath:
-                # nothing to be done
-                status['finished'] = True
-                self.redirect('process completed')
-            else:
-                # Note the error: is expected by the laxctl command line tool,
-                # deal with this if internationalization is introduced
-                self.msg(u'error: strange creation state, can\'t find %s'
-                         % cpath)
-                self.w(u'<div>click <a href="%s?vid=contentclear">here</a> to '
-                       '<b>delete all datastore content</b> so process can be '
-                       'reinitialized</div>' % xml_escape(self.req.base_url()))
-        Put(status)
-
-    @property
-    @cached
-    def _migrhandler(self):
-        return self.config.migration_handler(self.schema, interactive=False,
-                                             cnx=self.req.cnx,
-                                             repo=self.config.repository())
-
-    def msg(self, msg):
-        self.w(u'<div class="message">%s</div>' % xml_escape(msg))
-    def redirect(self, msg):
-        raise Redirect(self.req.build_url('', msg))
-    def continue_link(self):
-        self.w(u'<a href="%s">continue</a><br/>' % xml_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?
-        for eschema in self.schema.entities():
-            if eschema.final or eschema in self.skip_etypes:
-                continue
-            self.req.execute('DELETE %s X' % eschema)
-            self.w(u'deleted all %s entities<br/>' % eschema)
-        status = _get_status('creation', create=False)
-        if status:
-            Delete(status)
-        self.w(u'done<br/>')
-        self.w(u'click <a href="%s?vid=contentinit">here</a> to start the data '
-               'initialization process<br/>' % self.req.base_url())
--- a/goa/appobjects/gauthservice.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""authentication using google authentication service
-
-"""
-__docformat__ = "restructuredtext en"
-
-from cubicweb.web.views.basecomponents import UserLink
-from cubicweb.web.views.actions import LogoutAction
-
-from google.appengine.api import users
-
-
-class GACWUserLink(UserLink):
-
-    def anon_user_link(self):
-        self.w(self.req._('anonymous'))
-        self.w(u'&#160;[<a class="logout" href="%s">%s</a>]'
-               % (users.create_login_url(self.req.url()), self.req._('login')))
-
-class GAELogoutAction(LogoutAction):
-
-    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)
-        vreg.register(GAELogoutAction, clear=True)
--- a/goa/appobjects/sessions.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,291 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""persistent sessions stored in big table
-
-
-XXX TODO:
-* cleanup persistent session
-* use user as ancestor?
-"""
-__docformat__ = "restructuredtext en"
-
-from pickle import loads, dumps
-from time import localtime, strftime
-
-from logilab.common.decorators import cached, clear_cache
-
-from cubicweb import BadConnectionId
-from cubicweb.dbapi import Connection, ConnectionProperties, repo_connect
-from cubicweb.selectors import none_rset, match_user_groups
-from cubicweb.server.session import Session
-from cubicweb.web import InvalidSession
-from cubicweb.web.application import AbstractSessionManager
-from cubicweb.web.application import AbstractAuthenticationManager
-
-from google.appengine.api.datastore import Key, Entity, Get, Put, Delete, Query
-from google.appengine.api.datastore_errors import EntityNotFoundError
-from google.appengine.api.datastore_types import Blob
-
-try:
-    del Connection.__del__
-except AttributeError:
-    pass # already deleted
-
-
-class GAEAuthenticationManager(AbstractAuthenticationManager):
-    """authenticate user associated to a request and check session validity,
-    using google authentication service
-    """
-
-    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)
-        """
-        if _login is not None:
-            login, password = _login, _password
-        else:
-            login, password = req.get_authorization()
-        # remove possibly cached cursor coming from closed connection
-        clear_cache(req, 'cursor')
-        cnxprops = ConnectionProperties(self.vreg.config.repo_method,
-                                        close=False, log=False)
-        cnx = repo_connect(self._repo, login, password=password, cnxprops=cnxprops)
-        self._init_cnx(cnx, login, password)
-        # associate the connection to the current request
-        req.set_connection(cnx)
-        return cnx
-
-    def _init_cnx(self, cnx, login, password):
-        cnx.anonymous_connection = self.config.is_anonymous_user(login)
-        cnx.vreg = self.vreg
-        cnx.login = login
-        cnx.password = password
-
-
-class GAEPersistentSessionManager(AbstractSessionManager):
-    """manage session data associated to a session identifier"""
-
-    def __init__(self, vreg, *args, **kwargs):
-        super(GAEPersistentSessionManager, self).__init__(vreg, *args, **kwargs)
-        self._repo = self.config.repository(vreg=vreg)
-
-    def get_session(self, req, sessionid):
-        """return existing session for the given session identifier"""
-        # search a record for the given session
-        key = Key.from_path('CubicWebSession', 'key_' + sessionid, parent=None)
-        try:
-            record = Get(key)
-        except EntityNotFoundError:
-            raise InvalidSession()
-        repo = self._repo
-        if self.has_expired(record):
-            repo._sessions.pop(sessionid, None)
-            Delete(record)
-            raise InvalidSession()
-        # associate it with a repository session
-        try:
-            reposession = repo._get_session(sessionid)
-            user = reposession.user
-            # touch session to avoid closing our own session when sessions are
-            # cleaned (touch is done on commit/rollback on the server side, too
-            # late in that case)
-            reposession._touch()
-        except BadConnectionId:
-            # can't found session in the repository, this probably mean the
-            # session is not yet initialized on this server, hijack the repo
-            # to create it
-            # use an internal connection
-            ssession = repo.internal_session()
-            # try to get a user object
-            try:
-                user = repo.authenticate_user(ssession, record['login'],
-                                              record['password'])
-            finally:
-                ssession.close()
-            reposession = Session(user, self._repo, _id=sessionid)
-            self._repo._sessions[sessionid] = reposession
-        cnx = Connection(self._repo, sessionid)
-        return self._get_proxy(req, record, cnx, user)
-
-    def open_session(self, req):
-        """open and return a new session for the given request"""
-        cnx = self.authmanager.authenticate(req)
-        # avoid rebuilding a user
-        user = self._repo._get_session(cnx.sessionid).user
-        # build persistent record for session data
-        record = Entity('CubicWebSession', name='key_' + cnx.sessionid)
-        record['login'] = cnx.login
-        record['password'] = cnx.password
-        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...)
-        """
-        proxy.close()
-
-    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
-        req.set_connection(proxy, user)
-        return proxy
-
-
-class ConnectionProxy(object):
-
-    def __init__(self, record, cnx=None, user=None):
-        self.__record = record
-        self.__cnx = cnx
-        self.__user = user
-        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:
-            sstr += ' (anonymous)'
-        elif self.__user:
-            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)
-        except AttributeError:
-            return getattr(self.__cnx, name)
-
-    def _set_last_usage_time(self, value):
-        self.__is_dirty = True
-        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
-    def anonymous_connection(self):
-        # 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):
-        if self.__record.get('data') is not None:
-            try:
-                return loads(self.__record['data'])
-            except:
-                self.__is_dirty = True
-                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:
-            try:
-                value = self.data.pop(key)
-                self.__is_dirty = True
-                return value
-            except KeyError:
-                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
-
-    def commit(self):
-        if self.__is_dirty:
-            self.__save()
-        self.__cnx.commit()
-
-    def rollback(self):
-        self.__save()
-        self.__cnx.rollback()
-
-    def close(self):
-        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))
-            Put(self.__record)
-            self.__is_dirty = False
-
-    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
-set_log_methods(ConnectionProxy, logging.getLogger('cubicweb.web.goa.session'))
-
-
-from cubicweb.view import StartupView
-from cubicweb.web import application
-
-class SessionsCleaner(StartupView):
-    id = 'cleansessions'
-    __select__ = none_rset() & match_user_groups('managers')
-
-    def call(self):
-        # clean web session
-        session_manager = application.SESSION_MANAGER
-        nbclosed, remaining = session_manager.clean_sessions()
-        self.w(u'<div class="message">')
-        self.w(u'%s web sessions closed<br/>\n' % nbclosed)
-        # clean repository sessions
-        repo = self.config.repository(vreg=self.vreg)
-        nbclosed = repo.clean_sessions()
-        self.w(u'%s repository sessions closed<br/>\n' % nbclosed)
-        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)
-    vreg.register(GAEPersistentSessionManager, clear=True)
--- a/goa/bin/laxctl	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-import os.path as osp
-
-APPLROOT = osp.abspath(osp.join(osp.dirname(osp.abspath(__file__)), '..'))
-if APPLROOT not in sys.path:
-    sys.path.insert(0, APPLROOT)
-CUBES_DIR = osp.join(APPLROOT, 'cw-cubes')
-if CUBES_DIR not in sys.path:
-    sys.path.insert(1, CUBES_DIR)
-    
-try:
-    import custom
-except ImportError, exc:
-    print exc
-    sys.exit(2)
-
-from tools.laxctl import run
-run()
--- a/goa/db.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,469 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""provide replacement classes for gae db module, so that a gae model can be
-used as base for a cubicweb application by simply replacing ::
-
-  from google.appengine.ext import db
-
-by
-
-  from cubicweb.goa import db
-
-The db.model api should be fully featured by replacement classes, with the
-following differences:
-
-* 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
-* XXX name/collection_name argument of properties constructor are ignored
-* XXX ListProperty
-
-"""
-__docformat__ = "restructuredtext en"
-
-from copy import deepcopy
-
-from logilab.common.decorators import cached, iclassmethod
-
-from cubicweb import Binary, entities
-from cubicweb.req import RequestSessionBase
-from cubicweb.rset import ResultSet
-from cubicweb.entity import metaentity
-from cubicweb.server.utils import crypt_password
-from cubicweb.goa import MODE
-from cubicweb.goa.dbinit import init_relations
-
-from google.appengine.api.datastore import Get, Put, Key, Entity, Query
-from google.appengine.api.datastore import NormalizeAndTypeCheck, RunInTransaction
-from google.appengine.api.datastore_types import Text, Blob
-from google.appengine.api.datastore_errors import BadKeyError
-
-# XXX remove this dependancy
-from google.appengine.ext import db
-
-
-def rset_from_objs(req, objs, attrs=('eid',), rql=None, args=None):
-    """return a ResultSet instance for list of objects"""
-    if objs is None:
-        objs = ()
-    elif isinstance(objs, Entity):
-        objs = (objs,)
-    if rql is None:
-        rql = 'Any X'
-    rows = []
-    description = []
-    rset = ResultSet(rows, rql, args, description=description)
-    vreg = req.vreg
-    for i, obj in enumerate(objs):
-        line = []
-        linedescr = []
-        eschema = vreg.schema.eschema(obj.kind())
-        for j, attr in enumerate(attrs):
-            if attr == 'eid':
-                value = obj.key()
-                obj.row, obj.col = i, j
-                descr = eschema.type
-                value = str(value)
-            else:
-                value = obj[attr]
-                descr = str(eschema.destination(attr))
-            line.append(value)
-            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.rowcount = len(rows)
-    rset.req = req
-    return rset
-
-
-def needrequest(wrapped):
-    def wrapper(cls, *args, **kwargs):
-        req = kwargs.pop('req', None)
-        if req is None and args and isinstance(args[0], RequestSessionBase):
-            args = list(args)
-            req = args.pop(0)
-        if req is None:
-            req = getattr(cls, 'req', None)
-            if req is None:
-                raise Exception('either call this method on an instance or '
-                                'specify the req argument')
-        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.
-    """
-    def __new__(mcs, name, bases, classdict):
-        if not 'id' in classdict:
-            classdict['id'] = name
-        entitycls = super(gaedbmetaentity, mcs).__new__(mcs, name, bases, classdict)
-        return entitycls
-
-
-TEST_MODELS = {}
-
-def extract_dbmodel(entitycls):
-    if MODE == 'test' and entitycls in TEST_MODELS:
-        dbclassdict = TEST_MODELS[entitycls]
-    else:
-        dbclassdict = {}
-        for attr, value in entitycls.__dict__.items():
-            if isinstance(value, db.Property) or isinstance(value, ReferencePropertyStub):
-                dbclassdict[attr] = value
-                # don't remove attr from entitycls, this make tests fail, and it's anyway
-                # overwritten by descriptor at class initialization time
-                #delattr(entitycls, attr)
-    if MODE == 'test':
-        TEST_MODELS[entitycls] = dbclassdict
-        dbclassdict = deepcopy(dbclassdict)
-        for propname, prop in TEST_MODELS[entitycls].iteritems():
-            if getattr(prop, 'reference_class', None) is db._SELF_REFERENCE:
-                dbclassdict[propname].reference_class = db._SELF_REFERENCE
-    return dbclassdict
-
-
-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.final)
-
-    def __init__(self, *args, **kwargs):
-        # db.Model prototype:
-        #   __init__(self, parent=None, key_name=None, **kw)
-        #
-        # Entity prototype:
-        #   __init__(self, req, rset, row=None, col=0)
-        if args and isinstance(args[0], RequestSessionBase) or 'req' in kwargs:
-            super(Model, self).__init__(*args, **kwargs)
-            self._gaeinitargs = None
-        else:
-            super(Model, self).__init__(None, None)
-            # if Model instances are given in kwargs, turn them into db model
-            for key, val in kwargs.iteritems():
-                if key in self.e_schema.subject_relations() and not self.e_schema.schema[key].final:
-                    if isinstance(kwargs, (list, tuple)):
-                        val = [isinstance(x, Model) and x._dbmodel or x for x in val]
-                    elif isinstance(val, Model):
-                        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))
-
-    def _cubicweb_to_datastore(self, attr, value):
-        attr = attr[2:] # remove 's_' / 'o_' prefix
-        if attr in self._attributes:
-            tschema = self.e_schema.destination(attr)
-            if tschema == 'String':
-                if len(value) > 500:
-                    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
-                if isinstance(value, Binary):
-                    value = value.getvalue()
-                else:
-                    value = crypt_password(value)
-            elif tschema == 'Bytes':
-                if isinstance(value, Binary):
-                    value = value.getvalue()
-                value = Blob(value)
-        else:
-            value = Key(value)
-        return value
-
-    def _to_gae_dict(self, convert=True):
-        gaedict = {}
-        for attr, value in self.iteritems():
-            attr = 's_' + attr
-            if value is not None and convert:
-                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())
-        return dbmodel
-
-    @property
-    @cached
-    def _dbmodel(self):
-        if self.has_eid():
-            assert self._gaeinitargs is None
-            try:
-                return self.req.datastore_get(self.eid)
-            except AttributeError: # self.req is not a server session
-                return Get(self.eid)
-        self._cw_set_defaults()
-        values = self._to_gae_dict(convert=False)
-        parent = key_name = _app = None
-        if self._gaeinitargs is not None:
-            args, kwargs = self._gaeinitargs
-            args = list(args)
-            if args:
-                parent = args.pop(0)
-            if args:
-                key_name = args.pop(0)
-            if args:
-                _app = args.pop(0)
-            assert not args
-            if 'parent' in kwargs:
-                assert parent is None
-                parent = kwargs.pop('parent')
-            if 'key_name' in kwargs:
-                assert key_name is None
-                key_name = kwargs.pop('key_name')
-            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
-        else:
-            kwargs = None
-        if key_name is None:
-            key_name = self.db_key_name()
-            if key_name is not None:
-                key_name = 'key_' + key_name
-        for key, value in values.iteritems():
-            if value is None:
-                continue
-            values[key] = self._cubicweb_to_datastore(key, value)
-        entity = Entity(self.id, parent, _app, key_name)
-        entity.update(values)
-        init_relations(entity, self.e_schema)
-        return entity
-
-    def db_key_name(self):
-        """override this method to control datastore key name that should be
-        used at entity creation.
-
-        Note that if this function return something else than None, the returned
-        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[__registry].render(vid, self.req, rset=self.rset,
-                                           row=self.row, col=self.col, **kwargs)
-
-    @classmethod
-    def _rest_attr_info(cls):
-        mainattr, needcheck = super(Model, cls)._rest_attr_info()
-        if needcheck:
-            return 'eid', False
-        return mainattr, needcheck
-
-    def get_value(self, name):
-        try:
-            value = self[name]
-        except KeyError:
-            if not self.has_eid():
-                return None
-            value = self._dbmodel.get('s_'+name)
-            if value is not None:
-                if isinstance(value, Text):
-                    value = unicode(value)
-                elif isinstance(value, Blob):
-                    value = Binary(str(value))
-            self[name] = value
-        return value
-
-    def has_eid(self):
-        if self.eid is None:
-            return False
-        try:
-            Key(self.eid)
-            return True
-        except BadKeyError:
-            return False
-
-    def complete(self, skip_bytes=True):
-        pass
-
-    def unrelated(self, rtype, targettype, role='subject', limit=None,
-                  ordermethod=None):
-        # XXX dumb implementation
-        if limit is not None:
-            objs = Query(str(targettype)).Get(limit)
-        else:
-            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)
-
-    def put(self, req=None):
-        if req is not None and self.req is None:
-            self.req = req
-        dbmodel = self.to_gae_model()
-        key = Put(dbmodel)
-        self.eid = str(key)
-        if self.req is not None and self.rset is None:
-            self.rset = rset_from_objs(self.req, dbmodel, ('eid',),
-                                       '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
-        if isinstance(cls, Model) and keys in cls._attributes:
-            return super(Model, cls).get(keys)
-        rset = rset_from_objs(req, Get(keys), ('eid',),
-                              'Any X WHERE X eid IN %(x)s', {'x': keys})
-        return list(rset.entities())
-
-    @needrequest
-    def get_by_id(cls, req, ids, parent=None):
-        if isinstance(parent, Model):
-            parent = parent.key()
-        ids, multiple = NormalizeAndTypeCheck(ids, (int, long))
-        keys = [Key.from_path(cls.kind(), id, parent=parent)
-                for id in ids]
-        rset = rset_from_objs(req, Get(keys))
-        return list(rset.entities())
-
-    @classmethod
-    def get_by_key_name(cls, req, key_names, parent=None):
-        if isinstance(parent, Model):
-            parent = parent.key()
-        key_names, multiple = NormalizeAndTypeCheck(key_names, basestring)
-        keys = [Key.from_path(cls.kind(), name, parent=parent)
-                for name in key_names]
-        rset = rset_from_objs(req, Get(keys))
-        return list(rset.entities())
-
-    @classmethod
-    def get_or_insert(cls, req, key_name, **kwds):
-        def txn():
-            entity = cls.get_by_key_name(key_name, parent=kwds.get('parent'))
-            if entity is None:
-                entity = cls(key_name=key_name, **kwds)
-                entity.put()
-            return entity
-        return RunInTransaction(txn)
-
-    @classmethod
-    def all(cls, req):
-        rset = rset_from_objs(req, Query(cls.id).Run())
-        return list(rset.entities())
-
-    @classmethod
-    def gql(cls, req, query_string, *args, **kwds):
-        raise NotImplementedError('use rql')
-
-    @classmethod
-    def kind(cls):
-        return cls.id
-
-    @classmethod
-    def properties(cls):
-        raise NotImplementedError('use eschema')
-
-    def dynamic_properties(self):
-        raise NotImplementedError('use eschema')
-
-    def cw_is_saved(self):
-        return self.has_eid()
-
-    def parent(self):
-        parent = self._dbmodel.parent()
-        if not parent is None:
-            rset = rset_from_objs(self.req, (parent,), ('eid',),
-                                  'Any X WHERE X eid %(x)s', {'x': parent.key()})
-            parent = rset.get_entity(0, 0)
-        return parent
-
-    def parent_key(self):
-        return self.parent().key()
-
-    def to_xml(self):
-        return self._dbmodel.ToXml()
-
-# hijack AnyEntity class
-entities.AnyEntity = Model
-
-BooleanProperty = db.BooleanProperty
-URLProperty = db.URLProperty
-DateProperty = db.DateProperty
-DateTimeProperty = db.DateTimeProperty
-TimeProperty = db.TimeProperty
-StringProperty = db.StringProperty
-TextProperty = db.TextProperty
-BlobProperty = db.BlobProperty
-IntegerProperty = db.IntegerProperty
-FloatProperty = db.FloatProperty
-ListProperty = db.ListProperty
-SelfReferenceProperty = db.SelfReferenceProperty
-UserProperty = db.UserProperty
-
-
-class ReferencePropertyStub(object):
-    def __init__(self, cls, args, kwargs):
-        self.cls = cls
-        self.args = args
-        self.kwargs = kwargs
-        self.required = False
-        self.__dict__.update(kwargs)
-        self.creation_counter = db.Property.creation_counter
-        db.Property.creation_counter += 1
-
-    @property
-    def data_type(self):
-        class FakeDataType(object):
-            @staticmethod
-            def kind():
-                return self.cls.__name__
-        return FakeDataType
-
-def ReferenceProperty(cls, *args, **kwargs):
-    if issubclass(cls, db.Model):
-        cls = db.class_for_kind(cls.__name__)
-        return db.ReferenceProperty(cls, *args, **kwargs)
-    return ReferencePropertyStub(cls, args, kwargs)
--- a/goa/dbinit.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""some utility functions for datastore initialization.
-
-"""
-__docformat__ = "restructuredtext en"
-
-from google.appengine.api.datastore import Key, Entity, Put, Get, Query
-from google.appengine.api import datastore_errors
-
-_GROUP_CACHE = {} # XXX use memcache
-
-def _get_group(groupname):
-    try:
-        return _GROUP_CACHE[groupname]
-    except KeyError:
-        key = Key.from_path('CWGroup', 'key_' + groupname, parent=None)
-        try:
-            group = Get(key)
-        except datastore_errors.EntityNotFoundError:
-            raise Exception('can\'t find required group %s, is your instance '
-                            'correctly initialized (eg did you run the '
-                            'initialization script) ?' % groupname)
-        _GROUP_CACHE[groupname] = group
-        return group
-
-
-def create_user(login, password, groups):
-    """create a cubicweb user"""
-    from cubicweb.server.utils import crypt_password
-    user = Entity('CWUser', name=login)
-    user['s_login'] = unicode(login)
-    user['s_upassword'] = crypt_password(password)
-    set_user_groups(user, groups)
-    Put(user)
-    return user
-
-def create_groups():
-    """create initial cubicweb groups"""
-    for groupname in ('managers', 'users', 'guests'):
-        group = Entity('CWGroup', name='key_' + groupname)
-        group['s_name'] = unicode(groupname)
-        Put(group)
-        _GROUP_CACHE[groupname] = group
-
-def set_user_groups(user, groups):
-    """set user in the given groups (as string). The given user entity
-    (datastore.Entity) is not putted back to the repository, this is the caller
-    responsability.
-    """
-    groups = [_get_group(g) for g in groups]
-    user['s_in_group'] = [g.key() for g in groups] or None
-    for group in groups:
-        try:
-            group['o_in_group'].append(user.key())
-        except (KeyError, AttributeError):
-            group['o_in_group'] = [user.key()]
-        Put(group)
-
-def init_relations(gaeentity, eschema):
-    """set None for every subject relations which is not yet defined"""
-    for rschema in eschema.subject_relations():
-        if rschema in ('identity', 'has_text'):
-            continue
-        dsrelation = 's_' + rschema.type
-        if not dsrelation in gaeentity:
-            gaeentity[dsrelation] = None
-    for rschema in eschema.object_relations():
-        if rschema == 'identity':
-            continue
-        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)
-        for gaeentity in Query(etype).Run():
-            init_relations(gaeentity, eschema)
-            # 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.execute
-    rql = ('INSERT CWEType X: X name %(name)s, X description %(descr)s,'
-           'X final FALSE')
-    eschema = schema.eschema('CWEType')
-    execute(rql, {'name': u'CWEType', 'descr': unicode(eschema.description)})
-    for eschema in schema.entities():
-        if eschema.final or eschema == 'CWEType':
-            continue
-        execute(rql, {'name': unicode(eschema),
-                      'descr': unicode(eschema.description)})
-
-def insert_versions(ssession, config):
-    execute = ssession.execute
-    # insert versions
-    execute('INSERT CWProperty X: X pkey %(pk)s, X value%(v)s',
-            {'pk': u'system.version.cubicweb',
-             'v': unicode(config.cubicweb_version())})
-    for cube in config.cubes():
-        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	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,223 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""extends yams to be able to load google appengine's schemas
-
-MISSING FEATURES:
- - ListProperty, StringList, EmailProperty, etc. (XXX)
- - ReferenceProperty.verbose_name, collection_name, etc. (XXX)
-
-XXX proprify this knowing we'll use goa.db
-"""
-
-from os.path import join
-from datetime import datetime, date, time
-
-from google.appengine.ext import db
-from google.appengine.api import datastore_types
-
-from yams.buildobjs import (String, Int, Float, Boolean, Date, Time, Datetime,
-                            Bytes, SubjectRelation)
-from yams.buildobjs import metadefinition, EntityType
-
-from cubicweb.schema import CubicWebSchemaLoader
-from cubicweb.goa import db as goadb
-
-# db.Model -> yams ############################################################
-
-DBM2Y_TYPESMAP = {
-    basestring: String,
-    datastore_types.Text: String,
-    int: Int,
-    float: Float,
-    bool: Boolean,
-    time: Time,
-    date: Date,
-    datetime: Datetime,
-    datastore_types.Blob: Bytes,
-    }
-
-
-def dbm2y_default_factory(prop, **kwargs):
-    """just wraps the default types map to set
-    basic constraints like `required`, `default`, etc.
-    """
-    yamstype = DBM2Y_TYPESMAP[prop.data_type]
-    if 'default' not in kwargs:
-        default = prop.default_value()
-        if default is not None:
-            kwargs['default'] = default
-    if prop.required:
-        kwargs['required'] = True
-    return yamstype(**kwargs)
-
-def dbm2y_string_factory(prop):
-    """like dbm2y_default_factory but also deals with `maxsize` and `vocabulary`"""
-    kwargs = {}
-    if prop.data_type is basestring:
-        kwargs['maxsize'] = 500
-    if prop.choices is not None:
-        kwargs['vocabulary'] = prop.choices
-    return dbm2y_default_factory(prop, **kwargs)
-
-def dbm2y_date_factory(prop):
-    """like dbm2y_default_factory but also deals with today / now definition"""
-    kwargs = {}
-    if prop.auto_now_add:
-        if prop.data_type is datetime:
-            kwargs['default'] = 'now'
-        else:
-            kwargs['default'] = 'today'
-    # 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:
-        cardinality = '**'
-    elif prop.required:
-        cardinality = '1*'
-    else:
-        cardinality = '?*'
-    # XXX deal with potential kwargs of ReferenceProperty.__init__()
-    try:
-        return SubjectRelation(prop.data_type.kind(), cardinality=cardinality)
-    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,
-    int: dbm2y_default_factory,
-    float: dbm2y_default_factory,
-    bool: dbm2y_default_factory,
-    time: dbm2y_date_factory,
-    date: dbm2y_date_factory,
-    datetime: dbm2y_date_factory,
-    datastore_types.Blob: dbm2y_default_factory,
-    }
-
-
-class GaeSchemaLoader(CubicWebSchemaLoader):
-    """Google appengine schema loader class"""
-    def __init__(self, *args, **kwargs):
-        self.use_gauthservice = kwargs.pop('use_gauthservice', False)
-        super(GaeSchemaLoader, self).__init__(*args, **kwargs)
-        self.defined = {}
-        self.created = []
-        self.loaded_files = []
-        self._instantiate_handlers()
-
-    def finalize(self, register_base_types=False):
-        return self._build_schema('google-appengine', register_base_types)
-
-    def load_dbmodel(self, name, props):
-        clsdict = {}
-        ordered_props = sorted(props.items(),
-                               key=lambda x: x[1].creation_counter)
-        for pname, prop in ordered_props:
-            if isinstance(prop, db.ListProperty):
-                if not issubclass(prop.item_type, db.Model):
-                    self.error('ignoring list property with %s item type'
-                               % prop.item_type)
-                    continue
-                rdef = dbm2y_relation_factory(name, prop, multiple=True)
-            else:
-                try:
-                    if isinstance(prop, (db.ReferenceProperty,
-                                         goadb.ReferencePropertyStub)):
-                        rdef = dbm2y_relation_factory(name, prop)
-                    else:
-                        rdef = DBM2Y_FACTORY[prop.data_type](prop)
-                except KeyError, ex:
-                    import traceback
-                    traceback.print_exc()
-                    self.error('ignoring property %s (keyerror on %s)' % (pname, ex))
-                    continue
-            rdef.creation_rank = prop.creation_counter
-            clsdict[pname] = rdef
-        edef = metadefinition(name, (EntityType,), clsdict)
-        self.add_definition(self, edef())
-
-    def error(self, msg):
-        print 'ERROR:', msg
-
-    def import_yams_schema(self, ertype, schemamod):
-        erdef = self.pyreader.import_erschema(ertype, schemamod)
-
-    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
-
-def load_schema(config, schemaclasses=None, extrahook=None):
-    """high level method to load all the schema for a lax instance"""
-    # IMPORTANT NOTE: dbmodel schemas must be imported **BEFORE**
-    # the loader is instantiated because this is where the dbmodels
-    # are registered in the yams schema
-    for compname in config['included-cubes']:
-        __import__('%s.schema' % compname)
-    loader = GaeSchemaLoader(use_gauthservice=config['use-google-auth'], db=db)
-    if schemaclasses is not None:
-        for cls in schemaclasses:
-            loader.load_dbmodel(cls.__name__, goadb.extract_dbmodel(cls))
-    elif config['schema-type'] == 'dbmodel':
-        import schema as appschema
-        for obj in vars(appschema).values():
-            if isinstance(obj, type) and issubclass(obj, goadb.Model) and obj.__module__ == appschema.__name__:
-                loader.load_dbmodel(obj.__name__, goadb.extract_dbmodel(obj))
-    for erschema in ('CWGroup', 'CWEType', 'CWRType', 'RQLExpression',
-                     'is_', 'is_instance_of',
-                     'read_permission', 'add_permission',
-                     'delete_permission', 'update_permission'):
-        loader.import_yams_schema(erschema, 'bootstrap')
-    loader.handle_file(join(CW_SOFTWARE_ROOT, 'schemas', 'base.py'))
-    cubes = config['included-yams-cubes']
-    for cube in reversed(config.expand_cubes(cubes)):
-        config.info('loading cube %s', cube)
-        loader.import_yams_cube_schema(config.cube_dir(cube))
-    if config['schema-type'] == 'yams':
-        loader.import_yams_cube_schema('.')
-    if extrahook is not None:
-        extrahook(loader)
-    if config['use-google-auth']:
-        loader.defined['CWUser'].remove_relation('upassword')
-        loader.defined['CWUser'].permissions['add'] = ()
-        loader.defined['CWUser'].permissions['delete'] = ()
-    for etype in ('CWGroup', 'RQLExpression'):
-        read_perm_rel = loader.defined[etype].get_relations('read_permission').next()
-        read_perm_rel.cardinality = '**'
-    # XXX not yet ready for CWUser workflow
-    loader.defined['CWUser'].remove_relation('in_state')
-    loader.defined['CWUser'].remove_relation('wf_info_for')
-    # remove RQLConstraint('NOT O name "owners"') on CWUser in_group CWGroup
-    # since "owners" group is not persistent with gae
-    loader.defined['CWUser'].get_relations('in_group').next().constraints = []
-    # return the full schema including the cubes' schema
-    for ertype in loader.defined.values():
-        if getattr(ertype, 'inlined', False):
-            ertype.inlined = False
-    return loader.finalize()
--- a/goa/doc/FAQ.en.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-==============================
-LAX Frequently Asked Questions
-==============================
-
-[WRITE ME]
\ No newline at end of file
--- a/goa/doc/README_LAX.fr.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-Qu'est-ce que ``LAX`` ?
-=======================
-
-``LAX`` (Logilab Application engine eXtension) est un framework 
-d'application web qui facilite les développements faits pour
-``Google AppEngine``.
-
-``LAX`` est un portage de la partie web de la plate-forme
-applicative développée par Logilab depuis 2001. Cette plate-forme 
-publie des données que la partie stockage tire de bases SQL, 
-d'annuaires LDAP et de systèmes de gestion de version. Depuis mai 
-2008, elle fonctionne sur le "datastore" de ``Google AppEngine``.
-
-``LAX`` est pour le moment en version alpha.
-
-Django/GAE vs. LAX/GAE
-=======================
-
-NotImplementedError()
-
-
-Téléchargement des sources
-==========================
-
-- Les sources de ``Google AppEngine`` peuvent être obtenues à l'adresse
-  suivante : http://code.google.com/appengine/downloads.html
-
-- Les sources de ``LAX`` se trouvent à l'adresse suivante :
-  http://lax.logilab.org/
-
-
-Installation
-============
-
-Les sources de ``Google AppEngine`` doivent être décompressées et le
-répertoire `google` qui s'y trouve doit être accessible par la variable
-d'environnement ``PYTHONPATH``. Correctement définir le ``PYTHONPATH`` 
-n'est pas nécessaire pour le lancement de l'application elle-même mais 
-pour l'utilisation des scripts fournis par ``LAX`` ou pour l'exécution 
-des tests unitaires.
-
-Une fois décompactée, l'archive ``lax-0.1.0-alpha.tar.gz``, on obtient
-l'arborescence suivante::
-  
-  .
-  |-- app.yaml
-  |-- custom.py
-  |-- data
-  |-- cubicweb/
-  |-- i18n/
-  |-- logilab/
-  |-- main.py
-  |-- mx/
-  |-- rql/
-  |-- schema.py
-  |-- simplejson/
-  |-- tools/
-  |   |-- generate_schema_img.py
-  |   `-- i18ncompile.py
-  |-- views.py
-  |-- yams/
-  `-- yapps/
-
-  
-On retrouve le squelette d'une application web de ``Google AppEngine``
-(fichiers ``app.yaml``, ``main.py``en particulier) avec les dépendances
-supplémentaires nécessaires à l'utilisation du framework ``LAX``
-
-
-Lancement de l'application de base
-==================================
-
-python /path/to/google_appengine/dev_appserver.py /path/to/lax
-
-
--- a/goa/doc/devmanual_fr/advanced_notes.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-
-La différence entre la classe `AppRsetObject` et la classe `AppObject` est que
-les instances de la premières sont séléctionnées pour une requête et un "result
-set" et alors que les secondes ne sont séléctionnées qu'en fonction de leur
-identifiant.
Binary file goa/doc/devmanual_fr/archi_globale.dia has changed
Binary file goa/doc/devmanual_fr/archi_globale.png has changed
--- a/goa/doc/devmanual_fr/chap_autres_composants_ui.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-Autres composants de l'interface web
-====================================
-
-Actions
--------
-XXXFILLME
-
-Component, VComponent
----------------------
-XXXFILLME
-
-CWProperty
----------
-XXXFILLME
--- a/goa/doc/devmanual_fr/chap_bases_framework_erudi.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-Fondements du framework CubicWeb
-=============================
-
-Le moteur web d'cubicweb consiste en quelques classes gérant un ensemble d'objets
-chargés dynamiquement au lancement d'cubicweb. Ce sont ces objets dynamiques, issus
-du modèle ou de la librairie, qui construisent le site web final. Les différents
-composants dynamiques sont par exemple : 
-
-* coté client et serveur
-
- - les définitions d'entités, contenant la logique permettant la manipulation des
-   données de l'application
-
-* coté client
-
-  - les *vues* , ou encore plus spécifiquement 
-
-    - les boites
-    - l'en-tête et le pied de page
-    - les formulaires
-    - les gabarits de pages
-
-  - les *actions*
-  - les *controleurs*
-
-* coté serveur
-
-  - les crochets de notification
-  - les vues de notification
-
-Les différents composants du moteur sont :
-
-* un frontal web (seul twisted disponible pour le moment), transparent du point
-  de vue des objets dynamiques
-* un objet encapsulant la configuration
-* un `vregistry` (`cubicweb.cwvreg`) contenant les objets chargés dynamiquements
-
-
-Détail de la procédure d'enregistrement
----------------------------------------
-Au démarage le `vregistry` ou base de registres inspecte un certain nombre de
-répertoires à la recherche de définition de classes "compatible". Après une
-procédure d'enregistrement les objets sont affectés dans différents registres
-afin d'être ensuite séléctionné dynamiquement pendant le fonctionnement de
-l'application.
-
-La classe de base de tout ces objets est la classe `AppRsetObject` (module
-`cubicweb.common.appobject`). 
-
-
-API Python/RQL
---------------
-
-Inspiré de la db-api standard, avec un object Connection possédant les méthodes
-cursor, rollback et commit principalement. La méthode importante est la méthode
-`execute` du curseur :
-
-`execute(rqlstring, args=None, eid_key=None, build_descr=True)`
-
-:rqlstring: la requête rql à éxécuter (unicode)
-:args: si la requête contient des substitutions, un dictionnaire contenant les
-       valeurs à utiliser
-:eid_key: 
-   un détail d'implémentation du cache de requêtes RQL fait que si une substitution est
-   utilisée pour introduire un eid *levant des ambiguités dans la résolution de
-   type de la requête*, il faut spécifier par cet argument la clé correspondante
-   dans le dictionnaire
-
-C'est l'objet Connection qui possède les méthodes classiques `commit` et
-`rollback`. Vous ne *devriez jamais avoir à les utiliser* lors du développement
-d'interface web sur la base du framework CubicWeb étant donné que la fin de la
-transaction est déterminée par celui-ci en fonction du succès d'éxécution de la
-requête. 
-
-NOTE : lors de l'éxécution de requêtes de modification (SET,INSERT,DELETE), si une
-requête génère une erreur liée à la sécurité, un rollback est systématiquement
-effectuée sur la transaction courante.
-
-
-La classe `Request` (`cubicweb.web`)
----------------------------------
-Une instance de requête est créée lorsque une requête HTTP est transmise au
-serveur web. Elle contient des informations telles que les paramètres de
-formulaires, l'utilisateur connecté, etc. 
-
-**De manière plus générale une requête représente une demande d'un utilisateur,
-que se soit par HTTP ou non (on parle également de requête rql coté serveur par
-exemple)**
-
-Une instance de la classe `Request` possède les attributs :
-
-* `user`, instance de`cubicweb.common.utils.User` correspondant à l'utilisateur
-  connecté 
-* `form`, dictionaire contenant les valeurs de formulaire web
-* `encoding`, l'encodage de caractère à utiliser dans la réponse
-
-Mais encore :
-
-:Gestion des données de session:        
-  * `session_data()`, retourne un dictionaire contenant l'intégralité des
-    données de la session
-  * `get_session_data(key, default=None)`, retourne la valeur associée à
-    la clé ou la valeur `default` si la clé n'est pas définie
-  * `set_session_data(key, value)`, associe une valeur à une clé
-  * `del_session_data(key)`,  supprime la valeur associé à une clé
-    
-
-:Gestion de cookie:
-  * `get_cookie()`, retourne un dictionnaire contenant la valeur de l'entête
-    HTTP 'Cookie'
-  * `set_cookie(cookie, key, maxage=300)`, ajoute un en-tête HTTP `Set-Cookie`,
-    avec une durée de vie 5 minutes par défault (`maxage` = None donne un cooke
-    *de session"* expirant quand l'utilisateur ferme son navigateur
-  * `remove_cookie(cookie, key)`, fait expirer une valeur
-
-:Gestion d'URL:
-  * `url()`, retourne l'url complète de la requête HTTP
-  * `base_url()`, retourne l'url de la racine de l'application
-  * `relative_path()`, retourne chemin relatif de la requête
-
-:Et encore...:
-  * `set_content_type(content_type, filename=None)`, place l'en-tête HTTP
-    'Content-Type'
-  * `get_header(header)`, retourne la valeur associé à un en-tête HTTP
-    arbitraire de la requête
-  * `set_header(header, value)`, ajoute un en-tête HTTP arbitraire dans la
-    réponse 
-  * `cursor()` retourne un curseur RQL sur la session
-  * `execute(*args, **kwargs)`, raccourci vers .cursor().execute()
-  * `property_value(key)`, gestion des propriétés (`CWProperty`)
-  * le dictionaire `data` pour stocker des données pour partager de
-    l'information entre les composants *durant l'éxécution de la requête*.
-
-A noter que cette classe est en réalité abstraite et qu'une implémentation
-concrète sera fournie par le *frontend* web utilisé (en l'occurent *twisted*
-aujourd'hui). Enfin pour les vues ou autres qui sont éxécutés coté serveur,
-la majeure partie de l'interface de `Request` est définie sur la session
-associée au client. 
-
-
-La classe `AppObject`
----------------------
-
-En général :
-
-* on n'hérite pas directement des cette classe mais plutôt d'une classe
-  plus spécifique comme par exemple `AnyEntity`, `EntityView`, `AnyRsetView`,
-  `Action`...
-
-* pour être enregistrable, un classe fille doit définir son registre (attribut
-  `__registry__`) et son identifiant (attribut `id`). Généralement on n'a pas à
-  s'occuper du registre, uniquement de l'identifiant `id` :) 
-
-On trouve un certain nombre d'attributs et de méthodes définis dans cette classe
-et donc commune à tous les objets de l'application :
-
-A l'enregistrement, les attributs suivants sont ajoutés dynamiquement aux
-*classes* filles:
-
-* `vreg`, le `vregistry` de l'application
-* `schema`, le schéma de l'application
-* `config`, la configuration de l'application
-
-On trouve également sur les instances les attributs :
-
-* `req`, instance de `Request`
-* `rset`, le "result set" associé à l'objet le cas échéant
-* `cursor`, curseur rql sur la session
-
-
-:Gestion d'URL:
-  * `build_url(method=None, **kwargs)`, retourne une URL absolue construites à
-    partir des arguments donnés. Le *controleur* devant gérer la réponse
-    peut-être spécifié via l'argument spécial `method` (le branchement est
-    théoriquement bien effectué automatiquement :).
-
-  * `datadir_url()`, retourne l'url du répertoire de données de l'application
-    (contenant les fichiers statiques tels que les images, css, js...)
-
-  * `base_url()`, raccourci sur `req.base_url()`
-
-  * `url_quote(value)`, version *unicode safe* de de la fonction `urllib.quote`
-
-:Manipulation de données:
-
-  * `etype_rset(etype, size=1)`, raccourci vers `vreg.etype_rset()`
-
-  * `eid_rset(eid, rql=None, descr=True)`, retourne un objet result set pour
-    l'eid donné
-  * `entity(row, col=0)`, retourne l'entité correspondant à la position données
-    du "result set" associé à l'objet
-
-  * `complete_entity(row, col=0, skip_bytes=True)`, équivalent à `entity` mais
-    appelle également la méthode `complete()` sur l'entité avant de la retourner
-
-:Formattage de données:
-  * `format_date(date, date_format=None, time=False)`
-  * `format_time(time)`,
-
-:Et encore...:
-
-  * `external_resource(rid, default=_MARKER)`, accède à une valeur définie dans
-    le fichier de configuration `external_resource`
-    
-  * `tal_render(template, variables)`, 
-
-
-**NOTE IMPORTANTE**
-Lorsqu'on hérite d'`AppObject` (même indirectement), il faut **toujours**
-utiliser **super()** pour récupérer les méthodes et attributs des classes
-parentes, et pas passer par l'identifiant de classe parente directement.
-(sous peine de tomber sur des bugs bizarres lors du rechargement automatique
-des vues). Par exemple, plutôt que d'écrire::
-
-      class Truc(PrimaryView):
-          def f(self, arg1):
-              PrimaryView.f(self, arg1)
-
-Il faut écrire::
-      
-      class Truc(PrimaryView):
-          def f(self, arg1):
-              super(Truc, self).f(arg1)
-
-
-XXX FILLME diagramme interaction application/controller/template/view
--- a/goa/doc/devmanual_fr/chap_configuration_instance.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-Configuration d'une instance
-============================
-
-À la création d'une instance, un fichier de configuration est généré dans ::
-
-   $(CW_REGISTRY)/<instance>/<nom configuration>.conf
-
-par exemple ::
-
-   /etc/cubicweb.d/jpl/all-in-one.conf
-
-C'est un simple fichier texte au format INI. Dans la description suivante,
-chaque nom d'option est préfixé de sa section et suivi de sa valeur par défaut
-le cas échéant, e.g. "`<section>.<option>` [valeur]".
-
-
-Configuration du serveur web
-----------------------------
-:`web.auth-mode` [cookie]: 
-   mode d'authentification, cookie ou http
-:`web.realm`: 
-   realm de l'application en mode d'authentification http
-:`web.http-session-time` [0]:
-   délai d'inactivité d'une session HTTP avant sa fermeture automatique. Durée
-   en secondes, 0 signifiant pas d'expiration (ou plus exactement lors de la
-   fermeture du navigateur du client)
-
-:`main.anonymous-user`, `main.anonymous-password`:
-   login et mot de passe à utiliser pour se connecter au serveur RQL lors des
-   connexions HTTP anonymes. Il faut que le compte CWUser associé existe.
-
-:`main.base-url`:
-   url de base du site, à utiliser pour générer les urls des pages web
-
-Configuration https
-```````````````````
-Il est possible de rendre un site accessible en http pour les connections 
-anonymes et en https pour les utilisateurs authentifié. Il faut pour cela
-utiliser apache (par ex.) pour la redirection et la variable `main.https-url` du
-fichier de configuration.
-
-:Exemple:
-
-  pour une redirection apache d'un site accessible via `http://localhost/demo`
-  et `https://localhost/demo` et qui tourne en réalité sur le port 8080, il 
-  faut avoir pour la version http : ::
-
-    RewriteCond %{REQUEST_URI} ^/demo
-    RewriteRule ^/demo$ /demo/
-    RewriteRule ^/demo/(.*) http://127.0.0.1:8080/$1 [L,P]
-  
-  et pour la version https : ::
-
-    RewriteCond %{REQUEST_URI} ^/demo
-    RewriteRule ^/demo$ /demo/
-    RewriteRule ^/demo/(.*) http://127.0.0.1:8080/https/$1 [L,P]
-
-
-  et on aura dans le fichier all-in-one.conf de l'instance : ::
-
-    base-url = http://localhost/demo
-    https-url = `https://localhost/demo`
-
-Configuration de l'interface web
---------------------------------
-:`web.embed-allowed`:
-   expression régulière correspondant aux sites pouvant être "incorporé" dans
-   le site (controleur 'embed')
-:`web.submit-url`:
-   url à laquelle les bugs rencontrés dans l'application peuvent être posté
-
-
-Configuration du serveur RQL
-----------------------------
-:`main.host`:
-   nom de l'hôte s'il ne peut être détecter correctement
-:`main.pid-file`:
-   fichier où sera écrit le pid du serveur
-:`main.uid`:
-   compte utilisateur à utiliser pour le lancement du serveur quand il est
-   lancé en root par init
-:`main.session-time [30*60]`:
-   temps d'expiration d'une session RQL
-:`main.query-log-file`:
-   fichier dans lequel écrire toutes les requêtes RQL éxécutées par le serveur
-
-
-Configuration Pyro pour l'instance
------------------------------------
-Coté serveur web :
-
-:`pyro-client.pyro-application-id`: 
-   identifiant pyro du serveur RQL (e.g. le nom de l'instance)
-
-Coté serveur RQL :
-
-:`pyro-server.pyro-port`:
-   numéro de port pyro. Si aucune valeur n'est spécifiée, un port est attribué
-   automatiquement.
-
-Coté serveur RQL et serveur web :
-
-:`pyro-name-server.pyro-ns-host`:
-   nom de l'hôte hébergeant le serveur de nom pyro. Si aucune valeur n'est
-   spécifié, il est localisé par une requête de broadcast
-:`pyro-name-server.pyro-ns-group` [cubicweb]:
-   groupe pyro sous lequel enregistrer l'application
-
-
-Configuration courriel
-----------------------
-Coté serveur RQL et serveur web :
-
-:`email.mangle-emails [no]`:
-   indique si les adresses email doivent être affichées telle quelle ou
-   transformée
-
-Coté serveur RQL :
-
-:`email.smtp-host [mail]`:
-   nom de l'hôte hébergeant le serveur SMTP à utiliser pour le courriel sortant
-:`email.smtp-port [25]`:
-   port du serveur SMTP à utiliser pour le courriel sortant
-:`email.sender-name`:
-   nom à utiliser pour les courriels sortant de l'application
-:`email.sender-addr`:
-   adresse à utiliser pour les courriels sortant de l'application
-:`email.default-dest-addrs`:
-   adresses de destination par défaut, si utilisé par la configuration de la 
-   diffusion du modèle (séparées par des virgules)
-:`email.supervising-addrs`:
-   addresses de destination des courriels de supervision (séparées par des 
-   virgules)
-
-
-Configuration journalisation
-----------------------------
-:`main.log-threshold`:
-   niveau de filtrage des messages (DEBUG, INFO, WARNING, ERROR)
-:`main.log-file`:
-   fichier dans lequel écrire les messages
-
-
-Configuration Eproperties
--------------------------
-D'autres paramètres de configuration sont sous la forme d'entités `CWProperty`
-dans la base de données. Il faut donc les éditer via l'interface web ou par des
-requêtes rql.
-
-:`ui.encoding`:
-   encodage de caractères à utiliser pour l'interface web
-:`navigation.short-line-size`: # XXX should be in ui
-   nombre de caractères maximum pour les affichages "courts"
-:`navigation.page-size`:
-   nombre d'entités maximum à afficher par page de résultat
-:`navigation.related-limit`:
-   nombre d'entités liées maximum à afficher sur la vue primaire d'une entité
-:`navigation.combobox-limit`:
-   nombre d'entités non liées maximum à afficher sur les listes déroulantes de
-   la vue d'édition d'une entité
--- a/goa/doc/devmanual_fr/chap_definition_schema.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-Définition du modèle de données (*schéma*)
-==========================================
-
-Le schéma est l'élément central d'une application d'CubicWeb, définissant le modèle
-de données manipulé. Il est généralement défini à partir de type d'entités
-existants dans la librairie et d'autres spécifiques, généralement décrites dans
-un ou plusieurs fichiers python dans le sous-répertoire `schema` du modèle.
-
-A ce niveau il est important de noter la différence entre type de relation et
-définition de relation : un type de relation est uniquement un nom de relation
-avec éventuellement quelques propriétés supplémentaires (voir plus bas), alors
-qu'une définition de relation est un triplet complet "<type d'entité sujet>
-<type de relation> <type d'entité objet>". Eventuellement un type de relation
-sera créé implicitement si aucun n'est associé à une définition de relation du
-schema.
-
-.. include:: sect_stdlib_schemas.txt
-.. include:: sect_definition_schema.txt
-
--- a/goa/doc/devmanual_fr/chap_definition_workflows.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-Définition de workflow
-======================
-On peut mettre une condition rql ou/et un groupe auquel doit appartenir l'utilisateur.
-
-Si on met à la fois un(ou plusieurs) groupe et une condition RQL, il faut que les deux soient respectés.
-
-Si on met plusieurs groupes, il faut que l'utilisateur soit dans un des groupes.
-
-Pour la condition RQL sur une transition, on peut y mettre les substitutions suivantes :
-
-* `%(eid)s`, eid de l'objet
-* `%(ueid)s`, eid de l'utilisateur qui fait la requête
-* `%(seid)s`, eid de l'état courant de l'objet
-
-Dans le script de création d'un workflow, penser à mettre `_()` autour des noms d'états et de transitions
-pour que ceux si soient pris en compte par les scripts de gestion des catalogues i18n.
\ No newline at end of file
--- a/goa/doc/devmanual_fr/chap_fondements_erudi.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-Fondements CubicWeb
-================
-
-Concepts et vocabulaire
------------------------
-
-*schéma*
-  le schéma définit le modèle de données d'une application sous forme d'entités
-  et de relations, grâce au package `yams`_. C'est l'élément central d'une
-  application. Il est initialement défini sur le système de fichiers et est
-  stocké dans la base de données lors de la création d'une instance. CubicWeb 
-  fournit un certain nombres de types d'entités inclus systématiquement 
-  car nécessaire au noyau CubicWeb et une librairie de composants devant être
-  inclus explicitement le cas échéant.
-
-*source*
-  une source de données est un conteneur de données quelquonque (SGBD, annuaire
-  LDAP...) intégré par l'entrepôt CubicWeb. Un entrepôt possède au moins une source
-  dite "system" contenant le schéma de l'application, l'index plein-texte et
-  d'autres informations vitales au système.
-
-*composant*
-  un composant est un modèle regroupant un ou plusieurs types de données et/ou
-  des vues afin de fournir une fonctionalité précise, ou une application CubicWeb
-  complète utilisant éventuellement d'autres composants. Les différents
-  composants disponibles sur une machine sont installés dans
-  `/usr/share/cubicweb/templates`
-
-*result set*
-  objet encaspulant les résultats d'une requête RQL et des informations sur
-  cette requête.
-
-.. _`Python Remote Object`: http://pyro.sourceforge.net/
-.. _`yams`: http://www.logilab.org/project/name/yams/
-
-
-Structure générale d'une application LAX
-----------------------------------------
-
-Un composant complexe est structuré selon le modèle suivant :
-
-::
-    
-  .
-  |-- app.yaml
-  |-- custom.py
-  |-- data
-  |-- cubicweb/
-  |-- i18n/
-  |-- logilab/
-  |-- main.py
-  |-- mx/
-  |-- rql/
-  |-- schema.py
-  |-- simplejson/
-  |-- tools/
-  |   |-- generate_schema_img.py
-  |   `-- i18ncompile.py
-  |-- views.py
-  |-- yams/
-  `-- yapps/
-        
-
-où :
-
-* ``schema.py`` contient la définition du schéma
-* ``views.py`` contient les définitions des vues
-* ``i18n`` contient les catalogues de messages pour les langues supportées (coté
-  serveur et interface web) 
-* ``data`` contient des fichiers de données arbitraires servis statiquement
-  (images, css, fichiers javascripts)... (coté interface web uniquement)
--- a/goa/doc/devmanual_fr/chap_i18n.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-Internationalisation
-====================
-
-Le système d'internationalisation de l'interface web d'cubicweb est basé sur le
-système `GNU gettext`_.
-
-.. _`GNU gettext`: http://www.gnu.org/software/gettext/
-
-Messages à internationaliser
-----------------------------
-
-Marquage des messages à internaliser
-````````````````````````````````````
-Les chaines de caractères à internationaliser sont marqués par l'appel à la
-fonction `_` *OU* par la méthode équivalent de la requête dans le code python ou
-dans les expressions python de template TAL. 
-
-Dans les templates cubicweb-tal, il est également possible d'insérer une chaine à
-traduire via les balises `i18n:content` et  `i18n:replace`.
-
-De plus des messages correspondant aux entités/relations utilisés par le schéma
-de l'application seront automatiquement ajoutés.
-
-Renvoi d'un message internationalisé lors de la construction d'une page
-```````````````````````````````````````````````````````````````````````
-La fonction *built-in* `_` ne doit servir qu'**à marquer les messages à
-traduire**, non pas à récupérer une traduction. Il faut pour cela utiliser la
-méthode `_` de l'objet requête, sans quoi vous récupérerez l'identifiant de
-message au lieu de sa traduction dans la langue propre à la requête.1
-
-
-Gestion des catalogues de traduction
-------------------------------------
-Une fois l'application rendu internationalisable coté code, reste à gérer les
-catalogues de traductions. cubicweb-ctl intègre pour cela les commandes suivantes : 
-
-* `i18ncubicweb`, met à jour les catalogues de messages *de la librairie
-  cubicweb*. Sauf si vous développez sur le framework (et non votre propre
-  application), vous ne devriez pas avoir à utiliser cette commande
-
-* `i18ncube`, met à jour les catalogues de messages *du composant* (ou de tous
-  les composants). A la suite de cette commande, vous devez mettre à jour les
-  fichiers de traduction *.po* dans le sous-répertoire "i18n" de votre
-  template. Évidemment les traductions précédentes toujours utilisées ont été
-  conservées.
-
-* `i18ninstance`, recompile les catalogues de messages *d'une instance* (ou de
-  toutes les instances) après mise à jour des catalogues de son composant. Cela
-  est effectué automatiquement lors d'une création ou d'une mise à jour. Les
-  catalogues de messages compilés se trouvent dans le répertoire
-  "i18n/<lang>/LC_MESSAGES/cubicweb.mo" de l'application où `lang` est
-  l'identifiant de la langue sur 2 lettres ('en' ou 'fr' par exemple)
-
-
-Le cas classique
-````````````````
-Vous avez ajouté et/ou modifié des messages d'un composant utilisé par votre
-application (en ajoutant une nouvelle vue ou en ayant modifié le schéma par
-exemple) :
-
-1. `cubicweb-ctl i18ncube <composant>`
-2. éditer les fichiers <composant>/xxx.po dans pour y rajouter les traductions
-   manquantes (`msgstr` vide) 
-3. `hg ci -m "updated i18n catalogs"`
-4. `cubicweb-ctl i18ninstance <monapplication>`
-
--- a/goa/doc/devmanual_fr/chap_manipulation_donnees.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-Manipulation des données stockées
-=================================
-
-Les classes `Entity` et `AnyEntity`
------------------------------------
-Pour fournir un comportement spécifique à un type d'entité, il suffit de définir
-une classe héritant de la class `cubicweb.entities.AnyEntity`. En général il faut
-définir ces classes dans un module du package `entities` d'une application pour 
-qu'elle soit disponible à la fois coté serveur et coté client.
-
-La classe `AnyEntity` est une classe chargée dynamiquement héritant de la classe
-de base `Entity` (`cubicweb.common.entity`). On définit une sous-classe pour
-ajouter des méthodes ou spécialiser les comportements d'un type d'entité donné.
-
-Des descripteurs sont ajoutés à l'enregistrement pour initialiser la classe en
-fonction du schéma :
-
-* on peut accéder aux attributs définis dans le schéma via les attributs de même
-  nom sur les instances (valeur typée)
-
-* on peut accéder aux relations définies dans le schéma via les attributs de même
-  nom sur les instances (liste d'instances d'entité)
-
-Les méthodes définies sur la classe `AnyEntity` ou `Entity` sont les suivantes :
-
-* `has_eid()`, retourne vrai si l'entité à un eid affecté (i.e. pas en cours de
-  création) 
-        
-* `check_perm(action)`, vérifie que l'utilisateur à le droit d'effectuer
-  l'action demandée sur l'entité
-
-:Formattage et génération de la sortie:
-
-  * `view(vid, **kwargs)`, applique la vue donnée à l'entité
-
-  * `absolute_url(**kwargs)`, retourne une URL absolue permettant d'accéder à la
-    vue primaire d'une entité
-
-  * `format(attr)`, retourne le format (type MIME) du champ passé en argument
-
-  * `printable_value(attr, value=_marker, attrtype=None, format='text/html')`, 
-    retourne une chaine permettant l'affichage dans un format donné de la valeur
-    d'un attribut (la valeur est automatiquement récupérée au besoin)
-
-  * `display_name(form='')`, retourne une chaîne pour afficher le type de
-    l'entité, en spécifiant éventuellement la forme désirée ('plural' pour la
-    forme plurielle) 
-
-:Gestion de données:
-
-  * `complete(skip_bytes=True)`, effectue une requête permettant de récupérer d'un
-    coup toutes les valeurs d'attributs manquant sur l'entité
-
-  * `get_value(name)`, récupere la valeur associée à l'attribut passé en argument
-
-  * `related(rtype, x='subject', limit=None, entities=False)`, retourne une liste
-    des entités liées à l'entité courant par la relation donnée en argument
-
-  * `unrelated(rtype, targettype, x='subject', limit=None)`, retourne un result set
-    des entités not liées à l'entité courante par la relation donnée en argument
-    et satisfaisants les contraintes de celle-ci
-
-  * `copy_relations(ceid)`, copie les relations de l'entité ayant l'eid passé en
-    argument sur l'entité courante
-
-  * `last_modified(view)`, retourne la date à laquelle on doit considérer
-    l'objet comme modifié (utiliser par la gestion de cache HTTP)
-
-:Meta-données standard (Dublin Core):
-
-  * `dc_title()`, retourne une chaine unicode correspondant à la méta-donnée
-    'Title' (utilise par défaut le premier attribut non 'meta' du schéma de
-    l'entité) 
-
-  * `dc_long_title()`, comme dc_title mais peut retourner un titre plus détaillé
-
-  * `dc_description(format='text/plain')`, retourne une chaine unicode
-     correspondant à la méta-donnée 'Description' (cherche un attribut
-     'description' par défaut)
-
-  * `dc_authors()`, retourne une chaine unicode correspondant à la méta-donnée
-    'Authors' (propriétaires par défaut)
-
-  * `dc_date(date_format=None)`, retourne une chaine unicode
-     correspondant à la méta-donnée 'Date' (date de modification par défaut)
-            
-:Contrôle du vocabulaire pour les relations:
-  * `vocabulary(rtype, x='subject', limit=None)`
-  * `subject_relation_vocabulary(rtype, limit=None)`
-  * `object_relation_vocabulary(rtype, limit=None)`
-  * `relation_vocabulary(rtype, targettype, x, limit=None)`
-
-
-Les *rtags*
------------
-Les *rtags* permettent de spécifier certains comportements propres aux relations
-d'un type d'entité donné (voir plus loin). Ils sont définis sur la classe 
-d'entité via l'attribut `rtags` qui est un dictionnaire dont les clés sont un 
-triplet ::
-
-  <type de relation>, <type d'entité cible>, <position du contexte ("subject" ou "object"
-
-et les valeurs un `set` ou un tuple de marqueurs définissant des propriétés 
-s'appliquant à cette relation. 
-
-Il est possible de simplifier ce dictionnaire :
-
-* si l'on veut spécifier un seul marqueur, il n'est pas nécessaire d'utiliser
-  un tuple comme valeur, le marqueur seul (chaine de caractères) suffit
-* si l'on s'intéresse uniquement à un type de relation et non à la cible et à la
-  position du contexte (ou que celui-ci n'est pas ambigüe), on peut simplement
-  utiliser le nom du type de relation comme clé
-* si l'on veut qu'un marqueur s'applique quelque soit le type d'entité cible, il
-  faut utiliser la chaine `*` comme type d'entité cible
-
-A noter également que ce dictionnaire est *traité à la création de la classe*. 
-Il est automatiquement fusionné avec celui de la ou des classe(s) parentes (pas
-besoin de copier celui de la classe parent pour le modifier). De même modifier
-celui-ci après création de la classe n'aura aucun effet...
-
-
-.. include:: sect_definition_entites.txt
--- a/goa/doc/devmanual_fr/chap_migration.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-Migration
-=========
-
-Une des idées de base d'CubicWeb est la création incrémentale d'application, et
-pour cela de nombreuses actions sont fournies afin de facilement faire évoluer
-une application et tout particulièrement le modèle de données manipulé sans
-perdre les données des instances existantes.
-
-La version courante d'un modèle d'application est données dans le fichier
-`__pkginfo__.py` sous forme d'un tuple de 3 entiers.
-
-
-Gestion des scripts de migrations
----------------------------------
-Les scripts des migrations doivent être placés dans le répertoire `migration` de
-l'application, et nommé de la manière suivante :
-
-  <n° de version X.Y.Z>[_<description>]_<mode>.py
-
-dans lequel : 
-
-* X.Y.Z correspond au n° de version du modèle vers lequel le script permet de
-  migrer,
-
-* le *mode* (entre le dernier "_" et l'extension ".py") indique à quelle partie
-  de l'application (serveur RQL, serveur web) le script s'applique en cas
-  d'installation distribuée. Il peut valoir : 
-
-  * `common`, s'applique aussi bien sur le serveur RQL que sur le serveur web,
-    et met à jour des fichiers sur le disque (migration de fichier de
-    configuration par exemple).
-
-  * `web`, s'applique uniquement sur le serveur web, et met à jour des fichiers
-    sur le disque 
-
-  * `repository`, s'applique uniquement sur le serveur RQL, et met à jour des
-    fichiers sur le disque 
-
-  * `Any`, s'applique uniquement sur le serveur RQL, et met à jour des
-    données en base (migrations de schéma et de données par ex.)
-
-
-Toujours dans le répertoire `migration`, le fichier spécial `depends.map` permet
-d'indiquer que pour migrer vers une version spécifique du modèle, il faut tout
-d'abord avoir migrer vers une version données de cubicweb. Ce fichier peut contenir
-des commentaires (lignes commençant par un "#"), et une dépendance est notée sur
-une ligne de la manière suivante : ::
-
-  <n° de version du modèle X.Y.Z> : <n° de version cubicweb X.Y.Z>
-
-Par exemple ::
-
-  0.12.0: 2.26.0
-  0.13.0: 2.27.0
-  # 0.14 works with 2.27 <= cubicweb <= 2.28 at least
-  0.15.0: 2.28.0
-
-
-Contexte de base
-----------------
-Les identifiants suivants sont préféfinis dans les scripts de migration : 
-
-* `config`, configuration de l'instance
-
-* `interactive_mode`, booléen indiquant si le script est éxécuté en mode
-  interactif ou non
-
-* `appltemplversion`, version du modèle d'application de l'instance
-
-* `applcubicwebversion`, version cubicweb de l'instance
-
-* `templversion`, version du modéle d'application installée
-
-* `cubicwebversion`, version cubicweb installée
-
-* `confirm(question)`, fonction posant une question et retournant vrai si
-  l'utilisateur a répondu oui, faux sinon (retourne toujours vrai en mode non
-  interactif) 
-
-* `_`, fonction équivalente à `unicode` permettant de marquer des chaines à
-  internationaliser dans les scripts de migration
-
-Dans les scripts "repository", les identifiants suivant sont également définis :
-
-* `checkpoint`, demande confirmant et effectue un "commit" au point d'appel
-
-* `repo_schema`, schéma persistent de l'instance (i.e. schéma de l'instance en
-  cours de migration)
-
-* `newschema`, schéma installé sur le système de fichier (i.e. schéma de la
-  version à jour du modèle et de cubicweb)
-
-* `sqlcursor`, un curseur SQL pour les très rares cas où il est réellement
-  nécessaire ou avantageux de passer par du sql
-
-* `repo`, l'objet repository
-
-                        
-Migration de schéma
--------------------
-Les fonctions de migration de schéma suivantes sont disponibles dans les scripts
-"repository" : 
-
-* `add_attribute(etype, attrname, attrtype=None, commit=True)`, ajoute un
-  nouvel attribut à un type d'entité existante. Si le type de celui-ci n'est pas
-  spécifié il est extrait du schéma à jour.
-        
-* `drop_attribute(etype, attrname, commit=True)`, supprime un
-  attribut à un type d'entité existante.
-
-* `rename_attribute(etype, oldname, newname, commit=True)`, renomme un attribut
-            
-* `add_entity_type(etype, auto=True, commit=True)`, ajoute un nouveau type
-  d'entité. Si `auto` est vrai, toutes les relations utilisant ce type d'entité
-  et ayant un type d'entité connu à l'autre extrémité vont également être
-  ajoutées.
-
-* `drop_entity_type(etype, commit=True)`, supprime un type d'entité et toutes
-  les relations l'utilisant.
-
-* `rename_entity_type(oldname, newname, commit=True)`, renomme un type d'entité
-            
-* `add_relation_type(rtype, addrdef=True, commit=True)`, ajoute un nouveau type
-  de relation. Si `addrdef` est vrai, toutes les définitions de relation de ce
-  type seront également ajoutées.
-
-* `drop_relation_type(rtype, commit=True)`, supprime un type de relation et
-  toutes les définitions de ce type.
-
-* `rename_relation(oldname, newname, commit=True)`, renomme une relation.
-
-* `add_relation_definition(subjtype, rtype, objtype, commit=True)`, ajoute une
-  définition de relation.
-
-* `drop_relation_definition(subjtype, rtype, objtype, commit=True)`, supprime
-  une définition de relation.
-
-* `synchronize_permissions(ertype, commit=True)`, synchronise les permissions
-  d'un type d'entité ou de relation
-        
-* `synchronize_rschema(rtype, commit=True)`, synchronise les propriétés et
-  permissions d'un type de relation.
-                
-* `synchronize_eschema(etype, commit=True)`, synchronise les propriétés et
-  permissions d'un type d'entité.
-    
-* `synchronize_schema(commit=True)`, synchronise le schéma persistent avec le
-  schéma à jour (mais sans ajouter ni supprimer de nouveaux types d'entités ou
-  de relations ni de définitions de relation).
-        
-* `change_relation_props(subjtype, rtype, objtype, commit=True, **kwargs)`, change
-  les propriétés d'une definition de relation en utilisant les arguments nommés
-  pour les propriétés à changer.
-
-* `set_widget(etype, rtype, widget, commit=True)`, change le widget à utiliser
-  pour la relation <rtype> du type d'entité <etype>
-
-* `set_size_constraint(etype, rtype, size, commit=True)`, change la contrainte
-  de taille pour la relation <rtype> du type d'entité <etype>
-
-
-Migration de données
---------------------
-Les fonctions de migration de données suivantes sont disponibles dans les scripts
-"repository" : 
-
-* `rqlexec(rql, kwargs=None, cachekey=None, ask_confirm=True)`, éxécute une
-  requête rql arbitraire, d'interrogation ou de modification. Un objet result
-  set est retourné.
-
-* `rqlexecall(rqliter, cachekey=None, ask_confirm=True)`, éxécute une série
-  de requêtes rql arbitraires, d'interrogation ou de modification. rqliter est
-  un itérateur retournant des couples (rql, kwargs). Le result set de la
-  dernière requête éxécutée est retourné.
-
-* `add_entity(etype, *args, **kwargs)`, ajoute une nouvelle entité du type
-  données. La valeur des attributs et relations est spécifiée en utilisant les
-  arguments nommés et positionnels.
-
-  
-Création de workflow
---------------------
-Les fonctions de création de workflow suivantes sont disponibles dans les scripts
-"repository" : 
-
-* `add_state(name, stateof, initial=False, commit=False, **kwargs)`, ajoute un
-  nouvel état de workflow
-    
-* `add_transition(name, transitionof, fromstates, tostate, requiredgroups=(), commit=False, **kwargs)`, 
-  ajoute une nouvelle transtion de workflow
-
-Migration de configuration
---------------------------
-Les fonctions de migration de configuration suivantes sont disponibles dans tout
-les scripts : 
-
-* `option_renamed(oldname, newname)`, indique qu'une option a été renommée
-
-* `option_group_change(option, oldgroup, newgroup)`, indique qu'une option a
-  changé de groupe
-
-* `option_added(oldname, newname)`, indique qu'une option a été ajoutée
-
-* `option_removed(oldname, newname)`, indique qu'une option a été supprimée
-
-
-Autres fonctions de migration
------------------------------
-Ces fonctions ne sont utilisés que pour des opérations de bas niveau
-irréalisables autrement ou pour réparer des bases cassées lors de session
-interactive. Elles sont disponibles dans les scripts "repository".
-
-* `sqlexec(sql, args=None, ask_confirm=True)`, éxécute une requête sql
-  arbitraire, à n'utiliser 
-
-* `add_entity_type_table(etype, commit=True)`
-* `add_relation_type_table(rtype, commit=True)`
-* `uninline_relation(rtype, commit=True)`
--- a/goa/doc/devmanual_fr/chap_mise_en_place_environnement.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-Mise en place d'un environnement de développement CubicWeb
-=======================================================
-
-.. include:: sect_mercurial.txt
-.. include:: sect_installation.txt
-.. include:: sect_cubicweb-ctl.txt
-
-
-
-Création d'un composant
------------------------
-Commençons par créer un squelette qui nous servira de base au développement de
-notre composant ou application ::
-
-  cd ~/hg
-  cubicweb-ctl newtemplate moncomposant
-  # répondre aux questions
-  hg init moncomposant
-  cd moncomposant
-  hg add .
-  hg ci
-
-A partir de là si tout va bien, votre composant devrait être affiché par
-`cubicweb-ctl list` dans la section *Avaible components*, si ce n'est pas le cas
-revoir la section `Configuration de l'environnement`_.
-
-
-Création d'une instance de développement
-----------------------------------------
-
-Maintenant que nous avons notre squelette de modèle, on peut en créer une
-instance afin de voir ce que tout ça donne dans un simple navigateur web.
-Nous allons utiliser une configuration `all-in-one` afin de simplifier les
-choses ::
-
-  cubicweb-ctl create all-in-one moncomposant moninstance
-
-Une série de questions vont être posées, la réponse par défaut est généralement
-suffisante. Vous pourrez de toute façon modifier la configuration par la suite
-en éditant les fichiers générés. Lorsqu'un login/mot de passe d'accès au sgbd
-vous est demandé, il est recommandé d'utilisé l'utilisateur créé lors de la
-`Configuration Postgres`_.
-
-Il est important de distinguer ici l'utilisateur utilisé pour accéder au sgbd,
-et l'utilisateur utilisé pour s'authentifier dans l'application cubicweb. Lorsque
-l'application cubicweb démarre, elle utilise le login/mot de passe sgdb pour
-récupérer le schéma et gérer les transactions bas-niveau. En revanche, lorsque
-`cubicweb-ctl create` vous demande un login/mot de passe `manager` pour cubicweb, il
-s'agit d'un utilisateur qui sera créé dans l'application `cubicweb` pour pouvoir
-s'y connecter dans un premier temps et l'administrer. Il sera par la suite possible
-de créer des utilisateurs différents pour l'application.
-
-A l'issue de cette commande, la définition de votre instance se trouve dans
-*~/etc/cubicweb.d/moninstance/*. Pour la lancer, il suffit de taper ::
-
-  cubicweb-ctl start -D moninstance
-
-L'option `-D` indique le *debug mode* : l'instance ne passe pas en mode serveur
-et ne se déconnecte pas du terminal, ce qui simplifie le dépannage en cas de non
-démarrage de l'instance. Vous pouvez ensuite allez voir ce que ça donne en
-pointant votre navigateur sur l'url `http://localhost:8080` (le n° de port
-dépend de votre configuration). Pour vous authentifier vous pouvez utiliser le
-login/mot de passe administrateur que vous avez spécifié lors de la création de
-l'instance.
-
-Pour arrêter l'instance, un Ctrl-C dans la fenêtre où vous l'avez lancé
-suffit. Si l'option `-D` a été omise, il faut taper ::
-
-  cubicweb-ctl stop moninstance
-
-Voilà, tout est en place pour démarrer le développement du modèle...
-
-
-Utilisation de cubicweb-liveserver
--------------------------------
-
-Afin de tester rapidement un nouveau composant, on peut également
-utiliser le script `cubicweb-liveserver` qui permet de créer une
-application en mémoire (utilisant une base de données SQLite par
-défaut) et la rendre accessible via un serveur web::
-
-  cubicweb-liveserver moncomposant
-
-ou bien, pour utiliser une base de données existante (SQLite ou postgres)::
-
-  cubicweb-liveserver -s monfichier_sources moncomposant
-
--- a/goa/doc/devmanual_fr/chap_rql.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-Le langage RQL (Relation Query Language)
-========================================
-
-Présentation
-------------
-* langage mettant l'accent sur le parcours de relations.
-* Les attributs sont considérés comme des cas particuliers de relations.
-* RQL s'inspire de SQL mais se veut plus haut niveau.
-* Une connaissance du schéma CubicWeb définissant l'application est nécessaire.
-
-
-Les différents types de requêtes
---------------------------------
-Recherche (`Any`)
-  interroger l'entrepôt afin d'extraire des entités et/ou des attributs
-  d'entités.
-
-Insertion (`INSERT`)
-  insérer de nouvelles entités dans la base.
-
-Mise à jour d'entités, création de relations (`SET`)
-  mettre à jours des entités existantes dans la base, ou de créer des
-  relations entres des entités existantes.
-
-Suppression d'entités ou de relation (`DELETE`)
-  supprimer des entités et relations existantes dans la base.
-
-
-Variables et typage
--------------------
-Les entités et valeurs à parcourir et / ou séléctionner sont représentées dans
-la requête par des *variables* qui doivent être écrites en majuscule.
-
-Les types possibles pour chaque variable sont déduits à partir du schéma en
-fonction des contraintes présentes dans la requête.
-
-On peut contraindre les types possibles pour une variable à l'aide de la
-relation spéciale `is`.
-
-Types de bases
---------------
-* `String` (litéral: entre doubles ou simples quotes).
-* `Int`, `Float` (le séparateur étant le '.').
-* `Date`, `Datetime`, `Time` (litéral: chaîne YYYY/MM/DD[ hh:mm] ou mots-clés
-  `TODAY` et `NOW`).
-* `Boolean` (mots-clés `TRUE` et `FALSE`).
-* mot-clé `NULL`.
-
-Opérateurs
-----------
-* Opérateurs logiques : `AND`, `OR`, `,`.
-* Opérateurs mathématiques: `+`, `-`, `*`, `/`.
-* Operateur de comparaisons: `=`, `<`, `<=`, `>=`, `>`, `~=`, `LIKE`, `IN`.
-
-  * L'opérateur `=` est l'opérateur par défaut.
-
-  * L'opérateur `LIKE` / `~=` permet d'utiliser le caractère `%` dans une chaine
-    de caractère pour indiquer que la chaîne doit commencer ou terminer par un
-    préfix/suffixe::
-    
-      Any X WHERE X nom ~= 'Th%'
-      Any X WHERE X nom LIKE '%lt'
-
-  * L'opérateur `IN` permet de donner une liste de valeurs possibles::
-
-      Any X WHERE X nom IN ('chauvat', 'fayolle', 'di mascio', 'thenault')
-
-Requête de recherche
---------------------
-
-  [`DISTINCT`] <type d'entité> V1(, V2)\*
-  [`GROUPBY` V1(, V2)\*]  [`ORDERBY` <orderterms>]
-  [`WHERE` <restriction>] 
-  [`LIMIT` <value>] [`OFFSET` <value>]
-
-:type d'entité:
-  Type de la ou des variables séléctionnées. 
-  Le type spécial `Any`, revient à ne pas spécifier de type.
-:restriction:
-  liste des relations à parcourir sous la forme 
-    `V1 relation V2|<valeur constante>`
-:orderterms:
-  Définition de l'ordre de selection : variable ou n° de colonne suivie de la
-  méthode de tri (`ASC`, `DESC`), ASC étant la valeur par défaut.
-:note pour les requêtes groupées:
-  Pour les requêtes groupées (i.e. avec une clause `GROUPBY`), toutes les
-  variables sélectionnée doivent être soit groupée soit aggrégée.
-
-Exemples - recherche
-`````````````````````
-::
-
-      Any X WHERE X eid 53
-      Personne X
-      Personne X WHERE X travaille_pour S, S nom "logilab"
-      Any E,COUNT(X) GROUPBY E ORDERBY EN WHERE X is E, E name EN 
-      Any E,COUNT(X) GROUPBY E ORDERBY 2 WHERE X is E 
-
-
-Fonctionnalités avancées
-````````````````````````
-* Fonctions d'aggrégat : `COUNT`, `MIN`, `MAX`, `SUM`.
-* Fonctions sur les chaines :`UPPER`, `LOWER`.
-* Relations optionnelles :
-
-  * Elles permettent de sélectionner des entités liées ou non à une autre.
-
-  * Il faut utiliser le `?` derrière la variable pour spécifier que la relation
-    vers celle-ci est optionnelle :
-
-    - Anomalies d'un projet attachées ou non à une version ::
-
-        Any X,V WHERE X concerns P, P eid 42, X corrected_in V?
-
-    - Toutes les fiches et le projet qu'elles documentent le cas échéant ::
-
-        Any C,P WHERE C is Card, P? documented_by C
-
-Négation
-````````
-* Une requête du type `Document X WHERE NOT X owned_by U` revient à dire "les
-  documents n'ayant pas de relation `owned_by`". 
-* En revanche la requête `Document X WHERE NOT X owned_by U, U login "syt"`
-  revient à dire "les  documents n'ayant pas de relation `owned_by` avec
-  l'utilisateur syt". Ils peuvent avoir une relation "owned_by" avec un autre
-  utilisateur.
-
-
-Requête d'insertion
--------------------
-   `INSERT` <type d'entité> V1(, <type d'entité> V2)\* `:` <assignements>
-   [`WHERE` <restriction>] 
-
-:assignements:
-  liste des relations à assigner sous la forme `V1 relation V2|<valeur constante>`
-
-La restriction permet de définir des variables utilisées dans les assignements.
-
-Attention, si une restriction est spécifiée, l'insertion est effectuée *pour
-chaque ligne de résultat renvoyée par la restriction*.
-
-Exemples - insertion
-`````````````````````
-* Insertion d'une nouvelle personne nommée 'bidule'::
-
-       INSERT Personne X: X nom 'bidule'
-
-* Insertion d'une nouvelle personne nommée 'bidule', d'une autre nommée
-  'chouette' et d'une relation 'ami' entre eux::
-
-       INSERT Personne X, Personne Y: X nom 'bidule', Y nom 'chouette', X ami Y
-
-* Insertion d'une nouvelle personne nommée 'bidule' et d'une relation 'ami' avec
-  une personne existante nommée 'chouette'::
-
-       INSERT Personne X: X nom 'bidule', X ami Y WHERE Y nom 'chouette'
-
-
-Requête de mise à jour
-----------------------
-   `SET` <assignements>
-   [`WHERE` <restriction>] 
-
-Attention, si une restriction est spécifiée, la mise à jour est effectuée *pour
-chaque ligne de résultat renvoyée par la restriction*.
-
-Exemples - mise à jour 
-````````````````````````
-* Renommage de la personne nommée 'bidule' en 'toto', avec modification du
-  prénom::
-
-       SET X nom 'toto', X prenom 'original' WHERE X is 'Person', X nom 'bidule'
-
-* Insertion d'une relation de type 'connait' entre les objets reliés par la
-  relation de type 'ami'::
-
-       SET X know Y WHERE X ami Y
-
-Requête de suppression
-----------------------
-   `DELETE` (<type d''entité> V) | (V1 relation v2),...
-   [`WHERE` <restriction>] 
-
-Attention, si une restriction est spécifiée, la suppression est effectuée *pour
-chaque ligne de résultat renvoyée par la restriction*.
-
-Exemples
-````````
-* Suppression de la personne nommé 'toto'::
-
-       DELETE Person X WHERE X nom 'toto'
-
-* Suppression de toutes les relations de type 'ami' partant de la personne
-  nommée 'toto'::
-
-       DELETE X ami Y WHERE X is 'Person', X nom 'toto'
--- a/goa/doc/devmanual_fr/chap_serveur_crochets.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-Les crochets (*hooks*)
-======================
-
-XXX FILLME
--- a/goa/doc/devmanual_fr/chap_serveur_notification.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-Gestion de notifications
-========================
-
-XXX FILLME
\ No newline at end of file
--- a/goa/doc/devmanual_fr/chap_tests.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-Tests
-=====
-
-Écriture de tests unitaires
----------------------------
-Le framework de test fournit principalement deux classes de tests dans le module
-`cubicweb.devtools.apptest`:
-
-* `EnvBasedTC`, pour simuler un environnement complet (web + repository)
-* `RepositoryBasedTC`, pour simuler un environnement de repository uniquement
-
-Ces deux classes ont quasiment la même interface et proposent un certain nombre de méthodes
-rendant l'écriture de test puissante et rapide.
-
-XXXFILLME describe API
-
-Dans la plupart des cas, vous allez vouloir hériter de `EnvBasedTC` pour écrire des tests
-unitaires ou fonctionnels pour vos entités, vues, crochets...
-
-
-Test des courriels de notifications
-```````````````````````````````````
-Lors de l'éxécution de tests les courriels potentiellement générés ne sont pas réellement
-envoyé mais se retrouve dans la liste `MAILBOX` du module `cubicweb.devtools.apptest`. Cette
-liste est remise à zéro au *setUp* de chaque test (par le setUp des classes `EnvBasedTC`
-et `RepositoryBasedTC`).
-
-Vous pouvez donc tester vos notifications en analysant le contenu de cette liste, qui
-contient des objets ayant deux attributs :
-* `recipients`, la liste des destinataires
-* `msg`, l'objet email.Message
-
-
-Tests automatiques
-------------------
-XXXFILLME
--- a/goa/doc/devmanual_fr/chap_ui_gestion_formulaire.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-Gestion de formulaires
-======================
-
-Contrôle de la génération automatique de formulaire pour les entités manipulée
-------------------------------------------------------------------------------
-XXX FILLME
-
-* les formulaires 'edition' et 'creation'
-
-Le formulaire généré par défaut ne vous convient pas ? Vous êtes peut-être pas
-obligé de le refaire à la main ! :)
-
-* rtags primary, secondary, generated, generic,
-  `Entity.relation_category(rtype, x='subject')`
-* inline_view (now a rtag?)
-* spécification widget
-
-
-Fonctionnement du contrôleur d'édition par défaut (id: 'edit')
---------------------------------------------------------------
-
-Contrôle de l'édition
-`````````````````````
-Prérequis: les paramètres liés aux entités à éditer sont spécifiés de la forme ::
-
-  <nom de champ>:<eid de l'entité>
-
-où l'eid de l'entité pourra être une lettre dans le cas d'une entité à créer. On
-dénommera ces paramètres comme *qualifié*.
-
-1. récupération des entités à éditer en cherchant les paramètres de formulaire
-   commençant par 'eid:' ayant également un paramètre '__type' associé
-   (également *qualifié* par l'eid évidemment)
-
-2. pour tous les attributs et relations de chaque entité à éditer
-
-   1. recherche d'un paramètre 'edits-<nom relation>' ou 'edito-<nom relation>'
-      qualifié dans le cas d'une relation dont l'entité est objet
-   2. si trouvé, la valeur récupérée est considérée comme la valeur originale
-      pour cette relation, et on cherche la (ou les) nouvelle(s) valeur(s) dans
-      le paramètre <nom relation> (qualifié)
-   3. si la valeur est différente de l'originale, une requête de modification en
-      base est effectuée
-
-3. pour chaque entité à éditer
-
-   1. si un paramètre `__linkto` qualifié est spécifié, sa valeur doit être une
-      chaine (ou une liste de chaine) de la forme : ::
-
-        <relation type>:<eids>:<target>
-
-      où <target> vaut 'subject' ou 'object' et chaque eid peut-être séparé d'un
-      autre par un '_'. Target spécifie *l'entité éditée* est sujet ou objet de la
-      relation et chaque relation ainsi spécifiée sera insérée.
-
-   2. si un paramètre `__cloned_eid` qualifié est spécifié pour une entité, les
-      relations de l'entité spécifiée en valeur de cette argument sont copiées sur
-      l'entité éditée
-
-
-   3. si un paramètre `__delete` qualifié est spécifié, sa valeur doit être une
-      chaine (ou une liste de chaine) de la forme : ::
-
-	<subject eids>:<relation type>:<object eids>
-
-      où chaque eid sujet ou objet peut-être séparé d'un autre par un '_'. Chaque
-      relation ainsi spécifiée sera supprimée.
-
-   4. si un paramètre `__insert` qualifié est spécifié, sa valeur doit être de
-      même format que pour `__delete`, mais chaque relation ainsi spécifiée sera 
-      insérée.
-
-4. si les paramètres `__insert` et/ou  `__delete` sont trouvés non qualifiés,
-   ils sont interprétés comme décrit ci-dessus (quelque soit le nombre d'entité
-   édité)
-
-5. si aucune entité n'est éditée mais que le formulaire contient les paramètres
-   `__linkto` et `eid`, celui-ci est interprété en prenant la valeur spécifié
-   par le paramètre `eid` pour désigner l'entité sur laquelle ajouter les
-   relations
-
-
-A noter que :
-
-* si le paramètre `__action_delete` est trouvé, toutes les entités comme
-  spécifiées à éditer seront supprimées
-
-* si le paramètre `__action_cancel` est trouvé, aucune action n'est effectuée
-
-* si le paramètre `__action_apply` est trouvé, l'édition est effectuée
-  normalement mais la redirection sera effectuée sur le formulaire (cf `Contrôle
-  de la redirection`_)
-
-* le paramètre `__method` est également supporté comme sur le template principal
-  (XXX not very consistent, maybe __method should be dealed in the view controller) 
-
-* si aucune entité à éditer n'est trouvée et qu'il n'y a pas de paramètre
-  `__action_delete`, `__action_cancel`, `__linkto`, `__delete` ou `__insert`,
-  une erreur est levée
-
-* placer dans le formulaire le paramètre `__message` permettra d'utiliser la
-  valeur de ce paramètre comme message d'information à l'utilisateur une fois
-  l'édition effectuée.
-
-
-Contrôle de la redirection
-``````````````````````````
-Une fois que l'édition s'est bien passé, reste un problème : c'est bien beau
-tout ça, mais où qu'on va maintenant ?? Si rien n'est spécifié, le controlleur
-se débrouille, mais comme il fait pas toujours ce qu'on voudrait, on peut
-controller ça en utilisant les paramètres suivant :
-
-* `__redirectpath`: chemin de l'url (relatif à la racine du site, sans paramètre
-  de formulaire
-  
-* `__redirectparams`: paramètres de formulaires à ajouter au chemin
-  
-* `__redirectrql`: requête RQL de redirection
-
-* `__redirectvid`: identifiant de vue de redirection
-
-* `__errorurl`: url du formulaire original, utilisé pour la redirection en cas
-  d'erreur de validation pendant l'édition. Si celui-ci n'est pas spécifié, une
-  page d'erreur sera présentée plutot qu'un retour sur le formulaire (qui est le
-  cas échéant responsable d'afficher les erreurs)
-
-* `__form_id`: identifiant de vue du formulaire original, utilisée si
-  `__action_apply` est trouvé
-
-En général on utilise soit `__redirectpath et `__redirectparams` soit
-`__redirectrql` et `__redirectvid`.
--- a/goa/doc/devmanual_fr/chap_ui_js_json.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-AJAX
-====
-JSON bla  bla
-XXX FILLME
-
-
-Le contrôleur 'json'
---------------------
-XXX FILLME
-
-
-API Javascript
---------------
-XXX FILLME
--- a/goa/doc/devmanual_fr/chap_visualisation_donnees.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-Définition de vues
-==================
-
-Les classes de base des vues
-----------------------------
-
-La class `View` (`cubicweb.common.view`)
-`````````````````````````````````````
-Un vue écrit dans son flux de sortie via son attribut `w` (`UStreamIO`).
-
-L'interface de base des vues est la suivante :
-
-* `dispatch(**context)`, appelle ("rend") la vue en appellent `call` ou
-  `cell_call` en fonction des arguments passé
-* `call(**kwargs)`, appelle la vue pour un result set complet ou nul
-* `cell_call(row, col, **kwargs)`, appelle la vue pour une cellule donnée d'un
-  result set
-* `url()`, retourne l'url permettant d'obtenir cette vue avec le result set en
-  cours 
-* `view(__vid, rset, __fallback_vid=None, **kwargs)`, appelle la vue
-  d'identificant `__vid` sur le result set donné. Il est possible de données un
-  identificant de vue de "fallback" qui sera utilisé si la vue demandée n'est
-  pas applicable au result set
-  
-* `wview(__vid, rset, __fallback_vid=None, **kwargs)`, pareil que `view` mais
-  passe automatiquement le flux en argument
-  
-* `html_headers()`, retourne une liste d'en-tête HTML à placer par le template
-  principal 
-
-* `page_title()`, retourne le titre à utiliser dans l'en tête HTML `title`
-
-* `creator(eid)`, retourne l'eid et le login du créateur de l'entité ayant
-  l'eid passé en argument
-
-Autres classes de base :
-
-* `EntityView`, vue s'appliquant à aux lignes ou cellule contenant une entité
-  (eg un eid)
-* `StartupView`, vue de départ n'ayant pas besoin de result set
-* `AnyRsetView`, vue s'appliquant à n'importe quelle result set
-
-
-Les templates ou patron
------------------------
-
-Les patrons (ou *template*) sont des cas particulier de vue ne dépendant a
-priori pas d'un result set. La classe de base `Template` (`cubicweb.common.view`)
-est une classe dérivée de la classe `View`.
-
-Pour construire une page HTML, un *template principal* est utilisé. Généralement
-celui possédant l'identifiant 'main' est utilisé (ce n'est pas le cas lors
-d'erreur dans celui-ci ou pour le formulaire de login par exemple). Ce patron
-utilise d'autres patrons en plus des vues dépendants du contenu pour générer la
-page à renvoyer.
-
-C'est ce template qui est chargé :
-
-1. d'éxécuter la requête RQL des données à afficher le cas échéant
-2. éventuellement de déterminer la vue à utiliser pour l'afficher si non
-   spécifiée
-3. de composer la page à retourner
-
-
-Le patron principal par défaut (`cubicweb.web.views.basetemplates.TheMainTemplate`)
---------------------------------------------------------------------------------
-
-Le template principal par défaut construit la page selon la décomposition
-suivante :
-
-.. image:: main_template_layout.png
-
-Le rectancle contenant le `view.dispatch()` représente l'emplacement où est
-inséré la vue de contenu à afficher. Les autres représentent des sous-templates
-appelé pour construire la page. Les implémentations par défaut de tout ces
-templates sont dans le module `cubicweb.web.views.basetemplates`. Vous pouvez
-évidemment surcharger l'un des sous-templates pour modifier l'aspect visuel
-d'une partie désirée de la page.
-
-On peut également contrôler certains comportements du template principal à
-l'aide des paramètres de formulaire suivante :
-
-* `__notemplate`, si présente (quelque soit la valeur associée), seule la vue de
-  contenu est renvoyée
-* `__force_display`, si présente et contient une valeur non nulle, pas de
-  navigation quelque soit le nombre d'entités à afficher
-* `__method`, si le result set à afficher ne contient qu'une entité et que ce
-  paramètre est spécifié, celui-ci désigne une méthode à appeler sur l'entité
-  en lui donnant en argument le dictionnaire des paramètres de formulaire, avant
-  de reprendre le comportement classique (s'insère entre les étapes 1. et
-  2. décrites ci-dessus)
-
-
-.. include:: sect_stdlib_vues.txt
-
-
-Vues xml, binaires...
----------------------
-Pour les vues générants autre que du html  (une image générée dynamiquement par
-exemple), et qui ne peuvent donc généralement pas être incluse dans la page
-HTML générée par le template principal (voir ci-dessus), il faut :
-
-* placer l'attribut `templatable` de la classe à `False`
-* indiquer via l'attribut `content_type` de la classe le type MIME généré par la
-  vue 'application/octet-stream'
-
-Pour les vues générants un contenu binaire (une image générée dynamiquement par
-exemple), il faut également placer l'attribut `binary` de la classe à `True` (ce
-qui implique `templatable == False` afin que l'attribut `w` de la vue soit
-remplacé par un flux binaire plutôt que unicode.
-
-
-Quelques trucs (X)HTML à respecter
-----------------------------------
-Certains navigateurs (dont firefox) n'aime pas les `<div>` vides (par vide
-j'entend sans contenu dans la balise, il peut y avoir des attributs), faut
-toujours mettre `<div></div>` même s'il n'y a rien dedans, et non `<div/>`. 
--- a/goa/doc/devmanual_fr/index.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-=======================================
-Développement d'applications avec CubicWeb
-=======================================
-
-
-:Author: Logilab
-:Organization: Logilab
-
-.. contents::
-
-.. include:: chap_fondements_cubicweb.txt
-.. include:: chap_mise_en_place_environnement.txt
-.. include:: chap_rql.txt
-.. include:: chap_definition_schema.txt
-.. include:: chap_definition_workflows.txt
-.. include:: chap_bases_framework_cubicweb.txt
-.. include:: chap_visualisation_donnees.txt
-.. include:: chap_manipulation_donnees.txt
-.. include:: chap_ui_gestion_formulaire.txt
-.. include:: chap_ui_js_json.txt
-.. include:: chap_autres_composants_ui.txt
-.. include:: chap_serveur_crochets.txt
-.. include:: chap_serveur_notification.txt
-
-.. include:: chap_tests.txt
-.. include:: chap_i18n.txt
-.. include:: chap_migration.txt
-
-.. include:: chap_configuration_instance.txt
-
-XXX: XXX FILLME, CSS, API sécurité
Binary file goa/doc/devmanual_fr/main_template_layout.dia has changed
Binary file goa/doc/devmanual_fr/main_template_layout.png has changed
--- a/goa/doc/devmanual_fr/makefile	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-MKHTMLOPTS=--doctype book --param toc.section.depth=1  --target html --stylesheet single-file
-SRC=.
-
-MKPDFOPTS=--doctype book --param toc.section.depth=2  --target pdf --stylesheet standard
-
-TXTFILES:= $(wildcard *.txt)
-TARGET := $(TXTFILES:.txt=.html)
-
-all: index.html
-
-index.html: *.txt
-	mkdoc ${MKHTMLOPTS} index.txt
-
-index.pdf: *.txt
-	mkdoc ${MKPDFOPTS} index.txt
-
-%.html: %.txt
-	mkdoc ${MKHTMLOPTS} $<
-
-clean:
-	rm -f *.html
--- a/goa/doc/devmanual_fr/sect_definition_entites.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-Paramétrages et extensions spécifiques
---------------------------------------
-
-Valeurs par défaut dynamiques
-`````````````````````````````
-Il est possible de définir dans le schéma des valeurs par défaut *statiques*.
-Il est également possible de définir des valeurs par défaut *dynamiques* en 
-définissant sur la classe d'entité une méthode `default_<nom attribut>` pour
-un attribut donnée.
-
-
-Contrôle des attributs chargés et du tri par défaut
-```````````````````````````````````````````````````
-* l'attribut de classe `fetch_attrs` permet de définir sur une classe d'entité
-  la liste des noms des attributs ou relations devant être chargés 
-  automatiquement lors de la récupération d'entité(s) de ce type. Dans le cas 
-  des relations, on est limité aux relations *sujets de cardinalité `?` ou `1`*.
-
-* la méthode de classe `fetch_order(attr, var)` prend en argument un nom 
-  d'attribut (ou de relation) et un nom de variable et doit retourner une chaine
-  à utiliser dans la close "ORDERBY" d'une requête RQL pour trier 
-  automatiquement les listes d'entités de ce type selon cet attribut, ou `None`
-  si l'on ne veut pas de tri sur l'attribut passé en argument. Par défaut les 
-  entités sont triées selon leur date de création
-
-* la méthode de classe `fetch_unrelated_order(attr, var)` est similaire à la 
-  méthode `fetch_order` mais est utilisée essentiellement pour contrôler le tri
-  des listes déroulantes permettant de créer des relations dans la vue d'édition
-  d'une entité
-
-La fonction `fetch_config(fetchattrs, mainattr=None)` permet de simplifier la 
-définition des attributs à précharger et du tri en retournant une liste des 
-attributs à précharger (en considérant ceux de la classe  `AnyEntity`
-automatiquement) et une fonction de tri sur l'attribut "principal" (le 2eme 
-argument si spécifié ou sinon le premier attribut de la liste `fetchattrs`).
-Cette fonction est définie dans le package `cubicweb.entities`.
-
-Par exemple : ::
-
-  class Transition(AnyEntity):
-    """..."""
-    id = 'Transition'
-    fetch_attrs, fetch_order = fetch_config(['name'])
-
-Indique que pour le type d'entité "Transition" il faut précharger l'attribut
-"name" et trier par défaut selon cet attribut.
-
-
-Contrôle des formulaires d'édition
-``````````````````````````````````
-Il est possible de contrôler les attributs/relations dans la vue d'édition
-simple ou multiple à l'aide des *rtags* suivants :
-
-* `primary`, indique qu'un attribut ou une relation doit être incorporé dans
-  les formulaires d'édition simple et multiple. Dans le cas d'une relation,
-  le formulaire d'édition de l'entité liée sera inclus dans le formulaire
-
-* `secondary`, indique qu'un attribut ou une relation doit être incorporé dans
-  le formulaire d'édition simple uniquement. Dans le cas d'une relation,
-  le formulaire d'édition de l'entité liée sera inclus dans le formulaire
-
-* `generic`, indique qu'une relation doit être incorporé dans le formulaire 
-  d'édition simple dans la boite générique d'ajout de relation
-
-* `generated`, indique qu'un attribut est caculé dynamiquement ou autre, et 
-  qu'il ne doit donc pas être présent dans les formulaires d'édition
-
-Au besoin il est possible de surcharger la méthode 
-`relation_category(rtype, x='subject')` pour calculer dynamiquement la catégorie
-d'édition d'une relation.
-
-
-Contrôle de la boîte "add_related"
-``````````````````````````````````
-La boite `add related` est une boite automatique proposant de créer une entité
-qui sera automatiquement liée à l'entité de départ (le contexte dans lequel 
-s'affiche la boite). Par défaut, les liens présents dans cette boite sont 
-calculés en fonction des propriétés du schéma de l'entité visualisée, mais il
-est possible de les spécifier explicitement à l'aide des *rtags* suivants :
-
-* `link`, indique qu'une relation est généralement créée vers une entité
-  existante et qu'il ne faut donc pas faire apparaitre de lien pour cette 
-  relation
-
-* `create`, indique qu'une relation est généralement créée vers de nouvelles
-  entités et qu'il faut donc faire apparaitre un lien pour créer une nouvelle
-  entité et la lier automatiquement
-
-Au besoin il est possible de surcharger la méthode  
-`relation_mode(rtype, targettype, x='subject')` pour caculer dynamiquement la
-catégorie de création d'une relation.
-
-A noter également que si au moins une action dans la catégorie "addrelated" est
-trouvée pour le contexte courant, le fonctionnement automatique est désactivé
-en faveur du fonctionnement explicite (i.e. affichage des actions de la
-catégorie "addrelated" uniquement).
-
-Contrôle des formulaires de filtrage de table
-`````````````````````````````````````````````
-La vue "table" par défaut gère dynamiquement un formulaire de filtrage du
-contenu de celle-ci. L'algorithme est le suivant : 
-
-1. on considère que la première colonne contient les entités à restreindre
-2. on recupère la première entité de la table (ligne 0) pour "représenter"
-   toutes les autres
-3. pour toutes les autres variables définies dans la requête originale :
-
-   1. si la variable est liée à la variable principale par au moins une
-      n'importe quelle relation
-   2. on appelle la méthode `filterform_vocabulary(rtype, x)` sur l'entité
-      et si rien est retourné (ou plus exactement un tuple de valeur `None`,
-      voir ci-dessous) on passe à la variable suivante, sinon un élément de
-      formulaire de filtrage sera créé avec les valeurs de vocabulaire
-      retournées
-
-4. il n'y a pas d'autres limitations sur le rql, il peut comporter des clauses
-   de tris, de groupes... Des fonctions javascripts sont utilisées pour
-   regénérer une requête à partir de la requête de départ et des valeurs
-   séléctionnées dans les filtres de formulaire.
-
-   
-La méthode `filterform_vocabulary(rtype, x, var, rqlst, args, cachekey)` prend
-en argument le nom d'une relation et la "cible", qui indique si l'entité sur
-laquelle la méthode est appellée est sujet ou objet de la relation. Elle doit
-retourner :
-
-* un 2-uple de None si elle ne sait pas gérer cette relation
-
-* un type et une liste contenant le vocabulaire
-
-  * la liste doit contenir des couples (valeur, label)
-  * le type indique si la valeur désigne un nombre entier (`type == 'int'`), une
-    chaîne de  caractères (`type == 'string'`) ou une entité non finale (`type
-    == 'eid'`)
-
-Par exemple dans notre application de gestion de tickets, on veut pouvoir
-filtrés ceux-ci par : 
-
-* type
-* priorité
-* état (in_state)
-* étiquette (tags)
-* version (done_in)
-
-On définit donc la méthode suivante : ::
-
-
-    class Ticket(AnyEntity):
-
-	...
-
-	def filterform_vocabulary(self, rtype, x, var, rqlst, args, cachekey):
-	    _ = self.req._
-	    if rtype == 'type':
-		return 'string', [(x, _(x)) for x in ('bug', 'story')]
-	    if rtype == 'priority':
-		return 'string', [(x, _(x)) for x in ('minor', 'normal', 'important')]
-	    if rtype == 'done_in':
-		rql = insert_attr_select_relation(rqlst, var, rtype, 'num')
-		return 'eid', self.req.execute(rql, args, cachekey)
-	    return super(Ticket, self).filterform_vocabulary(rtype, x, var, rqlst,
-							     args, cachekey)
-
-							     
-NOTE: Le support du filtrage sur les étiquettes et l'état est installé
-automatiquement, pas besoin de le gérer ici.
--- a/goa/doc/devmanual_fr/sect_definition_schema.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,339 +0,0 @@
-
-Définition d'un type d'entité
------------------------------
-
-Un type d'entité est définit par une classe python héritant de `EntityType`. Le
-nom de la classe correspond au nom du type. Ensuite le corps de la classe
-contient la description des attributs et des relations pour ce type d'entité,
-par exemple ::
-
-  class Personne(EntityType):
-    """une personne avec les propriétés et relations nécessaires à mon
-    application"""
-
-    nom = String(required=True, fulltextindexed=True)
-    prenom = String(required=True, fulltextindexed=True)
-    civilite = String(vocabulary=('M', 'Mme', 'Mlle'))
-    date_naiss = Date()
-    travaille_pour = SubjectRelation('Company', cardinality='?*')
-
-* le nom de l'attribut python correspond au nom de l'attribut ou de la relation
-  dans cubicweb.
-
-* tout les types de bases sont disponibles nativement : `String`, `Int`, `Float`,
-  `Boolean`, `Date`, `Datetime`, `Time`, `Byte`.
-
-* Chaque type d'entité a au moins les méta-relations suivantes :
-  - `eid` (`Int`)
-  - `creation_date` (`Datetime`)
-  - `modification_date` (`Datetime`)
-  - `owned_by` (`CWUser`)
-  - `is` (`CWEType`)
-
-* il est également possible de définir des relations dont le type d'entité est
-  l'objet en utilisant `ObjectRelation` plutôt que `SubjectRelation`
-
-* le premier argument de `SubjectRelation` et `ObjectRelation` donne
-  respectivement le type d'entité objet /sujet de la relation. Cela
-  peut être : 
-
-  * une chaine de caractères correspondant à un type d'entité
-
-  * un tuple de chaines de caractères correspondant à plusieurs types d'entité
-
-  * les chaînes de caractères spéciales suivantes :
-
-    - "**" : tout les types d'entité
-    - "*" : tout les types d'entité non méta
-    - "@" : tout les types d'entité méta mais non "système" (i.e. servant à la
-      description du schema en base)
-
-* il est possible d'utiliser l'attribut possible `meta` pour marquer un type
-  d'entité comme étant "méta" (i.e. servant à décrire / classifier d'autre
-  entités) 
-
-* propriétés optionnelles des attributs et relations : 
-
-  - `description` : chaine de caractères décrivant un attribut ou une
-    relation. Par défaut cette chaine sera utilisée dans le formulaire de saisie
-    de l'entité, elle est donc destinée à aider l'utilisateur final et doit être
-    marquée par la fonction `_` pour être correctement internationalisée.
-
-  - `constraints` : liste de contraintes devant être respecté par la relation
-    (c.f. `Contraintes`_)
-
-  - `cardinality` : chaine de 2 caractères spécifiant la cardinalité de la
-    relation. Le premier caractère donne la cardinalité de la relation sur le
-    sujet, le 2eme sur l'objet. Quand une relation possède plusieurs sujets ou
-    objets possibles, la cardinalité s'applique sur l'ensemble et non un à un (et
-    doit donc à priori être cohérente...). Les valeurs possibles sont inspirées
-    des expressions régulières :
-
-    * `1`: 1..1
-    * `?`: 0..1
-    * `+`: 1..n
-    * `*`: 0..n
-
-  - `meta` : booléen indiquant que la relation est une méta relation (faux par
-    défaut)
-
-* propriétés optionnelles des attributs : 
-
-  - `required` : booléen indiquant si l'attribut est obligatoire (faux par
-    défaut)
-
-  - `unique` : booléen indiquant si la valeur de l'attribut doit être unique
-    parmi toutes les entités de ce type (faux par défaut)
-
-  - `indexed` : booléen indiquant si un index doit être créé dans la base de
-    données sur cette attribut (faux par défaut). C'est utile uniquement si vous
-    savez que vous allez faire de nombreuses recherche sur la valeur de cet
-    attribut. 
-
-  - `default` : valeur par défaut de l'attribut. A noter que dans le cas des
-    types date, les chaines de caractères correspondant aux mots-clés RQL
-    `TODAY` et `NOW` sont utilisables.
-
-  - `vocabulary` : spécifie statiquement les valeurs possibles d'un attribut
-
-* propriétés optionnelles des attributs de type `String` : 
-
-  - `fulltextindexed` : booléen indiquant si l'attribut participe à l'index plein
-    texte (faux par défaut) (*valable également sur le type `Byte`*)
-
-  - `internationalizable` : booléen indiquant si la valeur de cet attribut est
-    internationalisable (faux par défaut) 
-
-  - `maxsize` : entier donnant la taille maximum de la chaine (pas de limite par
-    défaut)  
-
-* propriétés optionnelles des relations : 
-
-  - `composite` : chaîne indiquant que le sujet (composite == 'subject') est
-    composé de ou des objets de la relation. Pour le cas opposé (l'objet est
-    composé de ou des sujets de la relation, il suffit de mettre 'object' comme
-    valeur. La composition implique que quand la relation est supprimé (et donc
-    aussi quand le composite est supprimé), le ou les composés le sont
-    également. 
-
-
-Contraintes
-```````````
-Par défaut les types de contraintes suivant sont disponibles :
-
-* `SizeConstraint` : permet de spécifier une taille minimale et/ou maximale sur
-  les chaines de caractères (cas générique de `maxsize`)
-
-* `BoundConstraint` : permet de spécifier une valeur minimale et/ou maximale sur
-  les types numériques
-
-* `UniqueConstraint` : identique à "unique=True"
-
-* `StaticVocabularyConstraint` : identique à "vocabulary=(...)"
-
-* `RQLConstraint` : permet de spécifier une requête RQL devant être satisfaite
-  par le sujet et/ou l'objet de la relation. Dans cette requête les variables `S`
-  et `O` sont préféfinies respectivement comme l'entité sujet et objet de la
-  relation
-
-* `RQLVocabularyConstraint` : similaire à la précédente, mais exprimant une
-  contrainte "faible", i.e. servant uniquement à limiter les valeurs apparaissant
-  dans la liste déroulantes du formulaire d'édition, mais n'empêchant pas une
-  autre entité d'être séléctionnée
-
-
-Définition d'un type de relation
---------------------------------
-
-Un type de relation est définit par une classe python héritant de `RelationType`. Le
-nom de la classe correspond au nom du type. Ensuite le corps de la classe
-contient la description des propriétés de ce type de relation, ainsi
-qu'éventuellement une chaine pour le sujet et une autre pour l'objet permettant
-de créer des définitions de relations associées (auquel cas il est possibles de
-donner sur la classe les propriétés de définition de relation explicitées
-ci-dessus), par exemple ::
-
-  class verrouille_par(RelationType):
-    """relation sur toutes les entités applicatives indiquant que celles-ci sont vérouillées
-    inlined = True
-    cardinality = '?*'
-    subject = '*'
-    object = 'CWUser'
-
-En plus des permissions, les propriétés propres aux types de relation (et donc
-partagés par toutes les définitions de relation de ce type) sont :
-
-* `inlined` : booléen contrôlant l'optimisation physique consistant à stocker la
-  relation dans la table de l'entité sujet au lieu de créer une table spécifique
-  à la relation. Cela se limite donc aux relations dont la cardinalité
-  sujet->relation->objet vaut 0..1 ('?') ou 1..1 ('1')
-
-* `symmetric` : booléen indiquant que la relation est symétrique, i.e. "X relation
-   Y" implique "Y relation X"
-
-Dans le cas de définitions de relations simultanée, `sujet` et `object` peuvent
-tout deux valoir la même chose que décrite pour le 1er argument de
-`SubjectRelation` et `ObjectRelation`.
-
-A partir du moment où une relation n'est ni mise en ligne, ni symétrique, et
-ne nécessite pas de permissions particulières, sa définition (en utilisant
-`SubjectRelation` ou `ObjectRelation`) est suffisante.
-
-
-Définition des permissions
---------------------------
-
-La définition des permissions se fait à l'aide de l'attribut `permissions` des
-types d'entité ou de relation. Celui-ci est un dictionnaire dont les clés sont
-les types d'accès (action), et les valeurs les groupes ou expressions autorisées. 
-
-Pour un type d'entité, les actions possibles sont `read`, `add`, `update` et
-`delete`.
-
-Pour un type de relation, les actions possibles sont `read`, `add`, et `delete`.
-
-Pour chaque type d'accès, un tuple indique le nom des groupes autorisés et/ou
-une ou plusieurs expressions RQL devant être vérifiées pour obtenir
-l'accès. L'accès est donné à partir du moment où l'utilisateur fait parti d'un
-des groupes requis ou dès qu'une expression RQL est vérifiée.
-
-Les groupes standards sont :
-
-* `guests`
-
-* `users`
-
-* `managers`
-
-* `owners` : groupe virtuel correspondant au propriétaire d'une entité. Celui-ci
-  ne peut être utilisé que pour les actions `update` et `delete` d'un type
-  d'entité. 
-
-Il est également possible d'utiliser des groupes spécifiques devant être pour
-cela créés dans le precreate de l'application (`migration/precreate.py`).
-
-Utilisation d'expression RQL sur les droits en écriture
-```````````````````````````````````````````````````````
-Il est possible de définir des expressions RQL donnant des droits de
-modification (`add`, `delete`, `update`) sur les types d'entité et de relation.
-
-Expression RQL pour les permissions sur un type d'entité :
-
-* il faut utiliser la classe `ERQLExpression`
-
-* l'expression utilisée correspond à la clause WHERE d'une requête RQL
-
-* dans cette expression, les variables X et U sont des références prédéfinies
-  respectivement sur l'entité courante (sur laquelle l'action est vérifiée) et
-  sur l'utilisateur ayant effectué la requête
-
-* il est possible d'utiliser dans cette expression les relations spéciales
-  "has_<ACTION>_permission" dont le sujet est l'utilisateur et l'objet une
-  variable quelquonque, signifiant ainsi que l'utilisateur doit avoir la
-  permission d'effectuer l'action <ACTION> sur la ou les entités liées cette
-  variable
-
-Pour les expressions RQL sur un type de relation, les principes sont les mêmes
-avec les différences suivantes :
-
-* il faut utiliser la classe `RRQLExpression` dans le cas d'une relation non
-  finale
-
-* dans cette expression, les variables S, O et U sont des références
-  prédéfinies respectivement sur le sujet et l'objet de la relation
-  courante (sur laquelle l'action est vérifiée) et sur l'utilisateur
-  ayant effectué la requête
-
-* On peut aussi définir des droits sur les attributs d'une entité (relation non
-  finale), sachant les points suivants :
-
-  - pour définir des expressions rql, il faut utiliser la classe `ERQLExpression`
-    dans laquelle X représentera l'entité auquel appartient l'attribut
-
-  - les permissions 'add' et 'delete' sont équivalentes. En pratique seul
-    'add'/'read' son pris en considération
-
-
-En plus de cela, le type d'entité `CWPermission` de la librairie standard permet
-de construire des modèles de sécurités très complexes et dynamiques. Le schéma
-de ce type d'entité est le suivant : ::
-
-
-    class CWPermission(MetaEntityType):
-	"""entity type that may be used to construct some advanced security configuration
-	"""
-	name = String(required=True, indexed=True, internationalizable=True, maxsize=100)
-	require_group = SubjectRelation('CWGroup', cardinality='+*',
-					description=_('groups to which the permission is granted'))
-	require_state = SubjectRelation('State',
-				    description=_("entity'state in which the permission is applyable"))
-	# can be used on any entity
-	require_permission = ObjectRelation('**', cardinality='*1', composite='subject',
-					    description=_("link a permission to the entity. This "
-							  "permission should be used in the security "
-							  "definition of the entity's type to be useful."))
-
-
-Exemple de configuration extrait de *jpl* ::
-
-    ...
-
-    class Version(EntityType):
-	"""a version is defining the content of a particular project's release"""
-
-	permissions = {'read':   ('managers', 'users', 'guests',),
-		       'update': ('managers', 'logilab', 'owners',),
-		       'delete': ('managers', ),
-		       'add':    ('managers', 'logilab',
-				  ERQLExpression('X version_of PROJ, U in_group G,'
-						 'PROJ require_permission P, P name "add_version",'
-						 'P require_group G'),)}
-
-    ...
-
-    class version_of(RelationType):
-	"""link a version to its project. A version is necessarily linked to one and only one project.
-	"""
-	permissions = {'read':   ('managers', 'users', 'guests',),
-		       'delete': ('managers', ),
-		       'add':    ('managers', 'logilab',
-				  RRQLExpression('O require_permission P, P name "add_version",'
-						 'U in_group G, P require_group G'),)
-		       }
-	inlined = True
-
-Cette configuration suppose indique qu'une entité `CWPermission` de nom
-"add_version" peut-être associée à un projet et donner le droit de créer des
-versions sur ce projet à des groupes spécifiques. Il est important de noter les
-points suivants :
-
-* dans ce cas il faut protéger à la fois le type d'entité "Version" et la
-  relation liant une version à un projet ("version_of")
-
-* du fait de la généricité du type d'entité `CWPermission`, il faut effectuer
-  l'unification avec les groupes et / ou les états le cas échéant dans
-  l'expression ("U in_group G, P require_group G" dans l'exemple ci-dessus)
-
-
-Utilisation d'expression RQL sur les droits en lecture
-``````````````````````````````````````````````````````
-Les principes sont les mêmes mais avec les restrictions suivantes :
-
-* on ne peut de `RRQLExpression` sur les types de relation en lecture
-
-* les relations spéciales "has_<ACTION>_permission" ne sont pas utilisables
-
-
-Note sur l'utilisation d'expression RQL sur la permission 'add'
-```````````````````````````````````````````````````````````````
-L'utilisation d'expression RQL sur l'ajout d'entité ou de relation pose
-potentiellement un problème pour l'interface utilisateur car si l'expression
-utilise l'entité ou la relation à créer, on est pas capable de vérifier les
-droits avant d'avoir effectué l'ajout (noter que cela n'est pas un problème coté
-serveur rql car la vérification des droits est effectuée après l'ajout
-effectif). Dans ce cas les méthodes de vérification des droits (check_perm,
-has_perm) peuvent inidquer qu'un utilisateur n'a pas le droit d'ajout alors
-qu'il pourrait effectivement l'obtenir. Pour palier à ce soucis il est en général
-nécessaire dans tel cas d'utiliser une action reflétant les droits du schéma
-mais permettant de faire la vérification correctement afin qu'elle apparaisse
-bien le cas échéant.
--- a/goa/doc/devmanual_fr/sect_erudi-ctl.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-L'outil `cubicweb-ctl`
--------------------
-`cubicweb-ctl` est le couteau suisse pour la gestion d'instances CubicWeb.
-La syntaxe générale est ::
-
-  cubicweb-ctl <commande> [options commande] <arguments commandes>
-
-Pour voir les commandes disponibles ::
-
-  cubicweb-ctl
-  cubicweb-ctl --help
-
-A noter que les commandes disponibles varient en fonction des parties de CubicWeb
-qui sont installées.
-
-Pour voir l'aide pour une commande spécifiques ::
-
-  cubicweb-ctl <commande> --help
-
-Commandes pour la création d'un composant
-````````````````````````````````````````
-* ``newtemplate``, crée un nouveau composant sur le système de fichiers
-  à partir du nom passé en paramètre. Cette commande crée le composant à partir
-  d'une squelette d'application, incluant également les fichiers pour le
-  packaging debian)
-  
-Commandes pour la création d'une instance
-`````````````````````````````````````````
-* ``create``, crée les fichiers de configuration d'une instance
-* ``db-create``, crée la base de données système d'une instance (tables et
-  extensions uniquement)
-* ``db-init``, initialise la base de données système d'une instance (schéma,
-  groupes, utilisateurs, workflows...)
-
-Par défaut ces trois commandes sont enchainées.
-
-Commandes pour le lancement des instances
-`````````````````````````````````````````
-* ``start``, démarre une, plusieurs, ou toutes les instances
-* ``stop``, arrêt une, plusieurs, ou toutes les instances
-* ``restart``, redémarre une, plusieurs, ou toutes les instances
-* ``status``, donne l'état des instances
-
-Commandes pour la maintenance des instances
-```````````````````````````````````````````
-* ``upgrade``, lance la migration d'instance(s) existante(s) lorsqu'une nouvelle
-  version d'CubicWeb ou du composant est installée
-* ``shell``, ouvre un shell de migration pour maintenance manuelle d'une instance
-* ``db-dump``, crée un dump de la base de données système
-* ``db-restore``, restore un dump de la base de données système
-* ``db-check``, vérifie l'intégrité des données d'une instance. Si la correction
-  automatique est activée, il est conseillé de faire un dump avant cette
-  opération
-* ``schema-sync``, , synchronise le schéma persistent d'une instance avec le schéma
-  de l'application. Il est conseillé de faire un dump avant cette opération
-
-Commandes pour la maintenance des catalogues i18n
-`````````````````````````````````````````````````
-* ``i18ncubicweb``, regénère les catalogues de messages de la librairie CubicWeb
-* ``i18ncube``, regénère les catalogues de messages d'un composant
-* ``i18ninstance``, recompile les catalogues de messages d'une instance. Cela est
-  effectué automatiquement lors d'une upgrade
-
-Cf Internationalisation_.
-
-Autres commandes
-````````````````
-* ``list``, donne la liste des configurations, des composants et des instances
-  disponibles
-* ``delete``, supprime une instance (fichiers de configuration et base de données)
--- a/goa/doc/devmanual_fr/sect_installation.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-Installation de cubicweb et de ses dépendances
--------------------------------------------
-Tout le système CubicWeb est préparé pour l'installation sur une machine
-debian. L'installation manuelle est un peu pénible du fait des nombreuses
-dépendances à installer (twisted, postgres, autres paquets python...). Nous
-supposerons donc ici que l'installation se fait sur une machine debian ayant
-dans ses sources apt un entrepôt contenant les paquets pour CubicWeb.
-
-Pour tout installer sur le système ::
-
-  apt-get install cubicweb
-
-On peut également n'installer que les paquets cubicweb-server ou cubicweb-twisted pour
-n'avoir que la partie serveur ou client web sur une machine.
-
-Pour tout installer la documentation et les librairies/outils de développement ::
-
-  apt-get install cubicweb-documentation cubicweb-dev
-
-On pourra ensuite installer les paquets suivants :
-
-* `pyro` si vous voulez que l'entrepôt soit accessible via Pyro ou si le client
-  et le serveur ne sont pas sur la même machine (auquel cas il faut installer ce
-  paquet sur les machines clientes et serveur)
-
-* `python-ldap` si vous voulez utiliser une source ldap sur le serveur
-
-* `postgresql-8.1`, `postgresql-contrib-8.1` et `postgresql-plpython-8.1` la
-  machine devant héberger la base de données système
-
-Configuration de l'environnement
---------------------------------
-Ajouter les lignes suivantes à son `.bashrc` ou `.bash_profile` pour configurer
-votre environnement de développement ::
-
-  export CW_REGISTRY=~/etc/cubicweb.d/
-  export CW_CUBES=~/hg/
-  export CW_RUNTIME=/tmp/
-
-Cela suppose que le composant cubicweb que vous développez est dans un
-sous-répertoire de *~/hg/* et que vous avez créé le répertoire *~/etc/cubicweb.d/*
-pour que `cubicweb-ctl` y place vos instances de test.
-
-
-Configuration Postgres
-----------------------
-* création d'un super utilisateur pour la création d'instance (**root**) ::
-
-    createuser --superuser --createdb -P pgadmin
-
-  Un mot de passe de connection pour cet utilisateur vous sera demandé. Il
-  faudra utiliser ce login / mot de passe à la création d'instance via
-  `cubicweb-ctl`
-
-* installation des extensions pour l'index plein texte ::
-
-    cat /usr/share/postgresql/8.1/contrib/tsearch2.sql | psql -U pgadmin template1
-
-* installation du langage plpythonu par défaut ::
-
-    createlang -U pgadmin plpythonu template1
-
-
-Configuration Pyro
-------------------
-Si vous utilisez Pyro, il est nécessaire d'avoir un serveur de noms Pyro
-tournant sur votre réseau (par défaut celui-ci est repéré par une requête
-broadcast). Pour cela il faut soit :
-
-* le lancer à la main avant le démarrage de cubicweb avec la commande `pyro-ns`
-
-* le lancer à la main avant le démarrage de cubicweb sous forme d'un serveur avec
-  la commande `pyro-nsd start`
-
-* éditer le fichier */etc/default/pyro-nsd* pour que le serveur de nom pyro soit
-  lancé automatiquement au démarrage de la machine
--- a/goa/doc/devmanual_fr/sect_mercurial.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-Présentation de Mercurial
--------------------------
-
-Introduction
-````````````
-Mercurial_ gère un ensemble distribué d'entrepôts contenant des arbres de
-révisions (chaque révision indique les changements à effectuer pour obtenir la
-version suivante, et ainsi de suite). Localement, on dispose d'un entrepôt
-contenant un arbre de révisions, et d'un répertoire de travail. Il est possible
-de mettre dans son répertoire de travail, une des versions issue de son entrepôt
-local, de la modifier puis de la verser dans son entrepôt. Il est également
-possible de récuprer dans son entrepôt local des révisions venant d'un autre
-entrepôt, ou d'exporter ses propres révisions depuis son entrepôt local vers un
-autre entrepôt.
-
-A noter que contrairement à CVS/Subversion, on crée généralement un entrepôt par
-projet à gérer.
-
-Lors d'un développement collaboratif, on crée généralement un entrepôt central
-accessible à tout les développeurs du projet. Ces entrepôts centraux servent de
-référence. Selon ses besoins, chacun peut ensuite disposer d'un entrepôt local,
-qu'il faudra penser à synchroniser avec l'entrepôt central de temps à autre. 
-
-
-Principales commandes
-`````````````````````
-* Créer un entrepôt local ::
-
-    hg clone ssh://orion//home/src/prive/rep
-
-* Voir le contenu de l'entrepôt local (outil graphique en Tk) ::
-
-    hg view
-
-* Ajouter un sous-répertoire ou un fichier dans le répertoire courant ::
-
-    hg add rep
-
-* Placer dans son répertoire de travail une révision spécifique (ou la dernière
-  revision) issue de l'entrepôt local ::
-
-    hg update [identifiant-revision]
-    hg up [identifiant-revision]
-
-* Récupérer dans son entrepôt local, l'arbre de révisions contenu dans un
-  entrepôt distant (cette opération ne modifie pas le répertoire local) ::
-
-    hg pull ssh://orion//home/src/prive/rep
-    hg pull -u ssh://orion//home/src/prive/rep # équivalent à pull + update
-
-* Voir quelles sont les têtes de branches de l'entrepôt local si un `pull` a
-  tiré une nouvelle branche ::
-
-    hg heads
-
-* Verser le répertoire de travail dans l'entrepôt local (et créer une nouvelle
-  révision) ::
-
-    hg commit
-    hg ci
-
-* Fusionner, avec la révision mère du répertoire local, une autre révision issue
-  de l'entrepôt local (la nouvelle révision qui en résultera aura alors deux
-  révisions mères) ::
-
-    hg merge identifiant-revision
-
-* Exporter dans un entrepôt distant, l'arbre de révisions contenu dans son
-  entrepôt local (cette opération ne modifie pas le répertoire local) ::
-
-    hg push ssh://orion//home/src/prive/rep
-
-* Voir quelle sont les révisions locales non présentes dans un autre entrepôt ::
-
-    hg outgoing ssh://orion//home/src/prive/rep
-
-* Voir quelle sont les révisions d'un autre entrepôt non présentes localement ::
-
-    hg incoming ssh://orion//home/src/prive/rep
-
-* Voir quelle est la révision issue de l'entrepôt local qui a été sortie dans le
-  répertoire de travail et modifiée ::
-
-    hg parent
-
-* Voir les différences entre le répertoire de travail et la révision mère de
-  l'entrepôt local, éventuellement permettant de les verser dans l'entrepôt
-  local ::
-
-    hg diff
-    hg commit-tool
-    hg ct
-
-
-Bonnes pratiques
-````````````````
-* penser à faire un `hg pull -u` régulièrement et particulièrement avant de
-  faire un `hg commit`
-
-* penser à faire un `hg push` lorsque votre entrepôt contient une version
-  relativement stable de vos modifications
-
-* si un `hg pull -u` a créé une nouvelle tête de branche :
-
-  1. identifier l'identifiant de celle-ci avec `hg head`
-  2. fusionner avec `hg merge`
-  3. `hg ci`
-  4. `hg push`
-
-.. _Mercurial: http://www.selenic.com/mercurial/
--- a/goa/doc/devmanual_fr/sect_stdlib_schemas.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-Schémas prédéfinies dans la librairie
--------------------------------------
-
-La librairie définit un certain nombre de schémas d'entités nécessaires
-au système ou bien couramment utilisées dans les application `cubicweb`.
-Vous pouvez bien entendu étendre ces schémas au besoin.
-
-
-Schémas "systèmes"
-``````````````````
-
-* `CWUser`, utilisateurs du système
-* `CWGroup`, groupes d'utilisateurs
-* `CWEType`, types d'entité
-* `CWRType`, types de relation
-
-* `State`, état d'un workflow
-* `Transition`, transition d'un workflow
-* `TrInfo`, enregistrement d'un passage de transition pour une entité
-
-* `EmailAddress`, adresse électronique, utilisé par le système de notification
-  pour les utilisateurs et par d'autres schéma optionnels
-
-* `CWProperty`, utilisé pour configurer l'application
-* `CWPermission`, utilisé pour configurer la sécurité de l'application
-
-* `Card`, fiche documentaire générique
-* `Bookmark`, un type d'entité utilisé pour permetter à un utilisateur de
-  personnaliser ses liens de navigation dans l'application.
-
-
-Composants de la librairie
-``````````````````
-Une application est construite sur la base de plusieurs composants de base.
-Parmi les composants de base disponible, on trouve par exemple :
-
-* `ecomment`, fournit le type d'entité `Comment` permettant de commenter les
-  entités du site
-  
-* `emailinglist`, fournit le type d'entité `Mailinglist` regroupant des
-  informations sur une liste de discussion
-
-* `efile`, fournit les types d'entités `File` et `Image` utilisés pour
-  représenter des fichiers (texte ou binaire) avec quelques données
-  supplémentaires comme le type MIME ou l'encodage le cas échéant ().
-  
-* `elink`, fournit le type d'entité lien internet (`Link`)
-
-* `eblog`, fournit le type d'entité weblog (`Blog`)
-
-* `eperson`, fournit le type d'entité personne physique (`Person`)
-
-* `eaddressbook`, fournit les types d'entités utilisés pour représenter des n°
-  de téléphone (`PhoneNumber`) et des adresses postales (`PostalAddress`)
-  
-* `eclasstags`, système de classfication à base d'étiquettes (`Tag`)
-
-* `eclassfolders`, système de classification à base de dossiers hiérarchiques
-  destinés à créer des rubriques de navigation (`Folder`)
-
-* `eemail`, gestion d'archives de courriers électroniques (`Email`, `Emailpart`,
-  `Emailthread`)
-
-* `ebasket`, gestion de paniers (`Basket`) permettant de regrouper des entités
-
-Pour déclarer l'utilisation d'un composant, une fois celui-ci installé, ajoutez
-le nom du composant à la variable `__use__` du fichier `__pkginfo__.py` de
-votre propre composant.
--- a/goa/doc/devmanual_fr/sect_stdlib_vues.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-
-Vues prédéfinies dans la librairie
-----------------------------------
-Un certain nombre de vues sont utilisées pour construire l'interface web, qui
-s'appliquent à une ou plusieurs entités. On les distingue par leur identifiant,
-et les principales sont : 
-
-:primary:
-    vue principale pour une entité, elle est appelée par défaut lorsqu'il n'y a
-    qu'un seul élément correspondant à la recherche. Cette vue est censée
-    afficher le maximum d'informations à propos de l'objet.
-:secondary:
-    vue secondaire d'une entité. Par défaut, Elle affiche les deux premiers
-    attributs de l'entité sous la forme d'un lien cliquable amenant sur la vue
-    primaire.
-:oneline:
-    similaire à la vue `secondary`, mais appelée dans des cas où l'on désire que
-    la vue tient sur une ligne, ou de manière générale juste avoir une vue plus
-    abbrégée. Par défaut, cette vue utilise le paramètre de configuration
-    `MAX_LINE_CHAR` pour contrôler la taille du résultat.
-:text:
-    similaire à la vue `oneline`, mais ne devant pas contenir de html.
-:incontext, outofcontext:
-    similaire à la vue `secondary`, mais appelé si l'entité est considérée comme
-    en dehors ou dans son contexte. Par défault renvoie respectivement le
-    résultat de `textincontext` et `textoutofcontext` entouré par un lien
-    permettant d'accéder à la vue primaire de l'entité
-:textincontext, textoutofcontext:
-    similaire à la vue `text`, mais appelé si l'entité est considérée comme
-    en dehors ou dans son contexte. Par défault renvoie respectivement le
-    résultat des méthodes `.dc_title` et `.dc_long_title` de l'entité
-:list:
-    crée une liste html (<ul>) et appelle la vue `listitem` pour chaque entité
-:listitem:
-    redirige par défaut vers la vue `outofcontext`
-:rss:
-    crée unvue RSS/XML et appelle la vue `rssitem` pour chaque entité
-:rssitem:
-    crée unvue RSS/XML pour une entité à partir des résultats renvoyés par les
-    méthodes dublin core de l'objet (`dc_*`)
-
-Vues de départ :
-
-:index:
-    page d'acceuil
-:schema:
-    affiche le schéma de l'application
-
-Vues particulières :
-
-:noresult:
-    appelé si le result set est vide
-:finall:
-    affiche la valeur de la cellule sans transformation (dans le cas d'une
-    entité non finale, on voit son eid). Appelable sur n'importe quel result
-    set.
-:table:
-    crée une table html (<table>) et appelle la vue `cell` pour chaque cellule
-    du résultat. Appelable sur n'importe quel result set.
-:cell:
-    par défaut redirige sur la vue `final` si c'est une entité finale
-    ou sur la vue `outofcontext` sinon
-:null:
-    vue toujours appelable et ne retournant rien
--- a/goa/doc/quickstart.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Introduction
-=============
-
-
-Concepts et vocabulaire
------------------------
-
-*schéma*
-  le schéma définit le modèle de données d'une application sous forme
-  d'entités et de relations. C'est l'élément central d'une
-  application.
-
-*result set*
-  objet qui encaspule les résultats d'une requête adressée à l'entrepôt
-  de données et des informations sur cette requête.
-
-*vue*
-  une vue est une manière de représenter les données d'un `result set`
-  sous forme HTML, CSV, JSON, etc.
-
-
-
-Définition d'une application de Blog
-====================================
-
-La première chose à faire est de copier le squelette depuis le répertoire
-``lax/skel`` vers un nouveau répertoire qui sera votre application
-``Google AppEngine``::
-
-  $ cp -r lax/skel myapp
-
-Définition du schéma
---------------------
-
-Ouvrir le fichier ``myapp/schema.py`` afin de définir le schéma des
-données manipulées. La syntaxe de la définition est la même que celle
-proposée par `Google AppEngine`_ mais il faut remplacer la ligne
-d'import::
-
-  from google.appengine.ext import db
-
-par celle-ci::
-
-  from cubicweb.goa import db
-
-
-Un exemple de schéma de données pour un ``Blog`` pourrait être::
-
-  from cubicweb.goa import db
-
-  class Blog(db.Model):
-      # un titre à donner à l'entrée
-      title = db.StringProperty(required=True)
-      # la date à laquelle le blog est créé
-      diem = db.DateProperty(required=True, auto_now_add=True)
-      # le contenu de l'entrée
-      content = db.TextProperty()
-      # une entrée peut en citer une autre
-      cites = db.SelfReferenceProperty()
-
-
-Personnalisation des vues
--------------------------
-
-``LAX`` permet de générer directement, à partir de la définition
-du schéma, des vues de consultation, d'ajout et de modification
-pour tous les types de donées manipulés. Il est toutefois
-généralement souhaitable de personnaliser les vues de consultations.
-
-Dans ``LAX``, les vues sont représentées par des classes Python.
-
-Une vue se caractérise par :
-
-- un identifiant (tous les objets dans ``LAX`` sont enregistrés
-  dans un registre et cet identifiant sert de clé pour y retrouver
-  la vue)
-
-- une description des types de données auxquels elle s'applique
-
-Il existe dans ``LAX`` des vues prédéfinies et utilisées par le moteur
-d'affichage. Pour avoir une liste exhaustive de ces vues prédéfinies,
-vous pouvez consulter cette page. (XXX mettre le lien vers la liste).
-Par exemple, la vue ``primary`` est la vue utilisée pour générer la
-page principale de consultation d'un objet.
-
-Par exemple, si on souhaite modifier la page principale d'une entrée de
-blog, il faut surcharger la vue ``primary`` des objets ``Blog`` dans
-le fichier ``myapp/views.py``::
-
-  from cubicweb.web.views import baseviews
-
-  class BlogPrimaryView(baseviews.PrimaryView):
-      accepts = ('Blog',)
-
-      def cell_call(self, row, col):
-          entity = self.rset.get_entity(row, col)
-          self.w(u'<h1>%s</h1>' % entity.title)
-          self.w(u'<div>%s</div>' entity.content)
-
-
-Génération du graphique de schéma
----------------------------------
-
-Il existe une vue ``schema`` qui permet d'afficher un graphique
-représantant les différents types d'entités définis dans le schéma
-ainsi que les relations entre ces types. Ce graphique doit être généré
-statiquement. Le script à utiliser pour générer ce schéma est
-dans ``myapp/tools``. Ce script nécessite d'avoir accès aux
-bibliothèques fournies par le SDK de ``Google AppEngine``. Il faut
-donc modifier son PYTHONPATH::
-
-  $ export PYTHONPATH=GAE_ROOT/google:GAE_ROOT/lib/yaml
-  $ python tools/generate_schema_img.py
-
-
-Génération des fichiers de traduction
--------------------------------------
-
-Des catalogues de traduction se trouvent dans `myapp/i18n`. Il faut
-pour l'instant les mettre à jour à la main (et/ou avec les outils
-``GNU`` comme ``xgettext``) et ensuite les compiler grâce au script
-``myapp/tools/i18ncompile.py``::
-
-  $ python tools/i18ncompile.py
-
-.. _`Google AppEngine` :: http://code.google.com/appengine/docs/datastore/overview.html
--- a/goa/doc/tutorial-wine.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-=============
-LAX Tutorial
-=============
-
-Introduction
-------------
-
-LAX is a web framework on top of the Google AppEngine datastore.
-
-
-features: schema/data-model at core of app, selection/view mechanism,
-reuseable components, very fast development
-
-
-Since we are french, let us develop an example application that deals
-with wine and will allow any wine enthusiast to track the content of
-its cellar and share his tasting experiences.
-
-Schema
-------
-
-With LAX, the core of the application is the schema/datamodel.
-
-laxctl newapp ? XXX
-
-We will start by something simple and define three entities: WineMaker,
-Wine and Bottle.
-
-::
-
-  class WineMaker(EntityType):
-      name = String(maxsize=50, required=True)
-
-  class Wine(EntityType):
-      name = String(required=True, maxsize=100, fulltextindexed=True)
-      vintage = Int(required=True, constraints=[IntervalBoundConstraint(1850,2100)])
-      grown_by = SubjectRelation('WineMaker', cardinality='?*',
-                                 description=_('Winemaker who grew the wine'))
-
-  class Bottle(EntityType):
-      buy_date = Date(description=_('Date when the bottle was bought.'),
-                      default='TODAY')
-      bottle_of = SubjectRelation('Wine', cardinality='?*')
-
-A WineMaker only has a name which is a string that is required and
-must be less than 50 characters.
-
-A Wine has a name, which is a string that is required, must be less
-than 100 characters and will be indexed in the full-text index XXX
-fulltextindex marche pas encore. A Wine
-also has a vintage year which is an integer that is required and must
-be between 1850 and 2100. A Wine also has a relationship ``grown_by``
-that link it to a WineMaker. Cardinality ``?*`` means that a Wine can
-have zero or one WineMaker (``?`` means `zero or one`) and that a
-WineMaker can have any number of Wine entities (``*`` means `any number
-including zero`).
-
-A Bottle has a buy_date attribute, which is a date with a default
-value of TODAY, meaning that when a new bottle is created, it will
-have its creation date as buy_date unless the user changes it to some
-other date. A Bottle also has a relationship ``bottle_of`` that link
-it to a Wine. The cardinality of that relationship implies that a
-Bottle can be linked to zero or one Wine and that a Wine can by linked
-to any number of Bottle entities.
-
-
-Defining this simple schema is enough to get us started, launch the
-application with the command::
-
-   laxctl start Winopedia
-
-and point your browser at localhost:8080
-
-You will see the home page of your application. It lists the entity
-types: WineMaker, Wine, Bottle.
-
-Let us create a few of these. Click on the [+] at the right of the
-link WineMaker. Call this new WineMaker ``Domaine du château`` and
-validate the form by clicking on ``button_ok``. 
-
-Click on the logo at top left to get back to the home page, then
-follow the WineMaker link. You should be seeing a list with a single
-item ``Domaine du château``. Clicking on this item will get you to 
-its detailed description except that in this case, there is not much
-to display besides the name.
-
-Now get back to the home page by clicking on the top-left logo, then
-create a new WineMaker called ``Vallon de la Dame`` and get back to the
-home page again to follow the WineMaker link for the second time. The
-list now has two items.
-
-Get back to the home page and click on [+] at the right of the link
-Wine. Call this new wine ``Cuvée du Roi`` and enter 2008 as vintage,
-then click on ``button_ok``. You added a new wine without saying who
-made it. There is a box on the left entitled "actions", click on the
-menu item `modify`. You are back to the form to edit the wine entity
-you just created, except that the form now has another section with a
-combobox titled "add a relationship". Chose "grown_by" in this
-menu and a second combobox appears where you pick ``Domaine du
-château``. Validate the changes by clicking  ``button_ok``. The entity
-Wine that is displayed now includes a link to the entity WineMaker
-named ``Domaine du château``.
-
-Exercise
-~~~~~~~~
-
-Create new entities Wine and Bottle.
-
-What we learned
-~~~~~~~~~~~~~~~
-
-Creating a simple schema was enough to set up a new application that
-can store WineMaker, Wine, Bottle. 
-
-What is next ?
---------------
-
-Althought the application is fully functionnal, its look is very
-basic. We will now improve how information is displayed by writing
-views.
-
-
-Views
-======
-
-...
-
-Defining views with selection/views
-
-implementing interfaces, calendar for bottles bought and for tasting.
-calendar with export icalput attribute drink_date on bottle 
-
-add attribute wine color
-
-create view "bottle table" with color, buy_date, drink_date.
-
-in view wine, select Wine.bottles and apply view "bottle table"
-
-demo ajax with filter on bottle table
-
-Components
-===========
-
-...
-
-
-
-customize MainTemplate
-
-rss channel of new bottles or wines
-
-use URLRewriting for nice urls
-
-talk about security access rights
-
-talk about rql
\ No newline at end of file
--- a/goa/doc/tutorial.en.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-=============
-LAX Tutorial
-=============
-
-Introduction
-============
-
-LAX stands for Logilab App engine eXtension. It is a web framework
-running on top of the Google AppEngine datastore.
-
-Distinctive features include a data-model driven engine, a query
-language, a selection/view mechanism for HTML/XML/text generation,
-reuseable components, etc. It all sums up to very fast and efficient
-development.
-
-This tutorial will guide you to build a blog application step by step
-to discover the unique features of LAX. It assumes that you followed
-the installation guidelines and that both the AppEngine SDK and the
-LAX framework are setup on your computer.
-
-Creating a very simple application
-==================================
-
-Creating a new application
---------------------------
-
-When you installed lax, you saw a directory named skel. Make a copy of
-this directory and call it BlogDemo.
-
-Defining a schema
------------------
-
-With LAX, the schema/datamodel is the core of the application.
-
-Let us start with something simple and improve on it later. First, we
-make sure that in appconfig.py we have a line ::
-
-  schema_type = 'yams'
-
-Then, in schema.py, we define two entities : ``Blog`` and ``BlogEntry``.
-
-::
-				   
-  class Blog(EntityType):
-      title = String(maxsize=50, required=True)
-      description = String()
-
-  class BlogEntry(EntityType):
-      title = String(maxsize=100, required=True)
-      publish_date = Date(default='TODAY')
-      text = String(fulltextindexed=True)
-      category = String(vocabulary=('important','business'))
-      entry_of = SubjectRelation('Blog', cardinality='?*')
-
-A Blog has a title and a description. The title is a string that is
-required and must be less than 50 characters. The description is a
-string that is not constrained.
-
-A BlogEntry has a title, a publish_date and a text. The title is a
-string that is required and must be less than 100 characters. The
-publish_date is a Date with a default value of TODAY, meaning that
-when a BlogEntry is created, its publish_date will be the current day
-unless it is modified. The text is a string that will be indexed in
-the full-text index and has no constraint.
-
-A BlogEntry also has a relationship ``entry_of`` that link it to a
-Blog. The cardinality ``?*`` means that a BlogEntry can be part of
-zero or one Blog (``?`` means `zero or one`) and that a Blog can
-have any number of BlogEntry (``*`` means `any number including
-zero`). For completeness, remember that ``+`` means `one or more`.
-
-:note: in lax-0.3.0, cardinality checking is not fully ported to
-AppEngine, so cardinality limits are not enforced. This should be
-fixed in lax-0.4.0 available at the beginning of June.
-
-Using the application
----------------------
-
-Defining this simple schema is enough to get us started. Launch the
-application with the command::
-
-   python dev_appserver.py BlogDemo
-
-and point your browser at localhost:8080
-
-You will see the home page of your application. It lists the entity
-types: Blog and BlogEntry.
-
-Let us create a few of these. Click on the [+] at the right of the
-link Blog. Call this new Blog ``Tech-blog`` and type in
-``everything about technology`` as the description, then validate the
-form by clicking on ``button_ok``.
-
-Click on the logo at top left to get back to the home page, then
-follow the Blog link. If this link reads ``blog_plural`` it is because
-i18n is not working for you yet. Let us ignore this for a while. After
-following the link, you should be seeing a list with a single item
-``Tech-blog``. Clicking on this item will get you to its detailed
-description except that in this case, there is not much to display
-besides the name and the phrase ``everything about technology``.
-
-Now get back to the home page by clicking on the top-left logo, then
-create a new Blog called ``MyLife`` and get back to the home page
-again to follow the Blog link for the second time. The list now
-has two items.
-
-Get back to the home page and click on [+] at the right of the link
-BlogEntry. Call this new entry ``Hello World`` and type in some text
-before clicking on ``button_ok``. You added a new blog entry without
-saying to what blog it belongs. There is a box on the left entitled
-``actions``, click on the menu item ``modify``. You are back to the form
-to edit the blog entry you just created, except that the form now has
-another section with a combobox titled ``add relation``. Chose
-``entry_of`` in this menu and a second combobox appears where you pick
-``MyLife``. Validate the changes by clicking
-``button_ok``. The entity BlogEntry that is displayed now includes a link
-to the entity Blog named ``MyLife``.
-
-Conclusion
-----------
-
-Exercise
-~~~~~~~~
-
-Create new blog entries in ``Tech-blog``.
-
-What we learned
-~~~~~~~~~~~~~~~
-
-Creating a simple schema was enough to set up a new application that
-can store blogs and blog entries. 
-
-What is next ?
---------------
-
-Althought the application is fully functionnal, its look is very
-basic. We will now improve how information is displayed by writing
-views.
-
-
-Developing the user interface with Views
-========================================
-
-[WRITE ME]
-
-* Defining views with selection/views
-
-* implementing interfaces, calendar for blog entries.
-
-* show that a calendar view can export data to ical. 
-
-* create view "blogentry table" with title, publish_date, category.
-
-* in view blog, select blogentries and apply view "blogentry table"
-
-* demo ajax by filtering blogentry table on category
-
-Components
-===========
-
-[WRITE ME]
-
-* explain the component architecture
-
-* add comments to the blog by importing the comments component
-
-Boxes
-======
-
-[WRITE ME]
-
-* explain how to build a box
-
-* add an blogentry archives box
-
-Preferences
-============
-
-[WRITE ME]
-
-* talk about the user preferences
-
-* add an example on how to hide / display / move a component or a box
-
-MainTemplate
-============
-
-[WRITE ME]
-
-* customize MainTemplate and show that everything in the user
-  interface can be changed
-
-
-RSS Channel
-===========
-
-[WRITE ME]
-
-* show that the RSS view can be used to display an ordered selection
-  of blog entries, thus providing a RSS channel
-
-* show that a different selection (by category) means a different channel
-
-RQL
-====
-
-[WRITE ME]
-
-* talk about the Relation Query Language
-
-URL Rewriting
-=============
-
-[WRITE ME]
-
-* show how urls are mapped to selections and views and explain URLRewriting 
-
-Security
-=========
-
-[WRITE ME]
-
-* talk about security access rights and show that security is defined
-  using RQL
-
--- a/goa/gaesource.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,331 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""Adapter for google appengine source.
-
-"""
-__docformat__ = "restructuredtext en"
-
-from cubicweb import AuthenticationError, UnknownEid
-from cubicweb.server.sources import AbstractSource, ConnectionWrapper
-from cubicweb.server.pool import SingleOperation
-from cubicweb.server.utils import crypt_password
-from cubicweb.goa.dbinit import set_user_groups
-from cubicweb.goa.rqlinterpreter import RQLInterpreter
-
-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:
-        groups = ['guests']
-    else:
-        groups = ['users']
-        if users.is_current_user_admin():
-            groups.append('managers')
-    set_user_groups(euser, groups)
-
-def _clear_related_cache(session, gaesubject, rtype, gaeobject):
-    subject, object = str(gaesubject.key()), str(gaeobject.key())
-    for eid, role in ((subject, 'subject'), (object, 'object')):
-        # clear related cache if necessary
-        try:
-            entity = session.entity_cache(eid)
-        except KeyError:
-            pass
-        else:
-            entity.cw_clear_relation_cache(rtype, role)
-    if gaesubject.kind() == 'CWUser':
-        for asession in session.repo._sessions.itervalues():
-            if asession.user.eid == subject:
-                asession.user.cw_clear_relation_cache(rtype, 'subject')
-    if gaeobject.kind() == 'CWUser':
-        for asession in session.repo._sessions.itervalues():
-            if asession.user.eid == object:
-                asession.user.cw_clear_relation_cache(rtype, 'object')
-
-def _mark_modified(session, gaeentity):
-    modified = session.transaction_data.setdefault('modifiedentities', {})
-    modified[str(gaeentity.key())] = gaeentity
-    DatastorePutOp(session)
-
-def _rinfo(session, subject, rtype, object):
-    gaesubj = session.datastore_get(subject)
-    gaeobj = session.datastore_get(object)
-    rschema = session.vreg.schema.rschema(rtype)
-    cards = rschema.rproperty(gaesubj.kind(), gaeobj.kind(), 'cardinality')
-    return gaesubj, gaeobj, cards
-
-def _radd(session, gaeentity, targetkey, relation, card):
-    if card in '?1':
-        gaeentity[relation] = targetkey
-    else:
-        try:
-            related = gaeentity[relation]
-        except KeyError:
-            related = []
-        else:
-            if related is None:
-                related = []
-        related.append(targetkey)
-        gaeentity[relation] = related
-    _mark_modified(session, gaeentity)
-
-def _rdel(session, gaeentity, targetkey, relation, card):
-    if card in '?1':
-        gaeentity[relation] = None
-    else:
-        related = gaeentity[relation]
-        if related is not None:
-            related = [key for key in related if not key == targetkey]
-            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.
-    """
-    def insert_index(self):
-        return 0
-
-    def _put_entities(self):
-        pending = self.session.transaction_data.get('pendingeids', ())
-        modified = self.session.transaction_data.get('modifiedentities', {})
-        for eid, gaeentity in modified.iteritems():
-            assert not eid in pending
-            Put(gaeentity)
-        modified.clear()
-
-    def commit_event(self):
-        self._put_entities()
-
-    def precommit_event(self):
-        self._put_entities()
-
-
-class GAESource(AbstractSource):
-    """adapter for a system source on top of google appengine datastore"""
-
-    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)
-        if repo.config['use-google-auth']:
-            self.info('using google authentication service')
-            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
-
-    def init(self):
-        # XXX unregister unsupported hooks
-        from cubicweb.server.hooks import sync_owner_after_add_composite_relation
-        self.repo.hm.unregister_hook(sync_owner_after_add_composite_relation,
-                                     'after_add_relation', '')
-
-    def get_connection(self):
-        return ConnectionWrapper()
-
-    # ISource interface #######################################################
-
-    def compile_rql(self, rql):
-        rqlst = self.repo.vreg.parse(rql)
-        rqlst.restricted_vars = ()
-        rqlst.children[0].solutions = self._sols
-        return rqlst
-
-    def set_schema(self, schema):
-        """set the instance'schema"""
-        self.interpreter = RQLInterpreter(schema)
-        self.schema = schema
-        if 'CWUser' in schema and not self.repo.config['use-google-auth']:
-            # 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
-        """
-        return True
-
-    def authenticate_gauth(self, session, login, password):
-        guser = users.get_current_user()
-        # allowing or not anonymous connection should be done in the app.yaml
-        # file, suppose it's authorized if we are there
-        if guser is None:
-            login = u'anonymous'
-        else:
-            login = unicode(guser.nickname())
-        # XXX http://code.google.com/appengine/docs/users/userobjects.html
-        # use a reference property to automatically work with email address
-        # changes after the propagation feature is implemented
-        key = Key.from_path('CWUser', 'key_' + login, parent=None)
-        try:
-            euser = session.datastore_get(key)
-            # XXX fix user. Required until we find a better way to fix broken records
-            if not euser.get('s_in_group'):
-                _init_groups(guser, euser)
-                Put(euser)
-            return str(key)
-        except datastore_errors.EntityNotFoundError:
-            # create a record for this user
-            euser = Entity('CWUser', name='key_' + login)
-            euser['s_login'] = login
-            _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`
-
-        two queries are needed since passwords are stored crypted, so we have
-        to fetch the salt first
-        """
-        args = {'login': login, 'pwd' : password}
-        if password is not None:
-            rset = self.syntax_tree_search(session, self._passwd_rqlst, args)
-            try:
-                pwd = rset[0][0]
-            except IndexError:
-                raise AuthenticationError('bad login')
-            # passwords are stored using the bytea type, so we get a StringIO
-            if pwd is not None:
-                args['pwd'] = crypt_password(password, pwd[:2])
-        # get eid from login and (crypted) password
-        rset = self.syntax_tree_search(session, self._auth_rqlst, args)
-        try:
-            return rset[0][0]
-        except IndexError:
-            raise AuthenticationError('bad password')
-
-    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
-        possible type). If cachekey is given, the query necessary to fetch the
-        results (but not the results themselves) may be cached using this key.
-        """
-        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()
-        _mark_modified(session, entity.to_gae_model())
-        if gaeentity.kind() == 'CWUser':
-            for asession in self.repo._sessions.itervalues():
-                if asession.user.eid == entity.eid:
-                    asession.user.update(dict(gaeentity))
-
-    def delete_entity(self, session, entity):
-        """delete an entity from the source"""
-        # do not delay delete_entity as other modifications to ensure
-        # consistency
-        eid = entity.eid
-        key = Key(eid)
-        Delete(key)
-        session.clear_datastore_cache(key)
-        session.drop_entity_cache(eid)
-        session.transaction_data.get('modifiedentities', {}).pop(eid, None)
-
-    def add_relation(self, session, subject, rtype, object):
-        """add a relation to the source"""
-        gaesubj, gaeobj, cards = _rinfo(session, subject, rtype, object)
-        _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)
-        pending = session.transaction_data.setdefault('pendingeids', set())
-        if not subject in pending:
-            _rdel(session, gaesubj, gaeobj.key(), 's_' + rtype, cards[0])
-        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):
-        """return a tuple (type, source, extid) for the entity with id <eid>"""
-        try:
-            key = Key(eid)
-        except datastore_errors.BadKeyError:
-            raise UnknownEid(eid)
-        return key.kind(), 'system', None
-
-    def create_eid(self, session):
-        return None # let the datastore generating key
-
-    def add_info(self, session, entity, source, extid=None):
-        """add type and source info for an eid into the system table"""
-        pass
-
-    def delete_info(self, session, eid, etype, uri, extid):
-        """delete system information on deletion of an entity by transfering
-        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	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""google appengine configuration
-
-"""
-__docformat__ = "restructuredtext en"
-
-import os
-from os.path import join
-
-from cubicweb import CW_SOFTWARE_ROOT
-from cubicweb.cwconfig import CubicWebConfiguration
-from cubicweb.web.webconfig import WebConfiguration, merge_options
-from cubicweb.server.serverconfig import ServerConfiguration
-from cubicweb.goa.dbmyams import load_schema
-
-UNSUPPORTED_OPTIONS = set(('connections-pool-size',
-                           'pyro-host', 'pyro-instance-id',
-                           'pyro-ns-host', 'pyro-ns-group',
-                           'https-url', 'host', 'pid-file', 'uid', 'base-url', 'log-file',
-                           'smtp-host', 'smtp-port',
-                           'embed-allowed',
-                           ))
-
-# XXX fix:
-# * default sender-name / sender-addr value
-# * what about *session-time
-# * check auth-mode=http + fix doc (eg require use-google-auth = False)
-
-class GAEConfiguration(ServerConfiguration, WebConfiguration):
-    """repository and web instance in Google AppEngine environment"""
-    name = 'app'
-    repo_method = 'inmemory'
-    options = merge_options((
-        ('included-cubes',
-         {'type' : 'csv',
-          'default': [],
-          'help': 'list of db model based cubes used by the instance.',
-          'group': 'main', 'level': 1,
-          }),
-        ('included-yams-cubes',
-         {'type' : 'csv',
-          'default': [],
-          'help': 'list of yams based cubes used by the instance.',
-          'group': 'main', 'level': 1,
-          }),
-        ('use-google-auth',
-         {'type' : 'yn',
-          'default': True,
-          'help': 'does this instance rely on google authentication service or not.',
-          'group': 'main', 'level': 1,
-          }),
-        ('schema-type',
-         {'type' : 'choice', 'choices': ('yams', 'dbmodel'),
-          'default': 'yams',
-          'help': 'does this instance is defining its schema using yams or db model.',
-          'group': 'main', 'level': 1,
-          }),
-        # overriden options
-        ('query-log-file',
-         {'type' : 'string',
-          'default': None,
-          'help': 'web instance query log file: DON\'T SET A VALUE HERE WHEN '
-          'UPLOADING YOUR INSTANCE. This should only be used to analyse '
-          'queries issued by your instance in the development environment.',
-          'group': 'main', 'level': 2,
-          }),
-        ('anonymous-user',
-         {'type' : 'string',
-          'default': None,
-          'help': 'login of the CubicWeb user account to use for anonymous user '
-          '(if you want to allow anonymous). This option will be ignored if '
-          'use-google-auth option is set (in which case you should control '
-          'anonymous access using the app.yaml file)',
-          'group': 'main', 'level': 1,
-          }),
-
-        ) + WebConfiguration.options + ServerConfiguration.options)
-    options = [(optname, optdict) for optname, optdict in options
-               if not optname in UNSUPPORTED_OPTIONS]
-
-    cubicweb_appobject_path = WebConfiguration.cubicweb_appobject_path | ServerConfiguration.cubicweb_appobject_path
-    cubicweb_appobject_path = list(cubicweb_appobject_path) + ['goa/appobjects']
-    cube_appobject_path = WebConfiguration.cube_appobject_path | ServerConfiguration.cube_appobject_path
-
-    # use file system schema
-    read_instance_schema = False
-    # schema is not persistent, don't load schema hooks (unavailable)
-    schema_hooks = False
-    # no user workflow for now
-    consider_user_state = False
-
-    # 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'
-        self._apphome = apphome
-        self._base_url = None
-        CubicWebConfiguration.__init__(self, appid)
-
-    def __getitem__(self, key):
-        if key == 'connections-pool-size':
-            return 4 # > 1 to allow multiple user sessions in tests
-        if key == 'base-url':
-            return self._base_url
-        return super(GAEConfiguration, self).__getitem__(key)
-
-    # overriden from cubicweb base configuration
-
-    @property
-    def apphome(self):
-        return self._apphome
-
-    def cubes(self):
-        """return the list of top level cubes used by this instance (eg
-        without dependencies)
-        """
-        if self._cubes is None:
-            cubes = self['included-cubes'] + self['included-yams-cubes']
-            cubes = self.expand_cubes(cubes)
-            return self.reorder_cubes(cubes)
-        return self._cubes
-
-    def vc_config(self):
-        """return CubicWeb's engine and instance's cube versions number"""
-        return {}
-
-    # overriden from cubicweb web configuration
-
-    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
-        except AttributeError:
-            self._schema = load_schema(self, schemaclasses, extrahook)
-            return self._schema
-
-    # 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	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,252 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""cubicweb on appengine plugins for cubicweb-ctl"""
-
-__docformat__ = "restructuredtext en"
-
-from os.path import exists, join, split, basename, normpath, abspath
-
-from cubicweb import CW_SOFTWARE_ROOT, BadCommandUsage
-from cubicweb.cwctl import CWCTL
-from cubicweb.toolsutils import (Command, copy_skeleton, create_symlink,
-                                 create_dir)
-from cubicweb.cwconfig import CubicWebConfiguration
-
-
-def slink_directories():
-    import rql, yams, yapps, docutils, roman
-    try:
-        import json as simplejson
-    except ImportError:
-        import simplejson
-    from logilab import common as lgc
-    from logilab import constraint as lgcstr
-    from logilab import mtconverter as lgmtc
-    dirs = [
-        (lgc.__path__[0], 'logilab/common'),
-        (lgmtc.__path__[0], 'logilab/mtconverter'),
-        (lgcstr.__path__[0], 'logilab/constraint'),
-        (rql.__path__[0], 'rql'),
-        (simplejson.__path__[0], 'simplejson'),
-        (yams.__path__[0], 'yams'),
-        (yapps.__path__[0], 'yapps'),
-        (docutils.__path__[0], 'docutils'),
-        (roman.__file__.replace('.pyc', '.py'), 'roman.py'),
-
-        ('/usr/share/fckeditor/', 'fckeditor'),
-
-        (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'),
-        (join(CW_SOFTWARE_ROOT, 'goa', 'bin'), 'bin'),
-        ]
-
-    try:
-        import dateutil
-        import vobject
-        dirs.extend([ (dateutil.__path__[0], 'dateutil'),
-                      (vobject.__path__[0], 'vobject') ] )
-    except ImportError:
-        pass
-    return dirs
-
-COPY_CW_FILES = (
-    '__init__.py',
-    '__pkginfo__.py',
-    '_exceptions.py',
-    'appobject.py',
-    'dbapi.py',
-    'cwvreg.py',
-    'cwconfig.py',
-    'entity.py',
-    'interfaces.py',
-    'i18n.py',
-    'mail.py',
-    'migration.py',
-    'mixins.py',
-    'mttransforms.py',
-    'rqlrewrite.py',
-    'rset.py',
-    'schema.py',
-    'schemaviewer.py',
-    'selectors.py',
-    'uilib.py',
-    'utils.py',
-    'vregistry.py',
-    'view.py',
-
-    'ext/html4zope.py',
-    'ext/rest.py',
-
-    'server/hookhelper.py',
-    'server/hooksmanager.py',
-    'server/hooks.py',
-    'server/migractions.py',
-    'server/pool.py',
-    'server/querier.py',
-    'server/repository.py',
-    'server/securityhooks.py',
-    'server/session.py',
-    'server/serverconfig.py',
-    'server/ssplanner.py',
-    'server/utils.py',
-    'server/sources/__init__.py',
-
-    'entities/__init__.py',
-    'entities/authobjs.py',
-    'entities/lib.py',
-    'entities/schemaobjs.py',
-    'entities/wfobjs.py',
-
-    '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',
-    'web/application.py',
-    'web/box.py',
-    'web/component.py',
-    'web/controller.py',
-    'web/form.py',
-    'web/htmlwidgets.py',
-    'web/httpcache.py',
-    'web/request.py',
-    'web/webconfig.py',
-
-    'web/views/__init__.py',
-    'web/views/actions.py',
-    'web/views/basecomponents.py',
-    'web/views/basecontrollers.py',
-    'web/views/baseforms.py',
-    'web/views/basetemplates.py',
-    'web/views/baseviews.py',
-    'web/views/boxes.py',
-    'web/views/calendar.py',
-    'web/views/error.py',
-    'web/views/editcontroller.py',
-    'web/views/ibreadcrumbs.py',
-    'web/views/idownloadable.py',
-    'web/views/magicsearch.py',
-    'web/views/management.py',
-    'web/views/navigation.py',
-    'web/views/startup.py',
-    'web/views/vcard.py',
-    'web/views/wdoc.py',
-    'web/views/urlpublishing.py',
-    'web/views/urlrewrite.py',
-    'web/views/xbel.py',
-
-    'wsgi/__init__.py',
-    'wsgi/handler.py',
-    'wsgi/request.py',
-
-    'goa/__init__.py',
-    'goa/db.py',
-    'goa/dbinit.py',
-    'goa/dbmyams.py',
-    'goa/goaconfig.py',
-    'goa/goavreg.py',
-    'goa/gaesource.py',
-    'goa/rqlinterpreter.py',
-    'goa/appobjects/__init__.py',
-    'goa/appobjects/components.py',
-    'goa/appobjects/dbmgmt.py',
-    'goa/appobjects/gauthservice.py',
-    'goa/appobjects/sessions.py',
-
-    'schemas/bootstrap.py',
-    'schemas/base.py',
-    )
-
-OVERRIDEN_FILES = (
-    ('toolsutils.py', 'toolsutils.py'),
-    ('mttransforms.py', 'mttransforms.py'),
-    ('server__init__.py', 'server/__init__.py'),
-    ('rqlannotation.py', 'server/rqlannotation.py'),
-    )
-
-
-def create_init_file(pkgdir, pkgname):
-    open(join(pkgdir, '__init__.py'), 'w').write('"""%s pkg"""' % pkgname)
-
-
-class NewGoogleAppCommand(Command):
-    """Create a new google appengine instance.
-
-    <instance directory>
-      the path to the appengine instance directory
-    """
-    name = 'newgapp'
-    arguments = '<instance directory>'
-
-    def run(self, args):
-        if len(args) != 1:
-            raise BadCommandUsage("exactly one argument is expected")
-        appldir, = args
-        appldir = normpath(abspath(appldir))
-        appid = basename(appldir)
-        context = {'appname': appid}
-        # goa instance'skeleton
-        copy_skeleton(join(CW_SOFTWARE_ROOT, 'goa', 'skel'),
-                      appldir, context, askconfirm=True)
-        # cubicweb core dependencies
-        for directory, subdirectory in slink_directories():
-            subdirectory = join(appldir, subdirectory)
-            if not exists(split(subdirectory)[0]):
-                create_dir(split(subdirectory)[0])
-            create_symlink(directory, join(appldir, subdirectory))
-        create_init_file(join(appldir, 'logilab'), 'logilab')
-        # copy supported part of cubicweb
-        create_dir(join(appldir, 'cubicweb'))
-        for fpath in COPY_CW_FILES:
-            target = join(appldir, 'cubicweb', fpath)
-            if not exists(split(target)[0]):
-                create_dir(split(target)[0])
-            create_symlink(join(CW_SOFTWARE_ROOT, fpath), target)
-        # overriden files
-        for fpath, subfpath in OVERRIDEN_FILES:
-            create_symlink(join(CW_SOFTWARE_ROOT, 'goa', 'overrides', fpath),
-                           join(appldir, 'cubicweb', subfpath))
-        # link every supported components
-        packagesdir = join(appldir, 'cubes')
-        create_init_file(join(appldir, 'cubes'), 'cubes')
-        for include in ('addressbook','basket', 'blog','folder',
-                        'tag', 'comment', 'file', 'link',
-                        'mailinglist', 'person', 'task', 'zone',
-                        ):
-            create_symlink(CubicWebConfiguration.cube_dir(include),
-                           join(packagesdir, include))
-        # generate sample config
-        from cubicweb.goa.goaconfig import GAEConfiguration
-        from cubicweb.migration import MigrationHelper
-        config = GAEConfiguration(appid, appldir)
-        if exists(config.main_config_file()):
-            mih = MigrationHelper(config)
-            mih.rewrite_configuration()
-        else:
-            config.save()
-
-
-CWCTL.register(NewGoogleAppCommand)
--- a/goa/goavreg.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""goa specific registry
-
-"""
-__docformat__ = "restructuredtext en"
-
-from os import listdir
-from os.path import join, isdir
-
-from cubicweb import CW_SOFTWARE_ROOT
-from cubicweb.cwvreg import CubicWebVRegistry
-
-
-def _pkg_name(cube, module):
-    if cube is None:
-        return module
-    return 'cubes.%s.%s' % (cube, module)
-
-class GAEVRegistry(CubicWebVRegistry):
-
-    def set_schema(self, schema):
-        """disable reload hooks of cubicweb registry set_schema method"""
-        self.schema = schema
-
-    def load(self, applroot):
-        from cubicweb.goa import db
-        self.load_module(db) # AnyEntity class
-        # explicit loading, we don't want to load __init__.py
-        self.load_directory(join(CW_SOFTWARE_ROOT, 'entities'),
-                            'cubicweb.entities', skip=('__init__.py',))
-        self.load_directory(join(CW_SOFTWARE_ROOT, 'web', 'views'),
-                            'cubicweb.web.views')
-        self.load_directory(join(CW_SOFTWARE_ROOT, 'goa', 'appobjects'),
-                            'cubicweb.goa.appobjects')
-        for cube in reversed(self.config.cubes()):
-            self.load_cube(cube)
-        self.load_instance(applroot)
-
-    def load_directory(self, directory, cube, skip=()):
-        for filename in listdir(directory):
-            if filename[-3:] == '.py' and not filename in skip:
-                self._import('%s.%s' % (cube, filename[:-3]))
-
-    def load_cube(self, cube):
-        self._auto_load(self.config.cube_dir(cube),
-                        cube in self.config['included-cubes'],
-                        cube)
-
-    def load_instance(self, applroot):
-        self._auto_load(applroot, self.config['schema-type'] == 'dbmodel')
-
-    def _import(self, modname):
-        obj = __import__(modname)
-        for attr in modname.split('.')[1:]:
-            obj = getattr(obj, attr)
-        self.load_module(obj)
-
-    def _auto_load(self, path, loadschema, cube=None):
-        vobjpath = self.config.cube_appobject_path
-        for filename in listdir(path):
-            if filename[-3:] == '.py' and filename[:-3] in vobjpath:
-                self._import(_pkg_name(cube, filename[:-3]))
-            else:
-                abspath = join(path, filename)
-                if isdir(abspath) and filename in vobjpath:
-                    self.load_directory(abspath, _pkg_name(cube, filename))
-        if loadschema:
-            # 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/__init__.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# server.__init__
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
--- a/goa/overrides/mttransforms.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""mime type transformation engine for cubicweb, based on mtconverter
-
-"""
-__docformat__ = "restructuredtext en"
-
-from logilab import mtconverter
-
-from logilab.mtconverter.engine import TransformEngine
-from logilab.mtconverter.transform import Transform
-from cubicweb.uilib import rest_publish, html_publish, remove_html_tags
-
-HTML_MIMETYPES = ('text/html', 'text/xhtml', 'application/xhtml+xml')
-# CubicWeb specific transformations
-
-class rest_to_html(Transform):
-    inputs = ('text/rest', 'text/x-rst')
-    output = 'text/html'
-    def _convert(self, trdata):
-        return rest_publish(trdata.appobject, trdata.decode())
-
-class html_to_html(Transform):
-    inputs = HTML_MIMETYPES
-    output = 'text/html'
-    def _convert(self, trdata):
-        return html_publish(trdata.appobject, trdata.data)
-
-
-# Instantiate and configure the transformation engine
-
-mtconverter.UNICODE_POLICY = 'replace'
-
-ENGINE = TransformEngine()
-ENGINE.add_transform(rest_to_html())
-ENGINE.add_transform(html_to_html())
-
-HAS_PIL_TRANSFORMS = False
-HAS_PYGMENTS_TRANSFORMS = False
-
-class html_to_text(Transform):
-    inputs = HTML_MIMETYPES
-    output = 'text/plain'
-    def _convert(self, trdata):
-        return remove_html_tags(trdata.data)
-ENGINE.add_transform(html_to_text())
--- a/goa/overrides/rqlannotation.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-"""
-__docformat__ = "restructuredtext en"
-
-def set_qdata(getrschema, union, noinvariant):
-    pass
-
-class SQLGenAnnotator(object):
-    def __init__(self, schema):
-        self.schema = schema
-        self.nfdomain = frozenset(eschema.type for eschema in schema.entities()
-                                  if not eschema.final)
-    def annotate(self, rqlst):
-        rqlst.has_text_query = False
-        rqlst.need_distinct = False
-
-
--- a/goa/overrides/server__init__.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-# server debugging flag
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-DEBUG = False
-
-# sqlite'stored procedures have to be registered at connexion opening time
-SQL_CONNECT_HOOKS = {}
-
-# add to this set relations which should have their add security checking done
-# *BEFORE* adding the actual relation (done after by default)
-BEFORE_ADD_RELATIONS = set(('owned_by',))
-
-# add to this set relations which should have their add security checking done
-# *at COMMIT TIME* (done after by default)
-ON_COMMIT_ADD_RELATIONS = set(())
-
-# available sources registry
-SOURCE_TYPES = {}
--- a/goa/overrides/server_utils.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-
-class RepoThread(object):
-    def __init__(self, *args):
-        pass # XXX raise
-    def start(self):
-        pass
-    def join(self):
-        pass
-
-class LoopTask(RepoThread):
-    def cancel(self):
-        pass
--- a/goa/overrides/toolsutils.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-import sys
-from cubicweb import warning
-
-def lines(path, comments=None):
-    result = []
-    for line in open(path, 'U'):
-        line = line.strip()
-        if line and (comments is None or not line.startswith(comments)):
-            result.append(line)
-    return result
-
-def read_config(config_file):
-    """read the instance configuration from a file and return it as a
-    dictionnary
-
-    :type config_file: str
-    :param config_file: path to the configuration file
-
-    :rtype: dict
-    :return: a dictionary with specified values associated to option names
-    """
-    config = current = {}
-    try:
-        for line in lines(config_file, comments='#'):
-            try:
-                option, value = line.split('=', 1)
-            except ValueError:
-                option = line.strip().lower()
-                if option[0] == '[':
-                    # start a section
-                    section = option[1:-1]
-                    assert not config.has_key(section), \
-                           'Section %s is defined more than once' % section
-                    config[section] = current = {}
-                    continue
-                print >> sys.stderr, 'ignoring malformed line\n%r' % line
-                continue
-            option = option.strip().replace(' ', '_')
-            value = value.strip()
-            current[option] = value or None
-    except IOError, ex:
-        warning('missing or non readable configuration file %s (%s)',
-                config_file, ex)
-    return config
-
-def env_path(env_var, default, name):
-    return default
-
-def create_dir(*args):
-    raise RuntimeError()
--- a/goa/rqlinterpreter.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,684 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""provide a minimal RQL support for google appengine dbmodel
-
-"""
-__docformat__ = "restructuredtext en"
-
-from datetime import datetime
-
-from rql import RQLHelper, nodes
-
-from cubicweb import Binary
-from cubicweb.rset import ResultSet
-from cubicweb.server import SQL_CONNECT_HOOKS
-
-from google.appengine.api.datastore import Key, Get, Query, Entity
-from google.appengine.api.datastore_types import Text, Blob
-from google.appengine.api.datastore_errors import EntityNotFoundError, BadKeyError
-
-
-def etype_from_key(key):
-    return Key(key).kind()
-
-def poss_var_types(myvar, ovar, kind, solutions):
-    return frozenset(etypes[myvar] for etypes in solutions
-                     if etypes[ovar] == kind)
-
-def expand_result(results, result, myvar, values, dsget=None):
-    values = map(dsget, values)
-    if values:
-        result[myvar] = values.pop(0)
-        for value in values:
-            newresult = result.copy()
-            newresult[myvar] = value
-            results.append(newresult)
-    else:
-        results.remove(result)
-
-def _resolve(restrictions, solutions, fixed):
-    varname = restrictions[0].searched_var
-    objs = []
-    for etype in frozenset(etypes[varname] for etypes in solutions):
-        gqlargs = {}
-        query = Query(etype)
-        for restriction in restrictions:
-            restriction.fill_query(fixed, query)
-        pobjs = query.Run()
-        if varname in fixed:
-            value = fixed[varname]
-            objs += (x for x in pobjs if x == value)
-        else:
-            objs += pobjs
-    if varname in fixed and not objs:
-        raise EidMismatch(varname, value)
-    return objs
-
-def _resolve_not(restrictions, solutions, fixed):
-    restr = restrictions[0]
-    constrvarname = restr.constraint_var
-    if len(restrictions) > 1 or not constrvarname in fixed:
-        raise NotImplementedError()
-    varname = restr.searched_var
-    objs = []
-    for etype in frozenset(etypes[varname] for etypes in solutions):
-        gqlargs = {}
-        for operator in ('<', '>'):
-            query = Query(etype)
-            restr.fill_query(fixed, query, operator)
-            objs += query.Run()
-    return objs
-
-def _print_results(rlist):
-    return '[%s]' % ', '.join(_print_result(r) for r in rlist)
-
-def _print_result(rdict):
-    string = []
-    for k, v in rdict.iteritems():
-        if isinstance(v, Entity):
-            string.append('%s: %s' % (k, v.key()))#_print_result(v)))
-        elif isinstance(v, list):
-            string.append('%s: [%s]' % (k, ', '.join(str(i) for i in v)))
-        else:
-            string.append('%s: %s' % (k, v))
-    return '{%s}' % ', '.join(string)
-
-
-class EidMismatch(Exception):
-    def __init__(self, varname, value):
-        self.varname = varname
-        self.value = value
-
-
-class Restriction(object):
-    supported_operators = ('=',)
-    def __init__(self, rel):
-        operator = rel.children[1].operator
-        if not operator in self.supported_operators:
-            raise NotImplementedError('unsupported operator')
-        self.rel = rel
-        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(),)
-        value = entity.get(dsprefix + self.rtype)
-        if value is None:
-            return []
-        if not isinstance(value, list):
-            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
-        rtype = self.rtype
-        if self.schema.rschema(rtype).final:
-            # should be detected by rql.stcheck: "Any C WHERE NOT X attr C" doesn't make sense
-            #if self._not:
-            #    raise NotImplementedError()
-            for result in results:
-                result[myvar] = result[ovar].get('s_'+rtype)
-        elif self.var.name in results[0]:
-            if self.rhs.name in results[0]:
-                self.filter(solutions, results)
-            else:
-                if self._not:
-                    raise NotImplementedError()
-                for result in results[:]:
-                    values = self._possible_values(myvar, ovar, result[ovar],
-                                                   solutions, 's_')
-                    expand_result(results, result, myvar, values, self._dsget)
-        else:
-            assert self.rhs.name in results[0]
-            self.object_complete_and_filter(solutions, results)
-
-    def filter(self, solutions, results):
-        myvar = self.rhs.name
-        ovar = self.var.name
-        newsols = {}
-        for result in results[:]:
-            entity = result[ovar]
-            key = entity.key()
-            if not key in newsols:
-                values = self._possible_values(myvar, ovar, entity, solutions, 's_')
-                newsols[key] = frozenset(v for v in values)
-            if self._not:
-                if result[myvar].key() in newsols[key]:
-                    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()
-        myvar = self.var.name
-        ovar = self.rhs.name
-        for result in results[:]:
-            values = self._possible_values(myvar, ovar, result[ovar],
-                                           solutions, 'o_')
-            expand_result(results, result, myvar, values, self._dsget)
-
-
-class EidRestriction(Restriction):
-    def __init__(self, rel, dsget):
-        Restriction.__init__(self, rel)
-        self._dsget = dsget
-
-    def resolve(self, kwargs):
-        value = self.rel.children[1].children[0].eval(kwargs)
-        return self._dsget(value)
-
-
-class RelationRestriction(VariableSelection):
-
-    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)
-
-    def resolve(self, solutions, fixed):
-        if self.rtype == 'identity':
-            if self._not:
-                raise NotImplementedError()
-            return [fixed[self.constraint_var]]
-        if self._not:
-            return _resolve_not([self], solutions, fixed)
-        return _resolve([self], solutions, fixed)
-
-
-class NotRelationRestriction(RelationRestriction):
-
-    def _get_value(self, fixed):
-        return None
-
-    def resolve(self, solutions, fixed):
-        if self.rtype == 'identity':
-            raise NotImplementedError()
-        return _resolve([self], solutions, fixed)
-
-
-class AttributeRestriction(RelationRestriction):
-    supported_operators = ('=', '>', '>=', '<', '<=', 'ILIKE')
-    def __init__(self, rel, kwargs):
-        RelationRestriction.__init__(self, rel, None)
-        value = self.rhs.eval(kwargs)
-        self.value = value
-        if self.operator == 'ILIKE':
-            if value.startswith('%'):
-                raise NotImplementedError('LIKE is only supported for prefix search')
-            if not value.endswith('%'):
-                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
-        myvar, rtype, value = self.var.name, self.rtype, self.value
-        for result in results[:]:
-            if result[myvar].get('s_'+rtype) == value:
-                results.remove(result)
-
-    def _get_value(self, fixed):
-        return self.value
-
-
-class DateAttributeRestriction(AttributeRestriction):
-    """just a thin layer on top af `AttributeRestriction` that
-    tries to convert date strings such as in :
-    Any X WHERE X creation_date >= '2008-03-04'
-    """
-    def __init__(self, rel, kwargs):
-        super(DateAttributeRestriction, self).__init__(rel, kwargs)
-        if isinstance(self.value, basestring):
-#             try:
-            self.value = datetime.strptime(self.value, '%Y-%m-%d')
-#             except Exception, exc:
-#                 from logging import error
-#                 error('unable to parse date %s with format %%Y-%%m-%%d (exc=%s)', value, exc)
-
-
-class AttributeInRestriction(AttributeRestriction):
-    def __init__(self, rel, kwargs):
-        RelationRestriction.__init__(self, rel, None)
-        values = []
-        for c in self.rel.children[1].iget_nodes(nodes.Constant):
-            values.append(c.eval(kwargs))
-        self.value = values
-
-    @property
-    def operator(self):
-        return 'in'
-
-
-class TypeRestriction(AttributeRestriction):
-    def __init__(self, var):
-        self.var = var
-
-    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):
-            objs += Query(etype).Run()
-        return objs
-
-
-def append_result(res, descr, i, j, value, etype):
-    if value is not None:
-        if isinstance(value, Text):
-            value = unicode(value)
-        elif isinstance(value, Blob):
-            value = Binary(str(value))
-    if j == 0:
-        res.append([value])
-        descr.append([etype])
-    else:
-        res[i].append(value)
-        descr[i].append(etype)
-
-
-class ValueResolver(object):
-    def __init__(self, functions, args, term):
-        self.functions = functions
-        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)
-        """
-        return self.term.accept(self, result)
-
-    def visit_function(self, node, result):
-        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:
-            etype = value.kind()
-            value = str(value.key())
-        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
-       of a relation. Different restriction types are:
-       * EidRestriction
-       * AttributeRestriction
-       * RelationRestriction
-       * VariableSelection (not really a restriction)
-       -> dictionary {<variable>: [restriction...], ...}
-    2. resolve eid restrictions
-    3. for each select in union:
-           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
-    """
-    def __init__(self, schema):
-        self.schema = schema
-        Restriction.schema = schema # yalta!
-        self.rqlhelper = RQLHelper(schema, {'eid': etype_from_key})
-        self._stored_proc = {'LOWER': lambda x: x.lower(),
-                             '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:
-            self.rqlhelper.compute_solutions(rqlst, kwargs=parameters)
-        except BadKeyError:
-            results, description = [], []
-        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
-        else:
-            self._dsget = dsget
-        try:
-            return node.accept(self, kwargs)
-        except NotImplementedError:
-            self.critical('support for query not implemented: %s', node)
-            raise
-
-    def visit_union(self, node, kwargs):
-        results, description = [], []
-        extra = {'kwargs': kwargs}
-        for child in node.children:
-            pres, pdescr = self.visit_select(child, extra)
-            results += pres
-            description += pdescr
-        return results, description
-
-    def visit_select(self, node, extra):
-        constraints = {}
-        if node.where is not None:
-            node.where.accept(self, constraints, extra)
-        fixed, toresolve, postresolve, postfilters = {}, {}, {}, []
-        # extract NOT filters
-        for vname, restrictions in constraints.items():
-            for restr in restrictions[:]:
-                if isinstance(restr, AttributeRestriction) and restr._not:
-                    postfilters.append(restr)
-                    restrictions.remove(restr)
-                    if not restrictions:
-                        del constraints[vname]
-        # add TypeRestriction for variable which have no restrictions at all
-        for varname, var in node.defined_vars.iteritems():
-            if not varname in constraints:
-                constraints[varname] = [TypeRestriction(var)]
-        #print node, constraints
-        # compute eid restrictions
-        kwargs = extra['kwargs']
-        for varname, restrictions in constraints.iteritems():
-            for restr in restrictions[:]:
-                if isinstance(restr, EidRestriction):
-                    assert not varname in fixed
-                    try:
-                        value = restr.resolve(kwargs)
-                        fixed[varname] = value
-                    except EntityNotFoundError:
-                        return [], []
-                    restrictions.remove(restr)
-        #print 'fixed', fixed.keys()
-        # combine remaining restrictions
-        for varname, restrictions in constraints.iteritems():
-            for restr in restrictions:
-                if isinstance(restr, AttributeRestriction):
-                    toresolve.setdefault(varname, []).append(restr)
-                elif isinstance(restr, NotRelationRestriction) or (
-                    isinstance(restr, RelationRestriction) and
-                    not restr.searched_var in fixed and restr.constraint_var in fixed):
-                    toresolve.setdefault(varname, []).append(restr)
-                else:
-                    postresolve.setdefault(varname, []).append(restr)
-            try:
-                if len(toresolve[varname]) > 1:
-                    toresolve[varname] = MultipleRestriction(toresolve[varname])
-                else:
-                    toresolve[varname] = toresolve[varname][0]
-            except KeyError:
-                pass
-        #print 'toresolve %s' % toresolve
-        #print 'postresolve %s' % postresolve
-        # resolve additional restrictions
-        if fixed:
-            partres = [fixed.copy()]
-        else:
-            partres = []
-        for varname, restr in toresolve.iteritems():
-            varpartres = partres[:]
-            try:
-                values = tuple(restr.resolve(node.solutions, fixed))
-            except EidMismatch, ex:
-                varname = ex.varname
-                value = ex.value
-                partres = [res for res in partres if res[varname] != value]
-                if partres:
-                    continue
-                # some join failed, no possible results
-                return [], []
-            if not values:
-                # some join failed, no possible results
-                return [], []
-            if not varpartres:
-                # init results
-                for value in values:
-                    partres.append({varname: value})
-            elif not varname in partres[0]:
-                # cartesian product
-                for res in partres:
-                    res[varname] = values[0]
-                for res in partres[:]:
-                    for value in values[1:]:
-                        res = res.copy()
-                        res[varname] = value
-                        partres.append(res)
-            else:
-                # union
-                for res in varpartres:
-                    for value in values:
-                        res = res.copy()
-                        res[varname] = value
-                        partres.append(res)
-        #print 'partres', len(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
-        restrictions = sorted((restr for restrictions in postresolve.itervalues()
-                               for restr in restrictions),
-                              key=lambda x: not isinstance(x, RelationRestriction))
-        # compute stuff not doable in the previous step using datastore queries
-        for restr in restrictions + postfilters:
-            restr.complete_and_filter(node.solutions, partres)
-            if not partres:
-                # some join failed, no possible results
-                return [], []
-        if extra.pop('has_exists', False):
-            # remove potential duplicates introduced by exists
-            toremovevars = [v.name for v in node.defined_vars.itervalues()
-                            if not v.scope is node]
-            if toremovevars:
-                newpartres = []
-                for result in partres:
-                    for var in toremovevars:
-                        del result[var]
-                    if not result in newpartres:
-                        newpartres.append(result)
-                if not newpartres:
-                    # some join failed, no possible results
-                    return [], []
-                partres = newpartres
-        if node.orderby:
-            for sortterm in reversed(node.orderby):
-                resolver = ValueResolver(self._stored_proc, kwargs, sortterm.term)
-                partres.sort(reverse=not sortterm.asc,
-                             key=lambda x: resolver.compute(x)[1])
-        if partres:
-            if node.offset:
-                partres = partres[node.offset:]
-            if node.limit:
-                partres = partres[:node.limit]
-            if not partres:
-                return [], []
-        #print 'completed partres', _print_results(partres)
-        # compute results
-        res, descr = [], []
-        for j, term in enumerate(node.selection):
-            resolver = ValueResolver(self._stored_proc, kwargs, term)
-            if not partres:
-                etype, value = resolver.compute({})
-                # only constant selected
-                if not res:
-                    res.append([])
-                    descr.append([])
-                    res[0].append(value)
-                    descr[0].append(etype)
-            else:
-                for i, sol in enumerate(partres):
-                    etype, value = resolver.compute(sol)
-                    append_result(res, descr, i, j, value, etype)
-        #print '--------->', res
-        return res, descr
-
-    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)
-        try:
-            extra.pop(node)
-        except KeyError:
-            raise NotImplementedError()
-
-    def visit_relation(self, node, constraints, extra):
-        if node.is_types_restriction():
-            return
-        rschema = self.schema.rschema(node.r_type)
-        neged = node.neged(strict=True)
-        if neged:
-            # ok, we *may* process this Not node (not implemented error will be
-            # raised later if we can't)
-            extra[node.parent] = True
-        if rschema.final:
-            self._visit_final_relation(rschema, node, constraints, extra)
-        elif neged:
-            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')):
-            #if not_:
-            nbrels = len(v2.variable.stinfo['relations'])
-            #else:
-            #    nbrels = len(v2.variable.stinfo['relations']) - len(v2.variable.stinfo['uidrels'])
-            if nbrels > 1:
-                constraints.setdefault(v1.name, []).append(
-                    RelationRestriction(node, self._dsget, prefix))
-                # 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')):
-            stinfo = v2.variable.stinfo
-            if not stinfo['selected'] and len(stinfo['relations']) == 1:
-                constraints.setdefault(v1.name, []).append(
-                    NotRelationRestriction(node, self._dsget, prefix))
-                constraints.setdefault(v2.name, [])
-                break
-        else:
-            self._visit_non_final_relation(rschema, node, constraints, True)
-
-    def _visit_final_relation(self, rschema, node, constraints, extra):
-        varname = node.children[0].name
-        if rschema.type == 'eid':
-            constraints.setdefault(varname, []).append(
-                EidRestriction(node, self._dsget))
-        else:
-            rhs = node.children[1].children[0]
-            if isinstance(rhs, nodes.VariableRef):
-                constraints.setdefault(rhs.name, []).append(
-                    VariableSelection(node, self._dsget))
-            elif isinstance(rhs, nodes.Constant):
-                if rschema.objects()[0] in ('Datetime', 'Date'): # XXX
-                    constraints.setdefault(varname, []).append(
-                        DateAttributeRestriction(node, extra['kwargs']))
-                else:
-                    constraints.setdefault(varname, []).append(
-                        AttributeRestriction(node, extra['kwargs']))
-            elif isinstance(rhs, nodes.Function) and rhs.name == 'IN':
-                constraints.setdefault(varname, []).append(
-                    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
-set_log_methods(RQLInterpreter, getLogger('cubicweb.goa.rqlinterpreter'))
-set_log_methods(Restriction, getLogger('cubicweb.goa.rqlinterpreter'))
--- a/goa/skel/app.yaml.tmpl	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-application: %(appname)s
-version: 0-1
-runtime: python
-api_version: 1
-
-handlers:
-- url: /admin/.*
-  script: $PYTHON_LIB/google/appengine/ext/admin
-  login: admin
-- url: /data
-  static_dir: cubes/shared/data
-- url: /fckeditor
-  static_dir: fckeditor
-- url: /_load
-  script: loader.py
-  login: admin
-- url: .*
-  script: main.py
-  # comment the line below to allow anonymous access or if you don't want to use
-  # google authentication service
-  login: required
-
-skip_files: |
- ^(.*/)?(
- (app\.yaml)|
- (app\.yml)|
- (index\.yaml)|
- (index\.yml)|
- (#.*#)|
- (.*~)|
- (.*\.py[co])|
- (.*\.xcf)|
- (.*\.asp)|
- (.*\.aspx)|
- (.*\.cfm)|
- (.*\.po)|
- (.*/RCS/.*)|
- (\..*)|
- (.*ChangeLog)|
- (.*README)|
- (.*TODO)|
- (.*DEPENDS)|
- (.*MANIFEST)|
- (.*MANIFEST.in)|
- (.*setup\.py)|
- (.*,cover)|
- (.*\.orig)|
- (.*/test/.*)|
- (.*/tests/.*)|
- (.*/bin/.*)|
- (.*/build/.*)|
- (.*/debian/.*)|
- (.*/doc/.*)|
- (.*/skins/office2003/.*)|
- (.*/editor/skins/silver/.*)|
- (.*/editor/filemanager/.*)|
- (.*/editor/plugins/.*)|
- (.*/editor/images/smiley/.*)|
- (.*/editor/.*spellerpages.*)|
- (.*/docutils/writers/s5_html/.*)|
- (.*/docutils/writers/latex2e/.*)|
- (.*/docutils/writers/newlatex2e/.*)|
- (.*/docutils/writers/pep_html/.*)|
- (bin/.*)|
- (tools/.*)|
- (cubicweb.*/data/.*\.js)|
- (cubicweb.*/data/.*\.css)|
- (cubicweb.*/data/.*\.png)|
- (cubicweb.*/data/.*\.gif)|
- (cubicweb.*/data/.*\.gif)|
- )$
-
--- a/goa/skel/custom.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-def postinit(vreg):
-    """this callback is called at the end of initialization process
-    and can be used to load explicit modules (views or entities).
-
-    For instance :
-    import someviews
-    vreg.load_module(someviws)
-    """
-    # from migration import migrate
-    # migrate(vreg)
--- a/goa/skel/cw-cubes/README.txt	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-This directory is where you should put your lax components.
-
-For your application to actually use a component, you also 
-have to modify the ``INCLUDED_COMPONENTS`` variable in 
-the ``custom.py`` module.
-
-
--- a/goa/skel/i18n/en.po	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-# LAX application po file
-
-msgid ""
-msgstr ""
-"Project-Id-Version: erudi 2.48.2\n"
-"PO-Revision-Date: 2008-03-28 18:14+0100\n"
-"Last-Translator: Logilab Team <contact@logilab.fr>\n"
-"Language-Team: fr <contact@logilab.fr>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: ginco-devtools\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
--- a/goa/skel/i18n/fr.po	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-# LAX application po file
-
-msgid ""
-msgstr ""
-"Project-Id-Version: erudi 2.48.2\n"
-"PO-Revision-Date: 2008-03-28 18:14+0100\n"
-"Last-Translator: Logilab Team <contact@logilab.fr>\n"
-"Language-Team: fr <contact@logilab.fr>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: ginco-devtools\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-
--- a/goa/skel/loader.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-if __name__ == '__main__':
-
-    from os.path import dirname, abspath
-    from cubicweb import goa
-    from cubicweb.goa.goaconfig import GAEConfiguration
-    from cubicweb.goa.dbinit import create_user, create_groups
-
-    # compute instance's root directory
-    APPLROOT = dirname(abspath(__file__))
-    # apply monkey patches first
-    goa.do_monkey_patch()
-    # get instance's configuration (will be loaded from app.conf file)
-    GAEConfiguration.uiprops['JAVASCRIPTS'].append('DATADIR/goa.js')
-    config = GAEConfiguration('toto', APPLROOT)
-    # create default groups
-    create_groups()
-    if not config['use-google-auth']:
-        # create default admin
-        create_user('admin', 'admin', ('managers', 'users'))
-        # create anonymous user if specified
-        anonlogin = config['anonymous-user']
-        if anonlogin:
-            create_user(anonlogin, config['anonymous-password'], ('guests',))
-    print 'content initialized'
--- a/goa/skel/main.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""module defining the root handler for a lax instance. You should not have
-to change anything here.
-
-"""
-__docformat__ = "restructuredtext en"
-
-# compute instance's root directory
-from os.path import dirname, abspath
-APPLROOT = dirname(abspath(__file__))
-
-# apply monkey patches first
-from cubicweb import goa
-goa.do_monkey_patch()
-
-# get instance's configuration (will be loaded from app.conf file)
-from cubicweb.goa.goaconfig import GAEConfiguration
-GAEConfiguration.uiprops['JAVASCRIPTS'].append('DATADIR/goa.js')
-config = GAEConfiguration('toto', APPLROOT)
-
-# dynamic objects registry
-from cubicweb.goa.goavreg import GAEVregistry
-vreg = GAEVregistry(config, debug=goa.MODE == 'dev')
-
-# trigger automatic classes registration (metaclass magic), should be done
-# before schema loading
-import custom
-
-# load instance'schema
-vreg.schema = config.load_schema()
-
-# load dynamic objects
-vreg.load(APPLROOT)
-
-# call the postinit so custom get a chance to do instance specific stuff
-custom.postinit(vreg)
-
-from cubicweb.wsgi.handler import CubicWebWSGIApplication
-application = CubicWebWSGIApplication(config, vreg=vreg)
-
-# main function so this handler module is cached
-def main():
-    from wsgiref.handlers import CGIHandler
-    CGIHandler().run(application)
-
-if __name__ == "__main__":
-    main()
--- a/goa/skel/schema.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-
-class Blog(EntityType):
-    title = String(maxsize=50, required=True)
-    description = String()
-
-class BlogEntry(EntityType):
-    title = String(maxsize=100, required=True)
-    publish_date = Date(default='TODAY')
-    text = RichString(fulltextindexed=True)
-    category = String(vocabulary=('important','business'))
-    entry_of = SubjectRelation('Blog', cardinality='?*')
--- a/goa/skel/views.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-# custom application views
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-from datetime import date
-
-from logilab.common.date import last_day
-
-from cubicweb.web.views import baseviews, boxes, calendar
-from cubicweb.web.htmlwidgets import BoxLink, BoxWidget
-
-_ = unicode
-
-
-class BlogEntryPrimaryView(baseviews.PrimaryView):
-    accepts = ('BlogEntry',)
-
-    def cell_call(self, row, col):
-        entity = self.rset.get_entity(row, col)
-        self.w(u'<h1>%s</h1>' % entity.dc_title())
-        entity.view('metadata', w=self.w)
-        self.w(entity.printable_value('text'))
-
-
-class BlogArchiveBox(boxes.BoxTemplate):
-    """side box usually displaying some related entities in a primary view"""
-    id = 'blog_archives_box'
-    title = _('blog archives')
-
-    def call(self, **kwargs):
-        """display a list of entities by calling their <item_vid> view
-        """
-        _ = self.req._
-        rset = self.req.execute('Any CD ORDERBY CD DESC WHERE B is Blog, B creation_date CD')
-        blogmonths = []
-        for (blogdate,) in rset:
-            year, month = blogdate.year, blogdate.month
-            if (year, month) not in blogmonths:
-                blogmonths.append( (year, month) )
-        box = BoxWidget(_('Blog archives'), id=self.id)
-        for year, month in blogmonths:
-            firstday = date(year, month, 1)
-            lastday = last_day(firstday)
-            rql = ('Any B WHERE B is BlogEntry, B creation_date >= "%s", B creation_date <= "%s"'
-                   % (firstday.strftime('%Y-%m-%d'), lastday.strftime('%Y-%m-%d')))
-            url = self.build_url(rql=rql)
-            label = u'%s %s' % (_(calendar.MONTHNAMES[month-1]), year)
-            box.append( BoxLink(url, label) )
-        box.render(self.w)
-
-
-
-
--- a/goa/test/data/__init__.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""zou
-
-"""
--- a/goa/test/data/schema.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-
-
-class YamsEntity(EntityType):
-    if 'Blog' in defined_types and 'Article' in defined_types:
-        ambiguous_relation = SubjectRelation(('Blog', 'Article'))
-    if 'Blog' in defined_types:
-        inlined_relation = SubjectRelation('Blog', cardinality='?*')
-
-class inlined_relation(RelationType):
-    inlined = True
-
--- a/goa/test/data/settings.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-TEMPLATE_DEBUG = False
--- a/goa/test/data/views.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-# -*- coding: utf-8 -*-
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-import os
-os.environ["DJANGO_SETTINGS_MODULE"] = 'data.settings'
-
-from django import template
-
-
-def encode_output(self, output):
-    # Check type so that we don't run str() on a Unicode object
-    if not isinstance(output, basestring):
-        return unicode(output)
-    return output
-
-template.VariableNode.encode_output = encode_output
-
-from cubicweb.view import StartupView
-
-INDEX_TEMPLATE = template.Template(u'''
- <h1>hellô {{ user.login }}</h1>
-''')
-
-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	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-# -*- coding: utf-8 -*-
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-from cubicweb.goa.testlib import *
-
-from cubicweb import Binary
-from cubicweb.goa.goaconfig import GAEConfiguration
-from cubicweb.server.utils import crypt_password
-
-from google.appengine.api.datastore_types import Text, Blob
-
-
-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):
-        eprop = self.add_entity('CWProperty', pkey=u'ui.language', value=u'en')
-        self.failUnless('s_for_user' in eprop._dbmodel)
-        self.assertEquals(eprop._dbmodel['s_for_user'], None)
-
-    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')
-
-    def test_password_encryption(self):
-        euser = self.add_entity('CWUser', login=u'toto', upassword='toto')
-        self.failUnless(euser.upassword != 'toto', euser.upassword)
-        self.assertEquals(crypt_password('toto', euser.upassword[:2]), euser.upassword)
-
-    def test_long_text(self):
-        # datastore string type is limited to 500 bytes
-        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.assertEquals(entity.description, text)
-
-    def test_long_accentued_text(self):
-        # datastore string type is limited to 500 bytes
-        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.assertEquals(entity.description, text)
-
-    def test_blob(self):
-        data = 'e'*501
-        entity = self.add_entity('Blog', data=data)
-        self.assertIsInstance(entity.data, Binary)
-        value = entity.data.getvalue()
-        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	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,430 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-from cubicweb.goa.testlib import *
-
-from urllib import unquote
-
-from cubicweb import ValidationError
-from cubicweb.uilib import rql_for_eid
-
-from cubicweb.web import INTERNAL_FIELD_VALUE, Redirect
-
-from cubicweb.goa.goaconfig import GAEConfiguration
-from cubicweb.entities.authobjs import CWUser
-
-
-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('controllers', 'edit', req=req, appli=self)
-
-    def publish(self, req):
-        assert req is self.ctrl.req
-        try:
-            result = self.ctrl.publish()
-            req.cnx.commit()
-        except Redirect:
-            req.cnx.commit()
-            raise
-        except:
-            req.cnx.rollback()
-            raise
-        return result
-
-    def expect_redirect_publish(self, req=None):
-        if req is not None:
-            self.ctrl = self.get_ctrl(req)
-        else:
-            req = self.req
-        try:
-            res = self.publish(req)
-        except Redirect, ex:
-            try:
-                path, params = ex.location.split('?', 1)
-            except:
-                path, params = ex.location, ""
-            req._url = path
-            cleanup = lambda p: (p[0], unquote(p[1]))
-            params = dict(cleanup(p.split('=', 1)) for p in params.split('&') if p)
-            return req.relative_path(False), params # path.rsplit('/', 1)[-1], params
-        else:
-            self.fail('expected a Redirect exception')
-
-    def test_noparam_edit(self):
-        """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"""
-        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'',
-                         }
-        self.assertRaises(ValidationError, self.publish, self.req)
-
-
-    def test_user_editing_itself(self):
-        """checking that a manager user can edit itself"""
-        self.skip('missing actual gae support, retry latter')
-        user = self.user
-        basegroups = [str(eid) for eid, in self.req.execute('CWGroup G WHERE X in_group G, X eid %(x)s', {'x': user.eid})]
-        groupeids = [eid for eid, in self.req.execute('CWGroup G WHERE G name in ("managers", "users")')]
-        groups = [str(eid) for eid in groupeids]
-        stateeid = [eid for eid, in self.req.execute('State S WHERE S name "activated"')][0]
-        self.req.form = {
-            'eid':       user.eid,
-            '__type:'+user.eid:    'CWUser',
-            'login:'+user.eid:     unicode(user.login),
-            'firstname:'+user.eid: u'Th\xe9nault',
-            'surname:'+user.eid:   u'Sylvain',
-            'in_group:'+user.eid:  groups,
-            'in_state:'+user.eid:  stateeid,
-            #
-            'edits-login:'+user.eid:     unicode(user.login),
-            'edits-firstname:'+user.eid: u'',
-            'edits-surname:'+user.eid:   u'',
-            'edits-in_group:'+user.eid:  basegroups,
-            'edits-in_state:'+user.eid:  stateeid,
-            }
-        path, params = self.expect_redirect_publish()
-        e = self.req.execute('Any X WHERE X eid %(x)s', {'x': user.eid}, 'x').get_entity(0, 0)
-        self.assertEquals(e.firstname, u'Th\xe9nault')
-        self.assertEquals(e.surname, u'Sylvain')
-        self.assertEquals(e.login, user.login)
-        self.assertEquals([g.eid for g in e.in_group], groupeids)
-        self.assertEquals(e.in_state[0].eid, stateeid)
-
-    def test_user_can_change_its_password(self):
-        user = self.create_user('user')
-        cnx = self.login('user')
-        req = self.request()
-        #self.assertEquals(self.ctrl.schema['CWUser']._groups['read'],
-        #                  ('managers', 'users'))
-        req.form = {
-            'eid': user.eid, '__type:'+user.eid: 'CWUser',
-            '__maineid' : str(user.eid),
-            'upassword:'+user.eid: 'tournicoton',
-            'upassword-confirm:'+user.eid: 'tournicoton',
-            'edits-upassword:'+user.eid:  '',
-            }
-        path, params = self.expect_redirect_publish(req)
-        cnx.commit() # commit to check we don't get late validation error for instance
-        self.assertEquals(path, 'euser/user')
-        self.failIf('vid' in params)
-
-    def test_user_editing_itself_no_relation(self):
-        """checking we can edit an entity without specifying some required
-        relations (meaning no changes)
-        """
-        user = self.user
-        groupeids = [eid for eid, in self.req.execute('CWGroup G WHERE X in_group G, X eid %(x)s', {'x': user.eid})]
-        self.req.form = {
-            'eid':       user.eid,
-            '__type:'+user.eid:    'CWUser',
-            'login:'+user.eid:     unicode(user.login),
-            'firstname:'+user.eid: u'Th\xe9nault',
-            'surname:'+user.eid:   u'Sylvain',
-            #
-            'edits-login:'+user.eid:     unicode(user.login),
-            'edits-firstname:'+user.eid: u'',
-            'edits-surname:'+user.eid:   u'',
-            }
-        path, params = self.expect_redirect_publish()
-        self.req.drop_entity_cache(user.eid)
-        e = self.req.execute('Any X WHERE X eid %(x)s', {'x': user.eid}, 'x').get_entity(0, 0)
-        self.assertEquals(e.login, user.login)
-        self.assertEquals(e.firstname, u'Th\xe9nault')
-        self.assertEquals(e.surname, u'Sylvain')
-        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'',
-                         'surname:X': u'Di Mascio', 'edits-surname:X': '',
-
-                         '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,
-                         }
-        path, params = self.expect_redirect_publish()
-        # should be redirected on the created person
-        self.assertEquals(path, 'euser/adim')
-        e = self.req.execute('Any P WHERE P surname "Di Mascio"').get_entity(0, 0)
-        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()
-        # should be redirected on the created person
-        eid = params['rql'].split()[-1]
-        e = self.req.execute('Any X WHERE X eid %(x)s', {'x': eid}, 'x').get_entity(0, 0)
-        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,
-                         '__redirectrql': 'Any X WHERE X eid %s'%peid,
-                         }
-        path, params = self.expect_redirect_publish()
-        # should be redirected on the created person
-        eid = params['rql'].split()[-1]
-        # XXX this should not be necessary, it isn't with regular cubicweb
-        self.req._eid_cache = {}
-        e = self.req.execute('Any X WHERE X eid %(x)s', {'x': eid}, 'x').get_entity(0, 0)
-        self.assertEquals(e.surname, 'Di Masci')
-        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'',
-                         }
-        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'',
-                         }
-        self.assertRaises(ValidationError, self.publish, self.req)
-
-
-    def test_req_pending_insert(self):
-        """make sure req's pending insertions are taken into account"""
-        tmpgroup = self.add_entity('CWGroup', name=u"test")
-        user = self.user
-        self.req.set_session_data('pending_insert', set([(user.eid, 'in_group', tmpgroup.eid)]))
-        path, params = self.expect_redirect_publish()
-        usergroups = [gname for gname, in
-                      self.req.execute('Any N WHERE G name N, U in_group G, U eid %(u)s', {'u': user.eid})]
-        self.assertUnorderedIterableEquals(usergroups, ['managers', 'users', 'test'])
-        self.assertEquals(self.req.get_pending_inserts(), [])
-
-
-    def test_req_pending_delete(self):
-        """make sure req's pending deletions are taken into account"""
-        user = self.user
-        groupeid = self.req.execute('INSERT CWGroup G: G name "test", U in_group G WHERE U eid %(x)s',
-                                    {'x': user.eid})[0][0]
-        usergroups = [gname for gname, in
-                      self.req.execute('Any N WHERE G name N, U in_group G, U eid %(u)s', {'u': user.eid})]
-        # just make sure everything was set correctly
-        self.assertUnorderedIterableEquals(usergroups, ['managers', 'users', 'test'])
-        # now try to delete the relation
-        self.req.set_session_data('pending_delete', set([(user.eid, 'in_group', groupeid)]))
-        path, params = self.expect_redirect_publish()
-        usergroups = [gname for gname, in
-                      self.req.execute('Any N WHERE G name N, U in_group G, U eid %(u)s', {'u': user.eid})]
-        self.assertUnorderedIterableEquals(usergroups, ['managers', 'users'])
-        #self.assertUnorderedIterableEquals(usergroups, ['managers'])
-        self.assertEquals(self.req.get_pending_deletes(), [])
-
-    def test_custom_attribute_handler(self):
-        def custom_login_edit(self, formparams, value, relations):
-            formparams['login'] = value.upper()
-            relations.append('X login %(login)s')
-        CWUser.custom_login_edit = custom_login_edit
-        try:
-            user = self.user
-            eid = repr(user.eid)
-            self.req.form = {
-                'eid': eid,
-                '__type:'+eid:  'CWUser',
-                'login:'+eid: u'foo',
-                'edits-login:'+eid:  unicode(user.login),
-                }
-            path, params = self.expect_redirect_publish()
-            rset = self.req.execute('Any L WHERE X eid %(x)s, X login L', {'x': user.eid}, 'x')
-            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 = {
-                         'eid': 'A', '__type:A': 'BlogEntry',
-                         '__maineid' : 'A',
-                         'content:A': u'"13:03:43"', 'edits-content:A': '',
-                         'title:A': u'huuu', 'edits-title:A': '',
-                         '__redirectrql': redirectrql,
-                         '__redirectvid': 'primary',
-                         '__redirectparams': 'toto=tutu&tata=titi',
-                         '__form_id': 'edition',
-                         '__action_apply': '',
-                         }
-        path, params = self.expect_redirect_publish()
-        self.failUnless(path.startswith('blogentry/'))
-        eid = path.split('/')[1]
-        self.assertEquals(params['vid'], 'edition')
-        self.assertNotEquals(eid, '4012')
-        self.assertEquals(params['__redirectrql'], redirectrql)
-        self.assertEquals(params['__redirectvid'], 'primary')
-        self.assertEquals(params['__redirectparams'], 'toto=tutu&tata=titi')
-
-    def test_redirect_ok_button(self):
-        redirectrql = rql_for_eid(4012) # whatever
-        self.req.form = {
-                         'eid': 'A', '__type:A': 'BlogEntry',
-                         '__maineid' : 'A',
-                         'content:A': u'"13:03:43"', 'edits-content:A': '',
-                         'title:A': u'huuu', 'edits-title:A': '',
-                         '__redirectrql': redirectrql,
-                         '__redirectvid': 'primary',
-                         '__redirectparams': 'toto=tutu&tata=titi',
-                         '__form_id': 'edition',
-                         }
-        path, params = self.expect_redirect_publish()
-        self.assertEquals(path, 'view')
-        self.assertEquals(params['rql'], redirectrql)
-        self.assertEquals(params['vid'], 'primary')
-        self.assertEquals(params['tata'], 'titi')
-        self.assertEquals(params['toto'], 'tutu')
-
-    def test_redirect_delete_button(self):
-        eid = self.add_entity('BlogEntry', title=u'hop', content=u'hop').eid
-        self.req.form = {'eid': str(eid), '__type:%s'%eid: 'BlogEntry',
-                         '__action_delete': ''}
-        path, params = self.expect_redirect_publish()
-        self.assertEquals(path, 'blogentry')
-        self.assertEquals(params, {u'__message': u'entity deleted'})
-        eid = self.add_entity('EmailAddress', address=u'hop@logilab.fr').eid
-        self.req.execute('SET X use_email E WHERE E eid %(e)s, X eid %(x)s',
-                         {'x': self.user.eid, 'e': eid}, 'x')
-        self.commit()
-        self.req.form = {'eid': str(eid), '__type:%s'%eid: 'EmailAddress',
-                         '__action_delete': ''}
-        path, params = self.expect_redirect_publish()
-        self.assertEquals(unquote(path), 'euser/'+self.user.login)
-        self.assertEquals(params, {u'__message': u'entity deleted'})
-        eid1 = self.add_entity('BlogEntry', title=u'hop', content=u'hop').eid
-        eid2 = self.add_entity('EmailAddress', address=u'hop@logilab.fr').eid
-        self.req.form = {'eid': [str(eid1), str(eid2)],
-                         '__type:%s'%eid1: 'BlogEntry',
-                         '__type:%s'%eid2: 'EmailAddress',
-                         '__action_delete': ''}
-        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,
-
-                         '__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,
-                         }
-        self.assertRaises(ValidationError, self.publish, self.req)
-
-
-    def test_nonregr_rollback_on_validation_error(self):
-        self.skip('lax fix me')
-        p = self.create_user("doe")
-        # do not try to skip 'primary_email' for this test
-        old_skips = p.__class__.skip_copy_for
-        p.__class__.skip_copy_for = ()
-        try:
-            e = self.add_entity('EmailAddress', address=u'doe@doe.com')
-            self.req.execute('SET P use_email E, P primary_email E WHERE P eid %(p)s, E eid %(e)s',
-                         {'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',
-                             'surname:X': u'Boom', 'edits-surname:X': u'',
-                             '__errorurl' : "whatever but required",
-                             }
-            # try to emulate what really happens in the web application
-            # 1/ validate form => EditController.publish raises a ValidationError
-            #    which fires a Redirect
-            # 2/ When re-publishing the copy form, the publisher implicitly commits
-            try:
-                self.app.publish('edit', self.req)
-            except Redirect:
-                self.req.form['rql'] = 'Any X WHERE X eid %s' % p.eid
-                self.req.form['vid'] = 'copy'
-                self.app.publish('view', self.req)
-            rset = self.req.execute('CWUser P WHERE P surname "Boom"')
-            self.assertEquals(len(rset), 0)
-        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	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-from cubicweb.goa.testlib import *
-
-import time
-from mx.DateTime import DateTimeType
-from datetime import datetime
-from cubicweb.goa import db
-
-from google.appengine.api import datastore
-
-class Article(db.Model):
-    content = db.TextProperty()
-    synopsis = db.StringProperty(default='hello')
-
-class Blog(db.Model):
-    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()
-
-
-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)
-        self.assertIsInstance(timestamp, DateTimeType)
-        self.assertIsInstance(entity.to_gae_model()['s_'+attr], datetime)
-        time.sleep(sleep)
-        if entity.id == 'Article':
-            entity.set_attributes(content=u'zou')
-        else:
-            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)
-        self.failUnless(mdate < p.modification_date, (mdate, p.modification_date))
-
-    def _test_owned_by(self, entity):
-        self.assertEquals(len(entity.owned_by), 1)
-        owner = entity.owned_by[0]
-        self.assertIsInstance(owner, db.Model)
-        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)
-
-    def _test_created_by(self, entity):
-        self.assertEquals(len(entity.created_by), 1)
-        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))
-
-    def test_is_relation(self):
-        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')
-        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	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,625 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-from cubicweb.goa.testlib import *
-
-from cubicweb import Binary
-
-from logilab.common.testlib import unittest_main
-from mx.DateTime import now, today, DateTimeType
-import rql
-
-from google.appengine.api.datastore_types import Blob, Text
-
-# stored procedure definition #################################################
-
-from rql.utils import register_function, FunctionDescr
-
-class itemtype_sort_value(FunctionDescr):
-    supported_backends = ('sqlite',)
-    rtype = 'Int'
-
-try:
-    register_function(itemtype_sort_value)
-except AssertionError:
-    pass
-
-def init_sqlite_connexion(cnx):
-    def itemtype_sort_value(text):
-        return {"personal":2, "business":1}[text]
-    cnx.create_function("ITEMTYPE_SORT_VALUE", 1, itemtype_sort_value)
-
-from cubicweb.server import SQL_CONNECT_HOOKS
-sqlite_hooks = SQL_CONNECT_HOOKS.setdefault('sqlite', [])
-sqlite_hooks.append(init_sqlite_connexion)
-
-# end stored procedure definition #############################################
-
-class Article(db.Model):
-    content = db.TextProperty()
-    synopsis = db.StringProperty(default=u'hello')
-
-class Blog(db.Model):
-    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()
-    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 ?*
-        self.schema.rschema('talks_about').set_rproperty('Blog', 'Article',
-                                                         'cardinality', '**')
-        self.req = self.request()
-        self.article = self.add_entity('Article', content=u'very interesting')
-        self.blog = self.add_entity('Blog', itemtype=u'personal', content=u'hop')
-        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')
-        self.assertEquals(rset[0][0], self.blog.eid)
-        self.assertEquals(rset.get_entity(0, 0).eid, self.blog.eid)
-
-    def test_0_const(self):
-        rset = self.req.execute('Any 1')
-        self._check_rset_size(rset, 1, 1)
-        self.assertEquals(rset[0][0], 1)
-        self.assertEquals(rset.description[0][0], 'Int')
-
-    def test_0_now_const(self):
-        rset = self.req.execute('Any NOW')
-        self._check_rset_size(rset, 1, 1)
-        self.assertIsInstance(rset[0][0], DateTimeType)
-        self.assertEquals(rset.description[0][0], 'Datetime')
-
-    def test_0_today_const(self):
-        rset = self.req.execute('Any TODAY')
-        self._check_rset_size(rset, 1, 1)
-        self.assertIsInstance(rset[0][0], DateTimeType)
-        self.assertEquals(rset[0][0], today())
-        self.assertEquals(rset.description[0][0], 'Date')
-
-
-    def test_1_eid(self):
-        rset = self.req.execute('Any X WHERE X eid %(x)s', {'x': self.blog.eid})
-        self._check_blog_rset(rset)
-        rset = self.req.execute('Any X WHERE X eid "%s"' % self.blog.eid)
-        self._check_blog_rset(rset)
-
-    def test_1_eid_eid(self):
-        rset = self.req.execute('Any X,Y WHERE X eid %(x)s, Y eid %(y)s', {'x': self.blog.eid,
-                                                                           'y': self.article.eid})
-        self._check_rset_size(rset, 1, 2)
-        self.assertEquals(rset.description[0], ('Blog', 'Article'))
-        self.assertEquals(rset[0][0], self.blog.eid)
-        self.assertEquals(rset[0][1], self.article.eid)
-
-    def test_1_eid_with_is(self):
-        self.assertRaises(rql.TypeResolverException,
-                          self.req.execute, 'Any X WHERE X eid %(x)s, X is Article', {'x': self.blog.eid})
-        rset = self.req.execute('Any X WHERE X eid %(x)s, X is Blog', {'x': self.blog.eid})
-        self._check_blog_rset(rset)
-
-    def test_1_is(self):
-        rset = self.req.execute('Any X WHERE X is Blog')
-        self._check_blog_rset(rset)
-        blog2 = Blog(itemtype=u'personal', content=u'hop')
-        blog2.put()
-        rset = self.req.execute('Any X WHERE X is Blog')
-        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)
-        self.assertEquals(rset[0], [None])
-        self.assertEquals(rset.description[0], ('Bytes',))
-        self.blog['data'] = Binary('raw data')
-        self.blog.put()
-        rset = self.req.execute('Any D WHERE X is Blog, X data D')
-        self._check_rset_size(rset, 1, 1)
-        self.assertIsInstance(rset[0][0], Binary)
-        value = rset[0][0].getvalue()
-        self.assertIsInstance(value, str)
-        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.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)
-        self.assertEquals(rset[0], [self.blog.eid, u'HOP'])
-        self.assertEquals(rset.description[0], ('Blog', 'String',))
-
-
-    def test_3_attribute_restriction(self):
-        rset = self.req.execute('Any X WHERE X itemtype "personal"')
-        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()
-        rset = self.req.execute('Any X WHERE X content "hop"')
-        self._check_rset_size(rset, 2, 1)
-        self.assertUnorderedIterableEquals([r[0] for r in rset], [self.blog.eid, article.eid])
-        self.assertUnorderedIterableEquals([r[0] for r in rset.description], ['Blog', 'Article'])
-
-    def test_3_incoherant_attribute_restriction(self):
-        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)
-
-    def test_3_today_attribute_restriction(self):
-        rset = self.req.execute('Any X WHERE X diem < TODAY')
-        self.assertEquals(len(rset), 0)
-        rset = self.req.execute('Any X WHERE X diem <= TODAY')
-        self._check_blog_rset(rset)
-        rset = self.req.execute('Any X WHERE X diem > TODAY')
-        self.assertEquals(len(rset), 0)
-        rset = self.req.execute('Any X WHERE X diem >= TODAY')
-        self._check_blog_rset(rset)
-
-    def test_3_now_attribute_restriction(self):
-        rset = self.req.execute('Any X WHERE X diem < NOW')
-        self._check_blog_rset(rset)
-        rset = self.req.execute('Any X WHERE X diem <= NOW')
-        self._check_blog_rset(rset)
-        rset = self.req.execute('Any X WHERE X diem > NOW')
-        self.assertEquals(len(rset), 0)
-        rset = self.req.execute('Any X WHERE X diem >= NOW')
-        self.assertEquals(len(rset), 0)
-
-    def test_3_in_attribute_restriction(self):
-        self.skip('missing actual gae support, retry latter')
-        article2 = Article(content=u'hip')
-        rset = self.req.execute('Any X WHERE X content IN ("hop", "hip")')
-        self._check_rset_size(rset, 2, 1)
-        self.assertUnorderedIterableEquals([r[0] for r in rset], [self.blog.eid, article.eid])
-        self.assertUnorderedIterableEquals([r[0] for r in rset.description], ['Blog', 'Article'])
-
-    def test_3_like(self):
-        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')
-        self.execute('SET X talks_about Y WHERE X eid %(x)s, Y eid %(y)s',
-                     {'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')
-        self._check_rset_size(rset, 2, 1)
-        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')
-        self._check_rset_size(rset, 2, 1)
-        self.assertUnorderedIterableEquals([r[0] for r in rset],
-                             [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')
-        self._check_rset_size(rset, 2, 2)
-        self.assertUnorderedIterableEquals([tuple(r) for r in rset],
-                             [(self.blog.eid, self.article.eid),
-                              (self.blog2.eid, self.article2.eid)])
-        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',
-                                {'x': self.blog.eid})
-        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',
-                                {'x': self.article.eid})
-        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',
-                                {'c': 'hop'})
-        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',
-                                {'c': 'very interesting'})
-        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, '
-                                'X talks_about Y, Y content %(c)s',
-                                {'xc': 'hop', 'c': 'very interesting'})
-        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,'
-                                'X content XC, X diem XD, Y content YC',
-                                {'x': self.article.eid})
-        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})
-        self.assertEquals(len(rset), 0)
-
-    def test_4_relation_restriction_9(self):
-        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',
-                         {'x': self.blog.eid, 'y': article2.eid})
-        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',
-                         {'x': ye.eid, 'y': self.blog.eid})
-        self.req.execute('SET X ambiguous_relation Y WHERE X eid %(x)s, Y eid %(y)s',
-                         {'x': ye.eid, 'y': self.article.eid})
-        self.commit()
-        #ye = self.vreg.etype_class('YamsEntity ')(req, None)
-        #ye.to_gae_model()['s_ambiguous_relation'] = [self.blog.key(), self.article.key()]
-        #ye.put()
-        rset = self.req.execute('Any X WHERE Y ambiguous_relation X')
-        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'])
-        rset = self.req.execute('Any X WHERE Y ambiguous_relation X, Y eid %(x)s', {'x': ye.eid})
-        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})
-        self._check_rset_size(rset, 1, 1)
-        self.assertEquals(rset[0][0], 'very interesting')
-
-
-    def test_5_orderby(self):
-        self._setup_relation_description()
-        rset = self.req.execute('Any X,XC ORDERBY XC WHERE X is Blog, X content XC')
-        self._check_rset_size(rset, 3, 2)
-        self.assertEquals(rset.rows,
-                          [[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')
-        self._check_rset_size(rset, 3, 2)
-        self.assertEquals(rset.rows,
-                          [[self.blog.eid, 'hop'],
-                           [self.blog2.eid, 'hip'],
-                           [self.blog3.eid, 'hep']])
-
-    def test_5_orderby_several_terms(self):
-        self._setup_relation_description()
-        rset = self.req.execute('Any X,XC,XI ORDERBY XI,XC WHERE X is Blog, X content XC, X itemtype XI')
-        self._check_rset_size(rset, 3, 3)
-        self.assertEquals(rset.rows,
-                          [[self.blog3.eid, 'hep', 'business'],
-                           [self.blog2.eid, 'hip', 'personal'],
-                           [self.blog.eid, 'hop', 'personal']])
-
-    def test_5_orderby_several_terms_mixed_implicit(self):
-        self._setup_relation_description()
-        rset = self.req.execute('Any X,XC,XI ORDERBY XI,XC DESC WHERE X is Blog, X content XC, X itemtype XI')
-        self._check_rset_size(rset, 3, 3)
-        self.assertEquals(rset.rows,
-                          [[self.blog3.eid, 'hep', 'business'],
-                           [self.blog.eid, 'hop', 'personal'],
-                           [self.blog2.eid, 'hip', 'personal']])
-
-    def test_5_orderby_several_terms_explicit_order(self):
-        self._setup_relation_description()
-        rset = self.req.execute('Any X,XC,XI ORDERBY XI DESC,XC DESC WHERE X is Blog, X content XC, X itemtype XI')
-        self._check_rset_size(rset, 3, 3)
-        self.assertEquals(rset.rows,
-                          [[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')
-        self._check_rset_size(rset, 3, 3)
-        self.assertEquals(rset.rows,
-                          [[self.blog3.eid, 'hep', 'business'],
-                           [self.blog.eid, 'hop', 'personal'],
-                           [self.blog2.eid, 'hip', 'personal']])
-
-
-    def test_5_orderby_lower(self):
-        blog2 = self.add_entity('Blog', itemtype=u'business', content=u'Hup')
-        rset = self.req.execute('Any X ORDERBY LOWER(XC) '
-                                'WHERE X is Blog, X content XC')
-        self._check_rset_size(rset, 2, 1)
-        self.assertEquals(rset.rows, [[self.blog.eid], [blog2.eid]])
-        rset = self.req.execute('Any X ORDERBY LOWER(XC) DESC'
-                                'WHERE X is Blog, X content XC')
-        self._check_rset_size(rset, 2, 1)
-        self.assertEquals(rset.rows, [[blog2.eid], [self.blog.eid]])
-
-    def test_5_orderby_stored_proc(self):
-        blog2 = self.add_entity('Blog', itemtype=u'business', content=u'hop')
-        rset = self.req.execute('Any X ORDERBY ITEMTYPE_SORT_VALUE(XIT) '
-                                'WHERE X is Blog, X itemtype XIT')
-        self._check_rset_size(rset, 2, 1)
-        self.assertEquals(rset.rows, [[blog2.eid], [self.blog.eid]])
-        rset = self.req.execute('Any X ORDERBY ITEMTYPE_SORT_VALUE(XIT) DESC'
-                                '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')
-        self._check_rset_size(rset, 2, 1)
-        self.assertEquals(rset.rows, [['hep'], ['hip']])
-        rset = self.req.execute('Any XC ORDERBY XC LIMIT 2 OFFSET 1 WHERE X is Blog, X content XC')
-        self._check_rset_size(rset, 2, 1)
-        self.assertEquals(rset.rows, [['hip'], ['hop']])
-        rset = self.req.execute('Any XC ORDERBY XC LIMIT 2 OFFSET 2 WHERE X is Blog, X content XC')
-        self._check_rset_size(rset, 1, 1)
-        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()
-        _today = today()
-        _tomorrow = _today + 1
-        rset = self.req.execute('Any X WHERE X is Blog, X creation_date >= "%s"'
-                                % _tomorrow.strftime('%Y-%m-%d'))
-        self.failUnless(len(rset) == 0)
-        rset = self.req.execute('Any X WHERE X is Blog, X creation_date >= "%s"'
-                                % _today.strftime('%Y-%m-%d'))
-        self._check_rset_size(rset, 3, 1)
-        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})
-        self._check_rset_size(rset, 1, 1)
-        rset = self.req.execute('Any Y WHERE X identity Y, X eid %(x)s',
-                                {'x': self.user.eid})
-        self._check_rset_size(rset, 1, 1)
-        self.assertEquals(rset.rows, [[self.user.eid]])
-        blog2 = self.add_entity('Blog', itemtype=u'personal', content=u'hip')
-        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]])
-
-    def test_8_not_relation_linked_subject(self):
-        rset = self.req.execute('Any X WHERE NOT X talks_about Y, Y eid %(y)s',
-                                {'y': self.article.eid})
-        self.failIf(rset)
-        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})
-        self._check_rset_size(rset, 1, 1)
-        self.assertEquals(rset.rows, [[blog2.eid]])
-
-    def test_8_not_relation_linked_object(self):
-        rset = self.req.execute('Any Y WHERE NOT X talks_about Y, X eid %(x)s',
-                                {'x': self.blog.eid})
-        self.failIf(rset)
-        article2 = self.add_entity('Article', content=u'hop')
-        self.commit()
-        rset = self.req.execute('Any Y WHERE NOT X talks_about Y, X eid %(x)s',
-                                {'x': self.blog.eid})
-        self._check_rset_size(rset, 1, 1)
-        self.assertEquals(rset.rows, [[article2.eid]])
-
-    def test_8_not_relation_linked_attr(self):
-        self.skip('not yet implemented')
-        # 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',
-                         {'x': self.blog.eid, 'y': article2.eid})
-        self.commit()
-        rset = self.req.execute('Any X WHERE NOT X talks_about Y, Y content "hop"')
-        self._check_rset_size(rset, 1, 2)
-        self.assertEquals(rset.rows, [[self.blog.eid, self.article.eid]])
-
-    def test_8_not_relation_unlinked_subject(self):
-        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')
-        self._check_rset_size(rset, 1, 1)
-        self.assertEquals(rset.rows, [[blog2.eid]])
-
-    def test_8_not_relation_unlinked_object(self):
-        article2 = self.add_entity('Article', content=u'hop')
-        self.commit()
-        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'])
-
-    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)
-        self.assertUnorderedIterableEquals([gn for gn, in rset.rows],
-                                           ['users', 'managers'])
-
-
-    def test_9_exists(self):
-        blog2 = self.add_entity('Article', content=u'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',
-                         {'x': self.blog.eid, 'y': article2.eid})
-        self.commit()
-        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)
-        self.blog.cw_delete()
-        rset = self.req.execute('Any X WHERE X eid %(x)s', {'x': self.blog.eid})
-        self.assertEquals(len(rset), 0)
-
-    def test_nonregr_inlined_relation(self):
-        eid = self.execute('INSERT YamsEntity X: X inlined_relation Y WHERE Y eid %(y)s',
-                           {'y': self.blog.eid})[0][0]
-        self.commit()
-        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	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-from cubicweb.goa.testlib import *
-
-class Article(db.Model):
-    content = db.TextProperty()
-    synopsis = db.StringProperty(default='hello')
-
-class Blog(db.Model):
-    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()
-
-
-class SomeViewsTC(GAEBasedTC):
-    MODEL_CLASSES = (Article, Blog)
-
-    def test_entities_and_relation(self):
-        schema = self.schema
-        self.assertSetEquals(set(str(e) for e in schema.entities()),
-                             set(('Boolean', 'Bytes', 'Date', 'Datetime', 'Float',
-                              'Decimal',
-                              'Int', 'Interval', 'Password', 'String', 'Time',
-                              'CWEType', 'CWGroup', 'CWPermission', 'CWProperty', 'CWRType',
-                              'CWUser', 'EmailAddress',
-                              'RQLExpression', 'State', 'Transition', 'TrInfo',
-                              'Article', 'Blog', 'YamsEntity')))
-        self.assertSetEquals(set(str(e) for e in schema.relations()),
-                             set(('add_permission', 'address', 'alias', 'allowed_transition',
-                                  'ambiguous_relation', 'canonical', 'cites',
-                                  'comment', 'comment_format', 'condition', 'content',
-                                  'created_by', 'creation_date', 'delete_permission',
-                                  'description', 'description_format', 'destination_state',
-                                  'diem', 'eid', 'expression', 'exprtype', 'final', 'firstname',
-                                  'for_user', 'from_state', 'fulltext_container', 'has_text',
-                                  'identical_to', 'identity', 'in_group', 'initial_state',
-                                  'inlined', 'inlined_relation', 'is', 'is_instance_of',
-                                  'label', 'last_login_time', 'login',
-                                  'mainvars', 'meta', 'modification_date', 'name', 'owned_by', 'pkey', 'primary_email',
-                                  'read_permission', 'require_group', 'state_of', 'surname', 'symmetric',
-                                  'synopsis', 'talks_about', 'title', 'to_state', 'transition_of',
-                                  'update_permission', 'use_email', 'value')))
-
-    def test_dbmodel_imported(self):
-        eschema = self.schema['Blog']
-        orels = [str(e) for e in eschema.ordered_relations()]
-        # only relations defined in the class are actually ordered
-        orels, others = orels[:5], orels[5:]
-        self.assertEquals(orels,
-                          ['diem', 'title', 'content', 'talks_about', 'cites'])
-        self.assertUnorderedIterableEquals(others,
-                             ['eid', 'identity', 'owned_by', 'modification_date',
-                              'created_by', 'creation_date', 'is', 'is_instance_of'])
-        self.assertUnorderedIterableEquals((str(e) for e in eschema.object_relations()),
-                             ('ambiguous_relation', 'cites', 'identity', 'inlined_relation'))
-        eschema = self.schema['Article']
-        orels = [str(e) for e in eschema.ordered_relations()]
-        # only relations defined in the class are actually ordered
-        orels, others = orels[:2], orels[2:]
-        self.assertEquals(orels,
-                          ['content', 'synopsis'])
-        self.assertUnorderedIterableEquals(others,
-                             ['eid', 'identity', 'owned_by', 'modification_date',
-                              'created_by', 'creation_date', 'is', 'is_instance_of'])
-        self.assertUnorderedIterableEquals((str(e) for e in eschema.object_relations()),
-                             ('ambiguous_relation', 'talks_about', 'identity'))
-
-    def test_yams_imported(self):
-        eschema = self.schema['CWProperty']
-        # only relations defined in the class are actually ordered
-        orels = [str(e) for e in eschema.ordered_relations()]
-        orels, others = orels[:3], orels[3:]
-        self.assertEquals(orels,
-                          ['pkey', 'value', 'for_user'])
-        self.assertEquals(others,
-                          ['created_by', 'creation_date', 'eid', 'identity',
-                           '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
-        self.assertUnorderedIterableEquals((str(e) for e in rschema.subjects()),
-                             ('YamsEntity',))
-        self.assertUnorderedIterableEquals((str(e) for e in rschema.objects()),
-                             ('Blog', 'Article'))
-
-    def test_euser(self):
-        eschema = self.schema['CWUser']
-        # XXX pretend to have some relations it has not
-        self.assertEquals([str(e) for e in eschema.ordered_relations()],
-                          ['login', 'firstname', 'surname', 'last_login_time',
-                           'primary_email', 'use_email', 'in_group', 'created_by',
-                           'creation_date', 'eid', 'has_text', 'identity',
-                           'is', 'is_instance_of', 'modification_date',
-                           'owned_by'])
-        self.assertUnorderedIterableEquals((str(e) for e in eschema.object_relations()),
-                             ('owned_by', 'created_by', 'identity', 'for_user'))
-
-    def test_eid(self):
-        rschema = self.schema['eid']
-        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	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-from cubicweb.goa.testlib import *
-
-from cubicweb.interfaces import ICalendarable
-
-
-class Blog(db.Model):
-    diem = db.DateProperty(required=True, auto_now_add=True)
-    title = db.StringProperty(required=True)
-    content = db.TextProperty()
-
-    __implements__ = (ICalendarable,)
-
-    @property
-    def start(self):
-        return self.diem
-
-    @property
-    def stop(self):
-        return self.diem
-
-    def matching_dates(self, begin, end):
-        """calendar views interface"""
-        mydate = self.diem
-        if mydate:
-            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['views'].render('hcal', self.req, rset=self.blog.rset)
-
-    def test_django_index(self):
-        self.vreg['views'].render('index', self.req, rset=None)
-
-for vid in ('primary', '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	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,198 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-"""
-__docformat__ = "restructuredtext en"
-
-from logilab.common.testlib import TestCase, TestSkipped
-try:
-    import google.appengine
-except ImportError:
-    raise TestSkipped('Can not import google.appengine. Skip this module')
-
-import os, os.path as osp
-import time
-from shutil import copy
-
-# additional monkey patches necessary in regular cubicweb environment
-from cubicweb.server import rqlannotation
-from cubicweb.goa.overrides import rqlannotation as goarqlannotation
-rqlannotation.SQLGenAnnotator = goarqlannotation.SQLGenAnnotator
-rqlannotation.set_qdata = goarqlannotation.set_qdata
-
-from google.appengine.api import apiproxy_stub_map
-from google.appengine.api import datastore_file_stub
-from google.appengine.ext import db as gdb
-
-from cubicweb.devtools.fake import FakeRequest
-
-from cubicweb.goa import db, do_monkey_patch
-from cubicweb.goa.goavreg import GAEVRegistry
-from cubicweb.goa.goaconfig import GAEConfiguration
-from cubicweb.goa.dbinit import (create_user, create_groups, fix_entities,
-                                 init_persistent_schema, insert_versions)
-
-import logging
-logger = logging.getLogger()
-logger.setLevel(logging.CRITICAL)
-
-do_monkey_patch()
-
-class GAEBasedTC(TestCase):
-    APP_ID = u'test_app'
-    AUTH_DOMAIN = 'gmail.com'
-    LOGGED_IN_USER = u't...@example.com'  # set to '' for no logged in user
-    MODEL_CLASSES = None
-    LOAD_APP_MODULES = None
-    config = None
-    _DS_TEMPL_FILE = 'tmpdb-template'
-
-    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))
-
-    def _set_ds_file(self, dsfile):
-        # Start with a fresh api proxy.
-        apiproxy_stub_map.apiproxy = apiproxy_stub_map.APIProxyStubMap()
-        # Use a fresh stub datastore.
-        stub = datastore_file_stub.DatastoreFileStub(self.APP_ID, dsfile,
-                                                     dsfile+'.history')
-        apiproxy_stub_map.apiproxy.RegisterStub('datastore_v3', stub)
-
-    def setUp(self):
-        # Ensure we're in UTC.
-        os.environ['TZ'] = 'UTC'
-        time.tzset()
-        if osp.exists(self.DS_TEMPL_FILE):
-            copy(self.DS_TEMPL_FILE, self.DS_FILE)
-            need_ds_init = False
-            self._set_ds_file(self.DS_FILE)
-        else:
-            need_ds_init = True
-            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
-#         # Use a fresh stub UserService.
-#         apiproxy_stub_map.apiproxy.RegisterStub(
-#             'user', user_service_stub.UserServiceStub())
-        os.environ['AUTH_DOMAIN'] = self.AUTH_DOMAIN
-        os.environ['USER_EMAIL'] = self.LOGGED_IN_USER
-#         # Use a fresh urlfetch stub.
-#         apiproxy_stub_map.apiproxy.RegisterStub(
-#             'urlfetch', urlfetch_stub.URLFetchServiceStub())
-#         # Use a fresh mail stub.
-#         apiproxy_stub_map.apiproxy.RegisterStub(
-#             'mail', mail_stub.MailServiceStub())
-        if self.MODEL_CLASSES is None:
-            raise Exception('GAEBasedTC should set MODEL_CLASSES class attribute')
-        gdb._kind_map = {}
-        self.config = self.config or GAEConfiguration('toto')
-        self.config.init_log(logging.CRITICAL)
-        self.schema = self.config.load_schema(self.MODEL_CLASSES,
-                                              self.load_schema_hook)
-        self.vreg = GAEVregistry(self.config)
-        self.vreg.schema = self.schema
-        self.vreg.load_module(db)
-        from cubicweb.goa.appobjects import sessions
-        self.vreg.load_module(sessions)
-        from cubicweb.entities import authobjs, schemaobjs
-        self.vreg.load_module(authobjs)
-        self.vreg.load_module(schemaobjs)
-        if self.config['use-google-auth']:
-            from cubicweb.goa.appobjects import gauthservice
-            self.vreg.load_module(gauthservice)
-        if self.LOAD_APP_MODULES is not None:
-            for module in self.LOAD_APP_MODULES:
-                self.vreg.load_module(module)
-        for cls in self.MODEL_CLASSES:
-            self.vreg.register(cls)
-        self.session_manager = self.vreg.select('components', 'sessionmanager')
-        if need_ds_init:
-            # create default groups and create entities according to the schema
-            create_groups()
-            if not self.config['use-google-auth']:
-                create_user(self.LOGGED_IN_USER, 'toto', ('users', 'managers'))
-                self.session = self.login(self.LOGGED_IN_USER, 'toto')
-            else:
-                req = FakeRequest(vreg=self.vreg)
-                self.session = self.session_manager.open_session(req)
-            self.user = self.session.user()
-            ssession = self.config.repo_session(self.session.sessionid)
-            ssession.set_pool()
-            init_persistent_schema(ssession, self.schema)
-            insert_versions(ssession, self.config)
-            ssession.commit()
-            fix_entities(self.schema)
-            copy(self.DS_TEMPL_FILE, self.DS_FILE)
-            self._set_ds_file(self.DS_FILE)
-        else:
-            if not self.config['use-google-auth']:
-                self.session = self.login(self.LOGGED_IN_USER, 'toto')
-            else:
-                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
-        if kwargs:
-            rql += ': %s' % ', '.join('X %s %%(%s)s' % (key, key) for key in kwargs)
-        rset = cu.execute(rql, kwargs)
-        return rset.get_entity(0, 0)
-
-    def execute(self, *args):
-        return self.session.cursor().execute(*args)
-
-    def commit(self):
-        self.session.commit()
-
-    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))
-        cu = self.session.cursor()
-        cu.execute('SET X in_group G WHERE X eid %%(x)s, G name IN(%s)'
-                    % ','.join(repr(g) for g in groups),
-                    {'x': user.eid}, 'x')
-        return user
-
-    def login(self, login, password=None):
-        assert not self.config['use-google-auth']
-        req = FakeRequest(vreg=self.vreg)
-        req.form['__login'] = login
-        req.form['__password'] = password or login
-        return self.session_manager.open_session(req)
--- a/goa/tools/__init__.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""lax tools cube
-
-"""
--- a/goa/tools/generate_schema_img.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-import sys
-from os.path import dirname, abspath, join
-from yams import schema2dot
-from cubicweb.web.views.schema import SKIP_TYPES
-
-APPLROOT = abspath(join(dirname(abspath(__file__)), '..'))
-
-try:
-    import custom
-except ImportError:
-    sys.path.insert(0, APPLROOT)
-    import custom
-
-
-schema = custom.SCHEMA
-skip_rels = ('owned_by', 'created_by', 'identity', 'is', 'is_instance_of')
-path = join(APPLROOT, 'data', 'schema.png')
-schema2dot.schema2dot(schema, path, #size=size,
-                      skiptypes=SKIP_TYPES)
-print 'generated', path
-path = join(APPLROOT, 'data', 'metaschema.png')
-schema2dot.schema2dot(schema, path)
-print 'generated', path
--- a/goa/tools/laxctl.py	Fri Sep 24 18:20:57 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,269 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""provides all lax instances management commands into a single utility script
-
-"""
-__docformat__ = "restructuredtext en"
-
-import sys
-import os
-import os.path as osp
-import time
-import re
-import urllib2
-from urllib import urlencode
-from Cookie import SimpleCookie
-
-from logilab.common.clcommands import Command, register_commands, main_run
-
-from cubicweb.uilib import remove_html_tags
-from cubicweb.web.views.schema import SKIP_TYPES
-
-APPLROOT = osp.abspath(osp.join(osp.dirname(osp.abspath(__file__)), '..'))
-
-
-def initialize_vregistry(applroot):
-    # apply monkey patches first
-    from cubicweb.goa import do_monkey_patch
-    do_monkey_patch()
-    from cubicweb.goa.goavreg import GAEVregistry
-    from cubicweb.goa.goaconfig import GAEConfiguration
-    #WebConfiguration.uiprops['JAVASCRIPTS'].append('DATADIR/goa.js')
-    config = GAEConfiguration('toto', applroot)
-    vreg = GAEVregistry(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
-    """
-    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"""
-    name = 'genschema'
-
-    def _run(self, args):
-        assert not args, 'no argument expected'
-        from yams import schema2dot
-        schema = self.vreg.schema
-        path = osp.join(APPLROOT, 'data', 'schema.png')
-        schema2dot.schema2dot(schema, path, #size=size,
-                              skiptypes=SKIP_TYPES)
-        print 'generated', path
-        path = osp.join(APPLROOT, 'data', 'metaschema.png')
-        schema2dot.schema2dot(schema, path)
-        print 'generated', path
-
-
-class PopulateDataDirCommand(LaxCommand):
-    """populate instance's data directory according to used cubes"""
-    name = 'populatedata'
-
-    def _run(self, args):
-        assert not args, 'no argument expected'
-        # first clean everything which is a symlink from the data directory
-        datadir = osp.join(APPLROOT, 'data')
-        if not osp.exists(datadir):
-            print 'created data directory'
-            os.mkdir(datadir)
-        for filepath in alistdir(datadir):
-            if osp.islink(filepath):
-                print 'removing', filepath
-                os.remove(filepath)
-        cubes = list(self.vreg.config.cubes()) + ['shared']
-        for templ in cubes:
-            templpath = self.vreg.config.cube_dir(templ)
-            templdatadir = osp.join(templpath, 'data')
-            if not osp.exists(templdatadir):
-                print 'no data provided by', templ
-                continue
-            for resource in os.listdir(templdatadir):
-                if resource == 'external_resources':
-                    continue
-                if not osp.exists(osp.join(datadir, resource)):
-                    print 'symlinked %s from %s' % (resource, templ)
-                    os.symlink(osp.join(templdatadir, resource),
-                               osp.join(datadir, resource))
-
-
-class NoRedirectHandler(urllib2.HTTPRedirectHandler):
-    def http_error_302(self, req, fp, code, msg, headers):
-        raise urllib2.HTTPError(req.get_full_url(), code, msg, headers, fp)
-    http_error_301 = http_error_303 = http_error_307 = http_error_302
-
-
-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
-        print 'session id', sessionid
-        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 instance
-    """
-    min_args = max_args = 1
-    arguments = '<site url>'
-
-    options = (
-        ('cookie',
-         {'short': 'C', 'type' : 'string', 'metavar': 'key=value',
-          'default': None,
-          'help': 'session/authentication cookie.'}),
-        ('user',
-         {'short': 'u', 'type' : 'string', 'metavar': 'login',
-          'default': None,
-          'help': 'user login instead of giving raw cookie string (require lax '
-          'based authentication).'}),
-        ('password',
-         {'short': 'p', 'type' : 'string', 'metavar': 'password',
-          'default': None,
-          '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'):
-            baseurl = 'http://' + baseurl
-        if not baseurl.endswith('/'):
-            baseurl += '/'
-        self.base_url = baseurl
-        if not self.config.cookie and self.config.user:
-            # no cookie specified but a user is. Try to open a session using
-            # given authentication info
-            print 'opening session for', self.config.user
-            opener = urllib2.build_opener(GetSessionIdHandler(self.config))
-            urllib2.install_opener(opener)
-            data = urlencode(dict(__login=self.config.user,
-                                  __password=self.config.password))
-            self.open_url(urllib2.Request(baseurl, data))
-        opener = urllib2.build_opener(NoRedirectHandler())
-        urllib2.install_opener(opener)
-        self.do_base_url(baseurl)
-
-    def build_req(self, url):
-        req = urllib2.Request(url)
-        if self.config.cookie:
-            req.headers['Cookie'] = self.config.cookie
-        return req
-
-    def open_url(self, req):
-        try:
-            return urllib2.urlopen(req)
-        except urllib2.HTTPError, ex:
-            if ex.code == 302:
-                self.error_302(req, ex)
-            elif ex.code == 500:
-                self.error_500(req, ex)
-            else:
-                raise
-
-    def error_302(self, req, ex):
-        print 'authentication required'
-        print ('visit %s?vid=authinfo with your browser to get '
-               'authentication info' % self.base_url)
-        sys.exit(1)
-
-    def error_500(self, req, ex):
-        print 'an unexpected error occured on the server'
-        print ('you may get more information by visiting '
-               '%s' % req.get_full_url())
-        sys.exit(1)
-
-    def extract_message(self, data):
-        match = re.search(r'<div class="message">(.*?)</div>', data.read(), re.M|re.S)
-        if match:
-            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'
-
-    options = URLCommand.options + (
-        ('sleep',
-         {'short': 's', 'type' : 'int', 'metavar': 'nb seconds',
-          'default': None,
-          '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:
-            try:
-                data = self.open_url(req)
-            except urllib2.HTTPError, ex:
-                if ex.code == 303: # redirect
-                    print 'process completed'
-                    break
-                raise
-            msg = self.extract_message(data)
-            if msg and msg.startswith('error: '):
-                print ('you may to cleanup datastore by visiting '
-                       '%s?vid=contentclear (ALL ENTITIES WILL BE DELETED)'
-                       % baseurl)
-                break
-            if self.config.sleep:
-                time.sleep(self.config.sleep)
-
-
-class CleanSessionsCommand(URLCommand):
-    """cleanup sessions on the server. This command should usually be called
-    regularly by a cron job or equivalent.
-    """
-    name = "cleansessions"
-    def do_base_url(self, baseurl):
-        req = self.build_req(baseurl + '?vid=cleansessions')
-        data = self.open_url(req)
-        self.extract_message(data)
-
-
-register_commands([GenerateSchemaCommand,
-                   PopulateDataDirCommand,
-                   DSInitCommand,
-                   CleanSessionsCommand,
-                   ])
-
-def run():
-    main_run(sys.argv[1:])
-
-if __name__ == '__main__':
-    run()
--- a/hooks/test/unittest_hooks.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/hooks/test/unittest_hooks.py	Fri Sep 24 18:20:59 2010 +0200
@@ -49,7 +49,7 @@
         self.commit()
 
     def test_delete_required_relations_object(self):
-        self.skip('no sample in the schema ! YAGNI ? Kermaat ?')
+        self.skipTest('no sample in the schema ! YAGNI ? Kermaat ?')
 
     def test_static_vocabulary_check(self):
         self.assertRaises(ValidationError,
@@ -63,14 +63,14 @@
                           self.commit)
 
     def test_inlined(self):
-        self.assertEquals(self.repo.schema['sender'].inlined, True)
+        self.assertEqual(self.repo.schema['sender'].inlined, True)
         self.execute('INSERT EmailAddress X: X address "toto@logilab.fr", X alias "hop"')
         self.execute('INSERT EmailPart X: X content_format "text/plain", X ordernum 1, X content "this is a test"')
         eeid = self.execute('INSERT Email X: X messageid "<1234>", X subject "test", X sender Y, X recipients Y, X parts P '
                             'WHERE Y is EmailAddress, P is EmailPart')[0][0]
         self.execute('SET X sender Y WHERE X is Email, Y is EmailAddress')
         rset = self.execute('Any S WHERE X sender S, X eid %s' % eeid)
-        self.assertEquals(len(rset), 1)
+        self.assertEqual(len(rset), 1)
 
     def test_composite_1(self):
         self.execute('INSERT EmailAddress X: X address "toto@logilab.fr", X alias "hop"')
@@ -81,10 +81,10 @@
         self.commit()
         self.execute('DELETE Email X')
         rset = self.execute('Any X WHERE X is EmailPart')
-        self.assertEquals(len(rset), 1)
+        self.assertEqual(len(rset), 1)
         self.commit()
         rset = self.execute('Any X WHERE X is EmailPart')
-        self.assertEquals(len(rset), 0)
+        self.assertEqual(len(rset), 0)
 
     def test_composite_2(self):
         self.execute('INSERT EmailAddress X: X address "toto@logilab.fr", X alias "hop"')
@@ -96,7 +96,7 @@
         self.execute('DELETE EmailPart X')
         self.commit()
         rset = self.execute('Any X WHERE X is EmailPart')
-        self.assertEquals(len(rset), 0)
+        self.assertEqual(len(rset), 0)
 
     def test_composite_redirection(self):
         self.execute('INSERT EmailAddress X: X address "toto@logilab.fr", X alias "hop"')
@@ -110,74 +110,74 @@
         self.execute('SET X parts Y WHERE X messageid "<2345>"')
         self.commit()
         rset = self.execute('Any X WHERE X is EmailPart')
-        self.assertEquals(len(rset), 1)
-        self.assertEquals(rset.get_entity(0, 0).reverse_parts[0].messageid, '<2345>')
+        self.assertEqual(len(rset), 1)
+        self.assertEqual(rset.get_entity(0, 0).reverse_parts[0].messageid, '<2345>')
 
     def test_unsatisfied_constraints(self):
         releid = self.execute('SET U in_group G WHERE G name "owners", U login "admin"')[0][0]
         ex = self.assertRaises(ValidationError, self.commit)
-        self.assertEquals(ex.errors,
+        self.assertEqual(ex.errors,
                           {'in_group-object': u'RQLConstraint NOT O name "owners" failed'})
 
     def test_html_tidy_hook(self):
         req = self.request()
         entity = req.create_entity('Workflow', name=u'wf1', description_format=u'text/html',
                                  description=u'yo')
-        self.assertEquals(entity.description, u'yo')
+        self.assertEqual(entity.description, u'yo')
         entity = req.create_entity('Workflow', name=u'wf2', description_format=u'text/html',
                                  description=u'<b>yo')
-        self.assertEquals(entity.description, u'<b>yo</b>')
+        self.assertEqual(entity.description, u'<b>yo</b>')
         entity = req.create_entity('Workflow', name=u'wf3', description_format=u'text/html',
                                  description=u'<b>yo</b>')
-        self.assertEquals(entity.description, u'<b>yo</b>')
+        self.assertEqual(entity.description, u'<b>yo</b>')
         entity = req.create_entity('Workflow', name=u'wf4', description_format=u'text/html',
                                  description=u'<b>R&D</b>')
-        self.assertEquals(entity.description, u'<b>R&amp;D</b>')
+        self.assertEqual(entity.description, u'<b>R&amp;D</b>')
         entity = req.create_entity('Workflow', name=u'wf5', description_format=u'text/html',
                                  description=u"<div>c&apos;est <b>l'ét&eacute;")
-        self.assertEquals(entity.description, u"<div>c'est <b>l'été</b></div>")
+        self.assertEqual(entity.description, u"<div>c'est <b>l'été</b></div>")
 
     def test_nonregr_html_tidy_hook_no_update(self):
         entity = self.request().create_entity('Workflow', name=u'wf1', description_format=u'text/html',
                                  description=u'yo')
         entity.set_attributes(name=u'wf2')
-        self.assertEquals(entity.description, u'yo')
+        self.assertEqual(entity.description, u'yo')
         entity.set_attributes(description=u'R&D<p>yo')
         entity.pop('description')
-        self.assertEquals(entity.description, u'R&amp;D<p>yo</p>')
+        self.assertEqual(entity.description, u'R&amp;D<p>yo</p>')
 
 
     def test_metadata_cwuri(self):
         entity = self.request().create_entity('Workflow', name=u'wf1')
-        self.assertEquals(entity.cwuri, self.repo.config['base-url'] + 'eid/%s' % entity.eid)
+        self.assertEqual(entity.cwuri, self.repo.config['base-url'] + 'eid/%s' % entity.eid)
 
     def test_metadata_creation_modification_date(self):
         _now = datetime.now()
         entity = self.request().create_entity('Workflow', name=u'wf1')
-        self.assertEquals((entity.creation_date - _now).seconds, 0)
-        self.assertEquals((entity.modification_date - _now).seconds, 0)
+        self.assertEqual((entity.creation_date - _now).seconds, 0)
+        self.assertEqual((entity.modification_date - _now).seconds, 0)
 
     def test_metadata_created_by(self):
         entity = self.request().create_entity('Bookmark', title=u'wf1', path=u'/view')
         self.commit() # fire operations
-        self.assertEquals(len(entity.created_by), 1) # make sure we have only one creator
-        self.assertEquals(entity.created_by[0].eid, self.session.user.eid)
+        self.assertEqual(len(entity.created_by), 1) # make sure we have only one creator
+        self.assertEqual(entity.created_by[0].eid, self.session.user.eid)
 
     def test_metadata_owned_by(self):
         entity = self.request().create_entity('Bookmark', title=u'wf1', path=u'/view')
         self.commit() # fire operations
-        self.assertEquals(len(entity.owned_by), 1) # make sure we have only one owner
-        self.assertEquals(entity.owned_by[0].eid, self.session.user.eid)
+        self.assertEqual(len(entity.owned_by), 1) # make sure we have only one owner
+        self.assertEqual(entity.owned_by[0].eid, self.session.user.eid)
 
     def test_user_login_stripped(self):
         u = self.create_user('  joe  ')
         tname = self.execute('Any L WHERE E login L, E eid %(e)s',
                              {'e': u.eid})[0][0]
-        self.assertEquals(tname, 'joe')
+        self.assertEqual(tname, 'joe')
         self.execute('SET X login " jijoe " WHERE X eid %(x)s', {'x': u.eid})
         tname = self.execute('Any L WHERE E login L, E eid %(e)s',
                              {'e': u.eid})[0][0]
-        self.assertEquals(tname, 'jijoe')
+        self.assertEqual(tname, 'jijoe')
 
 
 
@@ -198,15 +198,15 @@
 
     def test_user_group_synchronization(self):
         user = self.session.user
-        self.assertEquals(user.groups, set(('managers',)))
+        self.assertEqual(user.groups, set(('managers',)))
         self.execute('SET X in_group G WHERE X eid %s, G name "guests"' % user.eid)
-        self.assertEquals(user.groups, set(('managers',)))
+        self.assertEqual(user.groups, set(('managers',)))
         self.commit()
-        self.assertEquals(user.groups, set(('managers', 'guests')))
+        self.assertEqual(user.groups, set(('managers', 'guests')))
         self.execute('DELETE X in_group G WHERE X eid %s, G name "guests"' % user.eid)
-        self.assertEquals(user.groups, set(('managers', 'guests')))
+        self.assertEqual(user.groups, set(('managers', 'guests')))
         self.commit()
-        self.assertEquals(user.groups, set(('managers',)))
+        self.assertEqual(user.groups, set(('managers',)))
 
     def test_user_composite_owner(self):
         ueid = self.create_user('toto').eid
@@ -214,7 +214,7 @@
         self.execute('INSERT EmailAddress X: X address "toto@logilab.fr", U use_email X '
                      'WHERE U login "toto"')
         self.commit()
-        self.assertEquals(self.execute('Any A WHERE X owned_by U, U use_email X,'
+        self.assertEqual(self.execute('Any A WHERE X owned_by U, U use_email X,'
                                        'U login "toto", X address A')[0][0],
                           'toto@logilab.fr')
 
@@ -230,23 +230,23 @@
     def test_unexistant_eproperty(self):
         ex = self.assertRaises(ValidationError,
                           self.execute, 'INSERT CWProperty X: X pkey "bla.bla", X value "hop", X for_user U')
-        self.assertEquals(ex.errors, {'pkey-subject': 'unknown property key'})
+        self.assertEqual(ex.errors, {'pkey-subject': 'unknown property key'})
         ex = self.assertRaises(ValidationError,
                           self.execute, 'INSERT CWProperty X: X pkey "bla.bla", X value "hop"')
-        self.assertEquals(ex.errors, {'pkey-subject': 'unknown property key'})
+        self.assertEqual(ex.errors, {'pkey-subject': 'unknown property key'})
 
     def test_site_wide_eproperty(self):
         ex = self.assertRaises(ValidationError,
                                self.execute, 'INSERT CWProperty X: X pkey "ui.site-title", X value "hop", X for_user U')
-        self.assertEquals(ex.errors, {'for_user-subject': "site-wide property can't be set for user"})
+        self.assertEqual(ex.errors, {'for_user-subject': "site-wide property can't be set for user"})
 
     def test_bad_type_eproperty(self):
         ex = self.assertRaises(ValidationError,
                                self.execute, 'INSERT CWProperty X: X pkey "ui.language", X value "hop", X for_user U')
-        self.assertEquals(ex.errors, {'value-subject': u'unauthorized value'})
+        self.assertEqual(ex.errors, {'value-subject': u'unauthorized value'})
         ex = self.assertRaises(ValidationError,
                           self.execute, 'INSERT CWProperty X: X pkey "ui.language", X value "hop"')
-        self.assertEquals(ex.errors, {'value-subject': u'unauthorized value'})
+        self.assertEqual(ex.errors, {'value-subject': u'unauthorized value'})
 
 
 class SchemaHooksTC(CubicWebTC):
@@ -266,7 +266,7 @@
             self.execute('INSERT CWUser X: X login "admin"')
         except ValidationError, ex:
             self.assertIsInstance(ex.entity, int)
-            self.assertEquals(ex.errors, {'login-subject': 'the value "admin" is already used, use another one'})
+            self.assertEqual(ex.errors, {'login-subject': 'the value "admin" is already used, use another one'})
 
 
 if __name__ == '__main__':
--- a/hooks/test/unittest_syncschema.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/hooks/test/unittest_syncschema.py	Fri Sep 24 18:20:59 2010 +0200
@@ -98,7 +98,7 @@
         self.execute('Societe2 X WHERE X name "logilab"')
         self.execute('SET X concerne2 X WHERE X name "logilab"')
         rset = self.execute('Any X WHERE X concerne2 Y')
-        self.assertEquals(rset.rows, [[s2eid]])
+        self.assertEqual(rset.rows, [[s2eid]])
         # check that when a relation definition is deleted, existing relations are deleted
         rdefeid = self.execute('INSERT CWRelation X: X cardinality "**", X relation_type RT, '
                                '   X from_entity E, X to_entity E '
@@ -125,9 +125,9 @@
     def test_is_instance_of_insertions(self):
         seid = self.execute('INSERT Transition T: T name "subdiv"')[0][0]
         is_etypes = [etype for etype, in self.execute('Any ETN WHERE X eid %s, X is ET, ET name ETN' % seid)]
-        self.assertEquals(is_etypes, ['Transition'])
+        self.assertEqual(is_etypes, ['Transition'])
         instanceof_etypes = [etype for etype, in self.execute('Any ETN WHERE X eid %s, X is_instance_of ET, ET name ETN' % seid)]
-        self.assertEquals(sorted(instanceof_etypes), ['BaseTransition', 'Transition'])
+        self.assertEqual(sorted(instanceof_etypes), ['BaseTransition', 'Transition'])
         snames = [name for name, in self.execute('Any N WHERE S is BaseTransition, S name N')]
         self.failIf('subdiv' in snames)
         snames = [name for name, in self.execute('Any N WHERE S is_instance_of BaseTransition, S name N')]
@@ -136,27 +136,27 @@
 
     def test_perms_synchronization_1(self):
         schema = self.repo.schema
-        self.assertEquals(schema['CWUser'].get_groups('read'), set(('managers', 'users')))
+        self.assertEqual(schema['CWUser'].get_groups('read'), set(('managers', 'users')))
         self.failUnless(self.execute('Any X, Y WHERE X is CWEType, X name "CWUser", Y is CWGroup, Y name "users"')[0])
         self.execute('DELETE X read_permission Y WHERE X is CWEType, X name "CWUser", Y name "users"')
-        self.assertEquals(schema['CWUser'].get_groups('read'), set(('managers', 'users', )))
+        self.assertEqual(schema['CWUser'].get_groups('read'), set(('managers', 'users', )))
         self.commit()
-        self.assertEquals(schema['CWUser'].get_groups('read'), set(('managers',)))
+        self.assertEqual(schema['CWUser'].get_groups('read'), set(('managers',)))
         self.execute('SET X read_permission Y WHERE X is CWEType, X name "CWUser", Y name "users"')
         self.commit()
-        self.assertEquals(schema['CWUser'].get_groups('read'), set(('managers', 'users',)))
+        self.assertEqual(schema['CWUser'].get_groups('read'), set(('managers', 'users',)))
 
     def test_perms_synchronization_2(self):
         schema = self.repo.schema['in_group'].rdefs[('CWUser', 'CWGroup')]
-        self.assertEquals(schema.get_groups('read'), set(('managers', 'users', 'guests')))
+        self.assertEqual(schema.get_groups('read'), set(('managers', 'users', 'guests')))
         self.execute('DELETE X read_permission Y WHERE X relation_type RT, RT name "in_group", Y name "guests"')
-        self.assertEquals(schema.get_groups('read'), set(('managers', 'users', 'guests')))
+        self.assertEqual(schema.get_groups('read'), set(('managers', 'users', 'guests')))
         self.commit()
-        self.assertEquals(schema.get_groups('read'), set(('managers', 'users')))
+        self.assertEqual(schema.get_groups('read'), set(('managers', 'users')))
         self.execute('SET X read_permission Y WHERE X relation_type RT, RT name "in_group", Y name "guests"')
-        self.assertEquals(schema.get_groups('read'), set(('managers', 'users')))
+        self.assertEqual(schema.get_groups('read'), set(('managers', 'users')))
         self.commit()
-        self.assertEquals(schema.get_groups('read'), set(('managers', 'users', 'guests')))
+        self.assertEqual(schema.get_groups('read'), set(('managers', 'users', 'guests')))
 
     def test_nonregr_user_edit_itself(self):
         ueid = self.session.user.eid
@@ -187,7 +187,7 @@
             self.failIf(self.schema['state_of'].inlined)
             self.failIf(self.index_exists('State', 'state_of'))
             rset = self.execute('Any X, Y WHERE X state_of Y')
-            self.assertEquals(len(rset), 2) # user states
+            self.assertEqual(len(rset), 2) # user states
         except:
             import traceback
             traceback.print_exc()
@@ -198,7 +198,7 @@
             self.failUnless(self.schema['state_of'].inlined)
             self.failUnless(self.index_exists('State', 'state_of'))
             rset = self.execute('Any X, Y WHERE X state_of Y')
-            self.assertEquals(len(rset), 2)
+            self.assertEqual(len(rset), 2)
 
     def test_indexed_change(self):
         self.session.set_pool()
@@ -317,7 +317,7 @@
         rdef = self.schema['Transition'].rdef('type')
         cstr = rdef.constraint_by_type('StaticVocabularyConstraint')
         if not getattr(cstr, 'eid', None):
-            self.skip('start me alone') # bug in schema reloading, constraint's eid not restored
+            self.skipTest('start me alone') # bug in schema reloading, constraint's eid not restored
         self.execute('SET X value %(v)s WHERE X eid %(x)s',
                      {'x': cstr.eid, 'v': u"u'normal', u'auto', u'new'"})
         self.execute('INSERT CWConstraint X: X value %(value)s, X cstrtype CT, EDEF constrained_by X '
@@ -325,7 +325,7 @@
                      {'ct': 'SizeConstraint', 'value': u'max=10', 'x': rdef.eid})
         self.commit()
         cstr = rdef.constraint_by_type('StaticVocabularyConstraint')
-        self.assertEquals(cstr.values, (u'normal', u'auto', u'new'))
+        self.assertEqual(cstr.values, (u'normal', u'auto', u'new'))
         self.execute('INSERT Transition T: T name "hop", T type "new"')
 
 if __name__ == '__main__':
--- a/server/test/unittest_fti.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_fti.py	Fri Sep 24 18:20:59 2010 +0200
@@ -12,7 +12,7 @@
 
     def setUp(self):
         if not socket.gethostname().endswith('.logilab.fr'):
-            self.skip('XXX require logilab configuration')
+            self.skipTest('XXX require logilab configuration')
         super(PostgresFTITC, self).setUp()
 
     def test_occurence_count(self):
@@ -24,7 +24,7 @@
         c3 = req.create_entity('Card', title=u'c2',
                                content=u'cubicweb cubicweb')
         self.commit()
-        self.assertEquals(req.execute('Card X ORDERBY FTIRANK(X) DESC WHERE X has_text "cubicweb"').rows,
+        self.assertEqual(req.execute('Card X ORDERBY FTIRANK(X) DESC WHERE X has_text "cubicweb"').rows,
                           [[c1.eid], [c3.eid], [c2.eid]])
 
 
@@ -41,7 +41,7 @@
             c3 = req.create_entity('Card', title=u'cubicweb',
                                    content=u'autre chose')
             self.commit()
-            self.assertEquals(req.execute('Card X ORDERBY FTIRANK(X) DESC WHERE X has_text "cubicweb"').rows,
+            self.assertEqual(req.execute('Card X ORDERBY FTIRANK(X) DESC WHERE X has_text "cubicweb"').rows,
                               [[c3.eid], [c1.eid], [c2.eid]])
 
 
@@ -55,5 +55,5 @@
             c2 = req.create_entity('Comment', content=u'cubicweb cubicweb', comments=c1)
             c3 = req.create_entity('Comment', content=u'cubicweb cubicweb cubicweb', comments=c1)
             self.commit()
-            self.assertEquals(req.execute('Any X ORDERBY FTIRANK(X) DESC WHERE X has_text "cubicweb"').rows,
+            self.assertEqual(req.execute('Any X ORDERBY FTIRANK(X) DESC WHERE X has_text "cubicweb"').rows,
                               [[c1.eid], [c3.eid], [c2.eid]])
--- a/server/test/unittest_hook.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_hook.py	Fri Sep 24 18:20:59 2010 +0200
@@ -47,7 +47,7 @@
         l1 = hook.LateOperation(session)
         l2 = hook.LateOperation(session)
         l3 = hook.Operation(session)
-        self.assertEquals(session.pending_operations, [l3, l1, l2])
+        self.assertEqual(session.pending_operations, [l3, l1, l2])
 
     @clean_session_ops
     def test_single_last_operation(self):
@@ -56,9 +56,9 @@
         l1 = hook.LateOperation(session)
         l2 = hook.LateOperation(session)
         l3 = hook.Operation(session)
-        self.assertEquals(session.pending_operations, [l3, l1, l2, l0])
+        self.assertEqual(session.pending_operations, [l3, l1, l2, l0])
         l4 = hook.SingleLastOperation(session)
-        self.assertEquals(session.pending_operations, [l3, l1, l2, l4])
+        self.assertEqual(session.pending_operations, [l3, l1, l2, l4])
 
     @clean_session_ops
     def test_global_operation_order(self):
@@ -70,7 +70,7 @@
         op3 = syncschema.MemSchemaNotifyChanges(session)
         op4 = integrity._DelayedDeleteOp(session)
         op5 = integrity._CheckORelationOp(session)
-        self.assertEquals(session.pending_operations, [op1, op2, op4, op5, op3])
+        self.assertEqual(session.pending_operations, [op1, op2, op4, op5, op3])
 
 
 class HookCalled(Exception): pass
@@ -102,19 +102,19 @@
         class _Hook(hook.Hook):
             events = ('before_add_entiti',)
         ex = self.assertRaises(Exception, self.o.register, _Hook)
-        self.assertEquals(str(ex), 'bad event before_add_entiti on %s._Hook' % __name__)
+        self.assertEqual(str(ex), 'bad event before_add_entiti on %s._Hook' % __name__)
 
     def test_register_bad_hook2(self):
         class _Hook(hook.Hook):
             events = None
         ex = self.assertRaises(Exception, self.o.register, _Hook)
-        self.assertEquals(str(ex), 'bad .events attribute None on %s._Hook' % __name__)
+        self.assertEqual(str(ex), 'bad .events attribute None on %s._Hook' % __name__)
 
     def test_register_bad_hook3(self):
         class _Hook(hook.Hook):
             events = 'before_add_entity'
         ex = self.assertRaises(Exception, self.o.register, _Hook)
-        self.assertEquals(str(ex), 'bad event b on %s._Hook' % __name__)
+        self.assertEqual(str(ex), 'bad event b on %s._Hook' % __name__)
 
     def test_call_hook(self):
         self.o.register(AddAnyHook)
@@ -138,17 +138,17 @@
 
     def test_startup_shutdown(self):
         import hooks # cubicweb/server/test/data/hooks.py
-        self.assertEquals(hooks.CALLED_EVENTS['server_startup'], True)
+        self.assertEqual(hooks.CALLED_EVENTS['server_startup'], True)
         # don't actually call repository.shutdown !
         self.repo.hm.call_hooks('server_shutdown', repo=self.repo)
-        self.assertEquals(hooks.CALLED_EVENTS['server_shutdown'], True)
+        self.assertEqual(hooks.CALLED_EVENTS['server_shutdown'], True)
 
     def test_session_open_close(self):
         import hooks # cubicweb/server/test/data/hooks.py
         cnx = self.login('anon')
-        self.assertEquals(hooks.CALLED_EVENTS['session_open'], 'anon')
+        self.assertEqual(hooks.CALLED_EVENTS['session_open'], 'anon')
         cnx.close()
-        self.assertEquals(hooks.CALLED_EVENTS['session_close'], 'anon')
+        self.assertEqual(hooks.CALLED_EVENTS['session_close'], 'anon')
 
 
 # class RelationHookTC(TestCase):
@@ -162,30 +162,30 @@
 #         """make sure before_xxx_relation hooks are called directly"""
 #         self.o.register(self._before_relation_hook,
 #                              'before_add_relation', 'concerne')
-#         self.assertEquals(self.called, [])
+#         self.assertEqual(self.called, [])
 #         self.o.call_hooks('before_add_relation', 'concerne', 'USER',
 #                           1, 'concerne', 2)
-#         self.assertEquals(self.called, [(1, 'concerne', 2)])
+#         self.assertEqual(self.called, [(1, 'concerne', 2)])
 
 #     def test_after_add_relation(self):
 #         """make sure after_xxx_relation hooks are deferred"""
 #         self.o.register(self._after_relation_hook,
 #                              'after_add_relation', 'concerne')
-#         self.assertEquals(self.called, [])
+#         self.assertEqual(self.called, [])
 #         self.o.call_hooks('after_add_relation', 'concerne', 'USER',
 #                           1, 'concerne', 2)
 #         self.o.call_hooks('after_add_relation', 'concerne', 'USER',
 #                           3, 'concerne', 4)
-#         self.assertEquals(self.called, [(1, 'concerne', 2), (3, 'concerne', 4)])
+#         self.assertEqual(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(self._before_relation_hook,
 #                              'before_delete_relation', 'concerne')
-#         self.assertEquals(self.called, [])
+#         self.assertEqual(self.called, [])
 #         self.o.call_hooks('before_delete_relation', 'concerne', 'USER',
 #                           1, 'concerne', 2)
-#         self.assertEquals(self.called, [(1, 'concerne', 2)])
+#         self.assertEqual(self.called, [(1, 'concerne', 2)])
 
 #     def test_after_delete_relation(self):
 #         """make sure after_xxx_relation hooks are deferred"""
@@ -195,7 +195,7 @@
 #                           1, 'concerne', 2)
 #         self.o.call_hooks('after_delete_relation', 'concerne', 'USER',
 #                           3, 'concerne', 4)
-#         self.assertEquals(self.called, [(1, 'concerne', 2), (3, 'concerne', 4)])
+#         self.assertEqual(self.called, [(1, 'concerne', 2), (3, 'concerne', 4)])
 
 
 #     def _before_relation_hook(self, pool, subject, r_type, object):
--- a/server/test/unittest_ldapuser.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_ldapuser.py	Fri Sep 24 18:20:59 2010 +0200
@@ -92,19 +92,19 @@
     def test_base(self):
         # check a known one
         e = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT}).get_entity(0, 0)
-        self.assertEquals(e.login, SYT)
+        self.assertEqual(e.login, SYT)
         e.complete()
-        self.assertEquals(e.creation_date, None)
-        self.assertEquals(e.modification_date, None)
-        self.assertEquals(e.firstname, None)
-        self.assertEquals(e.surname, None)
-        self.assertEquals(e.in_group[0].name, 'users')
-        self.assertEquals(e.owned_by[0].login, SYT)
-        self.assertEquals(e.created_by, ())
-        self.assertEquals(e.primary_email[0].address, 'Sylvain Thenault')
+        self.assertEqual(e.creation_date, None)
+        self.assertEqual(e.modification_date, None)
+        self.assertEqual(e.firstname, None)
+        self.assertEqual(e.surname, None)
+        self.assertEqual(e.in_group[0].name, 'users')
+        self.assertEqual(e.owned_by[0].login, SYT)
+        self.assertEqual(e.created_by, ())
+        self.assertEqual(e.primary_email[0].address, 'Sylvain Thenault')
         # email content should be indexed on the user
         rset = self.sexecute('CWUser X WHERE X has_text "thenault"')
-        self.assertEquals(rset.rows, [[e.eid]])
+        self.assertEqual(rset.rows, [[e.eid]])
 
     def test_not(self):
         eid = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT})[0][0]
@@ -117,16 +117,16 @@
         aeid = self.sexecute('CWUser X WHERE X login %(login)s', {'login': ADIM})[0][0]
         rset = self.sexecute('CWUser X, Y WHERE X login %(syt)s, Y login %(adim)s',
                             {'syt': SYT, 'adim': ADIM})
-        self.assertEquals(rset.rows, [[seid, aeid]])
+        self.assertEqual(rset.rows, [[seid, aeid]])
         rset = self.sexecute('Any X,Y,L WHERE X login L, X login %(syt)s, Y login %(adim)s',
                             {'syt': SYT, 'adim': ADIM})
-        self.assertEquals(rset.rows, [[seid, aeid, SYT]])
+        self.assertEqual(rset.rows, [[seid, aeid, SYT]])
 
     def test_in(self):
         seid = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT})[0][0]
         aeid = self.sexecute('CWUser X WHERE X login %(login)s', {'login': ADIM})[0][0]
         rset = self.sexecute('Any X,L ORDERBY L WHERE X login IN("%s", "%s"), X login L' % (SYT, ADIM))
-        self.assertEquals(rset.rows, [[aeid, ADIM], [seid, SYT]])
+        self.assertEqual(rset.rows, [[aeid, ADIM], [seid, SYT]])
 
     def test_relations(self):
         eid = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT})[0][0]
@@ -144,28 +144,28 @@
     def test_upper(self):
         eid = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT})[0][0]
         rset = self.sexecute('Any UPPER(L) WHERE X eid %s, X login L' % eid)
-        self.assertEquals(rset[0][0], SYT.upper())
+        self.assertEqual(rset[0][0], SYT.upper())
 
     def test_unknown_attr(self):
         eid = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT})[0][0]
         rset = self.sexecute('Any L,C,M WHERE X eid %s, X login L, '
                             'X creation_date C, X modification_date M' % eid)
-        self.assertEquals(rset[0][0], SYT)
-        self.assertEquals(rset[0][1], None)
-        self.assertEquals(rset[0][2], None)
+        self.assertEqual(rset[0][0], SYT)
+        self.assertEqual(rset[0][1], None)
+        self.assertEqual(rset[0][2], None)
 
     def test_sort(self):
         logins = [l for l, in self.sexecute('Any L ORDERBY L WHERE X login L')]
-        self.assertEquals(logins, sorted(logins))
+        self.assertEqual(logins, sorted(logins))
 
     def test_lower_sort(self):
         logins = [l for l, in self.sexecute('Any L ORDERBY lower(L) WHERE X login L')]
-        self.assertEquals(logins, sorted(logins))
+        self.assertEqual(logins, sorted(logins))
 
     def test_or(self):
         rset = self.sexecute('DISTINCT Any X WHERE X login %(login)s OR (X in_group G, G name "managers")',
                             {'login': SYT})
-        self.assertEquals(len(rset), 2, rset.rows) # syt + admin
+        self.assertEqual(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
@@ -173,7 +173,7 @@
         self.sexecute('SET X in_group G WHERE X login %(syt)s, G name "managers"', {'syt': SYT})
         self.commit()
         syt = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT}).get_entity(0, 0)
-        self.assertEquals([g.name for g in syt.in_group], ['managers', 'users'])
+        self.assertEqual([g.name for g in syt.in_group], ['managers', 'users'])
         self.patch_authenticate()
         cnx = self.login(SYT, password='dummypassword')
         cu = cnx.cursor()
@@ -183,15 +183,15 @@
         try:
             cnx.commit()
             adim.clear_all_caches()
-            self.assertEquals(adim.in_state[0].name, 'deactivated')
+            self.assertEqual(adim.in_state[0].name, 'deactivated')
             trinfo = iworkflowable.latest_trinfo()
-            self.assertEquals(trinfo.owned_by[0].login, SYT)
+            self.assertEqual(trinfo.owned_by[0].login, SYT)
             # select from_state to skip the user's creation TrInfo
             rset = self.sexecute('Any U ORDERBY D DESC WHERE WF wf_info_for X,'
                                 'WF creation_date D, WF from_state FS,'
                                 'WF owned_by U?, X eid %(x)s',
                                 {'x': adim.eid})
-            self.assertEquals(rset.rows, [[syt.eid]])
+            self.assertEqual(rset.rows, [[syt.eid]])
         finally:
             # restore db state
             self.restore_connection()
@@ -213,14 +213,14 @@
         self.sexecute('SET U in_group G WHERE G name ~= "bougloup%", U login "admin"')
         self.sexecute('SET U in_group G WHERE G name = "bougloup1", U login %(syt)s', {'syt': SYT})
         rset = self.sexecute('Any L,SN ORDERBY L WHERE X in_state S, S name SN, X login L, EXISTS(X in_group G, G name ~= "bougloup%")')
-        self.assertEquals(rset.rows, [['admin', 'activated'], [SYT, 'activated']])
+        self.assertEqual(rset.rows, [['admin', 'activated'], [SYT, 'activated']])
 
     def test_exists2(self):
         self.create_user('comme')
         self.create_user('cochon')
         self.sexecute('SET X copain Y WHERE X login "comme", Y login "cochon"')
         rset = self.sexecute('Any GN ORDERBY GN WHERE X in_group G, G name GN, (G name "managers" OR EXISTS(X copain T, T login in ("comme", "cochon")))')
-        self.assertEquals(rset.rows, [['managers'], ['users']])
+        self.assertEqual(rset.rows, [['managers'], ['users']])
 
     def test_exists3(self):
         self.create_user('comme')
@@ -230,7 +230,7 @@
         self.sexecute('SET X copain Y WHERE X login %(syt)s, Y login "cochon"', {'syt': SYT})
         self.failUnless(self.sexecute('Any X, Y WHERE X copain Y, X login %(syt)s, Y login "cochon"', {'syt': SYT}))
         rset = self.sexecute('Any GN,L WHERE X in_group G, X login L, G name GN, G name "managers" OR EXISTS(X copain T, T login in ("comme", "cochon"))')
-        self.assertEquals(sorted(rset.rows), [['managers', 'admin'], ['users', 'comme'], ['users', SYT]])
+        self.assertEqual(sorted(rset.rows), [['managers', 'admin'], ['users', 'comme'], ['users', SYT]])
 
     def test_exists4(self):
         self.create_user('comme')
@@ -252,7 +252,7 @@
         all = self.sexecute('Any GN, L WHERE X in_group G, X login L, G name GN')
         all.rows.remove(['users', 'comme'])
         all.rows.remove(['users', SYT])
-        self.assertEquals(sorted(rset.rows), sorted(all.rows))
+        self.assertEqual(sorted(rset.rows), sorted(all.rows))
 
     def test_exists5(self):
         self.create_user('comme')
@@ -265,25 +265,25 @@
         rset= self.sexecute('Any L WHERE X login L, '
                            'EXISTS(X copain T, T login in ("comme", "cochon")) AND '
                            'NOT EXISTS(X copain T2, T2 login "billy")')
-        self.assertEquals(sorted(rset.rows), [['cochon'], [SYT]])
+        self.assertEqual(sorted(rset.rows), [['cochon'], [SYT]])
         rset= self.sexecute('Any GN,L WHERE X in_group G, X login L, G name GN, '
                            'EXISTS(X copain T, T login in ("comme", "cochon")) AND '
                            'NOT EXISTS(X copain T2, T2 login "billy")')
-        self.assertEquals(sorted(rset.rows), [['guests', 'cochon'],
+        self.assertEqual(sorted(rset.rows), [['guests', 'cochon'],
                                               ['users', 'cochon'],
                                               ['users', SYT]])
 
     def test_cd_restriction(self):
         rset = self.sexecute('CWUser X WHERE X creation_date > "2009-02-01"')
         # admin/anon but no ldap user since it doesn't support creation_date
-        self.assertEquals(sorted(e.login for e in rset.entities()),
+        self.assertEqual(sorted(e.login for e in rset.entities()),
                           ['admin', 'anon'])
 
     def test_union(self):
         afeids = self.sexecute('State X')
         ueids = self.sexecute('CWUser X')
         rset = self.sexecute('(Any X WHERE X is State) UNION (Any X WHERE X is CWUser)')
-        self.assertEquals(sorted(r[0] for r in rset.rows),
+        self.assertEqual(sorted(r[0] for r in rset.rows),
                           sorted(r[0] for r in afeids + ueids))
 
     def _init_security_test(self):
@@ -294,23 +294,23 @@
     def test_security1(self):
         cu = self._init_security_test()
         rset = cu.execute('CWUser X WHERE X login %(login)s', {'login': SYT})
-        self.assertEquals(rset.rows, [])
+        self.assertEqual(rset.rows, [])
         rset = cu.execute('Any X WHERE X login "iaminguestsgrouponly"')
-        self.assertEquals(len(rset.rows), 1)
+        self.assertEqual(len(rset.rows), 1)
 
     def test_security2(self):
         cu = self._init_security_test()
         rset = cu.execute('Any X WHERE X has_text %(syt)s', {'syt': SYT})
-        self.assertEquals(rset.rows, [])
+        self.assertEqual(rset.rows, [])
         rset = cu.execute('Any X WHERE X has_text "iaminguestsgrouponly"')
-        self.assertEquals(len(rset.rows), 1)
+        self.assertEqual(len(rset.rows), 1)
 
     def test_security3(self):
         cu = self._init_security_test()
         rset = cu.execute('Any F WHERE X has_text %(syt)s, X firstname F', {'syt': SYT})
-        self.assertEquals(rset.rows, [])
+        self.assertEqual(rset.rows, [])
         rset = cu.execute('Any F WHERE X has_text "iaminguestsgrouponly", X firstname F')
-        self.assertEquals(rset.rows, [[None]])
+        self.assertEqual(rset.rows, [[None]])
 
     def test_nonregr1(self):
         self.sexecute('Any X,AA ORDERBY AA DESC WHERE E eid %(x)s, E owned_by X, '
@@ -351,34 +351,34 @@
     def test_count(self):
         trfunc = GlobTrFunc('count', 0)
         res = trfunc.apply([[1], [2], [3], [4]])
-        self.assertEquals(res, [[4]])
+        self.assertEqual(res, [[4]])
         trfunc = GlobTrFunc('count', 1)
         res = trfunc.apply([[1, 2], [2, 4], [3, 6], [1, 5]])
-        self.assertEquals(res, [[1, 2], [2, 1], [3, 1]])
+        self.assertEqual(res, [[1, 2], [2, 1], [3, 1]])
 
     def test_sum(self):
         trfunc = GlobTrFunc('sum', 0)
         res = trfunc.apply([[1], [2], [3], [4]])
-        self.assertEquals(res, [[10]])
+        self.assertEqual(res, [[10]])
         trfunc = GlobTrFunc('sum', 1)
         res = trfunc.apply([[1, 2], [2, 4], [3, 6], [1, 5]])
-        self.assertEquals(res, [[1, 7], [2, 4], [3, 6]])
+        self.assertEqual(res, [[1, 7], [2, 4], [3, 6]])
 
     def test_min(self):
         trfunc = GlobTrFunc('min', 0)
         res = trfunc.apply([[1], [2], [3], [4]])
-        self.assertEquals(res, [[1]])
+        self.assertEqual(res, [[1]])
         trfunc = GlobTrFunc('min', 1)
         res = trfunc.apply([[1, 2], [2, 4], [3, 6], [1, 5]])
-        self.assertEquals(res, [[1, 2], [2, 4], [3, 6]])
+        self.assertEqual(res, [[1, 2], [2, 4], [3, 6]])
 
     def test_max(self):
         trfunc = GlobTrFunc('max', 0)
         res = trfunc.apply([[1], [2], [3], [4]])
-        self.assertEquals(res, [[4]])
+        self.assertEqual(res, [[4]])
         trfunc = GlobTrFunc('max', 1)
         res = trfunc.apply([[1, 2], [2, 4], [3, 6], [1, 5]])
-        self.assertEquals(res, [[1, 5], [2, 4], [3, 6]])
+        self.assertEqual(res, [[1, 5], [2, 4], [3, 6]])
 
 # XXX
 LDAPUserSourceTC._init_repo()
@@ -405,13 +405,13 @@
 
     def test_base(self):
         rqlst = self._prepare('CWUser X WHERE X login "toto"').children[0]
-        self.assertEquals(self.o.generate(rqlst, 'X')[1],
+        self.assertEqual(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],
+        self.assertEqual(self.o.generate(rqlst, 'X')[1],
                           '(&(objectClass=top)(objectClass=posixAccount)(uid=toto))')
 
     def test_get_attr(self):
--- a/server/test/unittest_migractions.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_migractions.py	Fri Sep 24 18:20:59 2010 +0200
@@ -80,11 +80,11 @@
                                          'RDEF relation_type RT, RDEF ordernum O, RT name RTN'))
         self.mh.cmd_add_attribute('Note', 'whatever')
         self.failUnless('whatever' in self.schema)
-        self.assertEquals(self.schema['whatever'].subjects(), ('Note',))
-        self.assertEquals(self.schema['whatever'].objects(), ('Int',))
-        self.assertEquals(self.schema['Note'].default('whatever'), 2)
+        self.assertEqual(self.schema['whatever'].subjects(), ('Note',))
+        self.assertEqual(self.schema['whatever'].objects(), ('Int',))
+        self.assertEqual(self.schema['Note'].default('whatever'), 2)
         note = self.execute('Note X').get_entity(0, 0)
-        self.assertEquals(note.whatever, 2)
+        self.assertEqual(note.whatever, 2)
         orderdict2 = dict(self.mh.rqlexec('Any RTN, O WHERE X name "Note", RDEF from_entity X, '
                                           'RDEF relation_type RT, RDEF ordernum O, RT name RTN'))
         whateverorder = migrschema['whatever'].rdef('Note', 'Int').order
@@ -93,7 +93,7 @@
                 orderdict[k] = v+1
         orderdict['whatever'] = whateverorder
         self.assertDictEquals(orderdict, orderdict2)
-        #self.assertEquals([r.type for r in self.schema['Note'].ordered_relations()],
+        #self.assertEqual([r.type for r in self.schema['Note'].ordered_relations()],
         #                  ['modification_date', 'creation_date', 'owned_by',
         #                   'eid', 'ecrit_par', 'inline1', 'date', 'type',
         #                   'whatever', 'date', 'in_basket'])
@@ -106,12 +106,12 @@
         self.failIf('shortpara' in self.schema)
         self.mh.cmd_add_attribute('Note', 'shortpara')
         self.failUnless('shortpara' in self.schema)
-        self.assertEquals(self.schema['shortpara'].subjects(), ('Note', ))
-        self.assertEquals(self.schema['shortpara'].objects(), ('String', ))
+        self.assertEqual(self.schema['shortpara'].subjects(), ('Note', ))
+        self.assertEqual(self.schema['shortpara'].objects(), ('String', ))
         # test created column is actually a varchar(64)
         notesql = self.mh.sqlexec("SELECT sql FROM sqlite_master WHERE type='table' and name='%sNote'" % SQL_PREFIX)[0][0]
         fields = dict(x.strip().split()[:2] for x in notesql.split('(', 1)[1].rsplit(')', 1)[0].split(','))
-        self.assertEquals(fields['%sshortpara' % SQL_PREFIX], 'varchar(64)')
+        self.assertEqual(fields['%sshortpara' % SQL_PREFIX], 'varchar(64)')
         self.mh.rollback()
 
     def test_add_datetime_with_default_value_attribute(self):
@@ -119,15 +119,15 @@
         self.failIf('shortpara' in self.schema)
         self.mh.cmd_add_attribute('Note', 'mydate')
         self.failUnless('mydate' in self.schema)
-        self.assertEquals(self.schema['mydate'].subjects(), ('Note', ))
-        self.assertEquals(self.schema['mydate'].objects(), ('Date', ))
+        self.assertEqual(self.schema['mydate'].subjects(), ('Note', ))
+        self.assertEqual(self.schema['mydate'].objects(), ('Date', ))
         testdate = date(2005, 12, 13)
         eid1 = self.mh.rqlexec('INSERT Note N')[0][0]
         eid2 = self.mh.rqlexec('INSERT Note N: N mydate %(mydate)s', {'mydate' : testdate})[0][0]
         d1 = self.mh.rqlexec('Any D WHERE X eid %(x)s, X mydate D', {'x': eid1})[0][0]
         d2 = self.mh.rqlexec('Any D WHERE X eid %(x)s, X mydate D', {'x': eid2})[0][0]
-        self.assertEquals(d1, date.today())
-        self.assertEquals(d2, testdate)
+        self.assertEqual(d1, date.today())
+        self.assertEqual(d2, testdate)
         self.mh.rollback()
 
     def test_rename_attribute(self):
@@ -149,10 +149,10 @@
         for etype in ('Personne', 'Email'):
             s1 = self.mh.rqlexec('Any N WHERE WF workflow_of ET, ET name "%s", WF name N' %
                                  etype)[0][0]
-            self.assertEquals(s1, "foo")
+            self.assertEqual(s1, "foo")
             s1 = self.mh.rqlexec('Any N WHERE ET default_workflow WF, ET name "%s", WF name N' %
                                  etype)[0][0]
-            self.assertEquals(s1, "foo")
+            self.assertEqual(s1, "foo")
 
     def test_add_entity_type(self):
         self.failIf('Folder2' in self.schema)
@@ -163,18 +163,18 @@
         self.failUnless('filed_under2' in self.schema)
         self.failUnless(self.execute('CWRType X WHERE X name "filed_under2"'))
         self.schema.rebuild_infered_relations()
-        self.assertEquals(sorted(str(rs) for rs in self.schema['Folder2'].subject_relations()),
+        self.assertEqual(sorted(str(rs) for rs in self.schema['Folder2'].subject_relations()),
                           ['created_by', 'creation_date', 'cwuri',
                            'description', 'description_format',
                            'eid',
                            'filed_under2', 'has_text',
                            'identity', 'in_basket', 'is', 'is_instance_of',
                            'modification_date', 'name', 'owned_by'])
-        self.assertEquals([str(rs) for rs in self.schema['Folder2'].object_relations()],
+        self.assertEqual([str(rs) for rs in self.schema['Folder2'].object_relations()],
                           ['filed_under2', 'identity'])
-        self.assertEquals(sorted(str(e) for e in self.schema['filed_under2'].subjects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['filed_under2'].subjects()),
                           sorted(str(e) for e in self.schema.entities() if not e.final))
-        self.assertEquals(self.schema['filed_under2'].objects(), ('Folder2',))
+        self.assertEqual(self.schema['filed_under2'].objects(), ('Folder2',))
         eschema = self.schema.eschema('Folder2')
         for cstr in eschema.rdef('name').constraints:
             self.failUnless(hasattr(cstr, 'eid'))
@@ -201,22 +201,22 @@
         self.mh.cmd_add_relation_type('filed_under2')
         self.schema.rebuild_infered_relations()
         self.failUnless('filed_under2' in self.schema)
-        self.assertEquals(sorted(str(e) for e in self.schema['filed_under2'].subjects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['filed_under2'].subjects()),
                           sorted(str(e) for e in self.schema.entities() if not e.final))
-        self.assertEquals(self.schema['filed_under2'].objects(), ('Folder2',))
+        self.assertEqual(self.schema['filed_under2'].objects(), ('Folder2',))
         self.mh.cmd_drop_relation_type('filed_under2')
         self.failIf('filed_under2' in self.schema)
 
     def test_add_relation_definition_nortype(self):
         self.mh.cmd_add_relation_definition('Personne', 'concerne2', 'Affaire')
-        self.assertEquals(self.schema['concerne2'].subjects(),
+        self.assertEqual(self.schema['concerne2'].subjects(),
                           ('Personne',))
-        self.assertEquals(self.schema['concerne2'].objects(),
+        self.assertEqual(self.schema['concerne2'].objects(),
                           ('Affaire', ))
-        self.assertEquals(self.schema['concerne2'].rdef('Personne', 'Affaire').cardinality,
+        self.assertEqual(self.schema['concerne2'].rdef('Personne', 'Affaire').cardinality,
                           '1*')
         self.mh.cmd_add_relation_definition('Personne', 'concerne2', 'Note')
-        self.assertEquals(sorted(self.schema['concerne2'].objects()), ['Affaire', 'Note'])
+        self.assertEqual(sorted(self.schema['concerne2'].objects()), ['Affaire', 'Note'])
         self.mh.create_entity('Personne', nom=u'tot')
         self.mh.create_entity('Affaire')
         self.mh.rqlexec('SET X concerne2 Y WHERE X is Personne, Y is Affaire')
@@ -227,59 +227,59 @@
         self.failIf('concerne2' in self.schema)
 
     def test_drop_relation_definition_existant_rtype(self):
-        self.assertEquals(sorted(str(e) for e in self.schema['concerne'].subjects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()),
                           ['Affaire', 'Personne'])
-        self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
                           ['Affaire', 'Division', 'Note', 'Societe', 'SubDivision'])
         self.mh.cmd_drop_relation_definition('Personne', 'concerne', 'Affaire')
-        self.assertEquals(sorted(str(e) for e in self.schema['concerne'].subjects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()),
                           ['Affaire'])
-        self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
                           ['Division', 'Note', 'Societe', 'SubDivision'])
         self.mh.cmd_add_relation_definition('Personne', 'concerne', 'Affaire')
-        self.assertEquals(sorted(str(e) for e in self.schema['concerne'].subjects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()),
                           ['Affaire', 'Personne'])
-        self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
                           ['Affaire', 'Division', 'Note', 'Societe', 'SubDivision'])
         # trick: overwrite self.maxeid to avoid deletion of just reintroduced types
         self.maxeid = self.execute('Any MAX(X)')[0][0]
 
     def test_drop_relation_definition_with_specialization(self):
-        self.assertEquals(sorted(str(e) for e in self.schema['concerne'].subjects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()),
                           ['Affaire', 'Personne'])
-        self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
                           ['Affaire', 'Division', 'Note', 'Societe', 'SubDivision'])
         self.mh.cmd_drop_relation_definition('Affaire', 'concerne', 'Societe')
-        self.assertEquals(sorted(str(e) for e in self.schema['concerne'].subjects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()),
                           ['Affaire', 'Personne'])
-        self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
                           ['Affaire', 'Division', 'Note', 'SubDivision'])
         self.schema.rebuild_infered_relations() # need to be explicitly called once everything is in place
-        self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
                           ['Affaire', 'Note'])
         self.mh.cmd_add_relation_definition('Affaire', 'concerne', 'Societe')
-        self.assertEquals(sorted(str(e) for e in self.schema['concerne'].subjects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()),
                           ['Affaire', 'Personne'])
-        self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
                           ['Affaire', 'Note', 'Societe'])
         self.schema.rebuild_infered_relations() # need to be explicitly called once everything is in place
-        self.assertEquals(sorted(str(e) for e in self.schema['concerne'].objects()),
+        self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
                           ['Affaire', 'Division', 'Note', 'Societe', 'SubDivision'])
         # trick: overwrite self.maxeid to avoid deletion of just reintroduced types
         self.maxeid = self.execute('Any MAX(X)')[0][0]
 
     def test_rename_relation(self):
-        self.skip('implement me')
+        self.skipTest('implement me')
 
     def test_change_relation_props_non_final(self):
         rschema = self.schema['concerne']
         card = rschema.rdef('Affaire', 'Societe').cardinality
-        self.assertEquals(card, '**')
+        self.assertEqual(card, '**')
         try:
             self.mh.cmd_change_relation_props('Affaire', 'concerne', 'Societe',
                                               cardinality='?*')
             card = rschema.rdef('Affaire', 'Societe').cardinality
-            self.assertEquals(card, '?*')
+            self.assertEqual(card, '?*')
         finally:
             self.mh.cmd_change_relation_props('Affaire', 'concerne', 'Societe',
                                               cardinality='**')
@@ -287,12 +287,12 @@
     def test_change_relation_props_final(self):
         rschema = self.schema['adel']
         card = rschema.rdef('Personne', 'String').fulltextindexed
-        self.assertEquals(card, False)
+        self.assertEqual(card, False)
         try:
             self.mh.cmd_change_relation_props('Personne', 'adel', 'String',
                                               fulltextindexed=True)
             card = rschema.rdef('Personne', 'String').fulltextindexed
-            self.assertEquals(card, True)
+            self.assertEqual(card, True)
         finally:
             self.mh.cmd_change_relation_props('Personne', 'adel', 'String',
                                               fulltextindexed=False)
@@ -312,11 +312,11 @@
         
         self.mh.cmd_sync_schema_props_perms(commit=False)
 
-        self.assertEquals(cursor.execute('Any D WHERE X name "Personne", X description D')[0][0],
+        self.assertEqual(cursor.execute('Any D WHERE X name "Personne", X description D')[0][0],
                           'blabla bla')
-        self.assertEquals(cursor.execute('Any D WHERE X name "titre", X description D')[0][0],
+        self.assertEqual(cursor.execute('Any D WHERE X name "titre", X description D')[0][0],
                           'usually a title')
-        self.assertEquals(cursor.execute('Any D WHERE X relation_type RT, RT name "titre",'
+        self.assertEqual(cursor.execute('Any D WHERE X relation_type RT, RT name "titre",'
                                          'X from_entity FE, FE name "Personne",'
                                          'X description D')[0][0],
                           'title for this person')
@@ -327,29 +327,29 @@
         expected = [u'nom', u'prenom', u'sexe', u'promo', u'ass', u'adel', u'titre',
                     u'web', u'tel', u'fax', u'datenaiss', u'test', 'description', u'firstname',
                     u'creation_date', 'cwuri', u'modification_date']
-        self.assertEquals(rinorder, expected)
+        self.assertEqual(rinorder, expected)
 
         # test permissions synchronization ####################################
         # new rql expr to add note entity
         eexpr = self._erqlexpr_entity('add', 'Note')
-        self.assertEquals(eexpr.expression,
+        self.assertEqual(eexpr.expression,
                           'X ecrit_part PE, U in_group G, '
                           'PE require_permission P, P name "add_note", P require_group G')
-        self.assertEquals([et.name for et in eexpr.reverse_add_permission], ['Note'])
-        self.assertEquals(eexpr.reverse_read_permission, ())
-        self.assertEquals(eexpr.reverse_delete_permission, ())
-        self.assertEquals(eexpr.reverse_update_permission, ())
+        self.assertEqual([et.name for et in eexpr.reverse_add_permission], ['Note'])
+        self.assertEqual(eexpr.reverse_read_permission, ())
+        self.assertEqual(eexpr.reverse_delete_permission, ())
+        self.assertEqual(eexpr.reverse_update_permission, ())
         # no more rqlexpr to delete and add para attribute
         self.failIf(self._rrqlexpr_rset('add', 'para'))
         self.failIf(self._rrqlexpr_rset('delete', 'para'))
         # new rql expr to add ecrit_par relation
         rexpr = self._rrqlexpr_entity('add', 'ecrit_par')
-        self.assertEquals(rexpr.expression,
+        self.assertEqual(rexpr.expression,
                           'O require_permission P, P name "add_note", '
                           'U in_group G, P require_group G')
-        self.assertEquals([rdef.rtype.name for rdef in rexpr.reverse_add_permission], ['ecrit_par'])
-        self.assertEquals(rexpr.reverse_read_permission, ())
-        self.assertEquals(rexpr.reverse_delete_permission, ())
+        self.assertEqual([rdef.rtype.name for rdef in rexpr.reverse_add_permission], ['ecrit_par'])
+        self.assertEqual(rexpr.reverse_read_permission, ())
+        self.assertEqual(rexpr.reverse_delete_permission, ())
         # no more rqlexpr to delete and add travaille relation
         self.failIf(self._rrqlexpr_rset('add', 'travaille'))
         self.failIf(self._rrqlexpr_rset('delete', 'travaille'))
@@ -360,13 +360,13 @@
         self.failIf(self._erqlexpr_rset('read', 'Affaire'))
         # rqlexpr to update Affaire entity has been updated
         eexpr = self._erqlexpr_entity('update', 'Affaire')
-        self.assertEquals(eexpr.expression, 'X concerne S, S owned_by U')
+        self.assertEqual(eexpr.expression, 'X concerne S, S owned_by U')
         # no change for rqlexpr to add and delete Affaire entity
-        self.assertEquals(len(self._erqlexpr_rset('delete', 'Affaire')), 1)
-        self.assertEquals(len(self._erqlexpr_rset('add', 'Affaire')), 1)
+        self.assertEqual(len(self._erqlexpr_rset('delete', 'Affaire')), 1)
+        self.assertEqual(len(self._erqlexpr_rset('add', 'Affaire')), 1)
         # no change for rqlexpr to add and delete concerne relation
-        self.assertEquals(len(self._rrqlexpr_rset('delete', 'concerne')), len(delete_concerne_rqlexpr))
-        self.assertEquals(len(self._rrqlexpr_rset('add', 'concerne')), len(add_concerne_rqlexpr))
+        self.assertEqual(len(self._rrqlexpr_rset('delete', 'concerne')), len(delete_concerne_rqlexpr))
+        self.assertEqual(len(self._rrqlexpr_rset('add', 'concerne')), len(add_concerne_rqlexpr))
         # * migrschema involve:
         #   * 7 rqlexprs deletion (2 in (Affaire read + Societe + travaille) + 1
         #     in para attribute)
@@ -374,36 +374,36 @@
         #   * 2 new (Note add, ecrit_par add)
         #   * 2 implicit new for attributes update_permission (Note.para, Personne.test)
         # remaining orphan rql expr which should be deleted at commit (composite relation)
-        self.assertEquals(cursor.execute('Any COUNT(X) WHERE X is RQLExpression, '
+        self.assertEqual(cursor.execute('Any COUNT(X) WHERE X is RQLExpression, '
                                          'NOT ET1 read_permission X, NOT ET2 add_permission X, '
                                          'NOT ET3 delete_permission X, NOT ET4 update_permission X')[0][0],
                           7+1)
         # finally
-        self.assertEquals(cursor.execute('Any COUNT(X) WHERE X is RQLExpression')[0][0],
+        self.assertEqual(cursor.execute('Any COUNT(X) WHERE X is RQLExpression')[0][0],
                           nbrqlexpr_start + 1 + 2 + 2)
         self.mh.commit()
         # unique_together test
         self.assertEqual(len(self.schema.eschema('Personne')._unique_together), 1)
-        self.assertUnorderedIterableEquals(self.schema.eschema('Personne')._unique_together[0],
+        self.assertItemsEqual(self.schema.eschema('Personne')._unique_together[0],
                                            ('nom', 'prenom', 'datenaiss'))
         rset = cursor.execute('Any C WHERE C is CWUniqueTogetherConstraint')
-        self.assertEquals(len(rset), 1)
+        self.assertEqual(len(rset), 1)
         relations = [r.rtype.name for r in rset.get_entity(0,0).relations]
-        self.assertUnorderedIterableEquals(relations, ('nom', 'prenom', 'datenaiss'))
+        self.assertItemsEqual(relations, ('nom', 'prenom', 'datenaiss'))
 
     def _erqlexpr_rset(self, action, ertype):
         rql = 'RQLExpression X WHERE ET is CWEType, ET %s_permission X, ET name %%(name)s' % action
         return self.mh.session.execute(rql, {'name': ertype})
     def _erqlexpr_entity(self, action, ertype):
         rset = self._erqlexpr_rset(action, ertype)
-        self.assertEquals(len(rset), 1)
+        self.assertEqual(len(rset), 1)
         return rset.get_entity(0, 0)
     def _rrqlexpr_rset(self, action, ertype):
         rql = 'RQLExpression X WHERE RT is CWRType, RDEF %s_permission X, RT name %%(name)s, RDEF relation_type RT' % action
         return self.mh.session.execute(rql, {'name': ertype})
     def _rrqlexpr_entity(self, action, ertype):
         rset = self._rrqlexpr_rset(action, ertype)
-        self.assertEquals(len(rset), 1)
+        self.assertEqual(len(rset), 1)
         return rset.get_entity(0, 0)
 
     def test_set_size_constraint(self):
@@ -421,7 +421,7 @@
     def test_add_remove_cube_and_deps(self):
         cubes = set(self.config.cubes())
         schema = self.repo.schema
-        self.assertEquals(sorted((str(s), str(o)) for s, o in schema['see_also'].rdefs.keys()),
+        self.assertEqual(sorted((str(s), str(o)) for s, o in schema['see_also'].rdefs.keys()),
                           sorted([('EmailThread', 'EmailThread'), ('Folder', 'Folder'),
                                   ('Bookmark', 'Bookmark'), ('Bookmark', 'Note'),
                                   ('Note', 'Note'), ('Note', 'Bookmark')]))
@@ -436,16 +436,16 @@
                 for ertype in ('Email', 'EmailThread', 'EmailPart', 'File',
                                'sender', 'in_thread', 'reply_to', 'data_format'):
                     self.failIf(ertype in schema, ertype)
-                self.assertEquals(sorted(schema['see_also'].rdefs.keys()),
+                self.assertEqual(sorted(schema['see_also'].rdefs.keys()),
                                   sorted([('Folder', 'Folder'),
                                           ('Bookmark', 'Bookmark'),
                                           ('Bookmark', 'Note'),
                                           ('Note', 'Note'),
                                           ('Note', 'Bookmark')]))
-                self.assertEquals(sorted(schema['see_also'].subjects()), ['Bookmark', 'Folder', 'Note'])
-                self.assertEquals(sorted(schema['see_also'].objects()), ['Bookmark', 'Folder', 'Note'])
-                self.assertEquals(self.execute('Any X WHERE X pkey "system.version.email"').rowcount, 0)
-                self.assertEquals(self.execute('Any X WHERE X pkey "system.version.file"').rowcount, 0)
+                self.assertEqual(sorted(schema['see_also'].subjects()), ['Bookmark', 'Folder', 'Note'])
+                self.assertEqual(sorted(schema['see_also'].objects()), ['Bookmark', 'Folder', 'Note'])
+                self.assertEqual(self.execute('Any X WHERE X pkey "system.version.email"').rowcount, 0)
+                self.assertEqual(self.execute('Any X WHERE X pkey "system.version.file"').rowcount, 0)
             except :
                 import traceback
                 traceback.print_exc()
@@ -459,19 +459,19 @@
             for ertype in ('Email', 'EmailThread', 'EmailPart', 'File',
                            'sender', 'in_thread', 'reply_to', 'data_format'):
                 self.failUnless(ertype in schema, ertype)
-            self.assertEquals(sorted(schema['see_also'].rdefs.keys()),
+            self.assertEqual(sorted(schema['see_also'].rdefs.keys()),
                               sorted([('EmailThread', 'EmailThread'), ('Folder', 'Folder'),
                                       ('Bookmark', 'Bookmark'),
                                       ('Bookmark', 'Note'),
                                       ('Note', 'Note'),
                                       ('Note', 'Bookmark')]))
-            self.assertEquals(sorted(schema['see_also'].subjects()), ['Bookmark', 'EmailThread', 'Folder', 'Note'])
-            self.assertEquals(sorted(schema['see_also'].objects()), ['Bookmark', 'EmailThread', 'Folder', 'Note'])
+            self.assertEqual(sorted(schema['see_also'].subjects()), ['Bookmark', 'EmailThread', 'Folder', 'Note'])
+            self.assertEqual(sorted(schema['see_also'].objects()), ['Bookmark', 'EmailThread', 'Folder', 'Note'])
             from cubes.email.__pkginfo__ import version as email_version
             from cubes.file.__pkginfo__ import version as file_version
-            self.assertEquals(self.execute('Any V WHERE X value V, X pkey "system.version.email"')[0][0],
+            self.assertEqual(self.execute('Any V WHERE X value V, X pkey "system.version.email"')[0][0],
                               email_version)
-            self.assertEquals(self.execute('Any V WHERE X value V, X pkey "system.version.file"')[0][0],
+            self.assertEqual(self.execute('Any V WHERE X value V, X pkey "system.version.file"')[0][0],
                               file_version)
             # trick: overwrite self.maxeid to avoid deletion of just reintroduced
             #        types (and their associated tables!)
@@ -509,19 +509,19 @@
 
     def test_remove_dep_cube(self):
         ex = self.assertRaises(ConfigurationError, self.mh.cmd_remove_cube, 'file')
-        self.assertEquals(str(ex), "can't remove cube file, used as a dependency")
+        self.assertEqual(str(ex), "can't remove cube file, used as a dependency")
 
     def test_introduce_base_class(self):
         self.mh.cmd_add_entity_type('Para')
         self.mh.repo.schema.rebuild_infered_relations()
-        self.assertEquals(sorted(et.type for et in self.schema['Para'].specialized_by()),
+        self.assertEqual(sorted(et.type for et in self.schema['Para'].specialized_by()),
                           ['Note'])
-        self.assertEquals(self.schema['Note'].specializes().type, 'Para')
+        self.assertEqual(self.schema['Note'].specializes().type, 'Para')
         self.mh.cmd_add_entity_type('Text')
         self.mh.repo.schema.rebuild_infered_relations()
-        self.assertEquals(sorted(et.type for et in self.schema['Para'].specialized_by()),
+        self.assertEqual(sorted(et.type for et in self.schema['Para'].specialized_by()),
                           ['Note', 'Text'])
-        self.assertEquals(self.schema['Text'].specializes().type, 'Para')
+        self.assertEqual(self.schema['Text'].specializes().type, 'Para')
         # test columns have been actually added
         text = self.execute('INSERT Text X: X para "hip", X summary "hop", X newattr "momo"').get_entity(0, 0)
         note = self.execute('INSERT Note X: X para "hip", X shortpara "hop", X newattr "momo"').get_entity(0, 0)
@@ -548,10 +548,10 @@
             self.commit()
         finally:
             self.session.data['rebuild-infered'] = False
-        self.assertEquals(sorted(et.type for et in self.schema['Para'].specialized_by()),
+        self.assertEqual(sorted(et.type for et in self.schema['Para'].specialized_by()),
                           [])
-        self.assertEquals(self.schema['Note'].specializes(), None)
-        self.assertEquals(self.schema['Text'].specializes(), None)
+        self.assertEqual(self.schema['Note'].specializes(), None)
+        self.assertEqual(self.schema['Text'].specializes(), None)
 
 
     def test_add_symmetric_relation_type(self):
--- a/server/test/unittest_msplanner.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_msplanner.py	Fri Sep 24 18:20:59 2010 +0200
@@ -141,8 +141,8 @@
             for var in sourcevars.keys():
                 solindices = sourcevars.pop(var)
                 sourcevars[var._ms_table_key()] = solindices
-        self.assertEquals(ppi._sourcesterms, sourcesterms)
-        self.assertEquals(ppi.needsplit, needsplit)
+        self.assertEqual(ppi._sourcesterms, sourcesterms)
+        self.assertEqual(ppi.needsplit, needsplit)
 
 
     def test_simple_system_only(self):
@@ -2032,7 +2032,7 @@
         # identity relation. BUT I think it's better to leave it as is and to
         # explain constraint propagation rules, and so why this should be
         # wrapped in exists() if used in multi-source
-        self.skip('take a look at me if you wish')
+        self.skipTest('take a look at me if you wish')
         self._test('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, (U identity ME '
                    'OR (EXISTS(U in_group G, G name IN("managers", "staff")))) '
--- a/server/test/unittest_multisources.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_multisources.py	Fri Sep 24 18:20:59 2010 +0200
@@ -101,34 +101,34 @@
 
     def test_eid_comp(self):
         rset = self.sexecute('Card X WHERE X eid > 1')
-        self.assertEquals(len(rset), 4)
+        self.assertEqual(len(rset), 4)
         rset = self.sexecute('Any X,T WHERE X title T, X eid > 1')
-        self.assertEquals(len(rset), 4)
+        self.assertEqual(len(rset), 4)
 
     def test_metainformation(self):
         rset = self.sexecute('Card X ORDERBY T WHERE X title T')
         # 2 added to the system source, 2 added to the external source
-        self.assertEquals(len(rset), 4)
+        self.assertEqual(len(rset), 4)
         # since they are orderd by eid, we know the 3 first one is coming from the system source
         # and the others from external source
-        self.assertEquals(rset.get_entity(0, 0).cw_metainformation(),
+        self.assertEqual(rset.get_entity(0, 0).cw_metainformation(),
                           {'source': {'adapter': 'native', 'uri': 'system'},
                            'type': u'Card', 'extid': None})
         externent = rset.get_entity(3, 0)
         metainf = externent.cw_metainformation()
-        self.assertEquals(metainf['source'], {'adapter': 'pyrorql', 'base-url': 'http://extern.org/', 'uri': 'extern'})
-        self.assertEquals(metainf['type'], 'Card')
+        self.assertEqual(metainf['source'], {'adapter': 'pyrorql', 'base-url': 'http://extern.org/', 'uri': 'extern'})
+        self.assertEqual(metainf['type'], 'Card')
         self.assert_(metainf['extid'])
         etype = self.sexecute('Any ETN WHERE X is ET, ET name ETN, X eid %(x)s',
                              {'x': externent.eid})[0][0]
-        self.assertEquals(etype, 'Card')
+        self.assertEqual(etype, 'Card')
 
     def test_order_limit_offset(self):
         rsetbase = self.sexecute('Any W,X ORDERBY W,X WHERE X wikiid W')
-        self.assertEquals(len(rsetbase), 4)
-        self.assertEquals(sorted(rsetbase.rows), rsetbase.rows)
+        self.assertEqual(len(rsetbase), 4)
+        self.assertEqual(sorted(rsetbase.rows), rsetbase.rows)
         rset = self.sexecute('Any W,X ORDERBY W,X LIMIT 2 OFFSET 2 WHERE X wikiid W')
-        self.assertEquals(rset.rows, rsetbase.rows[2:4])
+        self.assertEqual(rset.rows, rsetbase.rows[2:4])
 
     def test_has_text(self):
         self.repo.sources_by_uri['extern'].synchronize(MTIME) # in case fti_update has been run before
@@ -148,9 +148,9 @@
         cu = cnx.cursor()
         rset = cu.execute('Any X WHERE X has_text "card"')
         # 5: 4 card + 1 readable affaire
-        self.assertEquals(len(rset), 5, zip(rset.rows, rset.description))
+        self.assertEqual(len(rset), 5, zip(rset.rows, rset.description))
         rset = cu.execute('Any X ORDERBY FTIRANK(X) WHERE X has_text "card"')
-        self.assertEquals(len(rset), 5, zip(rset.rows, rset.description))
+        self.assertEqual(len(rset), 5, zip(rset.rows, rset.description))
         Connection_close(cnx.cnx) # cnx is a TestCaseConnectionProxy
 
     def test_synchronization(self):
@@ -178,14 +178,14 @@
         affeid = self.sexecute('Affaire X WHERE X ref "AFFREF"')[0][0]
         rset = self.sexecute('Any X,AA,AB WHERE E eid %(x)s, E in_state X, X name AA, X modification_date AB',
                             {'x': affeid})
-        self.assertEquals(len(rset), 1)
-        self.assertEquals(rset[0][1], "pitetre")
+        self.assertEqual(len(rset), 1)
+        self.assertEqual(rset[0][1], "pitetre")
 
     def test_simplifiable_var_2(self):
         affeid = self.sexecute('Affaire X WHERE X ref "AFFREF"')[0][0]
         rset = self.sexecute('Any E WHERE E eid %(x)s, E in_state S, NOT S name "moved"',
                             {'x': affeid, 'u': self.session.user.eid})
-        self.assertEquals(len(rset), 1)
+        self.assertEqual(len(rset), 1)
 
     def test_sort_func(self):
         self.sexecute('Affaire X ORDERBY DUMB_SORT(RF) WHERE X ref RF')
@@ -197,31 +197,31 @@
         iec1 = self.repo.extid2eid(self.repo.sources_by_uri['extern'], str(self.ec1),
                                    'Card', self.session)
         rset = self.sexecute('Any X WHERE X eid IN (%s, %s)' % (iec1, self.ic1))
-        self.assertEquals(sorted(r[0] for r in rset.rows), sorted([iec1, self.ic1]))
+        self.assertEqual(sorted(r[0] for r in rset.rows), sorted([iec1, self.ic1]))
 
     def test_greater_eid(self):
         rset = self.sexecute('Any X WHERE X eid > %s' % (self.ic1 - 1))
-        self.assertEquals(len(rset.rows), 2) # self.ic1 and self.ic2
+        self.assertEqual(len(rset.rows), 2) # self.ic1 and self.ic2
         cu = cnx2.cursor()
         ec2 = cu.execute('INSERT Card X: X title "glup"')[0][0]
         cnx2.commit()
         # 'X eid > something' should not trigger discovery
         rset = self.sexecute('Any X WHERE X eid > %s' % (self.ic1 - 1))
-        self.assertEquals(len(rset.rows), 2)
+        self.assertEqual(len(rset.rows), 2)
         # trigger discovery using another query
         crset = self.sexecute('Card X WHERE X title "glup"')
-        self.assertEquals(len(crset.rows), 1)
+        self.assertEqual(len(crset.rows), 1)
         rset = self.sexecute('Any X WHERE X eid > %s' % (self.ic1 - 1))
-        self.assertEquals(len(rset.rows), 3)
+        self.assertEqual(len(rset.rows), 3)
         rset = self.sexecute('Any MAX(X)')
-        self.assertEquals(len(rset.rows), 1)
-        self.assertEquals(rset.rows[0][0], crset[0][0])
+        self.assertEqual(len(rset.rows), 1)
+        self.assertEqual(rset.rows[0][0], crset[0][0])
 
     def test_attr_unification_1(self):
         n1 = self.sexecute('INSERT Note X: X type "AFFREF"')[0][0]
         n2 = self.sexecute('INSERT Note X: X type "AFFREU"')[0][0]
         rset = self.sexecute('Any X,Y WHERE X is Note, Y is Affaire, X type T, Y ref T')
-        self.assertEquals(len(rset), 1, rset.rows)
+        self.assertEqual(len(rset), 1, rset.rows)
 
     def test_attr_unification_2(self):
         cu = cnx2.cursor()
@@ -230,7 +230,7 @@
         try:
             c1 = self.sexecute('INSERT Card C: C title "AFFREF"')[0][0]
             rset = self.sexecute('Any X,Y WHERE X is Card, Y is Affaire, X title T, Y ref T')
-            self.assertEquals(len(rset), 2, rset.rows)
+            self.assertEqual(len(rset), 2, rset.rows)
         finally:
             cu.execute('DELETE Card X WHERE X eid %(x)s', {'x': ec2})
             cnx2.commit()
@@ -247,26 +247,26 @@
         afeids = self.sexecute('Affaire X')
         ueids = self.sexecute('CWUser X')
         rset = self.sexecute('(Any X WHERE X is Affaire) UNION (Any X WHERE X is CWUser)')
-        self.assertEquals(sorted(r[0] for r in rset.rows),
+        self.assertEqual(sorted(r[0] for r in rset.rows),
                           sorted(r[0] for r in afeids + ueids))
 
     def test_subquery1(self):
         rsetbase = self.sexecute('Any W,X WITH W,X BEING (Any W,X ORDERBY W,X WHERE X wikiid W)')
-        self.assertEquals(len(rsetbase), 4)
-        self.assertEquals(sorted(rsetbase.rows), rsetbase.rows)
+        self.assertEqual(len(rsetbase), 4)
+        self.assertEqual(sorted(rsetbase.rows), rsetbase.rows)
         rset = self.sexecute('Any W,X LIMIT 2 OFFSET 2 WITH W,X BEING (Any W,X ORDERBY W,X WHERE X wikiid W)')
-        self.assertEquals(rset.rows, rsetbase.rows[2:4])
+        self.assertEqual(rset.rows, rsetbase.rows[2:4])
         rset = self.sexecute('Any W,X ORDERBY W,X LIMIT 2 OFFSET 2 WITH W,X BEING (Any W,X WHERE X wikiid W)')
-        self.assertEquals(rset.rows, rsetbase.rows[2:4])
+        self.assertEqual(rset.rows, rsetbase.rows[2:4])
         rset = self.sexecute('Any W,X WITH W,X BEING (Any W,X ORDERBY W,X LIMIT 2 OFFSET 2 WHERE X wikiid W)')
-        self.assertEquals(rset.rows, rsetbase.rows[2:4])
+        self.assertEqual(rset.rows, rsetbase.rows[2:4])
 
     def test_subquery2(self):
         affeid = self.sexecute('Affaire X WHERE X ref "AFFREF"')[0][0]
         rset = self.sexecute('Any X,AA,AB WITH X,AA,AB BEING (Any X,AA,AB WHERE E eid %(x)s, E in_state X, X name AA, X modification_date AB)',
                             {'x': affeid})
-        self.assertEquals(len(rset), 1)
-        self.assertEquals(rset[0][1], "pitetre")
+        self.assertEqual(len(rset), 1)
+        self.assertEqual(rset[0][1], "pitetre")
 
     def test_not_relation(self):
         states = set(tuple(x) for x in self.sexecute('Any S,SN WHERE S is State, S name SN'))
@@ -275,22 +275,22 @@
         states.remove((userstate.eid, userstate.name))
         notstates = set(tuple(x) for x in self.sexecute('Any S,SN WHERE S is State, S name SN, NOT X in_state S, X eid %(x)s',
                                                        {'x': self.session.user.eid}))
-        self.assertSetEquals(notstates, states)
+        self.assertSetEqual(notstates, states)
         aff1 = self.sexecute('Any X WHERE X is Affaire, X ref "AFFREF"')[0][0]
         aff1stateeid, aff1statename = self.sexecute('Any S,SN WHERE X eid %(x)s, X in_state S, S name SN', {'x': aff1})[0]
-        self.assertEquals(aff1statename, 'pitetre')
+        self.assertEqual(aff1statename, 'pitetre')
         states.add((userstate.eid, userstate.name))
         states.remove((aff1stateeid, aff1statename))
         notstates = set(tuple(x) for x in self.sexecute('Any S,SN WHERE S is State, S name SN, NOT X in_state S, X eid %(x)s',
                                                        {'x': aff1}))
-        self.assertSetEquals(notstates, states)
+        self.assertSetEqual(notstates, states)
 
     def test_absolute_url_base_url(self):
         cu = cnx2.cursor()
         ceid = cu.execute('INSERT Card X: X title "without wikiid to get eid based url"')[0][0]
         cnx2.commit()
         lc = self.sexecute('Card X WHERE X title "without wikiid to get eid based url"').get_entity(0, 0)
-        self.assertEquals(lc.absolute_url(), 'http://extern.org/card/eid/%s' % ceid)
+        self.assertEqual(lc.absolute_url(), 'http://extern.org/card/eid/%s' % ceid)
         cu.execute('DELETE Card X WHERE X eid %(x)s', {'x':ceid})
         cnx2.commit()
 
@@ -299,7 +299,7 @@
         ceid = cu.execute('INSERT Card X: X title "without wikiid to get eid based url"')[0][0]
         cnx3.commit()
         lc = self.sexecute('Card X WHERE X title "without wikiid to get eid based url"').get_entity(0, 0)
-        self.assertEquals(lc.absolute_url(), 'http://testing.fr/cubicweb/card/eid/%s' % lc.eid)
+        self.assertEqual(lc.absolute_url(), 'http://testing.fr/cubicweb/card/eid/%s' % lc.eid)
         cu.execute('DELETE Card X WHERE X eid %(x)s', {'x':ceid})
         cnx3.commit()
 
@@ -315,8 +315,8 @@
         treid = iworkflowable.latest_trinfo().eid
         rset = self.sexecute('Any X ORDERBY D DESC WHERE E eid %(x)s, E wf_info_for X, X modification_date D',
                             {'x': treid})
-        self.assertEquals(len(rset), 1)
-        self.assertEquals(rset.rows[0], [self.session.user.eid])
+        self.assertEqual(len(rset), 1)
+        self.assertEqual(rset.rows[0], [self.session.user.eid])
 
     def test_nonregr3(self):
         self.sexecute('DELETE Card X WHERE X eid %(x)s, NOT X multisource_inlined_rel Y', {'x': self.ic1})
--- a/server/test/unittest_querier.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_querier.py	Fri Sep 24 18:20:59 2010 +0200
@@ -57,7 +57,7 @@
 class MakeSchemaTC(TestCase):
     def test_known_values(self):
         solution = {'A': 'String', 'B': 'CWUser'}
-        self.assertEquals(make_schema((Variable('A'), Variable('B')), solution,
+        self.assertEqual(make_schema((Variable('A'), Variable('B')), solution,
                                       'table0', TYPEMAP),
                           ('C0 text,C1 integer', {'A': 'table0.C0', 'B': 'table0.C1'}))
 
@@ -84,7 +84,7 @@
     def test_preprocess_1(self):
         reid = self.execute('Any X WHERE X is CWRType, X name "owned_by"')[0][0]
         rqlst = self._prepare('Any COUNT(RDEF) WHERE RDEF relation_type X, X eid %(x)s', {'x': reid})
-        self.assertEquals(rqlst.solutions, [{'RDEF': 'CWAttribute'}, {'RDEF': 'CWRelation'}])
+        self.assertEqual(rqlst.solutions, [{'RDEF': 'CWAttribute'}, {'RDEF': 'CWRelation'}])
 
     def test_preprocess_2(self):
         teid = self.execute("INSERT Tag X: X name 'tag'")[0][0]
@@ -94,7 +94,7 @@
         rqlst = self._prepare('Any X WHERE E eid %(x)s, E tags X', {'x': teid})
         # the query may be optimized, should keep only one solution
         # (any one, etype will be discarded)
-        self.assertEquals(len(rqlst.solutions), 1)
+        self.assertEqual(len(rqlst.solutions), 1)
 
     def test_preprocess_security(self):
         plan = self._prepare_plan('Any ETN,COUNT(X) GROUPBY ETN '
@@ -102,24 +102,24 @@
         plan.session = self.user_groups_session('users')
         union = plan.rqlst
         plan.preprocess(union)
-        self.assertEquals(len(union.children), 1)
-        self.assertEquals(len(union.children[0].with_), 1)
+        self.assertEqual(len(union.children), 1)
+        self.assertEqual(len(union.children[0].with_), 1)
         subq = union.children[0].with_[0].query
-        self.assertEquals(len(subq.children), 3)
-        self.assertEquals([t.as_string() for t in union.children[0].selection],
+        self.assertEqual(len(subq.children), 3)
+        self.assertEqual([t.as_string() for t in union.children[0].selection],
                           ['ETN','COUNT(X)'])
-        self.assertEquals([t.as_string() for t in union.children[0].groupby],
+        self.assertEqual([t.as_string() for t in union.children[0].groupby],
                           ['ETN'])
         partrqls = sorted(((rqlst.as_string(), rqlst.solutions) for rqlst in subq.children))
         rql, solutions = partrqls[0]
-        self.assertEquals(rql,
+        self.assertEqual(rql,
                           'Any ETN,X WHERE X is ET, ET name ETN, (EXISTS(X owned_by %(B)s))'
                           ' OR ((((EXISTS(D concerne C?, C owned_by %(B)s, X identity D, C is Division, D is Affaire))'
                           ' OR (EXISTS(H concerne G?, G owned_by %(B)s, G is SubDivision, X identity H, H is Affaire)))'
                           ' OR (EXISTS(I concerne F?, F owned_by %(B)s, F is Societe, X identity I, I is Affaire)))'
                           ' OR (EXISTS(J concerne E?, E owned_by %(B)s, E is Note, X identity J, J is Affaire)))'
                           ', ET is CWEType, X is Affaire')
-        self.assertEquals(solutions, [{'C': 'Division',
+        self.assertEqual(solutions, [{'C': 'Division',
                                        'D': 'Affaire',
                                        'E': 'Note',
                                        'F': 'Societe',
@@ -130,8 +130,8 @@
                                        'X': 'Affaire',
                                        'ET': 'CWEType', 'ETN': 'String'}])
         rql, solutions = partrqls[1]
-        self.assertEquals(rql,  'Any ETN,X WHERE X is ET, ET name ETN, ET is CWEType, X is IN(BaseTransition, Bookmark, CWAttribute, CWCache, CWConstraint, CWConstraintType, CWEType, CWGroup, CWPermission, CWProperty, CWRType, CWRelation, CWUniqueTogetherConstraint, CWUser, Card, Comment, Division, Email, EmailAddress, EmailPart, EmailThread, ExternalUri, File, Folder, Note, Personne, RQLExpression, Societe, State, SubDivision, SubWorkflowExitPoint, Tag, TrInfo, Transition, Workflow, WorkflowTransition)')
-        self.assertListEquals(sorted(solutions),
+        self.assertEqual(rql,  'Any ETN,X WHERE X is ET, ET name ETN, ET is CWEType, X is IN(BaseTransition, Bookmark, CWAttribute, CWCache, CWConstraint, CWConstraintType, CWEType, CWGroup, CWPermission, CWProperty, CWRType, CWRelation, CWUniqueTogetherConstraint, CWUser, Card, Comment, Division, Email, EmailAddress, EmailPart, EmailThread, ExternalUri, File, Folder, Note, Personne, RQLExpression, Societe, State, SubDivision, SubWorkflowExitPoint, Tag, TrInfo, Transition, Workflow, WorkflowTransition)')
+        self.assertListEqual(sorted(solutions),
                               sorted([{'X': 'BaseTransition', 'ETN': 'String', 'ET': 'CWEType'},
                                       {'X': 'Bookmark', 'ETN': 'String', 'ET': 'CWEType'},
                                       {'X': 'Card', 'ETN': 'String', 'ET': 'CWEType'},
@@ -169,10 +169,10 @@
                                       {'X': 'Workflow', 'ETN': 'String', 'ET': 'CWEType'},
                                       {'X': 'WorkflowTransition', 'ETN': 'String', 'ET': 'CWEType'}]))
         rql, solutions = partrqls[2]
-        self.assertEquals(rql,
+        self.assertEqual(rql,
                           'Any ETN,X WHERE X is ET, ET name ETN, EXISTS(X owned_by %(C)s), '
                           'ET is CWEType, X is Basket')
-        self.assertEquals(solutions, [{'ET': 'CWEType',
+        self.assertEqual(solutions, [{'ET': 'CWEType',
                                        'X': 'Basket',
                                        'ETN': 'String',
                                        }])
@@ -182,45 +182,45 @@
         plan.session = self.user_groups_session('users')
         union = plan.rqlst
         plan.preprocess(union)
-        self.assertEquals(len(union.children), 1)
-        self.assertEquals(len(union.children[0].with_), 1)
+        self.assertEqual(len(union.children), 1)
+        self.assertEqual(len(union.children[0].with_), 1)
         subq = union.children[0].with_[0].query
-        self.assertEquals(len(subq.children), 3)
-        self.assertEquals([t.as_string() for t in union.children[0].selection],
+        self.assertEqual(len(subq.children), 3)
+        self.assertEqual([t.as_string() for t in union.children[0].selection],
                           ['MAX(X)'])
 
     def test_preprocess_nonregr(self):
         rqlst = self._prepare('Any S ORDERBY SI WHERE NOT S ecrit_par O, S para SI')
-        self.assertEquals(len(rqlst.solutions), 1)
+        self.assertEqual(len(rqlst.solutions), 1)
 
     def test_build_description(self):
         # should return an empty result set
         rset = self.execute('Any X WHERE X eid %(x)s', {'x': self.session.user.eid})
-        self.assertEquals(rset.description[0][0], 'CWUser')
+        self.assertEqual(rset.description[0][0], 'CWUser')
         rset = self.execute('Any 1')
-        self.assertEquals(rset.description[0][0], 'Int')
+        self.assertEqual(rset.description[0][0], 'Int')
         rset = self.execute('Any TRUE')
-        self.assertEquals(rset.description[0][0], 'Boolean')
+        self.assertEqual(rset.description[0][0], 'Boolean')
         rset = self.execute('Any "hop"')
-        self.assertEquals(rset.description[0][0], 'String')
+        self.assertEqual(rset.description[0][0], 'String')
         rset = self.execute('Any TODAY')
-        self.assertEquals(rset.description[0][0], 'Date')
+        self.assertEqual(rset.description[0][0], 'Date')
         rset = self.execute('Any NOW')
-        self.assertEquals(rset.description[0][0], 'Datetime')
+        self.assertEqual(rset.description[0][0], 'Datetime')
         rset = self.execute('Any %(x)s', {'x': 1})
-        self.assertEquals(rset.description[0][0], 'Int')
+        self.assertEqual(rset.description[0][0], 'Int')
         rset = self.execute('Any %(x)s', {'x': 1L})
-        self.assertEquals(rset.description[0][0], 'Int')
+        self.assertEqual(rset.description[0][0], 'Int')
         rset = self.execute('Any %(x)s', {'x': True})
-        self.assertEquals(rset.description[0][0], 'Boolean')
+        self.assertEqual(rset.description[0][0], 'Boolean')
         rset = self.execute('Any %(x)s', {'x': 1.0})
-        self.assertEquals(rset.description[0][0], 'Float')
+        self.assertEqual(rset.description[0][0], 'Float')
         rset = self.execute('Any %(x)s', {'x': datetime.now()})
-        self.assertEquals(rset.description[0][0], 'Datetime')
+        self.assertEqual(rset.description[0][0], 'Datetime')
         rset = self.execute('Any %(x)s', {'x': 'str'})
-        self.assertEquals(rset.description[0][0], 'String')
+        self.assertEqual(rset.description[0][0], 'String')
         rset = self.execute('Any %(x)s', {'x': u'str'})
-        self.assertEquals(rset.description[0][0], 'String')
+        self.assertEqual(rset.description[0][0], 'String')
 
 
 class QuerierTC(BaseQuerierTC):
@@ -244,46 +244,46 @@
                             {'data': Binary("xxx")})[0][0]
         fdata = self.execute('Any D WHERE X data D, X eid %(x)s', {'x': feid})[0][0]
         self.assertIsInstance(fdata, Binary)
-        self.assertEquals(fdata.getvalue(), 'xxx')
+        self.assertEqual(fdata.getvalue(), 'xxx')
 
     # selection queries tests #################################################
 
     def test_select_1(self):
         rset = self.execute('Any X ORDERBY X WHERE X is CWGroup')
         result, descr = rset.rows, rset.description
-        self.assertEquals(tuplify(result), [(1,), (2,), (3,), (4,)])
-        self.assertEquals(descr, [('CWGroup',), ('CWGroup',), ('CWGroup',), ('CWGroup',)])
+        self.assertEqual(tuplify(result), [(1,), (2,), (3,), (4,)])
+        self.assertEqual(descr, [('CWGroup',), ('CWGroup',), ('CWGroup',), ('CWGroup',)])
 
     def test_select_2(self):
         rset = self.execute('Any X ORDERBY N WHERE X is CWGroup, X name N')
-        self.assertEquals(tuplify(rset.rows), [(1,), (2,), (3,), (4,)])
-        self.assertEquals(rset.description, [('CWGroup',), ('CWGroup',), ('CWGroup',), ('CWGroup',)])
+        self.assertEqual(tuplify(rset.rows), [(1,), (2,), (3,), (4,)])
+        self.assertEqual(rset.description, [('CWGroup',), ('CWGroup',), ('CWGroup',), ('CWGroup',)])
         rset = self.execute('Any X ORDERBY N DESC WHERE X is CWGroup, X name N')
-        self.assertEquals(tuplify(rset.rows), [(4,), (3,), (2,), (1,)])
+        self.assertEqual(tuplify(rset.rows), [(4,), (3,), (2,), (1,)])
 
     def test_select_3(self):
         rset = self.execute('Any N GROUPBY N WHERE X is CWGroup, X name N')
         result, descr = rset.rows, rset.description
         result.sort()
-        self.assertEquals(tuplify(result), [('guests',), ('managers',), ('owners',), ('users',)])
-        self.assertEquals(descr, [('String',), ('String',), ('String',), ('String',)])
+        self.assertEqual(tuplify(result), [('guests',), ('managers',), ('owners',), ('users',)])
+        self.assertEqual(descr, [('String',), ('String',), ('String',), ('String',)])
 
     def test_select_is(self):
         rset = self.execute('Any X, TN ORDERBY TN LIMIT 10 WHERE X is T, T name TN')
         result, descr = rset.rows, rset.description
-        self.assertEquals(result[0][1], descr[0][0])
+        self.assertEqual(result[0][1], descr[0][0])
 
     def test_select_is_aggr(self):
         rset = self.execute('Any TN, COUNT(X) GROUPBY TN ORDERBY 2 DESC WHERE X is T, T name TN')
         result, descr = rset.rows, rset.description
-        self.assertEquals(descr[0][0], 'String')
-        self.assertEquals(descr[0][1], 'Int')
-        self.assertEquals(result[0][0], 'CWRelation') # XXX may change as schema evolve
+        self.assertEqual(descr[0][0], 'String')
+        self.assertEqual(descr[0][1], 'Int')
+        self.assertEqual(result[0][0], 'CWRelation') # XXX may change as schema evolve
 
     def test_select_groupby_orderby(self):
         rset = self.execute('Any N GROUPBY N ORDERBY N WHERE X is CWGroup, X name N')
-        self.assertEquals(tuplify(rset.rows), [('guests',), ('managers',), ('owners',), ('users',)])
-        self.assertEquals(rset.description, [('String',), ('String',), ('String',), ('String',)])
+        self.assertEqual(tuplify(rset.rows), [('guests',), ('managers',), ('owners',), ('users',)])
+        self.assertEqual(rset.description, [('String',), ('String',), ('String',), ('String',)])
 
     def test_select_complex_groupby(self):
         rset = self.execute('Any N GROUPBY N WHERE X name N')
@@ -295,20 +295,20 @@
 
     def test_select_complex_orderby(self):
         rset1 = self.execute('Any N ORDERBY N WHERE X name N')
-        self.assertEquals(sorted(rset1.rows), rset1.rows)
+        self.assertEqual(sorted(rset1.rows), rset1.rows)
         rset = self.execute('Any N ORDERBY N LIMIT 5 OFFSET 1 WHERE X name N')
-        self.assertEquals(rset.rows[0][0], rset1.rows[1][0])
-        self.assertEquals(len(rset), 5)
+        self.assertEqual(rset.rows[0][0], rset1.rows[1][0])
+        self.assertEqual(len(rset), 5)
 
     def test_select_5(self):
         rset = self.execute('Any X, TMP ORDERBY TMP WHERE X name TMP, X is CWGroup')
-        self.assertEquals(tuplify(rset.rows), [(1, 'guests',), (2, 'managers',), (3, 'owners',), (4, 'users',)])
-        self.assertEquals(rset.description, [('CWGroup', 'String',), ('CWGroup', 'String',), ('CWGroup', 'String',), ('CWGroup', 'String',)])
+        self.assertEqual(tuplify(rset.rows), [(1, 'guests',), (2, 'managers',), (3, 'owners',), (4, 'users',)])
+        self.assertEqual(rset.description, [('CWGroup', 'String',), ('CWGroup', 'String',), ('CWGroup', 'String',), ('CWGroup', 'String',)])
 
     def test_select_6(self):
         self.execute("INSERT Personne X: X nom 'bidule'")[0]
         rset = self.execute('Any Y where X name TMP, Y nom in (TMP, "bidule")')
-        #self.assertEquals(rset.description, [('Personne',), ('Personne',)])
+        #self.assertEqual(rset.description, [('Personne',), ('Personne',)])
         self.assert_(('Personne',) in rset.description)
         rset = self.execute('DISTINCT Any Y where X name TMP, Y nom in (TMP, "bidule")')
         self.assert_(('Personne',) in rset.description)
@@ -317,17 +317,17 @@
         peid = self.execute("INSERT Personne X: X nom 'bidule'")[0][0]
         seid = self.execute("INSERT Societe X: X nom 'chouette'")[0][0]
         rset = self.execute('Personne X WHERE NOT X nom "bidule"')
-        self.assertEquals(len(rset.rows), 0, rset.rows)
+        self.assertEqual(len(rset.rows), 0, rset.rows)
         rset = self.execute('Personne X WHERE NOT X nom "bid"')
-        self.assertEquals(len(rset.rows), 1, rset.rows)
+        self.assertEqual(len(rset.rows), 1, rset.rows)
         self.execute("SET P travaille S WHERE P nom 'bidule', S nom 'chouette'")
         rset = self.execute('Personne X WHERE NOT X travaille S')
-        self.assertEquals(len(rset.rows), 0, rset.rows)
+        self.assertEqual(len(rset.rows), 0, rset.rows)
 
     def test_select_is_in(self):
         self.execute("INSERT Personne X: X nom 'bidule'")
         self.execute("INSERT Societe X: X nom 'chouette'")
-        self.assertEquals(len(self.execute("Any X WHERE X is IN (Personne, Societe)")),
+        self.assertEqual(len(self.execute("Any X WHERE X is IN (Personne, Societe)")),
                           2)
 
     def test_select_not_rel(self):
@@ -336,9 +336,9 @@
         self.execute("INSERT Personne X: X nom 'autre'")
         self.execute("SET P travaille S WHERE P nom 'bidule', S nom 'chouette'")
         rset = self.execute('Personne X WHERE NOT X travaille S')
-        self.assertEquals(len(rset.rows), 1, rset.rows)
+        self.assertEqual(len(rset.rows), 1, rset.rows)
         rset = self.execute('Personne X WHERE NOT X travaille S, S nom "chouette"')
-        self.assertEquals(len(rset.rows), 1, rset.rows)
+        self.assertEqual(len(rset.rows), 1, rset.rows)
 
     def test_select_nonregr_inlined(self):
         self.execute("INSERT Note X: X para 'bidule'")
@@ -347,15 +347,15 @@
         self.execute("SET X ecrit_par P WHERE X para 'bidule', P nom 'chouette'")
         rset = self.execute('Any U,T ORDERBY T DESC WHERE U is CWUser, '
                             'N ecrit_par U, N type T')#, {'x': self.ueid})
-        self.assertEquals(len(rset.rows), 0)
+        self.assertEqual(len(rset.rows), 0)
 
     def test_select_nonregr_edition_not(self):
         groupeids = set((1, 2, 3))
         groupreadperms = set(r[0] for r in self.execute('Any Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), X read_permission Y'))
         rset = self.execute('DISTINCT Any Y WHERE X is CWEType, X name "CWGroup", Y eid IN(1, 2, 3), NOT X read_permission Y')
-        self.assertEquals(sorted(r[0] for r in rset.rows), sorted(groupeids - groupreadperms))
+        self.assertEqual(sorted(r[0] for r in rset.rows), sorted(groupeids - groupreadperms))
         rset = self.execute('DISTINCT Any Y WHERE X name "CWGroup", Y eid IN(1, 2, 3), NOT X read_permission Y')
-        self.assertEquals(sorted(r[0] for r in rset.rows), sorted(groupeids - groupreadperms))
+        self.assertEqual(sorted(r[0] for r in rset.rows), sorted(groupeids - groupreadperms))
 
     def test_select_outer_join(self):
         peid1 = self.execute("INSERT Personne X: X nom 'bidule'")[0][0]
@@ -363,27 +363,27 @@
         seid1 = self.execute("INSERT Societe X: X nom 'chouette'")[0][0]
         seid2 = self.execute("INSERT Societe X: X nom 'chouetos'")[0][0]
         rset = self.execute('Any X,S ORDERBY X WHERE X travaille S?')
-        self.assertEquals(rset.rows, [[peid1, None], [peid2, None]])
+        self.assertEqual(rset.rows, [[peid1, None], [peid2, None]])
         self.execute("SET P travaille S WHERE P nom 'bidule', S nom 'chouette'")
         rset = self.execute('Any X,S ORDERBY X WHERE X travaille S?')
-        self.assertEquals(rset.rows, [[peid1, seid1], [peid2, None]])
+        self.assertEqual(rset.rows, [[peid1, seid1], [peid2, None]])
         rset = self.execute('Any S,X ORDERBY S WHERE X? travaille S')
-        self.assertEquals(rset.rows, [[seid1, peid1], [seid2, None]])
+        self.assertEqual(rset.rows, [[seid1, peid1], [seid2, None]])
 
     def test_select_outer_join_optimized(self):
         peid1 = self.execute("INSERT Personne X: X nom 'bidule'")[0][0]
         rset = self.execute('Any X WHERE X eid %(x)s, P? connait X', {'x':peid1})
-        self.assertEquals(rset.rows, [[peid1]])
+        self.assertEqual(rset.rows, [[peid1]])
         rset = self.execute('Any X WHERE X eid %(x)s, X require_permission P?',
                             {'x':peid1})
-        self.assertEquals(rset.rows, [[peid1]])
+        self.assertEqual(rset.rows, [[peid1]])
 
     def test_select_left_outer_join(self):
         rset = self.execute('DISTINCT Any G WHERE U? in_group G')
-        self.assertEquals(len(rset), 4)
+        self.assertEqual(len(rset), 4)
         rset = self.execute('DISTINCT Any G WHERE U? in_group G, U eid %(x)s',
                             {'x': self.session.user.eid})
-        self.assertEquals(len(rset), 4)
+        self.assertEqual(len(rset), 4)
 
     def test_select_ambigous_outer_join(self):
         teid = self.execute("INSERT Tag X: X name 'tag'")[0][0]
@@ -395,7 +395,7 @@
         self.failUnless(['users', 'tag'] in rset.rows)
         self.failUnless(['activated', None] in rset.rows)
         rset = self.execute("Any GN,TN ORDERBY GN WHERE T tags G?, T name TN, G name GN")
-        self.assertEquals(rset.rows, [[None, 'tagbis'], ['users', 'tag']])
+        self.assertEqual(rset.rows, [[None, 'tagbis'], ['users', 'tag']])
 
     def test_select_not_inline_rel(self):
         self.execute("INSERT Personne X: X nom 'bidule'")
@@ -403,7 +403,7 @@
         self.execute("INSERT Note X: X type 'b'")
         self.execute("SET X ecrit_par Y WHERE X type 'a', Y nom 'bidule'")
         rset = self.execute('Note X WHERE NOT X ecrit_par P')
-        self.assertEquals(len(rset.rows), 1, rset.rows)
+        self.assertEqual(len(rset.rows), 1, rset.rows)
 
     def test_select_not_unlinked_multiple_solutions(self):
         self.execute("INSERT Personne X: X nom 'bidule'")
@@ -411,7 +411,7 @@
         self.execute("INSERT Note X: X type 'b'")
         self.execute("SET Y evaluee X WHERE X type 'a', Y nom 'bidule'")
         rset = self.execute('Note X WHERE NOT Y evaluee X')
-        self.assertEquals(len(rset.rows), 1, rset.rows)
+        self.assertEqual(len(rset.rows), 1, rset.rows)
 
     def test_select_date_extraction(self):
         self.execute("INSERT Personne X: X nom 'foo', X datenaiss %(d)s",
@@ -421,41 +421,41 @@
         for funcname, result in test_data:
             rset = self.execute('Any %s(D) WHERE X is Personne, X datenaiss D'
                                 % funcname)
-            self.assertEquals(len(rset.rows), 1)
-            self.assertEquals(rset.rows[0][0], result)
-            self.assertEquals(rset.description, [('Int',)])
+            self.assertEqual(len(rset.rows), 1)
+            self.assertEqual(rset.rows[0][0], result)
+            self.assertEqual(rset.description, [('Int',)])
 
     def test_select_aggregat_count(self):
         rset = self.execute('Any COUNT(X)')
-        self.assertEquals(len(rset.rows), 1)
-        self.assertEquals(len(rset.rows[0]), 1)
-        self.assertEquals(rset.description, [('Int',)])
+        self.assertEqual(len(rset.rows), 1)
+        self.assertEqual(len(rset.rows[0]), 1)
+        self.assertEqual(rset.description, [('Int',)])
 
     def test_select_aggregat_sum(self):
         rset = self.execute('Any SUM(O) WHERE X ordernum O')
-        self.assertEquals(len(rset.rows), 1)
-        self.assertEquals(len(rset.rows[0]), 1)
-        self.assertEquals(rset.description, [('Int',)])
+        self.assertEqual(len(rset.rows), 1)
+        self.assertEqual(len(rset.rows[0]), 1)
+        self.assertEqual(rset.description, [('Int',)])
 
     def test_select_aggregat_min(self):
         rset = self.execute('Any MIN(X) WHERE X is Personne')
-        self.assertEquals(len(rset.rows), 1)
-        self.assertEquals(len(rset.rows[0]), 1)
-        self.assertEquals(rset.description, [('Personne',)])
+        self.assertEqual(len(rset.rows), 1)
+        self.assertEqual(len(rset.rows[0]), 1)
+        self.assertEqual(rset.description, [('Personne',)])
         rset = self.execute('Any MIN(O) WHERE X ordernum O')
-        self.assertEquals(len(rset.rows), 1)
-        self.assertEquals(len(rset.rows[0]), 1)
-        self.assertEquals(rset.description, [('Int',)])
+        self.assertEqual(len(rset.rows), 1)
+        self.assertEqual(len(rset.rows[0]), 1)
+        self.assertEqual(rset.description, [('Int',)])
 
     def test_select_aggregat_max(self):
         rset = self.execute('Any MAX(X) WHERE X is Personne')
-        self.assertEquals(len(rset.rows), 1)
-        self.assertEquals(len(rset.rows[0]), 1)
-        self.assertEquals(rset.description, [('Personne',)])
+        self.assertEqual(len(rset.rows), 1)
+        self.assertEqual(len(rset.rows[0]), 1)
+        self.assertEqual(rset.description, [('Personne',)])
         rset = self.execute('Any MAX(O) WHERE X ordernum O')
-        self.assertEquals(len(rset.rows), 1)
-        self.assertEquals(len(rset.rows[0]), 1)
-        self.assertEquals(rset.description, [('Int',)])
+        self.assertEqual(len(rset.rows), 1)
+        self.assertEqual(len(rset.rows[0]), 1)
+        self.assertEqual(rset.description, [('Int',)])
 
     def test_select_custom_aggregat_concat_string(self):
         rset = self.execute('Any GROUP_CONCAT(N) WHERE X is CWGroup, X name N')
@@ -482,15 +482,15 @@
 
     def test_select_aggregat_sort(self):
         rset = self.execute('Any G, COUNT(U) GROUPBY G ORDERBY 2 WHERE U in_group G')
-        self.assertEquals(len(rset.rows), 2)
-        self.assertEquals(len(rset.rows[0]), 2)
-        self.assertEquals(rset.description[0], ('CWGroup', 'Int',))
+        self.assertEqual(len(rset.rows), 2)
+        self.assertEqual(len(rset.rows[0]), 2)
+        self.assertEqual(rset.description[0], ('CWGroup', 'Int',))
 
     def test_select_aggregat_having(self):
         rset = self.execute('Any N,COUNT(RDEF) GROUPBY N ORDERBY 2,N '
                             'WHERE RT name N, RDEF relation_type RT '
                             'HAVING COUNT(RDEF) > 10')
-        self.assertListEquals(rset.rows,
+        self.assertListEqual(rset.rows,
                               [[u'description_format', 12],
                                [u'description', 13],
                                [u'name', 14],
@@ -508,13 +508,13 @@
         rset = self.execute('Any U,COUNT(X) GROUPBY U '
                             'WHERE U eid %(x)s, X owned_by U '
                             'HAVING COUNT(X) > 10', {'x': self.ueid})
-        self.assertEquals(len(rset.rows), 1)
-        self.assertEquals(rset.rows[0][0], self.ueid)
+        self.assertEqual(len(rset.rows), 1)
+        self.assertEqual(rset.rows[0][0], self.ueid)
 
     def test_select_having_non_aggregat_1(self):
         rset = self.execute('Any L WHERE X login L, X creation_date CD '
                             'HAVING YEAR(CD) = %s' % date.today().year)
-        self.assertListEquals(rset.rows,
+        self.assertListEqual(rset.rows,
                               [[u'admin'],
                                [u'anon']])
 
@@ -522,7 +522,7 @@
         rset = self.execute('Any L GROUPBY L WHERE X login L, X in_group G, '
                             'X creation_date CD HAVING YEAR(CD) = %s OR COUNT(G) > 1'
                             % date.today().year)
-        self.assertListEquals(rset.rows,
+        self.assertListEqual(rset.rows,
                               [[u'admin'],
                                [u'anon']])
 
@@ -531,26 +531,26 @@
         rset = self.execute('Any X ORDERBY X,D LIMIT 5 WHERE X creation_date D')
         result = rset.rows
         result.sort()
-        self.assertEquals(tuplify(result), [(1,), (2,), (3,), (4,), (5,)])
+        self.assertEqual(tuplify(result), [(1,), (2,), (3,), (4,), (5,)])
 
     def test_select_upper(self):
         rset = self.execute('Any X, UPPER(L) ORDERBY L WHERE X is CWUser, X login L')
-        self.assertEquals(len(rset.rows), 2)
-        self.assertEquals(rset.rows[0][1], 'ADMIN')
-        self.assertEquals(rset.description[0], ('CWUser', 'String',))
-        self.assertEquals(rset.rows[1][1], 'ANON')
-        self.assertEquals(rset.description[1], ('CWUser', 'String',))
+        self.assertEqual(len(rset.rows), 2)
+        self.assertEqual(rset.rows[0][1], 'ADMIN')
+        self.assertEqual(rset.description[0], ('CWUser', 'String',))
+        self.assertEqual(rset.rows[1][1], 'ANON')
+        self.assertEqual(rset.description[1], ('CWUser', 'String',))
         eid = rset.rows[0][0]
         rset = self.execute('Any UPPER(L) WHERE X eid %s, X login L'%eid)
-        self.assertEquals(rset.rows[0][0], 'ADMIN')
-        self.assertEquals(rset.description, [('String',)])
+        self.assertEqual(rset.rows[0][0], 'ADMIN')
+        self.assertEqual(rset.description, [('String',)])
 
 ##     def test_select_simplified(self):
 ##         ueid = self.session.user.eid
 ##         rset = self.execute('Any L WHERE %s login L'%ueid)
-##         self.assertEquals(rset.rows[0][0], 'admin')
+##         self.assertEqual(rset.rows[0][0], 'admin')
 ##         rset = self.execute('Any L WHERE %(x)s login L', {'x':ueid})
-##         self.assertEquals(rset.rows[0][0], 'admin')
+##         self.assertEqual(rset.rows[0][0], 'admin')
 
     def test_select_searchable_text_1(self):
         rset = self.execute(u"INSERT Personne X: X nom 'bidüle'")
@@ -558,9 +558,9 @@
         rset = self.execute("INSERT Societe X: X nom 'chouette'")
         self.commit()
         rset = self.execute('Any X where X has_text %(text)s', {'text': u'bidüle'})
-        self.assertEquals(len(rset.rows), 2, rset.rows)
+        self.assertEqual(len(rset.rows), 2, rset.rows)
         rset = self.execute(u'Any N where N has_text "bidüle"')
-        self.assertEquals(len(rset.rows), 2, rset.rows)
+        self.assertEqual(len(rset.rows), 2, rset.rows)
         biduleeids = [r[0] for r in rset.rows]
         rset = self.execute(u'Any N where NOT N has_text "bidüle"')
         self.failIf([r[0] for r in rset.rows if r[0] in biduleeids])
@@ -573,7 +573,7 @@
         rset = self.execute("INSERT Societe X: X nom 'bidule'")
         self.commit()
         rset = self.execute('Personne N where N has_text "bidule"')
-        self.assertEquals(len(rset.rows), 1, rset.rows)
+        self.assertEqual(len(rset.rows), 1, rset.rows)
 
     def test_select_searchable_text_3(self):
         rset = self.execute("INSERT Personne X: X nom 'bidule', X sexe 'M'")
@@ -581,7 +581,7 @@
         rset = self.execute("INSERT Societe X: X nom 'bidule'")
         self.commit()
         rset = self.execute('Any X where X has_text "bidule" and X sexe "M"')
-        self.assertEquals(len(rset.rows), 1, rset.rows)
+        self.assertEqual(len(rset.rows), 1, rset.rows)
 
     def test_select_multiple_searchable_text(self):
         self.execute(u"INSERT Personne X: X nom 'bidüle'")
@@ -592,20 +592,20 @@
                             {'text': u'bidüle',
                              'text2': u'chouette',}
                             )
-        self.assertEquals(len(rset.rows), 1, rset.rows)
+        self.assertEqual(len(rset.rows), 1, rset.rows)
 
     def test_select_no_descr(self):
         rset = self.execute('Any X WHERE X is CWGroup', build_descr=0)
         rset.rows.sort()
-        self.assertEquals(tuplify(rset.rows), [(1,), (2,), (3,), (4,)])
-        self.assertEquals(rset.description, ())
+        self.assertEqual(tuplify(rset.rows), [(1,), (2,), (3,), (4,)])
+        self.assertEqual(rset.description, ())
 
     def test_select_limit_offset(self):
         rset = self.execute('CWGroup X ORDERBY N LIMIT 2 WHERE X name N')
-        self.assertEquals(tuplify(rset.rows), [(1,), (2,)])
-        self.assertEquals(rset.description, [('CWGroup',), ('CWGroup',)])
+        self.assertEqual(tuplify(rset.rows), [(1,), (2,)])
+        self.assertEqual(rset.description, [('CWGroup',), ('CWGroup',)])
         rset = self.execute('CWGroup X ORDERBY N LIMIT 2 OFFSET 2 WHERE X name N')
-        self.assertEquals(tuplify(rset.rows), [(3,), (4,)])
+        self.assertEqual(tuplify(rset.rows), [(3,), (4,)])
 
     def test_select_symmetric(self):
         self.execute("INSERT Personne X: X nom 'machin'")
@@ -615,24 +615,24 @@
         self.execute("SET X connait Y WHERE X nom 'chouette', Y nom 'bidule'")
         self.execute("SET X connait Y WHERE X nom 'machin', Y nom 'chouette'")
         rset = self.execute('Any P where P connait P2')
-        self.assertEquals(len(rset.rows), 3, rset.rows)
+        self.assertEqual(len(rset.rows), 3, rset.rows)
         rset = self.execute('Any P where NOT P connait P2')
-        self.assertEquals(len(rset.rows), 1, rset.rows) # trucmuche
+        self.assertEqual(len(rset.rows), 1, rset.rows) # trucmuche
         rset = self.execute('Any P where P connait P2, P2 nom "bidule"')
-        self.assertEquals(len(rset.rows), 1, rset.rows)
+        self.assertEqual(len(rset.rows), 1, rset.rows)
         rset = self.execute('Any P where P2 connait P, P2 nom "bidule"')
-        self.assertEquals(len(rset.rows), 1, rset.rows)
+        self.assertEqual(len(rset.rows), 1, rset.rows)
         rset = self.execute('Any P where P connait P2, P2 nom "chouette"')
-        self.assertEquals(len(rset.rows), 2, rset.rows)
+        self.assertEqual(len(rset.rows), 2, rset.rows)
         rset = self.execute('Any P where P2 connait P, P2 nom "chouette"')
-        self.assertEquals(len(rset.rows), 2, rset.rows)
+        self.assertEqual(len(rset.rows), 2, rset.rows)
 
     def test_select_inline(self):
         self.execute("INSERT Personne X: X nom 'bidule'")
         self.execute("INSERT Note X: X type 'a'")
         self.execute("SET X ecrit_par Y WHERE X type 'a', Y nom 'bidule'")
         rset = self.execute('Any N where N ecrit_par X, X nom "bidule"')
-        self.assertEquals(len(rset.rows), 1, rset.rows)
+        self.assertEqual(len(rset.rows), 1, rset.rows)
 
     def test_select_creation_date(self):
         self.execute("INSERT Personne X: X nom 'bidule'")
@@ -702,13 +702,13 @@
     def test_select_explicit_eid(self):
         rset = self.execute('Any X,E WHERE X owned_by U, X eid E, U eid %(u)s', {'u': self.session.user.eid})
         self.failUnless(rset)
-        self.assertEquals(rset.description[0][1], 'Int')
+        self.assertEqual(rset.description[0][1], 'Int')
 
 #     def test_select_rewritten_optional(self):
 #         eid = self.execute("INSERT Affaire X: X sujet 'cool'")[0][0]
 #         rset = self.execute('Any X WHERE X eid %(x)s, EXISTS(X owned_by U) OR EXISTS(X concerne S?, S owned_by U)',
 #                             {'x': eid}, 'x')
-#         self.assertEquals(rset.rows, [[eid]])
+#         self.assertEqual(rset.rows, [[eid]])
 
     def test_today_bug(self):
         self.execute("INSERT Tag X: X name 'bidule', X creation_date NOW")
@@ -729,14 +729,14 @@
     def test_select_boolean(self):
         rset = self.execute('Any N WHERE X is CWEType, X name N, X final %(val)s',
                             {'val': True})
-        self.assertEquals(sorted(r[0] for r in rset.rows), ['Boolean', 'Bytes',
+        self.assertEqual(sorted(r[0] for r in rset.rows), ['Boolean', 'Bytes',
                                                             'Date', 'Datetime',
                                                             'Decimal', 'Float',
                                                             'Int', 'Interval',
                                                             'Password', 'String',
                                                             'Time'])
         rset = self.execute('Any N WHERE X is CWEType, X name N, X final TRUE')
-        self.assertEquals(sorted(r[0] for r in rset.rows), ['Boolean', 'Bytes',
+        self.assertEqual(sorted(r[0] for r in rset.rows), ['Boolean', 'Bytes',
                                                             'Date', 'Datetime',
                                                             'Decimal', 'Float',
                                                             'Int', 'Interval',
@@ -745,17 +745,17 @@
 
     def test_select_constant(self):
         rset = self.execute('Any X, "toto" ORDERBY X WHERE X is CWGroup')
-        self.assertEquals(rset.rows,
+        self.assertEqual(rset.rows,
                           map(list, zip((1,2,3,4), ('toto','toto','toto','toto',))))
         self.assertIsInstance(rset[0][1], unicode)
-        self.assertEquals(rset.description,
+        self.assertEqual(rset.description,
                           zip(('CWGroup', 'CWGroup', 'CWGroup', 'CWGroup'),
                               ('String', 'String', 'String', 'String',)))
         rset = self.execute('Any X, %(value)s ORDERBY X WHERE X is CWGroup', {'value': 'toto'})
-        self.assertEquals(rset.rows,
+        self.assertEqual(rset.rows,
                           map(list, zip((1,2,3,4), ('toto','toto','toto','toto',))))
         self.assertIsInstance(rset[0][1], unicode)
-        self.assertEquals(rset.description,
+        self.assertEqual(rset.description,
                           zip(('CWGroup', 'CWGroup', 'CWGroup', 'CWGroup'),
                               ('String', 'String', 'String', 'String',)))
         rset = self.execute('Any X,GN WHERE X is CWUser, G is CWGroup, X login "syt", X in_group G, G name GN')
@@ -766,9 +766,9 @@
                             ' UNION '
                             '(Any X,N WHERE X name N, X state_of WF, WF workflow_of E, E name %(name)s))',
                             {'name': 'CWUser'})
-        self.assertEquals([x[1] for x in rset.rows],
+        self.assertEqual([x[1] for x in rset.rows],
                           ['activate', 'activated', 'deactivate', 'deactivated'])
-        self.assertEquals(rset.description,
+        self.assertEqual(rset.description,
                           [('Transition', 'String'), ('State', 'String'),
                            ('Transition', 'String'), ('State', 'String')])
 
@@ -788,13 +788,13 @@
                             '((Any N,COUNT(X) GROUPBY N WHERE X name N, X is State HAVING COUNT(X)>1)'
                             ' UNION '
                             '(Any N,COUNT(X) GROUPBY N WHERE X name N, X is Transition HAVING COUNT(X)>1))')
-        self.assertEquals(rset.rows, [[u'hop', 2], [u'hop', 2]])
+        self.assertEqual(rset.rows, [[u'hop', 2], [u'hop', 2]])
 
     def test_select_union_selection_with_diff_variables(self):
         rset = self.execute('(Any N WHERE X name N, X is State)'
                             ' UNION '
                             '(Any NN WHERE XX name NN, XX is Transition)')
-        self.assertEquals(sorted(r[0] for r in rset.rows),
+        self.assertEqual(sorted(r[0] for r in rset.rows),
                           ['abort', 'activate', 'activated', 'ben non',
                            'deactivate', 'deactivated', 'done', 'en cours',
                            'end', 'finie', 'markasdone', 'pitetre', 'redoit',
@@ -807,7 +807,7 @@
                             ' UNION '
                             '(Any Y WHERE Y eid %(y)s)',
                             {'x': eid1, 'y': eid2})
-        self.assertEquals(rset.description[:], [('CWGroup',), ('CWUser',)])
+        self.assertEqual(rset.description[:], [('CWGroup',), ('CWUser',)])
 
     def test_exists(self):
         geid = self.execute("INSERT CWGroup X: X name 'lulufanclub'")[0][0]
@@ -815,15 +815,15 @@
         peid = self.execute("INSERT Personne X: X prenom 'lulu', X nom 'petit'")[0][0]
         rset = self.execute("Any X WHERE X prenom 'lulu',"
                             "EXISTS (U in_group G, G name 'lulufanclub' OR G name 'managers');")
-        self.assertEquals(rset.rows, [[peid]])
+        self.assertEqual(rset.rows, [[peid]])
 
     def test_identity(self):
         eid = self.execute('Any X WHERE X identity Y, Y eid 1')[0][0]
-        self.assertEquals(eid, 1)
+        self.assertEqual(eid, 1)
         eid = self.execute('Any X WHERE Y identity X, Y eid 1')[0][0]
-        self.assertEquals(eid, 1)
+        self.assertEqual(eid, 1)
         login = self.execute('Any L WHERE X login "admin", X identity Y, Y login L')[0][0]
-        self.assertEquals(login, 'admin')
+        self.assertEqual(login, 'admin')
 
     def test_select_date_mathexp(self):
         rset = self.execute('Any X, TODAY - CD WHERE X is CWUser, X creation_date CD')
@@ -839,8 +839,8 @@
         rset = self.execute('Any GN, COUNT(X)*100/T GROUPBY GN ORDERBY 2,1'
                             ' WHERE G name GN, X in_group G'
                             ' WITH T BEING (Any COUNT(U) WHERE U is CWUser)')
-        self.assertEquals(rset.rows, [[u'guests', 50], [u'managers', 50], [u'users', 100]])
-        self.assertEquals(rset.description, [('String', 'Int'), ('String', 'Int'), ('String', 'Int')])
+        self.assertEqual(rset.rows, [[u'guests', 50], [u'managers', 50], [u'users', 100]])
+        self.assertEqual(rset.description, [('String', 'Int'), ('String', 'Int'), ('String', 'Int')])
 
     def test_select_subquery_aggregat_2(self):
         expected = self.execute('Any X, 0, COUNT(T) GROUPBY X '
@@ -851,55 +851,55 @@
               T? transition_of P, T type "auto"),
   P2,E BEING (Any P,COUNT(T) GROUPBY P WHERE P is Workflow, T is Transition,
               T? transition_of P, T type "normal")''')
-        self.assertEquals(sorted(rset.rows), sorted(expected))
+        self.assertEqual(sorted(rset.rows), sorted(expected))
 
     def test_select_subquery_const(self):
         rset = self.execute('Any X WITH X BEING ((Any NULL) UNION (Any "toto"))')
-        self.assertEquals(rset.rows, [[None], ['toto']])
-        self.assertEquals(rset.description, [(None,), ('String',)])
+        self.assertEqual(rset.rows, [[None], ['toto']])
+        self.assertEqual(rset.description, [(None,), ('String',)])
 
     # insertion queries tests #################################################
 
     def test_insert_is(self):
         eid, = self.execute("INSERT Personne X: X nom 'bidule'")[0]
         etype, = self.execute("Any TN WHERE X is T, X eid %s, T name TN" % eid)[0]
-        self.assertEquals(etype, 'Personne')
+        self.assertEqual(etype, 'Personne')
         self.execute("INSERT Personne X: X nom 'managers'")
 
     def test_insert_1(self):
         rset = self.execute("INSERT Personne X: X nom 'bidule'")
-        self.assertEquals(len(rset.rows), 1)
-        self.assertEquals(rset.description, [('Personne',)])
+        self.assertEqual(len(rset.rows), 1)
+        self.assertEqual(rset.description, [('Personne',)])
         rset = self.execute('Personne X WHERE X nom "bidule"')
         self.assert_(rset.rows)
-        self.assertEquals(rset.description, [('Personne',)])
+        self.assertEqual(rset.description, [('Personne',)])
 
     def test_insert_1_multiple(self):
         self.execute("INSERT Personne X: X nom 'bidule'")
         self.execute("INSERT Personne X: X nom 'chouette'")
         rset = self.execute("INSERT Societe Y: Y nom N, P travaille Y WHERE P nom N")
-        self.assertEquals(len(rset.rows), 2)
-        self.assertEquals(rset.description, [('Societe',), ('Societe',)])
+        self.assertEqual(len(rset.rows), 2)
+        self.assertEqual(rset.description, [('Societe',), ('Societe',)])
 
     def test_insert_2(self):
         rset = self.execute("INSERT Personne X, Personne Y: X nom 'bidule', Y nom 'tutu'")
-        self.assertEquals(rset.description, [('Personne', 'Personne')])
+        self.assertEqual(rset.description, [('Personne', 'Personne')])
         rset = self.execute('Personne X WHERE X nom "bidule" or X nom "tutu"')
         self.assert_(rset.rows)
-        self.assertEquals(rset.description, [('Personne',), ('Personne',)])
+        self.assertEqual(rset.description, [('Personne',), ('Personne',)])
 
     def test_insert_3(self):
         self.execute("INSERT Personne X: X nom Y WHERE U login 'admin', U login Y")
         rset = self.execute('Personne X WHERE X nom "admin"')
         self.assert_(rset.rows)
-        self.assertEquals(rset.description, [('Personne',)])
+        self.assertEqual(rset.description, [('Personne',)])
 
     def test_insert_4(self):
         self.execute("INSERT Societe Y: Y nom 'toto'")
         self.execute("INSERT Personne X: X nom 'bidule', X travaille Y WHERE Y nom 'toto'")
         rset = self.execute('Any X, Y WHERE X nom "bidule", Y nom "toto", X travaille Y')
         self.assert_(rset.rows)
-        self.assertEquals(rset.description, [('Personne', 'Societe',)])
+        self.assertEqual(rset.description, [('Personne', 'Societe',)])
 
     def test_insert_4bis(self):
         peid = self.execute("INSERT Personne X: X nom 'bidule'")[0][0]
@@ -924,7 +924,7 @@
         self.execute("INSERT Societe Y: Y nom 'toto', X travaille Y WHERE X nom 'bidule'")
         rset = self.execute('Any X, Y WHERE X nom "bidule", Y nom "toto", X travaille Y')
         self.assert_(rset.rows)
-        self.assertEquals(rset.description, [('Personne', 'Societe',)])
+        self.assertEqual(rset.description, [('Personne', 'Societe',)])
 
     def test_insert_5bis(self):
         peid = self.execute("INSERT Personne X: X nom 'bidule'")[0][0]
@@ -932,45 +932,45 @@
                      {'x': peid})
         rset = self.execute('Any X, Y WHERE X nom "bidule", Y nom "toto", X travaille Y')
         self.assert_(rset.rows)
-        self.assertEquals(rset.description, [('Personne', 'Societe',)])
+        self.assertEqual(rset.description, [('Personne', 'Societe',)])
 
     def test_insert_6(self):
         self.execute("INSERT Personne X, Societe Y: X nom 'bidule', Y nom 'toto', X travaille Y")
         rset = self.execute('Any X, Y WHERE X nom "bidule", Y nom "toto", X travaille Y')
         self.assert_(rset.rows)
-        self.assertEquals(rset.description, [('Personne', 'Societe',)])
+        self.assertEqual(rset.description, [('Personne', 'Societe',)])
 
     def test_insert_7(self):
         self.execute("INSERT Personne X, Societe Y: X nom N, Y nom 'toto', X travaille Y WHERE U login 'admin', U login N")
         rset = self.execute('Any X, Y WHERE X nom "admin", Y nom "toto", X travaille Y')
         self.assert_(rset.rows)
-        self.assertEquals(rset.description, [('Personne', 'Societe',)])
+        self.assertEqual(rset.description, [('Personne', 'Societe',)])
 
     def test_insert_7_2(self):
         self.execute("INSERT Personne X, Societe Y: X nom N, Y nom 'toto', X travaille Y WHERE U login N")
         rset = self.execute('Any X, Y WHERE Y nom "toto", X travaille Y')
-        self.assertEquals(len(rset), 2)
-        self.assertEquals(rset.description, [('Personne', 'Societe',),
+        self.assertEqual(len(rset), 2)
+        self.assertEqual(rset.description, [('Personne', 'Societe',),
                                              ('Personne', 'Societe',)])
 
     def test_insert_8(self):
         self.execute("INSERT Societe Y, Personne X: Y nom N, X nom 'toto', X travaille Y WHERE U login 'admin', U login N")
         rset = self.execute('Any X, Y WHERE X nom "toto", Y nom "admin", X travaille Y')
         self.assert_(rset.rows)
-        self.assertEquals(rset.description, [('Personne', 'Societe',)])
+        self.assertEqual(rset.description, [('Personne', 'Societe',)])
 
     def test_insert_9(self):
         self.execute("INSERT Societe X: X nom  'Lo'")
         self.execute("INSERT Societe X: X nom  'Gi'")
         self.execute("INSERT SubDivision X: X nom  'Lab'")
         rset = self.execute("INSERT Personne X: X nom N, X travaille Y, X travaille_subdivision Z WHERE Y is Societe, Z is SubDivision, Y nom N")
-        self.assertEquals(len(rset), 2)
-        self.assertEquals(rset.description, [('Personne',), ('Personne',)])
-        # self.assertSetEquals(set(x.nom for x in rset.entities()),
+        self.assertEqual(len(rset), 2)
+        self.assertEqual(rset.description, [('Personne',), ('Personne',)])
+        # self.assertSetEqual(set(x.nom for x in rset.entities()),
         #                      ['Lo', 'Gi'])
-        # self.assertSetEquals(set(y.nom for x in rset.entities() for y in x.travaille),
+        # self.assertSetEqual(set(y.nom for x in rset.entities() for y in x.travaille),
         #                      ['Lo', 'Gi'])
-        # self.assertEquals([y.nom for x in rset.entities() for y in x.travaille_subdivision],
+        # self.assertEqual([y.nom for x in rset.entities() for y in x.travaille_subdivision],
         #                      ['Lab', 'Lab'])
 
     def test_insert_query_error(self):
@@ -992,7 +992,7 @@
         rset = self.execute('INSERT CWUser E, EmailAddress EM: E login "X", E upassword "X", '
                             'E primary_email EM, EM address "X", E in_group G '
                             'WHERE G name "managers"')
-        self.assertEquals(list(rset.description[0]), ['CWUser', 'EmailAddress'])
+        self.assertEqual(list(rset.description[0]), ['CWUser', 'EmailAddress'])
 
     # deletion queries tests ##################################################
 
@@ -1007,10 +1007,10 @@
 
     def test_delete_2(self):
         rset = self.execute("INSERT Personne X, Personne Y, Societe Z : X nom 'syt', Y nom 'adim', Z nom 'Logilab', X travaille Z, Y travaille Z")
-        self.assertEquals(len(rset), 1)
-        self.assertEquals(len(rset[0]), 3)
-        self.assertEquals(rset.description[0], ('Personne', 'Personne', 'Societe'))
-        self.assertEquals(self.execute('Any N WHERE X nom N, X eid %s'% rset[0][0])[0][0], 'syt')
+        self.assertEqual(len(rset), 1)
+        self.assertEqual(len(rset[0]), 3)
+        self.assertEqual(rset.description[0], ('Personne', 'Personne', 'Societe'))
+        self.assertEqual(self.execute('Any N WHERE X nom N, X eid %s'% rset[0][0])[0][0], 'syt')
         rset = self.execute('Personne X WHERE X travaille Y, Y nom "Logilab"')
         self.assertEqual(len(rset.rows), 2, rset.rows)
         self.execute("DELETE X travaille Y WHERE X is Personne, Y nom 'Logilabo'")
@@ -1036,16 +1036,16 @@
         teid2 = self.execute("INSERT Folder T: T name 'tutu'")[0][0]
         self.execute('SET X see_also Y WHERE X eid %s, Y eid %s' % (teid1, teid2))
         rset = self.execute('Any X,Y WHERE X see_also Y')
-        self.assertEquals(len(rset) , 2, rset.rows)
+        self.assertEqual(len(rset) , 2, rset.rows)
         self.execute('DELETE X see_also Y WHERE X eid %s, Y eid %s' % (teid1, teid2))
         rset = self.execute('Any X,Y WHERE X see_also Y')
-        self.assertEquals(len(rset) , 0)
+        self.assertEqual(len(rset) , 0)
         self.execute('SET X see_also Y WHERE X eid %s, Y eid %s' % (teid1, teid2))
         rset = self.execute('Any X,Y WHERE X see_also Y')
-        self.assertEquals(len(rset) , 2)
+        self.assertEqual(len(rset) , 2)
         self.execute('DELETE X see_also Y WHERE X eid %s, Y eid %s' % (teid2, teid1))
         rset = self.execute('Any X,Y WHERE X see_also Y')
-        self.assertEquals(len(rset) , 0)
+        self.assertEqual(len(rset) , 0)
 
     def test_nonregr_delete_cache(self):
         """test that relations are properly cleaned when an entity is deleted
@@ -1060,9 +1060,9 @@
         self.o.execute(s, "DELETE Email X")
         sqlc = s.pool['system']
         sqlc.execute('SELECT * FROM recipients_relation')
-        self.assertEquals(len(sqlc.fetchall()), 0)
+        self.assertEqual(len(sqlc.fetchall()), 0)
         sqlc.execute('SELECT * FROM owned_by_relation WHERE eid_from=%s'%eeid)
-        self.assertEquals(len(sqlc.fetchall()), 0)
+        self.assertEqual(len(sqlc.fetchall()), 0)
 
     def test_nonregr_delete_cache2(self):
         eid = self.execute("INSERT Folder T: T name 'toto'")[0][0]
@@ -1075,13 +1075,13 @@
         self.execute("DELETE Folder T WHERE T eid %s" % eid)
         self.commit()
         rset = self.execute("Any X WHERE X eid %(x)s", {'x': eid})
-        self.assertEquals(rset.rows, [])
+        self.assertEqual(rset.rows, [])
         rset = self.execute("Any X WHERE X eid %s" % eid)
-        self.assertEquals(rset.rows, [])
+        self.assertEqual(rset.rows, [])
         rset = self.execute("Folder X WHERE X eid %(x)s", {'x': eid})
-        self.assertEquals(rset.rows, [])
+        self.assertEqual(rset.rows, [])
         rset = self.execute("Folder X WHERE X eid %s" %eid)
-        self.assertEquals(rset.rows, [])
+        self.assertEqual(rset.rows, [])
 
     # update queries tests ####################################################
 
@@ -1097,7 +1097,7 @@
     def test_update_2(self):
         peid, seid = self.execute("INSERT Personne X, Societe Y: X nom 'bidule', Y nom 'toto'")[0]
         rset = self.execute("SET X travaille Y WHERE X nom 'bidule', Y nom 'toto'")
-        self.assertEquals(tuplify(rset.rows), [(peid, seid)])
+        self.assertEqual(tuplify(rset.rows), [(peid, seid)])
         rset = self.execute('Any X, Y WHERE X travaille Y')
         self.assertEqual(len(rset.rows), 1)
 
@@ -1125,8 +1125,8 @@
         peid1 = self.execute("INSERT Personne Y: Y nom 'tutu'")[0][0]
         peid2 = self.execute("INSERT Personne Y: Y nom 'toto'")[0][0]
         self.execute("SET X nom 'tutu', Y nom 'toto' WHERE X nom 'toto', Y nom 'tutu'")
-        self.assertEquals(self.execute('Any X WHERE X nom "toto"').rows, [[peid1]])
-        self.assertEquals(self.execute('Any X WHERE X nom "tutu"').rows, [[peid2]])
+        self.assertEqual(self.execute('Any X WHERE X nom "toto"').rows, [[peid1]])
+        self.assertEqual(self.execute('Any X WHERE X nom "tutu"').rows, [[peid2]])
 
     def test_update_multiple2(self):
         ueid = self.execute("INSERT CWUser X: X login 'bob', X upassword 'toto'")[0][0]
@@ -1149,13 +1149,13 @@
                      {'order': orders[splitidx]})
         orders2 = [r[0] for r in self.execute('Any O ORDERBY O WHERE ST name "Personne", X from_entity ST, X ordernum O')]
         orders = orders[:splitidx] + [o+1 for o in orders[splitidx:]]
-        self.assertEquals(orders2, orders)
+        self.assertEqual(orders2, orders)
 
     def test_update_string_concat(self):
         beid = self.execute("INSERT Bookmark Y: Y title 'toto', Y path '/view'")[0][0]
         self.execute('SET X title XN + %(suffix)s WHERE X is Bookmark, X title XN', {'suffix': u'-moved'})
         newname = self.execute('Any XN WHERE X eid %(x)s, X title XN', {'x': beid})[0][0]
-        self.assertEquals(newname, 'toto-moved')
+        self.assertEqual(newname, 'toto-moved')
 
     def test_update_query_error(self):
         self.execute("INSERT Personne Y: Y nom 'toto'")
@@ -1168,34 +1168,34 @@
 
     def test_insert_upassword(self):
         rset = self.execute("INSERT CWUser X: X login 'bob', X upassword 'toto'")
-        self.assertEquals(len(rset.rows), 1)
-        self.assertEquals(rset.description, [('CWUser',)])
+        self.assertEqual(len(rset.rows), 1)
+        self.assertEqual(rset.description, [('CWUser',)])
         self.assertRaises(Unauthorized,
                           self.execute, "Any P WHERE X is CWUser, X login 'bob', X upassword P")
         cursor = self.pool['system']
         cursor.execute("SELECT %supassword from %sCWUser WHERE %slogin='bob'"
                        % (SQL_PREFIX, SQL_PREFIX, SQL_PREFIX))
         passwd = str(cursor.fetchone()[0])
-        self.assertEquals(passwd, crypt_password('toto', passwd[:2]))
+        self.assertEqual(passwd, crypt_password('toto', passwd[:2]))
         rset = self.execute("Any X WHERE X is CWUser, X login 'bob', X upassword %(pwd)s",
                             {'pwd': Binary(passwd)})
-        self.assertEquals(len(rset.rows), 1)
-        self.assertEquals(rset.description, [('CWUser',)])
+        self.assertEqual(len(rset.rows), 1)
+        self.assertEqual(rset.description, [('CWUser',)])
 
     def test_update_upassword(self):
         cursor = self.pool['system']
         rset = self.execute("INSERT CWUser X: X login 'bob', X upassword %(pwd)s", {'pwd': 'toto'})
-        self.assertEquals(rset.description[0][0], 'CWUser')
+        self.assertEqual(rset.description[0][0], 'CWUser')
         rset = self.execute("SET X upassword %(pwd)s WHERE X is CWUser, X login 'bob'",
                             {'pwd': 'tutu'})
         cursor.execute("SELECT %supassword from %sCWUser WHERE %slogin='bob'"
                        % (SQL_PREFIX, SQL_PREFIX, SQL_PREFIX))
         passwd = str(cursor.fetchone()[0])
-        self.assertEquals(passwd, crypt_password('tutu', passwd[:2]))
+        self.assertEqual(passwd, crypt_password('tutu', passwd[:2]))
         rset = self.execute("Any X WHERE X is CWUser, X login 'bob', X upassword %(pwd)s",
                             {'pwd': Binary(passwd)})
-        self.assertEquals(len(rset.rows), 1)
-        self.assertEquals(rset.description, [('CWUser',)])
+        self.assertEqual(len(rset.rows), 1)
+        self.assertEqual(rset.description, [('CWUser',)])
 
     # non regression tests ####################################################
 
@@ -1203,11 +1203,11 @@
         teid = self.execute("INSERT Tag X: X name 'tag'")[0][0]
         self.execute("SET X tags Y WHERE X name 'tag', Y is State, Y name 'activated'")
         rset = self.execute('Any X WHERE T tags X')
-        self.assertEquals(len(rset.rows), 1, rset.rows)
+        self.assertEqual(len(rset.rows), 1, rset.rows)
         rset = self.execute('Any T WHERE T tags X, X is State')
-        self.assertEquals(rset.rows, [[teid]])
+        self.assertEqual(rset.rows, [[teid]])
         rset = self.execute('Any T WHERE T tags X')
-        self.assertEquals(rset.rows, [[teid]])
+        self.assertEqual(rset.rows, [[teid]])
 
     def test_nonregr_2(self):
         teid = self.execute("INSERT Tag X: X name 'tag'")[0][0]
@@ -1216,7 +1216,7 @@
                        {'g': geid, 't': teid})
         rset = self.execute('Any X WHERE E eid %(x)s, E tags X',
                               {'x': teid})
-        self.assertEquals(rset.rows, [[geid]])
+        self.assertEqual(rset.rows, [[geid]])
 
     def test_nonregr_3(self):
         """bad sql generated on the second query (destination_state is not
@@ -1224,7 +1224,7 @@
         """
         rset = self.execute('Any S,ES,T WHERE S state_of WF, WF workflow_of ET, ET name "CWUser",'
                              'ES allowed_transition T, T destination_state S')
-        self.assertEquals(len(rset.rows), 2)
+        self.assertEqual(len(rset.rows), 2)
 
     def test_nonregr_4(self):
         # fix variables'type, else we get (nb of entity types with a 'name' attribute)**3
@@ -1232,7 +1232,7 @@
         # by the server (or client lib)
         rset = self.execute('Any ER,SE,OE WHERE SE name "Comment", ER name "comments", OE name "Comment",'
                             'ER is CWRType, SE is CWEType, OE is CWEType')
-        self.assertEquals(len(rset), 1)
+        self.assertEqual(len(rset), 1)
 
     def test_nonregr_5(self):
         # jpl #15505: equivalent queries returning different result sets
@@ -1252,9 +1252,9 @@
         rset4 = self.execute('Any N,U WHERE N todo_by U, T eid %s,'
                              'N filed_under T, W concerne N,'
                              'W filed_under A, A eid %s' % (teid1, teid2))
-        self.assertEquals(rset1.rows, rset2.rows)
-        self.assertEquals(rset1.rows, rset3.rows)
-        self.assertEquals(rset1.rows, rset4.rows)
+        self.assertEqual(rset1.rows, rset2.rows)
+        self.assertEqual(rset1.rows, rset3.rows)
+        self.assertEqual(rset1.rows, rset4.rows)
 
     def test_nonregr_6(self):
         self.execute('Any N,COUNT(S) GROUPBY N ORDERBY COUNT(N) WHERE S name N, S is State')
@@ -1272,7 +1272,7 @@
         rset = self.execute('Any lower(N) ORDERBY LOWER(N) WHERE X is Tag, X name N,'
                             'X owned_by U, U eid %(x)s',
                             {'x':self.session.user.eid})
-        self.assertEquals(rset.rows, [[u'\xe9name0']])
+        self.assertEqual(rset.rows, [[u'\xe9name0']])
 
 
     def test_nonregr_description(self):
@@ -1286,8 +1286,8 @@
         self.execute("SET X in_basket B WHERE X is Personne")
         self.execute("SET X in_basket B WHERE X is Societe")
         rset = self.execute('Any X WHERE X in_basket B, B eid %s' % beid)
-        self.assertEquals(len(rset), 2)
-        self.assertEquals(rset.description, [('Personne',), ('Societe',)])
+        self.assertEqual(len(rset), 2)
+        self.assertEqual(rset.description, [('Personne',), ('Societe',)])
 
 
     def test_nonregr_cache_1(self):
@@ -1297,19 +1297,19 @@
                        {'y': beid})
         rset = self.execute("Any X WHERE X in_basket B, B eid %(x)s",
                        {'x': beid})
-        self.assertEquals(rset.rows, [[peid]])
+        self.assertEqual(rset.rows, [[peid]])
         rset = self.execute("Any X WHERE X in_basket B, B eid %(x)s",
                        {'x': beid})
-        self.assertEquals(rset.rows, [[peid]])
+        self.assertEqual(rset.rows, [[peid]])
 
     def test_nonregr_has_text_cache(self):
         eid1 = self.execute("INSERT Personne X: X nom 'bidule'")[0][0]
         eid2 = self.execute("INSERT Personne X: X nom 'tag'")[0][0]
         self.commit()
         rset = self.execute("Any X WHERE X has_text %(text)s", {'text': 'bidule'})
-        self.assertEquals(rset.rows, [[eid1]])
+        self.assertEqual(rset.rows, [[eid1]])
         rset = self.execute("Any X WHERE X has_text %(text)s", {'text': 'tag'})
-        self.assertEquals(rset.rows, [[eid2]])
+        self.assertEqual(rset.rows, [[eid2]])
 
     def test_nonregr_sortterm_management(self):
         """Error: Variable has no attribute 'sql' in rql2sql.py (visit_variable)
@@ -1334,16 +1334,16 @@
         self.execute("SET X todo_by Y WHERE X is Note, Y eid %s" % ueid)
         rset = self.execute('Any N WHERE N todo_by U, N is Note, U eid %s, N filed_under T, T eid %s'
                              % (ueid, teid1))
-        self.assertEquals(len(rset), 1)
+        self.assertEqual(len(rset), 1)
 
     def test_nonregr_XXX(self):
         teid = self.execute('Transition S WHERE S name "deactivate"')[0][0]
         rset = self.execute('Any O WHERE O is State, '
                              'S eid %(x)s, S transition_of ET, O state_of ET', {'x': teid})
-        self.assertEquals(len(rset), 2)
+        self.assertEqual(len(rset), 2)
         rset = self.execute('Any O WHERE O is State, NOT S destination_state O, '
                              'S eid %(x)s, S transition_of ET, O state_of ET', {'x': teid})
-        self.assertEquals(len(rset), 1)
+        self.assertEqual(len(rset), 1)
 
 
     def test_nonregr_set_datetime(self):
@@ -1360,9 +1360,9 @@
         ueid = self.execute("INSERT CWUser X: X login 'bob', X upassword 'toto', X in_group G "
                              "WHERE G name 'users'")[0][0]
         rset = self.execute("CWUser U")
-        self.assertEquals(len(rset), 3) # bob + admin + anon
+        self.assertEqual(len(rset), 3) # bob + admin + anon
         rset = self.execute("Any U WHERE NOT U owned_by U")
-        self.assertEquals(len(rset), 0) # even admin created at repo initialization time should belong to itself
+        self.assertEqual(len(rset), 0) # even admin created at repo initialization time should belong to itself
 
     def test_nonreg_update_index(self):
         # this is the kind of queries generated by "cubicweb-ctl db-check -ry"
@@ -1377,11 +1377,11 @@
         self.execute('Any X,S, MAX(T) GROUPBY X,S ORDERBY S WHERE X is CWUser, T tags X, S eid IN(%s), X in_state S' % seid)
 
     def test_nonregr_solution_cache(self):
-        self.skip('XXX should be fixed or documented') # (doesn't occur if cache key is provided.)
+        self.skipTest('XXX should be fixed or documented') # (doesn't occur if cache key is provided.)
         rset = self.execute('Any X WHERE X is CWUser, X eid %(x)s', {'x':self.ueid})
-        self.assertEquals(len(rset), 1)
+        self.assertEqual(len(rset), 1)
         rset = self.execute('Any X WHERE X is CWUser, X eid %(x)s', {'x':12345})
-        self.assertEquals(len(rset), 0)
+        self.assertEqual(len(rset), 0)
 
     def test_nonregr_final_norestr(self):
         self.assertRaises(BadRQLQuery, self.execute, 'Date X')
--- a/server/test/unittest_repository.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_repository.py	Fri Sep 24 18:20:59 2010 +0200
@@ -65,10 +65,10 @@
             self.session.set_pool()
             cu = self.session.system_sql('SELECT %s FROM %s WHERE %s is NULL' % (
                 namecol, table, finalcol))
-            self.assertEquals(cu.fetchall(), [])
+            self.assertEqual(cu.fetchall(), [])
             cu = self.session.system_sql('SELECT %s FROM %s WHERE %s=%%(final)s ORDER BY %s'
                                          % (namecol, table, finalcol, namecol), {'final': 'TRUE'})
-            self.assertEquals(cu.fetchall(), [(u'Boolean',), (u'Bytes',),
+            self.assertEqual(cu.fetchall(), [(u'Boolean',), (u'Bytes',),
                                               (u'Date',), (u'Datetime',),
                                               (u'Decimal',),(u'Float',),
                                               (u'Int',),
@@ -84,15 +84,15 @@
                    ";")
             cu = self.session.system_sql(sql)
             rows = cu.fetchall()
-            self.assertEquals(len(rows), 3)
+            self.assertEqual(len(rows), 3)
             self.test_unique_together()
         finally:
             self.repo.set_schema(origshema)
 
     def test_unique_together(self):
         person = self.repo.schema.eschema('Personne')
-        self.assertEquals(len(person._unique_together), 1)
-        self.assertUnorderedIterableEquals(person._unique_together[0],
+        self.assertEqual(len(person._unique_together), 1)
+        self.assertItemsEqual(person._unique_together[0],
                                            ('nom', 'prenom', 'inline2'))
 
     def test_schema_has_owner(self):
@@ -161,14 +161,14 @@
         cnxid = repo.connect(self.admlogin, password=self.admpassword)
         repo.set_shared_data(cnxid, 'data', 4)
         cnxid2 = repo.connect(self.admlogin, password=self.admpassword)
-        self.assertEquals(repo.get_shared_data(cnxid, 'data'), 4)
-        self.assertEquals(repo.get_shared_data(cnxid2, 'data'), None)
+        self.assertEqual(repo.get_shared_data(cnxid, 'data'), 4)
+        self.assertEqual(repo.get_shared_data(cnxid2, 'data'), None)
         repo.set_shared_data(cnxid2, 'data', 5)
-        self.assertEquals(repo.get_shared_data(cnxid, 'data'), 4)
-        self.assertEquals(repo.get_shared_data(cnxid2, 'data'), 5)
+        self.assertEqual(repo.get_shared_data(cnxid, 'data'), 4)
+        self.assertEqual(repo.get_shared_data(cnxid2, 'data'), 5)
         repo.get_shared_data(cnxid2, 'data', pop=True)
-        self.assertEquals(repo.get_shared_data(cnxid, 'data'), 4)
-        self.assertEquals(repo.get_shared_data(cnxid2, 'data'), None)
+        self.assertEqual(repo.get_shared_data(cnxid, 'data'), 4)
+        self.assertEqual(repo.get_shared_data(cnxid2, 'data'), None)
         repo.close(cnxid)
         repo.close(cnxid2)
         self.assertRaises(BadConnectionId, repo.get_shared_data, cnxid, 'data')
@@ -179,7 +179,7 @@
     def test_check_session(self):
         repo = self.repo
         cnxid = repo.connect(self.admlogin, password=self.admpassword)
-        self.assertEquals(repo.check_session(cnxid), None)
+        self.assertEqual(repo.check_session(cnxid), None)
         repo.close(cnxid)
         self.assertRaises(BadConnectionId, repo.check_session, cnxid)
 
@@ -188,19 +188,19 @@
         cnxid = repo.connect(self.admlogin, password=self.admpassword)
         # check db state
         result = repo.execute(cnxid, 'Personne X')
-        self.assertEquals(result.rowcount, 0)
+        self.assertEqual(result.rowcount, 0)
         # rollback entity insertion
         repo.execute(cnxid, "INSERT Personne X: X nom 'bidule'")
         result = repo.execute(cnxid, 'Personne X')
-        self.assertEquals(result.rowcount, 1)
+        self.assertEqual(result.rowcount, 1)
         repo.rollback(cnxid)
         result = repo.execute(cnxid, 'Personne X')
-        self.assertEquals(result.rowcount, 0, result.rows)
+        self.assertEqual(result.rowcount, 0, result.rows)
         # commit
         repo.execute(cnxid, "INSERT Personne X: X nom 'bidule'")
         repo.commit(cnxid)
         result = repo.execute(cnxid, 'Personne X')
-        self.assertEquals(result.rowcount, 1)
+        self.assertEqual(result.rowcount, 1)
 
     def test_transaction_base2(self):
         repo = self.repo
@@ -208,10 +208,10 @@
         # rollback relation insertion
         repo.execute(cnxid, "SET U in_group G WHERE U login 'admin', G name 'guests'")
         result = repo.execute(cnxid, "Any U WHERE U in_group G, U login 'admin', G name 'guests'")
-        self.assertEquals(result.rowcount, 1)
+        self.assertEqual(result.rowcount, 1)
         repo.rollback(cnxid)
         result = repo.execute(cnxid, "Any U WHERE U in_group G, U login 'admin', G name 'guests'")
-        self.assertEquals(result.rowcount, 0, result.rows)
+        self.assertEqual(result.rowcount, 0, result.rows)
 
     def test_transaction_base3(self):
         repo = self.repo
@@ -222,13 +222,13 @@
         user = session.user
         user.cw_adapt_to('IWorkflowable').fire_transition('deactivate')
         rset = repo.execute(cnxid, 'TrInfo T WHERE T wf_info_for X, X eid %(x)s', {'x': user.eid})
-        self.assertEquals(len(rset), 1)
+        self.assertEqual(len(rset), 1)
         repo.rollback(cnxid)
         rset = repo.execute(cnxid, 'TrInfo T WHERE T wf_info_for X, X eid %(x)s', {'x': user.eid})
-        self.assertEquals(len(rset), 0)
+        self.assertEqual(len(rset), 0)
 
     def test_transaction_interleaved(self):
-        self.skip('implement me')
+        self.skipTest('implement me')
 
     def test_close_kill_processing_request(self):
         repo = self.repo
@@ -246,14 +246,14 @@
             repo.commit(cnxid)
         try:
             ex = self.assertRaises(Exception, run_transaction)
-            self.assertEquals(str(ex), 'try to access pool on a closed session')
+            self.assertEqual(str(ex), 'try to access pool on a closed session')
         finally:
             t.join()
 
     def test_initial_schema(self):
         schema = self.repo.schema
         # check order of attributes is respected
-        self.assertListEquals([r.type for r in schema.eschema('CWAttribute').ordered_relations()
+        self.assertListEqual([r.type for r in schema.eschema('CWAttribute').ordered_relations()
                                if not r.type in ('eid', 'is', 'is_instance_of', 'identity',
                                                  'creation_date', 'modification_date', 'cwuri',
                                                  'owned_by', 'created_by',
@@ -266,11 +266,11 @@
                                'indexed', 'fulltextindexed', 'internationalizable',
                                'defaultval', 'description', 'description_format'])
 
-        self.assertEquals(schema.eschema('CWEType').main_attribute(), 'name')
-        self.assertEquals(schema.eschema('State').main_attribute(), 'name')
+        self.assertEqual(schema.eschema('CWEType').main_attribute(), 'name')
+        self.assertEqual(schema.eschema('State').main_attribute(), 'name')
 
         constraints = schema.rschema('name').rdef('CWEType', 'String').constraints
-        self.assertEquals(len(constraints), 2)
+        self.assertEqual(len(constraints), 2)
         for cstr in constraints[:]:
             if isinstance(cstr, UniqueConstraint):
                 constraints.remove(cstr)
@@ -278,17 +278,17 @@
         else:
             self.fail('unique constraint not found')
         sizeconstraint = constraints[0]
-        self.assertEquals(sizeconstraint.min, None)
-        self.assertEquals(sizeconstraint.max, 64)
+        self.assertEqual(sizeconstraint.min, None)
+        self.assertEqual(sizeconstraint.max, 64)
 
         constraints = schema.rschema('relation_type').rdef('CWAttribute', 'CWRType').constraints
-        self.assertEquals(len(constraints), 1)
+        self.assertEqual(len(constraints), 1)
         cstr = constraints[0]
         self.assert_(isinstance(cstr, RQLConstraint))
-        self.assertEquals(cstr.restriction, 'O final TRUE')
+        self.assertEqual(cstr.restriction, 'O final TRUE')
 
         ownedby = schema.rschema('owned_by')
-        self.assertEquals(ownedby.objects('CWEType'), ('CWUser',))
+        self.assertEqual(ownedby.objects('CWEType'), ('CWUser',))
 
     def test_pyro(self):
         import Pyro
@@ -319,7 +319,7 @@
             schema = cnx.get_schema()
             self.failUnless(cnx.vreg)
             self.failUnless('etypes'in cnx.vreg)
-            self.assertEquals(schema.__hashmode__, None)
+            self.assertEqual(schema.__hashmode__, None)
             cu = cnx.cursor()
             rset = cu.execute('Any U,G WHERE U in_group G')
             user = iter(rset.entities()).next()
@@ -337,25 +337,25 @@
         repo = self.repo
         cnxid = repo.connect(self.admlogin, password=self.admpassword)
         session = repo._get_session(cnxid, setpool=True)
-        self.assertEquals(repo.type_and_source_from_eid(1, session),
+        self.assertEqual(repo.type_and_source_from_eid(1, session),
                           ('CWGroup', 'system', None))
-        self.assertEquals(repo.type_from_eid(1, session), 'CWGroup')
-        self.assertEquals(repo.source_from_eid(1, session).uri, 'system')
-        self.assertEquals(repo.eid2extid(repo.system_source, 1, session), None)
+        self.assertEqual(repo.type_from_eid(1, session), 'CWGroup')
+        self.assertEqual(repo.source_from_eid(1, session).uri, 'system')
+        self.assertEqual(repo.eid2extid(repo.system_source, 1, session), None)
         class dummysource: uri = 'toto'
         self.assertRaises(UnknownEid, repo.eid2extid, dummysource, 1, session)
 
     def test_public_api(self):
-        self.assertEquals(self.repo.get_schema(), self.repo.schema)
-        self.assertEquals(self.repo.source_defs(), {'system': {'adapter': 'native', 'uri': 'system'}})
+        self.assertEqual(self.repo.get_schema(), self.repo.schema)
+        self.assertEqual(self.repo.source_defs(), {'system': {'adapter': 'native', 'uri': 'system'}})
         # .properties() return a result set
-        self.assertEquals(self.repo.properties().rql, 'Any K,V WHERE P is CWProperty,P pkey K, P value V, NOT P for_user U')
+        self.assertEqual(self.repo.properties().rql, 'Any K,V WHERE P is CWProperty,P pkey K, P value V, NOT P for_user U')
 
     def test_session_api(self):
         repo = self.repo
         cnxid = repo.connect(self.admlogin, password=self.admpassword)
-        self.assertEquals(repo.user_info(cnxid), (5, 'admin', set([u'managers']), {}))
-        self.assertEquals(repo.describe(cnxid, 1), (u'CWGroup', u'system', None))
+        self.assertEqual(repo.user_info(cnxid), (5, 'admin', set([u'managers']), {}))
+        self.assertEqual(repo.describe(cnxid, 1), (u'CWGroup', u'system', None))
         repo.close(cnxid)
         self.assertRaises(BadConnectionId, repo.user_info, cnxid)
         self.assertRaises(BadConnectionId, repo.describe, cnxid, 1)
@@ -363,12 +363,12 @@
     def test_shared_data_api(self):
         repo = self.repo
         cnxid = repo.connect(self.admlogin, password=self.admpassword)
-        self.assertEquals(repo.get_shared_data(cnxid, 'data'), None)
+        self.assertEqual(repo.get_shared_data(cnxid, 'data'), None)
         repo.set_shared_data(cnxid, 'data', 4)
-        self.assertEquals(repo.get_shared_data(cnxid, 'data'), 4)
+        self.assertEqual(repo.get_shared_data(cnxid, 'data'), 4)
         repo.get_shared_data(cnxid, 'data', pop=True)
         repo.get_shared_data(cnxid, 'whatever', pop=True)
-        self.assertEquals(repo.get_shared_data(cnxid, 'data'), None)
+        self.assertEqual(repo.get_shared_data(cnxid, 'data'), None)
         repo.close(cnxid)
         self.assertRaises(BadConnectionId, repo.set_shared_data, cnxid, 'data', 0)
         self.assertRaises(BadConnectionId, repo.get_shared_data, cnxid, 'data')
@@ -394,14 +394,14 @@
                      {'x': note.eid, 'p': p1.eid})
         rset = self.execute('Any P WHERE A todo_by P, A eid %(x)s',
                             {'x': note.eid})
-        self.assertEquals(len(rset), 1)
+        self.assertEqual(len(rset), 1)
         p2 = self.request().create_entity('Personne', nom=u'tutu')
         self.execute('SET A todo_by P WHERE A eid %(x)s, P eid %(p)s',
                      {'x': note.eid, 'p': p2.eid})
         rset = self.execute('Any P WHERE A todo_by P, A eid %(x)s',
                             {'x': note.eid})
-        self.assertEquals(len(rset), 1)
-        self.assertEquals(rset.rows[0][0], p2.eid)
+        self.assertEqual(len(rset), 1)
+        self.assertEqual(rset.rows[0][0], p2.eid)
 
     def test_delete_if_object_inlined_singlecard(self):
         req = self.request()
@@ -409,7 +409,7 @@
         req.create_entity('Personne', nom=u'Vincent', fiche=c)
         req.create_entity('Personne', nom=u'Florent', fiche=c)
         self.commit()
-        self.assertEquals(len(c.reverse_fiche), 1)
+        self.assertEqual(len(c.reverse_fiche), 1)
 
     def test_set_attributes_in_before_update(self):
         # local hook
@@ -430,7 +430,7 @@
             addr.set_attributes(address=u'a@b.com')
             rset = self.execute('Any A,AA WHERE X eid %(x)s, X address A, X alias AA',
                                 {'x': addr.eid})
-            self.assertEquals(rset.rows, [[u'a@b.com', u'foo']])
+            self.assertEqual(rset.rows, [[u'a@b.com', u'foo']])
 
     def test_set_attributes_in_before_add(self):
         # local hook
@@ -477,7 +477,7 @@
 
     def test_source_from_eid(self):
         self.session.set_pool()
-        self.assertEquals(self.repo.source_from_eid(1, self.session),
+        self.assertEqual(self.repo.source_from_eid(1, self.session),
                           self.repo.sources_by_uri['system'])
 
     def test_source_from_eid_raise(self):
@@ -486,7 +486,7 @@
 
     def test_type_from_eid(self):
         self.session.set_pool()
-        self.assertEquals(self.repo.type_from_eid(1, self.session), 'CWGroup')
+        self.assertEqual(self.repo.type_from_eid(1, self.session), 'CWGroup')
 
     def test_type_from_eid_raise(self):
         self.session.set_pool()
@@ -503,12 +503,12 @@
         self.assertIsInstance(data[0][3], datetime)
         data[0] = list(data[0])
         data[0][3] = None
-        self.assertEquals(tuplify(data), [(-1, 'Personne', 'system', None, None)])
+        self.assertEqual(tuplify(data), [(-1, 'Personne', 'system', None, None)])
         self.repo.delete_info(self.session, entity, 'system', None)
         #self.repo.commit()
         cu = self.session.system_sql('SELECT * FROM entities WHERE eid = -1')
         data = cu.fetchall()
-        self.assertEquals(data, [])
+        self.assertEqual(data, [])
 
 
 class FTITC(CubicWebTC):
@@ -518,7 +518,7 @@
         eidp = self.execute('INSERT Personne X: X nom "toto", X prenom "tutu"')[0][0]
         self.commit()
         ts = datetime.now()
-        self.assertEquals(len(self.execute('Personne X WHERE X has_text "tutu"')), 1)
+        self.assertEqual(len(self.execute('Personne X WHERE X has_text "tutu"')), 1)
         self.session.set_pool()
         cu = self.session.system_sql('SELECT mtime, eid FROM entities WHERE eid = %s' % eidp)
         omtime = cu.fetchone()[0]
@@ -527,23 +527,23 @@
         time.sleep(1 - (ts.second - int(ts.second)))
         self.execute('SET X nom "tata" WHERE X eid %(x)s', {'x': eidp})
         self.commit()
-        self.assertEquals(len(self.execute('Personne X WHERE X has_text "tutu"')), 1)
+        self.assertEqual(len(self.execute('Personne X WHERE X has_text "tutu"')), 1)
         self.session.set_pool()
         cu = self.session.system_sql('SELECT mtime FROM entities WHERE eid = %s' % eidp)
         mtime = cu.fetchone()[0]
         self.failUnless(omtime < mtime)
         self.commit()
         date, modified, deleted = self.repo.entities_modified_since(('Personne',), omtime)
-        self.assertEquals(modified, [('Personne', eidp)])
-        self.assertEquals(deleted, [])
+        self.assertEqual(modified, [('Personne', eidp)])
+        self.assertEqual(deleted, [])
         date, modified, deleted = self.repo.entities_modified_since(('Personne',), mtime)
-        self.assertEquals(modified, [])
-        self.assertEquals(deleted, [])
+        self.assertEqual(modified, [])
+        self.assertEqual(deleted, [])
         self.execute('DELETE Personne X WHERE X eid %(x)s', {'x': eidp})
         self.commit()
         date, modified, deleted = self.repo.entities_modified_since(('Personne',), omtime)
-        self.assertEquals(modified, [])
-        self.assertEquals(deleted, [('Personne', eidp)])
+        self.assertEqual(modified, [])
+        self.assertEqual(deleted, [('Personne', eidp)])
 
     def test_fulltext_container_entity(self):
         assert self.schema.rschema('use_email').fulltext_container == 'subject'
@@ -551,27 +551,27 @@
         toto = req.create_entity('EmailAddress', address=u'toto@logilab.fr')
         self.commit()
         rset = req.execute('Any X WHERE X has_text %(t)s', {'t': 'toto'})
-        self.assertEquals(rset.rows, [])
+        self.assertEqual(rset.rows, [])
         req.user.set_relations(use_email=toto)
         self.commit()
         rset = req.execute('Any X WHERE X has_text %(t)s', {'t': 'toto'})
-        self.assertEquals(rset.rows, [[req.user.eid]])
+        self.assertEqual(rset.rows, [[req.user.eid]])
         req.execute('DELETE X use_email Y WHERE X login "admin", Y eid %(y)s',
                     {'y': toto.eid})
         self.commit()
         rset = req.execute('Any X WHERE X has_text %(t)s', {'t': 'toto'})
-        self.assertEquals(rset.rows, [])
+        self.assertEqual(rset.rows, [])
         tutu = req.create_entity('EmailAddress', address=u'tutu@logilab.fr')
         req.user.set_relations(use_email=tutu)
         self.commit()
         rset = req.execute('Any X WHERE X has_text %(t)s', {'t': 'tutu'})
-        self.assertEquals(rset.rows, [[req.user.eid]])
+        self.assertEqual(rset.rows, [[req.user.eid]])
         tutu.set_attributes(address=u'hip@logilab.fr')
         self.commit()
         rset = req.execute('Any X WHERE X has_text %(t)s', {'t': 'tutu'})
-        self.assertEquals(rset.rows, [])
+        self.assertEqual(rset.rows, [])
         rset = req.execute('Any X WHERE X has_text %(t)s', {'t': 'hip'})
-        self.assertEquals(rset.rows, [[req.user.eid]])
+        self.assertEqual(rset.rows, [[req.user.eid]])
 
     def test_no_uncessary_ftiindex_op(self):
         req = self.request()
@@ -584,7 +584,7 @@
 
     def test_versions_inserted(self):
         inserted = [r[0] for r in self.execute('Any K ORDERBY K WHERE P pkey K, P pkey ~= "system.version.%"')]
-        self.assertEquals(inserted,
+        self.assertEqual(inserted,
                           [u'system.version.basket', u'system.version.card', u'system.version.comment',
                            u'system.version.cubicweb', u'system.version.email',
                            u'system.version.file', u'system.version.folder',
@@ -616,15 +616,15 @@
             eidp = self.execute('INSERT Personne X: X nom "toto"')[0][0]
             eidn = self.execute('INSERT Note X: X type "T"')[0][0]
             self.execute('SET N ecrit_par Y WHERE N type "T", Y nom "toto"')
-            self.assertEquals(CALLED, [('before_add_relation', eidn, 'ecrit_par', eidp),
+            self.assertEqual(CALLED, [('before_add_relation', eidn, 'ecrit_par', eidp),
                                        ('after_add_relation', eidn, 'ecrit_par', eidp)])
             CALLED[:] = ()
             self.execute('DELETE N ecrit_par Y WHERE N type "T", Y nom "toto"')
-            self.assertEquals(CALLED, [('before_delete_relation', eidn, 'ecrit_par', eidp),
+            self.assertEqual(CALLED, [('before_delete_relation', eidn, 'ecrit_par', eidp),
                                        ('after_delete_relation', eidn, 'ecrit_par', eidp)])
             CALLED[:] = ()
             eidn = self.execute('INSERT Note N: N ecrit_par P WHERE P nom "toto"')[0][0]
-            self.assertEquals(CALLED, [('before_add_relation', eidn, 'ecrit_par', eidp),
+            self.assertEqual(CALLED, [('before_add_relation', eidn, 'ecrit_par', eidp),
                                        ('after_add_relation', eidn, 'ecrit_par', eidp)])
 
     def test_unique_contraint(self):
@@ -638,7 +638,7 @@
         req = self.request()
         req.create_entity('Note', type=u'todo', inline1=a01)
         ex = self.assertRaises(ValidationError, req.cnx.commit)
-        self.assertEquals(ex.errors, {'inline1-subject': u'RQLUniqueConstraint S type T, S inline1 A1, A1 todo_by C, Y type T, Y inline1 A2, A2 todo_by C failed'})
+        self.assertEqual(ex.errors, {'inline1-subject': u'RQLUniqueConstraint S type T, S inline1 A1, A1 todo_by C, Y type T, Y inline1 A2, A2 todo_by C failed'})
 
 if __name__ == '__main__':
     unittest_main()
--- a/server/test/unittest_rql2sql.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_rql2sql.py	Fri Sep 24 18:20:59 2010 +0200
@@ -1096,12 +1096,15 @@
             for sol in delete.solutions:
                 s.add(sol.get(var))
             return s
-        self.assertEquals(var_sols('FROM_ENTITYOBJECT'), set(('CWAttribute', 'CWRelation')))
-        self.assertEquals(var_sols('FROM_ENTITYOBJECT'), delete.defined_vars['FROM_ENTITYOBJECT'].stinfo['possibletypes'])
-        self.assertEquals(var_sols('ISOBJECT'),
+        self.assertEqual(var_sols('FROM_ENTITYOBJECT'), set(('CWAttribute', 'CWRelation')))
+        self.assertEqual(var_sols('FROM_ENTITYOBJECT'), delete.defined_vars['FROM_ENTITYOBJECT'].stinfo['possibletypes'])
+        self.assertEqual(var_sols('ISOBJECT'),
                           set(x.type for x in self.schema.entities() if not x.final))
-        self.assertEquals(var_sols('ISOBJECT'), delete.defined_vars['ISOBJECT'].stinfo['possibletypes'])
+        self.assertEqual(var_sols('ISOBJECT'), delete.defined_vars['ISOBJECT'].stinfo['possibletypes'])
+
 
+def strip(text):
+    return '\n'.join(l.strip() for l in text.strip().splitlines())
 
 class PostgresSQLGeneratorTC(RQLGeneratorTC):
     schema = schema
@@ -1118,7 +1121,7 @@
             r, nargs, cbs = self.o.generate(union, args,
                                             varmap=varmap)
             args.update(nargs)
-            self.assertLinesEquals((r % args).strip(), self._norm_sql(sql), striplines=True)
+            self.assertMultiLineEqual(strip(r % args), self._norm_sql(sql))
         except Exception, ex:
             if 'r' in locals():
                 try:
@@ -1200,7 +1203,7 @@
     def test_is_null_transform(self):
         union = self._prepare('Any X WHERE X login %(login)s')
         r, args, cbs = self.o.generate(union, {'login': None})
-        self.assertLinesEquals((r % args).strip(),
+        self.assertMultiLineEqual((r % args).strip(),
                                '''SELECT _X.cw_eid
 FROM cw_CWUser AS _X
 WHERE _X.cw_login IS NULL''')
@@ -1454,8 +1457,8 @@
         try:
             union = self._prepare('Any R WHERE X ref R')
             r, nargs, cbs = self.o.generate(union, args={})
-            self.assertLinesEquals(r.strip(), 'SELECT _X.cw_ref\nFROM cw_Affaire AS _X')
-            self.assertEquals(cbs, {0: [cb]})
+            self.assertMultiLineEqual(r.strip(), 'SELECT _X.cw_ref\nFROM cw_Affaire AS _X')
+            self.assertEqual(cbs, {0: [cb]})
         finally:
             self.o.attr_map.clear()
 
@@ -1712,7 +1715,7 @@
         rqlst = mock_object(defined_vars={})
         rqlst.defined_vars['A'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=True)
         rqlst.defined_vars['B'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=False)
-        self.assertEquals(remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'},
+        self.assertEqual(remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'},
                                                           {'A': 'FootGroup', 'B': 'FootTeam'}], {}, None),
                           ([{'A': 'RugbyGroup', 'B': 'RugbyTeam'},
                             {'A': 'FootGroup', 'B': 'FootTeam'}],
@@ -1723,7 +1726,7 @@
         rqlst = mock_object(defined_vars={})
         rqlst.defined_vars['A'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=True)
         rqlst.defined_vars['B'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=False)
-        self.assertEquals(remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'},
+        self.assertEqual(remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'},
                                                           {'A': 'FootGroup', 'B': 'RugbyTeam'}], {}, None),
                           ([{'A': 'RugbyGroup', 'B': 'RugbyTeam'}], {}, set())
                           )
--- a/server/test/unittest_rqlannotation.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_rqlannotation.py	Fri Sep 24 18:20:59 2010 +0200
@@ -41,256 +41,256 @@
 
     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)
-        self.assertEquals(rqlst.defined_vars['R']._q_invariant, False)
-        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)
+        self.assertEqual(rqlst.defined_vars['SE']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['OE']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['R']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['SE'].stinfo['attrvar'], None)
+        self.assertEqual(rqlst.defined_vars['OE'].stinfo['attrvar'], None)
+        self.assertEqual(rqlst.defined_vars['R'].stinfo['attrvar'], None)
 
     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)
+        self.assertEqual(rqlst.defined_vars['P']._q_invariant, True)
+        self.assertEqual(rqlst.defined_vars['O'].stinfo['attrvar'], None)
 
     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.assertEqual(rqlst.defined_vars['A']._q_invariant, False)
         self.assert_(rqlst.defined_vars['B'].stinfo['attrvar'])
-        self.assertEquals(rqlst.defined_vars['C']._q_invariant, False)
-        self.assertEquals(rqlst.solutions, [{'A': 'TrInfo', 'B': 'String', 'C': 'Affaire'},
+        self.assertEqual(rqlst.defined_vars['C']._q_invariant, False)
+        self.assertEqual(rqlst.solutions, [{'A': 'TrInfo', 'B': 'String', 'C': 'Affaire'},
                                       {'A': 'TrInfo', 'B': 'String', 'C': 'CWUser'},
                                       {'A': 'TrInfo', 'B': 'String', 'C': 'Note'}])
 
     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)
+        self.assertEqual(rqlst.defined_vars['N']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['P']._q_invariant, True)
 
     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)
+        self.assertEqual(rqlst.defined_vars['P']._q_invariant, False)
 
     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.assertEqual(rqlst.defined_vars['X']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False)
         self.assert_(rqlst.defined_vars['XE'].stinfo['attrvar'])
 
     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)
+        self.assertEqual(rqlst.defined_vars['P']._q_invariant, False)
+        #self.assertEqual(rqlst.defined_vars['X']._q_invariant, True)
+        self.assertEqual(len(rqlst.solutions), 1, rqlst.solutions)
 
     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)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, True)
+        self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False)
 
     def test_0_11(self):
         rqlst = self._prepare('Any X WHERE X todo_by Y, X is Affaire')
-        self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
-        self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['Y']._q_invariant, True)
 
     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)
+        self.assertEqual(rqlst.defined_vars['P']._q_invariant, True)
+        self.assertEqual(rqlst.defined_vars['A']._q_invariant, True)
+        self.assertEqual(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)
+        self.assertEqual(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)
+        self.assertEqual(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)
+        self.assertEqual(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)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False)
 
     def test_8(self):
         # DISTINCT Any P WHERE P require_group %(g)s, NOT %(u)s has_group_permission P, P is CWPermission
         rqlst = self._prepare('DISTINCT Any X WHERE A concerne X, NOT N migrated_from X, '
                               'X is Note, N eid 1')
-        self.assertEquals(rqlst.defined_vars['X']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, False)
 
     def test_diff_scope_identity_deamb(self):
         rqlst = self._prepare('Any X WHERE X concerne Y, Y is Note, EXISTS(Y identity Z, Z migrated_from N)')
-        self.assertEquals(rqlst.defined_vars['Z']._q_invariant, True)
-        self.assertEquals(rqlst.defined_vars['Y']._q_invariant, True)
+        self.assertEqual(rqlst.defined_vars['Z']._q_invariant, True)
+        self.assertEqual(rqlst.defined_vars['Y']._q_invariant, True)
 
     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)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, False)
+        self.assertEqual(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)
+        self.assertEqual(rqlst.defined_vars['N']._q_invariant, False)
+        self.assertEqual(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)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, False)
+        self.assertEqual(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)
+        self.assertEqual(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)
+        self.assertEqual(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)
+        self.assertEqual(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)
+        self.assertEqual(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)
+        self.assertEqual(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)
+        self.assertEqual(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')
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, True)
+        self.assertEqual(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')
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, True)
+        self.assertEqual(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(...))
         rqlst = self._prepare('Any P,G WHERE P require_group G, NOT X require_permission P')
-        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)
+        self.assertEqual(rqlst.defined_vars['P']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['G']._q_invariant, True)
+        self.assertEqual(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)
+        self.assertEqual(rqlst.defined_vars['Y']._q_invariant, True)
+        self.assertEqual(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)
+        self.assertEqual(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)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, False)
+        self.assertEqual(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)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, False)
+        self.assertEqual(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)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, True)
+        self.assertEqual(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)
-        self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False)
 
     def test_not_relation_4_5(self):
         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'}])
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, False)
+        self.assertEqual(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)
-        self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False)
 
     def test_not_relation_5_2(self):
         rqlst = self._prepare('DISTINCT 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)
-        self.assertEquals(rqlst.defined_vars['Y']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False)
 
     def test_not_relation_6(self):
         rqlst = self._prepare('Personne P where NOT P concerne A')
-        self.assertEquals(rqlst.defined_vars['P']._q_invariant, False)
-        self.assertEquals(rqlst.defined_vars['A']._q_invariant, True)
+        self.assertEqual(rqlst.defined_vars['P']._q_invariant, False)
+        self.assertEqual(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')
-        self.assertEquals(rqlst.defined_vars['P']._q_invariant, False)
-        self.assertEquals(rqlst.defined_vars['U']._q_invariant, True)
+        self.assertEqual(rqlst.defined_vars['P']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['U']._q_invariant, True)
 
     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)
+        self.assertEqual(rqlst.defined_vars['U']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, True)
 
     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)
+        self.assertEqual(rqlst.defined_vars['U']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, True)
 
     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)
+        self.assertEqual(rqlst.defined_vars['U']._q_invariant, False)
+        self.assertEqual(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)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, False)
+        self.assertEqual(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)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['Y']._q_invariant, True)
 
     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.assertEqual(rqlst.defined_vars['U']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, True)
 
     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)
+        self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False)
 
     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)
+        self.assertEqual(rqlst.defined_vars['Y']._q_invariant, False)
 
     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)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, False)
 
     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['X'].stinfo['principal'].r_type, 'created_by')
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, True)
+        self.assertEqual(rqlst.defined_vars['U']._q_invariant, True)
+        self.assertEqual(rqlst.defined_vars['X'].stinfo['principal'].r_type, 'created_by')
 
     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.assertEqual(rqlst.defined_vars['N']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['A']._q_invariant, True)
+        self.assertEqual(rqlst.defined_vars['U']._q_invariant, True)
 
     def test_or_exists_1(self):
         # query generated by security rewriting
@@ -300,30 +300,30 @@
                               'OR (EXISTS(I concerne H?, H owned_by D, H is Societe, A identity I, I is Affaire))) '
                               'OR (EXISTS(J concerne G?, G owned_by D, G is SubDivision, A identity J, J is Affaire))) '
                               'OR (EXISTS(K concerne F?, F owned_by D, F is Division, A identity K, K is Affaire)))')
-        self.assertEquals(rqlst.defined_vars['A']._q_invariant, False)
-        self.assertEquals(rqlst.defined_vars['S']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['A']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['S']._q_invariant, False)
 
     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)
+        self.assertEqual(rqlst.defined_vars['U']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['G']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['X']._q_invariant, True)
 
     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 D)) OR (EXISTS(S documented_by N, N title "published"))')
-        self.assertEquals(rqlst.defined_vars['S']._q_invariant, True)
+        self.assertEqual(rqlst.defined_vars['S']._q_invariant, True)
         rqlst = self._prepare('Any COUNT(S),CS GROUPBY CS ORDERBY 1 DESC LIMIT 10 '
                               'WHERE S is Affaire, C is Societe, S concerne C, C nom CS, '
                               '(EXISTS(S owned_by D)) OR (EXISTS(S documented_by N, N title "published"))')
-        self.assertEquals(rqlst.defined_vars['S']._q_invariant, True)
+        self.assertEqual(rqlst.defined_vars['S']._q_invariant, True)
 
     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)
-        self.assertEquals(rqlst.defined_vars['F']._q_invariant, True)
+        self.assertEqual(rqlst.defined_vars['N']._q_invariant, False)
+        self.assertEqual(rqlst.defined_vars['F']._q_invariant, True)
 
 if __name__ == '__main__':
     from logilab.common.testlib import unittest_main
--- a/server/test/unittest_schemaserial.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_schemaserial.py	Fri Sep 24 18:20:59 2010 +0200
@@ -47,7 +47,7 @@
 class Schema2RQLTC(TestCase):
 
     def test_eschema2rql1(self):
-        self.assertListEquals(list(eschema2rql(schema.eschema('CWAttribute'))),
+        self.assertListEqual(list(eschema2rql(schema.eschema('CWAttribute'))),
                               [
             ('INSERT CWEType X: X description %(description)s,X final %(final)s,X name %(name)s',
              {'description': u'define a final relation: link a final relation type from a non final entity to a final entity type. used to build the instance schema',
@@ -55,13 +55,13 @@
             ])
 
     def test_eschema2rql2(self):
-        self.assertListEquals(list(eschema2rql(schema.eschema('String'))), [
+        self.assertListEqual(list(eschema2rql(schema.eschema('String'))), [
                 ('INSERT CWEType X: X description %(description)s,X final %(final)s,X name %(name)s',
                  {'description': u'', 'final': True, 'name': u'String'})])
 
     def test_eschema2rql_specialization(self):
         # x: None since eschema.eid are None
-        self.assertListEquals(sorted(specialize2rql(schema)),
+        self.assertListEqual(sorted(specialize2rql(schema)),
                               [('SET X specializes ET WHERE X eid %(x)s, ET eid %(et)s',
                                 {'et': None, 'x': None}),
                                ('SET X specializes ET WHERE X eid %(x)s, ET eid %(et)s',
@@ -72,7 +72,7 @@
                                 {'et': None, 'x': None})])
 
     def test_rschema2rql1(self):
-        self.assertListEquals(list(rschema2rql(schema.rschema('relation_type'), cstrtypemap)),
+        self.assertListEqual(list(rschema2rql(schema.rschema('relation_type'), cstrtypemap)),
                              [
             ('INSERT CWRType X: X description %(description)s,X final %(final)s,X fulltext_container %(fulltext_container)s,X inlined %(inlined)s,X name %(name)s,X symmetric %(symmetric)s',
              {'description': u'link a relation definition to its relation type', 'symmetric': False, 'name': u'relation_type', 'final' : False, 'fulltext_container': None, 'inlined': True}),
@@ -93,7 +93,7 @@
             ])
 
     def test_rschema2rql2(self):
-        self.assertListEquals(list(rschema2rql(schema.rschema('add_permission'), cstrtypemap)),
+        self.assertListEqual(list(rschema2rql(schema.rschema('add_permission'), cstrtypemap)),
                               [
             ('INSERT CWRType X: X description %(description)s,X final %(final)s,X fulltext_container %(fulltext_container)s,X inlined %(inlined)s,X name %(name)s,X symmetric %(symmetric)s', {'description': u'', 'symmetric': False, 'name': u'add_permission', 'final': False, 'fulltext_container': None, 'inlined': False}),
 
@@ -113,7 +113,7 @@
             ])
 
     def test_rschema2rql3(self):
-        self.assertListEquals(list(rschema2rql(schema.rschema('cardinality'), cstrtypemap)),
+        self.assertListEqual(list(rschema2rql(schema.rschema('cardinality'), cstrtypemap)),
                              [
             ('INSERT CWRType X: X description %(description)s,X final %(final)s,X fulltext_container %(fulltext_container)s,X inlined %(inlined)s,X name %(name)s,X symmetric %(symmetric)s',
              {'description': u'', 'symmetric': False, 'name': u'cardinality', 'final': True, 'fulltext_container': None, 'inlined': False}),
@@ -136,7 +136,7 @@
             ])
 
     def test_rdef2rql(self):
-        self.assertListEquals(list(rdef2rql(schema['description_format'].rdefs[('CWRType', 'String')], cstrtypemap)),
+        self.assertListEqual(list(rdef2rql(schema['description_format'].rdefs[('CWRType', 'String')], cstrtypemap)),
                               [
             ('INSERT CWAttribute X: X cardinality %(cardinality)s,X defaultval %(defaultval)s,X description %(description)s,X fulltextindexed %(fulltextindexed)s,X indexed %(indexed)s,X internationalizable %(internationalizable)s,X ordernum %(ordernum)s,X relation_type ER,X from_entity SE,X to_entity OE WHERE SE eid %(se)s,ER eid %(rt)s,OE eid %(oe)s',
              {'se': None, 'rt': None, 'oe': None,
@@ -148,19 +148,19 @@
 
 
     def test_updateeschema2rql1(self):
-        self.assertListEquals(list(updateeschema2rql(schema.eschema('CWAttribute'), 1)),
+        self.assertListEqual(list(updateeschema2rql(schema.eschema('CWAttribute'), 1)),
                               [('SET X description %(description)s,X final %(final)s,X name %(name)s WHERE X eid %(x)s',
                                 {'description': u'define a final relation: link a final relation type from a non final entity to a final entity type. used to build the instance schema', 'x': 1, 'final': False, 'name': u'CWAttribute'}),
                                ])
 
     def test_updateeschema2rql2(self):
-        self.assertListEquals(list(updateeschema2rql(schema.eschema('String'), 1)),
+        self.assertListEqual(list(updateeschema2rql(schema.eschema('String'), 1)),
                               [('SET X description %(description)s,X final %(final)s,X name %(name)s WHERE X eid %(x)s',
                                 {'description': u'', 'x': 1, 'final': True, 'name': u'String'})
                                ])
 
     def test_updaterschema2rql1(self):
-        self.assertListEquals(list(updaterschema2rql(schema.rschema('relation_type'), 1)),
+        self.assertListEqual(list(updaterschema2rql(schema.rschema('relation_type'), 1)),
                              [
             ('SET X description %(description)s,X final %(final)s,X fulltext_container %(fulltext_container)s,X inlined %(inlined)s,X name %(name)s,X symmetric %(symmetric)s WHERE X eid %(x)s',
              {'x': 1, 'symmetric': False,
@@ -176,7 +176,7 @@
               'inlined': False, 'name': u'add_permission'})
             ]
         for i, (rql, args) in enumerate(updaterschema2rql(schema.rschema('add_permission'), 1)):
-            yield self.assertEquals, (rql, args), expected[i]
+            yield self.assertEqual, (rql, args), expected[i]
 
 class Perms2RQLTC(TestCase):
     GROUP_MAPPING = {
@@ -187,7 +187,7 @@
         }
 
     def test_eperms2rql1(self):
-        self.assertListEquals([(rql, kwargs) for rql, kwargs in erperms2rql(schema.eschema('CWEType'), self.GROUP_MAPPING)],
+        self.assertListEqual([(rql, kwargs) for rql, kwargs in erperms2rql(schema.eschema('CWEType'), self.GROUP_MAPPING)],
                               [('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 0}),
                                ('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 1}),
                                ('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 2}),
@@ -197,7 +197,7 @@
                                ])
 
     def test_rperms2rql2(self):
-        self.assertListEquals([(rql, kwargs) for rql, kwargs in erperms2rql(schema.rschema('read_permission').rdef('CWEType', 'CWGroup'), self.GROUP_MAPPING)],
+        self.assertListEqual([(rql, kwargs) for rql, kwargs in erperms2rql(schema.rschema('read_permission').rdef('CWEType', 'CWGroup'), self.GROUP_MAPPING)],
                               [('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 0}),
                                ('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 1}),
                                ('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 2}),
@@ -206,7 +206,7 @@
                                ])
 
     def test_rperms2rql3(self):
-        self.assertListEquals([(rql, kwargs) for rql, kwargs in erperms2rql(schema.rschema('name').rdef('CWEType', 'String'), self.GROUP_MAPPING)],
+        self.assertListEqual([(rql, kwargs) for rql, kwargs in erperms2rql(schema.rschema('name').rdef('CWEType', 'String'), self.GROUP_MAPPING)],
                               [('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 0}),
                                ('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 1}),
                                ('SET X read_permission Y WHERE Y eid %(g)s, X eid %(x)s', {'g': 2}),
@@ -214,7 +214,7 @@
                                ])
 
     #def test_perms2rql(self):
-    #    self.assertListEquals(perms2rql(schema, self.GROUP_MAPPING),
+    #    self.assertListEqual(perms2rql(schema, self.GROUP_MAPPING),
     #                         ['INSERT CWEType X: X name 'Societe', X final FALSE'])
 
 
--- a/server/test/unittest_security.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_security.py	Fri Sep 24 18:20:59 2010 +0200
@@ -81,10 +81,10 @@
         cnx = self.login('iaminusersgrouponly')
         self.hijack_source_execute()
         self.execute('Any U WHERE NOT A todo_by U, A is Affaire')
-        self.assertEquals(self.query[0][1].as_string(),
+        self.assertEqual(self.query[0][1].as_string(),
                           'Any U WHERE NOT EXISTS(A todo_by U), A is Affaire')
         self.execute('Any U WHERE NOT EXISTS(A todo_by U), A is Affaire')
-        self.assertEquals(self.query[0][1].as_string(),
+        self.assertEqual(self.query[0][1].as_string(),
                           'Any U WHERE NOT EXISTS(A todo_by U), A is Affaire')
 
 class SecurityTC(BaseSecurityTC):
@@ -103,7 +103,7 @@
         cu = cnx.cursor()
         cu.execute("INSERT Personne X: X nom 'bidule'")
         self.assertRaises(Unauthorized, cnx.commit)
-        self.assertEquals(cu.execute('Personne X').rowcount, 1)
+        self.assertEqual(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
@@ -113,7 +113,7 @@
         self.assertRaises(Unauthorized, cnx.commit)
         # test nothing has actually been inserted
         self.restore_connection()
-        self.assertEquals(self.execute('Affaire X').rowcount, 1)
+        self.assertEqual(self.execute('Affaire X').rowcount, 1)
         cnx = self.login('iaminusersgrouponly')
         cu = cnx.cursor()
         cu.execute("INSERT Affaire X: X sujet 'cool'")
@@ -128,7 +128,7 @@
         cu.execute( "SET X nom 'bidulechouette' WHERE X is Personne")
         self.assertRaises(Unauthorized, cnx.commit)
         self.restore_connection()
-        self.assertEquals(self.execute('Personne X WHERE X nom "bidulechouette"').rowcount, 0)
+        self.assertEqual(self.execute('Personne X WHERE X nom "bidulechouette"').rowcount, 0)
 
     def test_update_security_2(self):
         cnx = self.login('anon')
@@ -139,7 +139,7 @@
         #self.assertRaises(Unauthorized, cnx.commit)
         # test nothing has actually been inserted
         self.restore_connection()
-        self.assertEquals(self.execute('Personne X WHERE X nom "bidulechouette"').rowcount, 0)
+        self.assertEqual(self.execute('Personne X WHERE X nom "bidulechouette"').rowcount, 0)
 
     def test_update_security_3(self):
         cnx = self.login('iaminusersgrouponly')
@@ -210,14 +210,14 @@
         cnx.commit()
         # to actually get Unauthorized exception, try to insert a relation were we can read both entities
         rset = cu.execute('Personne P')
-        self.assertEquals(len(rset), 1)
+        self.assertEqual(len(rset), 1)
         ent = rset.get_entity(0, 0)
         session.set_pool() # necessary
         self.assertRaises(Unauthorized, ent.cw_check_perm, 'update')
         self.assertRaises(Unauthorized,
                           cu.execute, "SET P travaille S WHERE P is Personne, S is Societe")
         # test nothing has actually been inserted:
-        self.assertEquals(cu.execute('Any P,S WHERE P travaille S,P is Personne, S is Societe').rowcount, 0)
+        self.assertEqual(cu.execute('Any P,S WHERE P travaille S,P is Personne, S is Societe').rowcount, 0)
         cu.execute("INSERT Societe X: X nom 'chouette'")
         cu.execute("SET A concerne S WHERE A is Affaire, S nom 'chouette'")
         cnx.commit()
@@ -278,7 +278,7 @@
         cnx = self.login('iaminusersgrouponly')
         cu = cnx.cursor()
         rset = cu.execute('Affaire X')
-        self.assertEquals(rset.rows, [])
+        self.assertEqual(rset.rows, [])
         self.assertRaises(Unauthorized, cu.execute, 'Any X WHERE X eid %(x)s', {'x': eid})
         # cache test
         self.assertRaises(Unauthorized, cu.execute, 'Any X WHERE X eid %(x)s', {'x': eid})
@@ -287,12 +287,12 @@
         cu.execute("SET A concerne S WHERE A is Affaire, S is Societe")
         cnx.commit()
         rset = cu.execute('Any X WHERE X eid %(x)s', {'x': aff2})
-        self.assertEquals(rset.rows, [[aff2]])
+        self.assertEqual(rset.rows, [[aff2]])
         # more cache test w/ NOT eid
         rset = cu.execute('Affaire X WHERE NOT X eid %(x)s', {'x': eid})
-        self.assertEquals(rset.rows, [[aff2]])
+        self.assertEqual(rset.rows, [[aff2]])
         rset = cu.execute('Affaire X WHERE NOT X eid %(x)s', {'x': aff2})
-        self.assertEquals(rset.rows, [])
+        self.assertEqual(rset.rows, [])
         # test can't update an attribute of an entity that can't be readen
         self.assertRaises(Unauthorized, cu.execute, 'SET X sujet "hacked" WHERE X eid %(x)s', {'x': eid})
 
@@ -309,7 +309,7 @@
             self.failUnless(cu.execute('Any X WHERE X eid %(x)s', {'x':aff2}))
             # XXX would be nice if it worked
             rset = cu.execute("Affaire X WHERE X sujet 'cool'")
-            self.assertEquals(len(rset), 0)
+            self.assertEqual(len(rset), 0)
         finally:
             affschema.set_action_permissions('read', origperms)
             cnx.close()
@@ -329,7 +329,7 @@
         self.failUnless(cu.execute('Any X WHERE X eid %(x)s', {'x':aff2}))
         self.failUnless(cu.execute('Any X WHERE X eid %(x)s', {'x':card1}))
         rset = cu.execute("Any X WHERE X has_text 'cool'")
-        self.assertEquals(sorted(eid for eid, in rset.rows),
+        self.assertEqual(sorted(eid for eid, in rset.rows),
                           [card1, aff2])
 
     def test_read_erqlexpr_has_text2(self):
@@ -340,9 +340,9 @@
         cnx = self.login('iaminusersgrouponly')
         cu = cnx.cursor()
         rset = cu.execute('Any N WHERE N has_text "bidule"')
-        self.assertEquals(len(rset.rows), 1, rset.rows)
+        self.assertEqual(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.assertEqual(len(rset.rows), 1, rset.rows)
 
     def test_read_erqlexpr_optional_rel(self):
         self.execute("INSERT Personne X: X nom 'bidule'")
@@ -352,7 +352,7 @@
         cnx = self.login('anon')
         cu = cnx.cursor()
         rset = cu.execute('Any N,U WHERE N has_text "bidule", N owned_by U?')
-        self.assertEquals(len(rset.rows), 1, rset.rows)
+        self.assertEqual(len(rset.rows), 1, rset.rows)
 
     def test_read_erqlexpr_aggregat(self):
         self.execute("INSERT Affaire X: X sujet 'cool'")[0][0]
@@ -360,22 +360,22 @@
         cnx = self.login('iaminusersgrouponly')
         cu = cnx.cursor()
         rset = cu.execute('Any COUNT(X) WHERE X is Affaire')
-        self.assertEquals(rset.rows, [[0]])
+        self.assertEqual(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")
         cnx.commit()
         rset = cu.execute('Any COUNT(X) WHERE X is Affaire')
-        self.assertEquals(rset.rows, [[1]])
+        self.assertEqual(rset.rows, [[1]])
         rset = cu.execute('Any ETN, COUNT(X) GROUPBY ETN WHERE X is ET, ET name ETN')
         values = dict(rset)
-        self.assertEquals(values['Affaire'], 1)
-        self.assertEquals(values['Societe'], 2)
+        self.assertEqual(values['Affaire'], 1)
+        self.assertEqual(values['Societe'], 2)
         rset = cu.execute('Any ETN, COUNT(X) GROUPBY ETN WHERE X is ET, ET name ETN WITH X BEING ((Affaire X) UNION (Societe X))')
-        self.assertEquals(len(rset), 2)
+        self.assertEqual(len(rset), 2)
         values = dict(rset)
-        self.assertEquals(values['Affaire'], 1)
-        self.assertEquals(values['Societe'], 2)
+        self.assertEqual(values['Affaire'], 1)
+        self.assertEqual(values['Societe'], 2)
 
 
     def test_attribute_security(self):
@@ -415,7 +415,7 @@
         cnx.commit()
         note2.cw_adapt_to('IWorkflowable').fire_transition('markasdone')
         cnx.commit()
-        self.assertEquals(len(cu.execute('Any X WHERE X in_state S, S name "todo", X eid %(x)s', {'x': note2.eid})),
+        self.assertEqual(len(cu.execute('Any X WHERE X in_state S, S name "todo", X eid %(x)s', {'x': note2.eid})),
                           0)
         cu.execute("SET X para 'chouette' WHERE X eid %(x)s", {'x': note2.eid})
         self.assertRaises(Unauthorized, cnx.commit)
@@ -433,11 +433,11 @@
         rset = cu.execute('CWUser X')
         self.failUnless(rset)
         x = rset.get_entity(0, 0)
-        self.assertEquals(x.login, None)
+        self.assertEqual(x.login, None)
         self.failUnless(x.creation_date)
         x = rset.get_entity(1, 0)
         x.complete()
-        self.assertEquals(x.login, None)
+        self.assertEqual(x.login, None)
         self.failUnless(x.creation_date)
         cnx.rollback()
 
@@ -456,9 +456,9 @@
         affaire = self.execute('Any X WHERE X ref "ARCT01"').get_entity(0, 0)
         affaire.cw_adapt_to('IWorkflowable').fire_transition('abort')
         self.commit()
-        self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01"')),
+        self.assertEqual(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01"')),
                           1)
-        self.assertEquals(len(self.execute('TrInfo X WHERE X wf_info_for A, A ref "ARCT01",'
+        self.assertEqual(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
         cnx = self.login('iaminusersgrouponly')
@@ -473,9 +473,9 @@
         cu = cnx.cursor()
         # anonymous user can only read itself
         rset = cu.execute('Any L WHERE X owned_by U, U login L')
-        self.assertEquals(rset.rows, [['anon']])
+        self.assertEqual(rset.rows, [['anon']])
         rset = cu.execute('CWUser X')
-        self.assertEquals(rset.rows, [[anon.eid]])
+        self.assertEqual(rset.rows, [[anon.eid]])
         # anonymous user can read groups (necessary to check allowed transitions for instance)
         self.assert_(cu.execute('CWGroup X'))
         # should only be able to read the anonymous user, not another one
@@ -488,7 +488,7 @@
         #                  {'x': self.user.eid})
 
         rset = cu.execute('CWUser X WHERE X eid %(x)s', {'x': anon.eid})
-        self.assertEquals(rset.rows, [[anon.eid]])
+        self.assertEqual(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)
@@ -516,14 +516,14 @@
         cnx = self.login('anon')
         cu = cnx.cursor()
         anoneid = self.session.user.eid
-        self.assertEquals(cu.execute('Any T,P ORDERBY lower(T) WHERE B is Bookmark,B title T,B path P,'
+        self.assertEqual(cu.execute('Any T,P ORDERBY lower(T) WHERE B is Bookmark,B title T,B path P,'
                                      'B bookmarked_by U, U eid %s' % anoneid).rows,
                           [['index', '?vid=index']])
-        self.assertEquals(cu.execute('Any T,P ORDERBY lower(T) WHERE B is Bookmark,B title T,B path P,'
+        self.assertEqual(cu.execute('Any T,P ORDERBY lower(T) WHERE B is Bookmark,B title T,B path P,'
                                      'B bookmarked_by U, U eid %(x)s', {'x': anoneid}).rows,
                           [['index', '?vid=index']])
         # can read others bookmarks as well
-        self.assertEquals(cu.execute('Any B where B is Bookmark, NOT B bookmarked_by U').rows,
+        self.assertEqual(cu.execute('Any B where B is Bookmark, NOT B bookmarked_by U').rows,
                           [[beid1]])
         self.assertRaises(Unauthorized, cu.execute,'DELETE B bookmarked_by U')
         self.assertRaises(Unauthorized,
@@ -535,7 +535,7 @@
         cnx = self.login('anon')
         cu = cnx.cursor()
         names = [t for t, in cu.execute('Any N ORDERBY lower(N) WHERE X name N')]
-        self.assertEquals(names, sorted(names, key=lambda x: x.lower()))
+        self.assertEqual(names, sorted(names, key=lambda x: x.lower()))
 
     def test_in_state_without_update_perm(self):
         """check a user change in_state without having update permission on the
@@ -582,7 +582,7 @@
         self.commit()
         aff.cw_clear_relation_cache('wf_info_for', 'object')
         trinfo = iworkflowable.latest_trinfo()
-        self.assertEquals(trinfo.comment, 'bouh!')
+        self.assertEqual(trinfo.comment, 'bouh!')
         # but not from_state/to_state
         aff.cw_clear_relation_cache('wf_info_for', role='object')
         self.assertRaises(Unauthorized,
--- a/server/test/unittest_session.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_session.py	Fri Sep 24 18:20:59 2010 +0200
@@ -43,7 +43,7 @@
 class MakeDescriptionTC(TestCase):
     def test_known_values(self):
         solution = {'A': 'Int', 'B': 'CWUser'}
-        self.assertEquals(_make_description((Function('max', 'A'), Variable('B')), {}, solution),
+        self.assertEqual(_make_description((Function('max', 'A'), Variable('B')), {}, solution),
                           ['Int','CWUser'])
 
 class InternalSessionTC(CubicWebTC):
--- a/server/test/unittest_sqlutils.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_sqlutils.py	Fri Sep 24 18:20:59 2010 +0200
@@ -36,13 +36,13 @@
 
     def test_init(self):
         o = SQLAdapterMixIn(BASE_CONFIG)
-        self.assertEquals(o.dbhelper.dbencoding, 'UTF-8')
+        self.assertEqual(o.dbhelper.dbencoding, 'UTF-8')
 
     def test_init_encoding(self):
         config = BASE_CONFIG.copy()
         config['db-encoding'] = 'ISO-8859-1'
         o = SQLAdapterMixIn(config)
-        self.assertEquals(o.dbhelper.dbencoding, 'ISO-8859-1')
+        self.assertEqual(o.dbhelper.dbencoding, 'ISO-8859-1')
 
 if __name__ == '__main__':
     unittest_main()
--- a/server/test/unittest_storage.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_storage.py	Fri Sep 24 18:20:59 2010 +0200
@@ -78,15 +78,15 @@
         expected_filepath = osp.join(self.tempdir, '%s_data_%s' %
                                      (f1.eid, f1.data_name))
         self.failUnless(osp.isfile(expected_filepath))
-        self.assertEquals(file(expected_filepath).read(), 'the-data')
+        self.assertEqual(file(expected_filepath).read(), 'the-data')
         self.rollback()
         self.failIf(osp.isfile(expected_filepath))
         f1 = self.create_file()
         self.commit()
-        self.assertEquals(file(expected_filepath).read(), 'the-data')
+        self.assertEqual(file(expected_filepath).read(), 'the-data')
         f1.set_attributes(data=Binary('the new data'))
         self.rollback()
-        self.assertEquals(file(expected_filepath).read(), 'the-data')
+        self.assertEqual(file(expected_filepath).read(), 'the-data')
         f1.cw_delete()
         self.failUnless(osp.isfile(expected_filepath))
         self.rollback()
@@ -98,14 +98,14 @@
     def test_bfss_sqlite_fspath(self):
         f1 = self.create_file()
         expected_filepath = osp.join(self.tempdir, '%s_data_%s' % (f1.eid, f1.data_name))
-        self.assertEquals(self.fspath(f1), expected_filepath)
+        self.assertEqual(self.fspath(f1), expected_filepath)
 
     def test_bfss_fs_importing_doesnt_touch_path(self):
         self.session.transaction_data['fs_importing'] = True
         filepath = osp.abspath(__file__)
         f1 = self.session.create_entity('File', data=Binary(filepath),
                                         data_format=u'text/plain', data_name=u'foo')
-        self.assertEquals(self.fspath(f1), filepath)
+        self.assertEqual(self.fspath(f1), filepath)
 
     def test_source_storage_transparency(self):
         with self.temporary_appobjects(DummyBeforeHook, DummyAfterHook):
@@ -114,11 +114,11 @@
     def test_source_mapped_attribute_error_cases(self):
         ex = self.assertRaises(QueryError, self.execute,
                                'Any X WHERE X data ~= "hop", X is File')
-        self.assertEquals(str(ex), 'can\'t use File.data (X data ILIKE "hop") in restriction')
+        self.assertEqual(str(ex), 'can\'t use File.data (X data ILIKE "hop") in restriction')
         ex = self.assertRaises(QueryError, self.execute,
                                'Any X, Y WHERE X data D, Y data D, '
                                'NOT X identity Y, X is File, Y is File')
-        self.assertEquals(str(ex), "can't use D as a restriction variable")
+        self.assertEqual(str(ex), "can't use D as a restriction variable")
         # query returning mix of mapped / regular attributes (only file.data
         # mapped, not image.data for instance)
         ex = self.assertRaises(QueryError, self.execute,
@@ -127,19 +127,19 @@
                                '  UNION '
                                ' (Any D WHERE X data D, X is File)'
                                ')')
-        self.assertEquals(str(ex), 'query fetch some source mapped attribute, some not')
+        self.assertEqual(str(ex), 'query fetch some source mapped attribute, some not')
         ex = self.assertRaises(QueryError, self.execute,
                                '(Any D WHERE X data D, X is File)'
                                ' UNION '
                                '(Any D WHERE X title D, X is Bookmark)')
-        self.assertEquals(str(ex), 'query fetch some source mapped attribute, some not')
+        self.assertEqual(str(ex), 'query fetch some source mapped attribute, some not')
 
         storages.set_attribute_storage(self.repo, 'State', 'name',
                                        storages.BytesFileSystemStorage(self.tempdir))
         try:
             ex = self.assertRaises(QueryError,
                                    self.execute, 'Any D WHERE X name D, X is IN (State, Transition)')
-            self.assertEquals(str(ex), 'query fetch some source mapped attribute, some not')
+            self.assertEqual(str(ex), 'query fetch some source mapped attribute, some not')
         finally:
             storages.unset_attribute_storage(self.repo, 'State', 'name')
 
@@ -150,30 +150,30 @@
                             '  UNION '
                             ' (Any D, X WHERE X eid %(x)s, X data D)'
                             ')', {'x': f1.eid})
-        self.assertEquals(len(rset), 2)
-        self.assertEquals(rset[0][0], f1.eid)
-        self.assertEquals(rset[1][0], f1.eid)
-        self.assertEquals(rset[0][1].getvalue(), 'the-data')
-        self.assertEquals(rset[1][1].getvalue(), 'the-data')
+        self.assertEqual(len(rset), 2)
+        self.assertEqual(rset[0][0], f1.eid)
+        self.assertEqual(rset[1][0], f1.eid)
+        self.assertEqual(rset[0][1].getvalue(), 'the-data')
+        self.assertEqual(rset[1][1].getvalue(), 'the-data')
         rset = self.execute('Any X,LENGTH(D) WHERE X eid %(x)s, X data D',
                             {'x': f1.eid})
-        self.assertEquals(len(rset), 1)
-        self.assertEquals(rset[0][0], f1.eid)
-        self.assertEquals(rset[0][1], len('the-data'))
+        self.assertEqual(len(rset), 1)
+        self.assertEqual(rset[0][0], f1.eid)
+        self.assertEqual(rset[0][1], len('the-data'))
         rset = self.execute('Any X,LENGTH(D) WITH D,X BEING ('
                             ' (Any D, X WHERE X eid %(x)s, X data D)'
                             '  UNION '
                             ' (Any D, X WHERE X eid %(x)s, X data D)'
                             ')', {'x': f1.eid})
-        self.assertEquals(len(rset), 2)
-        self.assertEquals(rset[0][0], f1.eid)
-        self.assertEquals(rset[1][0], f1.eid)
-        self.assertEquals(rset[0][1], len('the-data'))
-        self.assertEquals(rset[1][1], len('the-data'))
+        self.assertEqual(len(rset), 2)
+        self.assertEqual(rset[0][0], f1.eid)
+        self.assertEqual(rset[1][0], f1.eid)
+        self.assertEqual(rset[0][1], len('the-data'))
+        self.assertEqual(rset[1][1], len('the-data'))
         ex = self.assertRaises(QueryError, self.execute,
                                'Any X,UPPER(D) WHERE X eid %(x)s, X data D',
                                {'x': f1.eid})
-        self.assertEquals(str(ex), 'UPPER can not be called on mapped attribute')
+        self.assertEqual(str(ex), 'UPPER can not be called on mapped attribute')
 
 
     def test_bfss_fs_importing_transparency(self):
@@ -181,7 +181,7 @@
         filepath = osp.abspath(__file__)
         f1 = self.session.create_entity('File', data=Binary(filepath),
                                         data_format=u'text/plain', data_name=u'foo')
-        self.assertEquals(f1.data.getvalue(), file(filepath).read(),
+        self.assertEqual(f1.data.getvalue(), file(filepath).read(),
                           'files content differ')
 
     @tag('Storage', 'BFSS', 'update')
@@ -193,10 +193,10 @@
         #       update f1's local dict. We want the pure rql version to work
         self.execute('SET F data %(d)s WHERE F eid %(f)s',
                      {'d': Binary('some other data'), 'f': f1.eid})
-        self.assertEquals(f1.data.getvalue(), 'some other data')
+        self.assertEqual(f1.data.getvalue(), 'some other data')
         self.commit()
         f2 = self.execute('Any F WHERE F eid %(f)s, F is File', {'f': f1.eid}).get_entity(0, 0)
-        self.assertEquals(f2.data.getvalue(), 'some other data')
+        self.assertEqual(f2.data.getvalue(), 'some other data')
 
     @tag('Storage', 'BFSS', 'update', 'extension', 'commit')
     def test_bfss_update_with_different_extension_commited(self):
@@ -208,7 +208,7 @@
         self.commit()
         old_path = self.fspath(f1)
         self.failUnless(osp.isfile(old_path))
-        self.assertEquals(osp.splitext(old_path)[1], '.txt')
+        self.assertEqual(osp.splitext(old_path)[1], '.txt')
         self.execute('SET F data %(d)s, F data_name %(dn)s, F data_format %(df)s WHERE F eid %(f)s',
                      {'d': Binary('some other data'), 'f': f1.eid, 'dn': u'bar.jpg', 'df': u'image/jpeg'})
         self.commit()
@@ -218,7 +218,7 @@
         new_path = self.fspath(f2)
         self.failIf(osp.isfile(old_path))
         self.failUnless(osp.isfile(new_path))
-        self.assertEquals(osp.splitext(new_path)[1], '.jpg')
+        self.assertEqual(osp.splitext(new_path)[1], '.jpg')
 
     @tag('Storage', 'BFSS', 'update', 'extension', 'rollback')
     def test_bfss_update_with_different_extension_rollbacked(self):
@@ -231,7 +231,7 @@
         old_path = self.fspath(f1)
         old_data = f1.data.getvalue()
         self.failUnless(osp.isfile(old_path))
-        self.assertEquals(osp.splitext(old_path)[1], '.txt')
+        self.assertEqual(osp.splitext(old_path)[1], '.txt')
         self.execute('SET F data %(d)s, F data_name %(dn)s, F data_format %(df)s WHERE F eid %(f)s',
                      {'d': Binary('some other data'), 'f': f1.eid, 'dn': u'bar.jpg', 'df': u'image/jpeg'})
         self.rollback()
@@ -241,9 +241,9 @@
         new_path = self.fspath(f2)
         new_data = f2.data.getvalue()
         self.failUnless(osp.isfile(new_path))
-        self.assertEquals(osp.splitext(new_path)[1], '.txt')
-        self.assertEquals(old_path, new_path)
-        self.assertEquals(old_data, new_data)
+        self.assertEqual(osp.splitext(new_path)[1], '.txt')
+        self.assertEqual(old_path, new_path)
+        self.assertEqual(old_data, new_data)
 
     def test_bfss_update_with_fs_importing(self):
         # use self.session to use server-side cache
@@ -256,8 +256,8 @@
         self.execute('SET F data %(d)s WHERE F eid %(f)s',
                      {'d': Binary(new_fspath), 'f': f1.eid})
         self.commit()
-        self.assertEquals(f1.data.getvalue(), 'the new data')
-        self.assertEquals(self.fspath(f1), new_fspath)
+        self.assertEqual(f1.data.getvalue(), 'the new data')
+        self.assertEqual(self.fspath(f1), new_fspath)
         self.failIf(osp.isfile(old_fspath))
 
 
--- a/server/test/unittest_undo.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/server/test/unittest_undo.py	Fri Sep 24 18:20:59 2010 +0200
@@ -54,36 +54,36 @@
                           self.cnx.undo_transaction, 'hop')
         txinfo = self.cnx.transaction_info(self.txuuid)
         self.failUnless(txinfo.datetime)
-        self.assertEquals(txinfo.user_eid, self.session.user.eid)
-        self.assertEquals(txinfo.user().login, 'admin')
+        self.assertEqual(txinfo.user_eid, self.session.user.eid)
+        self.assertEqual(txinfo.user().login, 'admin')
         actions = txinfo.actions_list()
-        self.assertEquals(len(actions), 2)
+        self.assertEqual(len(actions), 2)
         actions = txinfo.actions_list(public=False)
-        self.assertEquals(len(actions), 6)
+        self.assertEqual(len(actions), 6)
         a1 = actions[0]
-        self.assertEquals(a1.action, 'C')
-        self.assertEquals(a1.eid, self.toto.eid)
-        self.assertEquals(a1.etype,'CWUser')
-        self.assertEquals(a1.changes, None)
-        self.assertEquals(a1.public, True)
-        self.assertEquals(a1.order, 1)
+        self.assertEqual(a1.action, 'C')
+        self.assertEqual(a1.eid, self.toto.eid)
+        self.assertEqual(a1.etype,'CWUser')
+        self.assertEqual(a1.changes, None)
+        self.assertEqual(a1.public, True)
+        self.assertEqual(a1.order, 1)
         a4 = actions[3]
-        self.assertEquals(a4.action, 'A')
-        self.assertEquals(a4.rtype, 'in_group')
-        self.assertEquals(a4.eid_from, self.toto.eid)
-        self.assertEquals(a4.eid_to, self.toto.in_group[0].eid)
-        self.assertEquals(a4.order, 4)
+        self.assertEqual(a4.action, 'A')
+        self.assertEqual(a4.rtype, 'in_group')
+        self.assertEqual(a4.eid_from, self.toto.eid)
+        self.assertEqual(a4.eid_to, self.toto.in_group[0].eid)
+        self.assertEqual(a4.order, 4)
         for i, rtype in ((1, 'owned_by'), (2, 'owned_by'),
                          (4, 'in_state'), (5, 'created_by')):
             a = actions[i]
-            self.assertEquals(a.action, 'A')
-            self.assertEquals(a.eid_from, self.toto.eid)
-            self.assertEquals(a.rtype, rtype)
-            self.assertEquals(a.order, i+1)
+            self.assertEqual(a.action, 'A')
+            self.assertEqual(a.eid_from, self.toto.eid)
+            self.assertEqual(a.rtype, rtype)
+            self.assertEqual(a.order, i+1)
         # test undoable_transactions
         txs = self.cnx.undoable_transactions()
-        self.assertEquals(len(txs), 1)
-        self.assertEquals(txs[0].uuid, self.txuuid)
+        self.assertEqual(len(txs), 1)
+        self.assertEqual(txs[0].uuid, self.txuuid)
         # test transaction_info / undoable_transactions security
         cnx = self.login('anon')
         self.assertRaises(NoSuchTransaction,
@@ -93,7 +93,7 @@
         self.assertRaises(NoSuchTransaction,
                           cnx.undo_transaction, self.txuuid)
         txs = cnx.undoable_transactions()
-        self.assertEquals(len(txs), 0)
+        self.assertEqual(len(txs), 0)
 
     def test_undoable_transactions(self):
         toto = self.toto
@@ -105,31 +105,31 @@
         txuuid2 = self.commit()
         undoable_transactions = self.cnx.undoable_transactions
         txs = undoable_transactions(action='D')
-        self.assertEquals(len(txs), 1, txs)
-        self.assertEquals(txs[0].uuid, txuuid2)
+        self.assertEqual(len(txs), 1, txs)
+        self.assertEqual(txs[0].uuid, txuuid2)
         txs = undoable_transactions(action='C')
-        self.assertEquals(len(txs), 2, txs)
-        self.assertEquals(txs[0].uuid, txuuid1)
-        self.assertEquals(txs[1].uuid, self.txuuid)
+        self.assertEqual(len(txs), 2, txs)
+        self.assertEqual(txs[0].uuid, txuuid1)
+        self.assertEqual(txs[1].uuid, self.txuuid)
         txs = undoable_transactions(eid=toto.eid)
-        self.assertEquals(len(txs), 3)
-        self.assertEquals(txs[0].uuid, txuuid2)
-        self.assertEquals(txs[1].uuid, txuuid1)
-        self.assertEquals(txs[2].uuid, self.txuuid)
+        self.assertEqual(len(txs), 3)
+        self.assertEqual(txs[0].uuid, txuuid2)
+        self.assertEqual(txs[1].uuid, txuuid1)
+        self.assertEqual(txs[2].uuid, self.txuuid)
         txs = undoable_transactions(etype='CWUser')
-        self.assertEquals(len(txs), 2)
+        self.assertEqual(len(txs), 2)
         txs = undoable_transactions(etype='CWUser', action='C')
-        self.assertEquals(len(txs), 1)
-        self.assertEquals(txs[0].uuid, self.txuuid)
+        self.assertEqual(len(txs), 1)
+        self.assertEqual(txs[0].uuid, self.txuuid)
         txs = undoable_transactions(etype='EmailAddress', action='D')
-        self.assertEquals(len(txs), 0)
+        self.assertEqual(len(txs), 0)
         txs = undoable_transactions(etype='EmailAddress', action='D',
                                     public=False)
-        self.assertEquals(len(txs), 1)
-        self.assertEquals(txs[0].uuid, txuuid2)
+        self.assertEqual(len(txs), 1)
+        self.assertEqual(txs[0].uuid, txuuid2)
         txs = undoable_transactions(eid=toto.eid, action='R', public=False)
-        self.assertEquals(len(txs), 1)
-        self.assertEquals(txs[0].uuid, txuuid2)
+        self.assertEqual(len(txs), 1)
+        self.assertEqual(txs[0].uuid, txuuid2)
 
     def test_undo_deletion_base(self):
         toto = self.toto
@@ -143,34 +143,34 @@
                                        for_user=toto)
         self.commit()
         txs = self.cnx.undoable_transactions()
-        self.assertEquals(len(txs), 2)
+        self.assertEqual(len(txs), 2)
         toto.cw_delete()
         txuuid = self.commit()
         actions = self.cnx.transaction_info(txuuid).actions_list()
-        self.assertEquals(len(actions), 1)
+        self.assertEqual(len(actions), 1)
         toto.clear_all_caches()
         e.clear_all_caches()
         errors = self.cnx.undo_transaction(txuuid)
         undotxuuid = self.commit()
-        self.assertEquals(undotxuuid, None) # undo not undoable
-        self.assertEquals(errors, [])
+        self.assertEqual(undotxuuid, None) # undo not undoable
+        self.assertEqual(errors, [])
         self.failUnless(self.execute('Any X WHERE X eid %(x)s', {'x': toto.eid}))
         self.failUnless(self.execute('Any X WHERE X eid %(x)s', {'x': e.eid}))
         self.failUnless(self.execute('Any X WHERE X has_text "toto@logilab"'))
-        self.assertEquals(toto.cw_adapt_to('IWorkflowable').state, 'activated')
-        self.assertEquals(toto.cw_adapt_to('IEmailable').get_email(), 'toto@logilab.org')
-        self.assertEquals([(p.pkey, p.value) for p in toto.reverse_for_user],
+        self.assertEqual(toto.cw_adapt_to('IWorkflowable').state, 'activated')
+        self.assertEqual(toto.cw_adapt_to('IEmailable').get_email(), 'toto@logilab.org')
+        self.assertEqual([(p.pkey, p.value) for p in toto.reverse_for_user],
                           [('ui.default-text-format', 'text/rest')])
-        self.assertEquals([g.name for g in toto.in_group],
+        self.assertEqual([g.name for g in toto.in_group],
                           ['users'])
-        self.assertEquals([et.name for et in toto.related('is', entities=True)],
+        self.assertEqual([et.name for et in toto.related('is', entities=True)],
                           ['CWUser'])
-        self.assertEquals([et.name for et in toto.is_instance_of],
+        self.assertEqual([et.name for et in toto.is_instance_of],
                           ['CWUser'])
         # undoing shouldn't be visble in undoable transaction, and the undoed
         # transaction should be removed
         txs = self.cnx.undoable_transactions()
-        self.assertEquals(len(txs), 2)
+        self.assertEqual(len(txs), 2)
         self.assertRaises(NoSuchTransaction,
                           self.cnx.transaction_info, txuuid)
         self.check_transaction_deleted(txuuid)
@@ -191,9 +191,9 @@
         errors = self.cnx.undo_transaction(txuuid)
         self.commit()
         p.clear_all_caches()
-        self.assertEquals(p.fiche[0].eid, c2.eid)
-        self.assertEquals(len(errors), 1)
-        self.assertEquals(errors[0],
+        self.assertEqual(p.fiche[0].eid, c2.eid)
+        self.assertEqual(len(errors), 1)
+        self.assertEqual(errors[0],
                           "Can't restore object relation fiche to entity "
                           "%s which is already linked using this relation." % p.eid)
 
@@ -209,12 +209,12 @@
         g.cw_delete()
         self.commit()
         errors = self.cnx.undo_transaction(txuuid)
-        self.assertEquals(errors,
+        self.assertEqual(errors,
                           [u"Can't restore relation in_group, object entity "
                           "%s doesn't exist anymore." % g.eid])
         ex = self.assertRaises(ValidationError, self.commit)
-        self.assertEquals(ex.entity, self.toto.eid)
-        self.assertEquals(ex.errors,
+        self.assertEqual(ex.entity, self.toto.eid)
+        self.assertEqual(ex.errors,
                           {'in_group-subject': u'at least one relation in_group is '
                            'required on CWUser (%s)' % self.toto.eid})
 
@@ -254,8 +254,8 @@
         self.commit()
         ex = self.assertRaises(ValidationError,
                                self.cnx.undo_transaction, txuuid)
-        self.assertEquals(ex.entity, tutu.eid)
-        self.assertEquals(ex.errors,
+        self.assertEqual(ex.entity, tutu.eid)
+        self.assertEqual(ex.errors,
                           {None: 'some later transaction(s) touch entity, undo them first'})
 
     def test_undo_creation_integrity_2(self):
@@ -267,15 +267,15 @@
         self.commit()
         ex = self.assertRaises(ValidationError,
                                self.cnx.undo_transaction, txuuid)
-        self.assertEquals(ex.entity, g.eid)
-        self.assertEquals(ex.errors,
+        self.assertEqual(ex.entity, g.eid)
+        self.assertEqual(ex.errors,
                           {None: 'some later transaction(s) touch entity, undo them first'})
-        # self.assertEquals(errors,
+        # self.assertEqual(errors,
         #                   [u"Can't restore relation in_group, object entity "
         #                   "%s doesn't exist anymore." % g.eid])
         # ex = self.assertRaises(ValidationError, self.commit)
-        # self.assertEquals(ex.entity, self.toto.eid)
-        # self.assertEquals(ex.errors,
+        # self.assertEqual(ex.entity, self.toto.eid)
+        # self.assertEqual(ex.errors,
         #                   {'in_group-subject': u'at least one relation in_group is '
         #                    'required on CWUser (%s)' % self.toto.eid})
 
--- a/sobjects/test/unittest_email.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/sobjects/test/unittest_email.py	Fri Sep 24 18:20:59 2010 +0200
@@ -26,23 +26,23 @@
 
     def test_use_email_set_primary_email(self):
         self.execute('INSERT EmailAddress X: X address "admin@logilab.fr", U use_email X WHERE U login "admin"')
-        self.assertEquals(self.execute('Any A WHERE U primary_email X, U login "admin", X address A').rows,
+        self.assertEqual(self.execute('Any A WHERE U primary_email X, U login "admin", X address A').rows,
                           [])
         self.commit()
-        self.assertEquals(self.execute('Any A WHERE U primary_email X, U login "admin", X address A')[0][0],
+        self.assertEqual(self.execute('Any A WHERE U primary_email X, U login "admin", X address A')[0][0],
                           'admin@logilab.fr')
         # having another email should'nt change anything
         self.execute('INSERT EmailAddress X: X address "a@logilab.fr", U use_email X WHERE U login "admin"')
         self.commit()
-        self.assertEquals(self.execute('Any A WHERE U primary_email X, U login "admin", X address A')[0][0],
+        self.assertEqual(self.execute('Any A WHERE U primary_email X, U login "admin", X address A')[0][0],
                           'admin@logilab.fr')
 
     def test_primary_email_set_use_email(self):
         self.execute('INSERT EmailAddress X: X address "admin@logilab.fr", U primary_email X WHERE U login "admin"')
-        self.assertEquals(self.execute('Any A WHERE U use_email X, U login "admin", X address A').rows,
+        self.assertEqual(self.execute('Any A WHERE U use_email X, U login "admin", X address A').rows,
                           [])
         self.commit()
-        self.assertEquals(self.execute('Any A WHERE U use_email X, U login "admin", X address A')[0][0],
+        self.assertEqual(self.execute('Any A WHERE U use_email X, U login "admin", X address A')[0][0],
                           'admin@logilab.fr')
 
     def test_cardinality_check(self):
--- a/sobjects/test/unittest_notification.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/sobjects/test/unittest_notification.py	Fri Sep 24 18:20:59 2010 +0200
@@ -72,12 +72,12 @@
         finder = self.vreg['components'].select('recipients_finder',
                                                 self.request(), rset=urset)
         self.set_option('default-recipients-mode', 'none')
-        self.assertEquals(finder.recipients(), [])
+        self.assertEqual(finder.recipients(), [])
         self.set_option('default-recipients-mode', 'users')
-        self.assertEquals(finder.recipients(), [(u'admin@logilab.fr', 'fr')])
+        self.assertEqual(finder.recipients(), [(u'admin@logilab.fr', 'fr')])
         self.set_option('default-recipients-mode', 'default-dest-addrs')
         self.set_option('default-dest-addrs', 'abcd@logilab.fr, efgh@logilab.fr')
-        self.assertEquals(finder.recipients(), [('abcd@logilab.fr', 'en'), ('efgh@logilab.fr', 'en')])
+        self.assertEqual(finder.recipients(), [('abcd@logilab.fr', 'en'), ('efgh@logilab.fr', 'en')])
 
 
 class StatusChangeViewsTC(CubicWebTC):
@@ -88,9 +88,9 @@
         u.cw_adapt_to('IWorkflowable').fire_transition('deactivate', comment=u'yeah')
         self.failIf(MAILBOX)
         self.commit()
-        self.assertEquals(len(MAILBOX), 1)
+        self.assertEqual(len(MAILBOX), 1)
         email = MAILBOX[0]
-        self.assertEquals(email.content,
+        self.assertEqual(email.content,
                           '''
 admin changed status from <activated> to <deactivated> for entity
 'toto'
@@ -99,7 +99,7 @@
 
 url: http://testing.fr/cubicweb/cwuser/toto
 ''')
-        self.assertEquals(email.subject, 'status changed cwuser #%s (admin)' % u.eid)
+        self.assertEqual(email.subject, 'status changed cwuser #%s (admin)' % u.eid)
 
 if __name__ == '__main__':
     unittest_main()
--- a/sobjects/test/unittest_supervising.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/sobjects/test/unittest_supervising.py	Fri Sep 24 18:20:59 2010 +0200
@@ -52,16 +52,16 @@
         session = self.session
         sentops = [op for op in session.pending_operations
                    if isinstance(op, SupervisionMailOp)]
-        self.assertEquals(len(sentops), 1)
+        self.assertEqual(len(sentops), 1)
         # check view content
         op = sentops[0]
         view = sentops[0]._get_view()
-        self.assertEquals(view.recipients(), ['test@logilab.fr'])
-        self.assertEquals(view.subject(), '[data supervision] changes summary')
+        self.assertEqual(view.recipients(), ['test@logilab.fr'])
+        self.assertEqual(view.subject(), '[data supervision] changes summary')
         data = view.render(changes=session.transaction_data.get('pendingchanges')).strip()
         data = re.sub('#\d+', '#EID', data)
         data = re.sub('/\d+', '/EID', data)
-        self.assertTextEquals('''user admin has made the following change(s):
+        self.assertMultiLineEqual('''user admin has made the following change(s):
 
 * added cwuser #EID (toto)
   http://testing.fr/cubicweb/cwuser/toto
@@ -79,22 +79,22 @@
                               data)
         # check prepared email
         op._prepare_email()
-        self.assertEquals(len(op.to_send), 1)
+        self.assertEqual(len(op.to_send), 1)
         self.assert_(op.to_send[0][0])
-        self.assertEquals(op.to_send[0][1], ['test@logilab.fr'])
+        self.assertEqual(op.to_send[0][1], ['test@logilab.fr'])
         self.commit()
         # some other changes #######
         user.cw_adapt_to('IWorkflowable').fire_transition('deactivate')
         sentops = [op for op in session.pending_operations
                    if isinstance(op, SupervisionMailOp)]
-        self.assertEquals(len(sentops), 1)
+        self.assertEqual(len(sentops), 1)
         # check view content
         op = sentops[0]
         view = sentops[0]._get_view()
         data = view.render(changes=session.transaction_data.get('pendingchanges')).strip()
         data = re.sub('#\d+', '#EID', data)
         data = re.sub('/\d+', '/EID', data)
-        self.assertTextEquals('''user admin has made the following change(s):
+        self.assertMultiLineEqual('''user admin has made the following change(s):
 
 * changed state of cwuser #EID (toto)
   from state activated to state deactivated
--- a/test/unittest_cwconfig.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/test/unittest_cwconfig.py	Fri Sep 24 18:20:59 2010 +0200
@@ -54,17 +54,17 @@
         self.config.adjust_sys_path()
         # forge depends on email and file and comment
         # email depends on file
-        self.assertEquals(self.config.reorder_cubes(['file', 'email', 'forge']),
+        self.assertEqual(self.config.reorder_cubes(['file', 'email', 'forge']),
                           ('forge', 'email', 'file'))
-        self.assertEquals(self.config.reorder_cubes(['email', 'file', 'forge']),
+        self.assertEqual(self.config.reorder_cubes(['email', 'file', 'forge']),
                           ('forge', 'email', 'file'))
-        self.assertEquals(self.config.reorder_cubes(['email', 'forge', 'file']),
+        self.assertEqual(self.config.reorder_cubes(['email', 'forge', 'file']),
                           ('forge', 'email', 'file'))
-        self.assertEquals(self.config.reorder_cubes(['file', 'forge', 'email']),
+        self.assertEqual(self.config.reorder_cubes(['file', 'forge', 'email']),
                           ('forge', 'email', 'file'))
-        self.assertEquals(self.config.reorder_cubes(['forge', 'file', 'email']),
+        self.assertEqual(self.config.reorder_cubes(['forge', 'file', 'email']),
                           ('forge', 'email', 'file'))
-        self.assertEquals(self.config.reorder_cubes(('forge', 'email', 'file')),
+        self.assertEqual(self.config.reorder_cubes(('forge', 'email', 'file')),
                           ('forge', 'email', 'file'))
 
     def test_reorder_cubes_recommends(self):
@@ -75,13 +75,13 @@
         try:
             # email recommends comment
             # comment recommends file
-            self.assertEquals(self.config.reorder_cubes(('forge', 'email', 'file', 'comment')),
+            self.assertEqual(self.config.reorder_cubes(('forge', 'email', 'file', 'comment')),
                               ('forge', 'email', 'comment', 'file'))
-            self.assertEquals(self.config.reorder_cubes(('forge', 'email', 'comment', 'file')),
+            self.assertEqual(self.config.reorder_cubes(('forge', 'email', 'comment', 'file')),
                               ('forge', 'email', 'comment', 'file'))
-            self.assertEquals(self.config.reorder_cubes(('forge', 'comment', 'email', 'file')),
+            self.assertEqual(self.config.reorder_cubes(('forge', 'comment', 'email', 'file')),
                               ('forge', 'email', 'comment', 'file'))
-            self.assertEquals(self.config.reorder_cubes(('comment', 'forge', 'email', 'file')),
+            self.assertEqual(self.config.reorder_cubes(('comment', 'forge', 'email', 'file')),
                               ('forge', 'email', 'comment', 'file'))
         finally:
             comment_pkginfo.__recommends_cubes__ = {}
@@ -90,17 +90,17 @@
 #     def test_vc_config(self):
 #         vcconf = self.config.vc_config()
 #         self.assertIsInstance(vcconf['EEMAIL'], Version)
-#         self.assertEquals(vcconf['EEMAIL'], (0, 3, 1))
-#         self.assertEquals(vcconf['CW'], (2, 31, 2))
+#         self.assertEqual(vcconf['EEMAIL'], (0, 3, 1))
+#         self.assertEqual(vcconf['CW'], (2, 31, 2))
 #         self.assertRaises(KeyError, vcconf.__getitem__, 'CW_VERSION')
 #         self.assertRaises(KeyError, vcconf.__getitem__, 'CRM')
 
     def test_expand_cubes(self):
-        self.assertEquals(self.config.expand_cubes(('email', 'blog')),
+        self.assertEqual(self.config.expand_cubes(('email', 'blog')),
                           ['email', 'blog', 'file'])
 
     def test_vregistry_path(self):
-        self.assertEquals([unabsolutize(p) for p in self.config.vregistry_path()],
+        self.assertEqual([unabsolutize(p) for p in self.config.vregistry_path()],
                           ['entities', 'web/views', 'sobjects', 'hooks',
                            'file/entities.py', 'file/views', 'file/hooks.py',
                            'email/entities.py', 'email/views', 'email/hooks.py',
@@ -111,27 +111,27 @@
         import email
         self.assertNotEquals(dirname(email.__file__), self.config.CUBES_DIR)
         self.config.__class__.CUBES_PATH = [CUSTOM_CUBES_DIR]
-        self.assertEquals(self.config.cubes_search_path(),
+        self.assertEqual(self.config.cubes_search_path(),
                           [CUSTOM_CUBES_DIR, self.config.CUBES_DIR])
         self.config.__class__.CUBES_PATH = [CUSTOM_CUBES_DIR,
                                             self.config.CUBES_DIR, 'unexistant']
         # filter out unexistant and duplicates
-        self.assertEquals(self.config.cubes_search_path(),
+        self.assertEqual(self.config.cubes_search_path(),
                           [CUSTOM_CUBES_DIR,
                            self.config.CUBES_DIR])
         self.failUnless('mycube' in self.config.available_cubes())
         # test cubes python path
         self.config.adjust_sys_path()
         import cubes
-        self.assertEquals(cubes.__path__, self.config.cubes_search_path())
+        self.assertEqual(cubes.__path__, self.config.cubes_search_path())
         # this import should succeed once path is adjusted
         from cubes import mycube
-        self.assertEquals(mycube.__path__, [join(CUSTOM_CUBES_DIR, 'mycube')])
+        self.assertEqual(mycube.__path__, [join(CUSTOM_CUBES_DIR, 'mycube')])
         # file cube should be overriden by the one found in data/cubes
         sys.modules.pop('cubes.file', None)
         del cubes.file
         from cubes import file
-        self.assertEquals(file.__path__, [join(CUSTOM_CUBES_DIR, 'file')])
+        self.assertEqual(file.__path__, [join(CUSTOM_CUBES_DIR, 'file')])
 
 
 class FindPrefixTC(TestCase):
@@ -153,35 +153,35 @@
     def test_samedir(self):
         prefix = tempfile.tempdir
         self.make_dirs('share', 'cubicweb')
-        self.assertEquals(_find_prefix(prefix), prefix)
+        self.assertEqual(_find_prefix(prefix), prefix)
 
     @with_tempdir
     def test_samedir_filepath(self):
         prefix = tempfile.tempdir
         self.make_dirs('share', 'cubicweb')
         file_path = self.make_file('bob.py')
-        self.assertEquals(_find_prefix(file_path), prefix)
+        self.assertEqual(_find_prefix(file_path), prefix)
 
     @with_tempdir
     def test_dir_inside_prefix(self):
         prefix = tempfile.tempdir
         self.make_dirs('share', 'cubicweb')
         dir_path = self.make_dirs('bob')
-        self.assertEquals(_find_prefix(dir_path), prefix)
+        self.assertEqual(_find_prefix(dir_path), prefix)
 
     @with_tempdir
     def test_file_in_dir_inside_prefix(self):
         prefix = tempfile.tempdir
         self.make_dirs('share', 'cubicweb')
         file_path = self.make_file('bob', 'toto.py')
-        self.assertEquals(_find_prefix(file_path), prefix)
+        self.assertEqual(_find_prefix(file_path), prefix)
 
     @with_tempdir
     def test_file_in_deeper_dir_inside_prefix(self):
         prefix = tempfile.tempdir
         self.make_dirs('share', 'cubicweb')
         file_path = self.make_file('bob', 'pyves', 'alain', 'adim', 'syt', 'toto.py')
-        self.assertEquals(_find_prefix(file_path), prefix)
+        self.assertEqual(_find_prefix(file_path), prefix)
 
     @with_tempdir
     def test_multiple_candidate_prefix(self):
@@ -189,7 +189,7 @@
         prefix = self.make_dirs('bob')
         self.make_dirs('bob', 'share', 'cubicweb')
         file_path = self.make_file('bob', 'pyves', 'alain', 'adim', 'syt', 'toto.py')
-        self.assertEquals(_find_prefix(file_path), prefix)
+        self.assertEqual(_find_prefix(file_path), prefix)
 
     @with_tempdir
     def test_sister_candidate_prefix(self):
@@ -197,7 +197,7 @@
         self.make_dirs('share', 'cubicweb')
         self.make_dirs('bob', 'share', 'cubicweb')
         file_path = self.make_file('bell', 'toto.py')
-        self.assertEquals(_find_prefix(file_path), prefix)
+        self.assertEqual(_find_prefix(file_path), prefix)
 
     @with_tempdir
     def test_multiple_parent_candidate_prefix(self):
@@ -205,7 +205,7 @@
         prefix = self.make_dirs('share', 'cubicweb', 'bob')
         self.make_dirs('share', 'cubicweb', 'bob', 'share', 'cubicweb')
         file_path = self.make_file('share', 'cubicweb', 'bob', 'pyves', 'alain', 'adim', 'syt', 'toto.py')
-        self.assertEquals(_find_prefix(file_path), prefix)
+        self.assertEqual(_find_prefix(file_path), prefix)
 
     @with_tempdir
     def test_upper_candidate_prefix(self):
@@ -213,12 +213,12 @@
         self.make_dirs('share', 'cubicweb')
         self.make_dirs('bell','bob',  'share', 'cubicweb')
         file_path = self.make_file('bell', 'toto.py')
-        self.assertEquals(_find_prefix(file_path), prefix)
+        self.assertEqual(_find_prefix(file_path), prefix)
 
     @with_tempdir
     def test_no_prefix(self):
         prefix = tempfile.tempdir
-        self.assertEquals(_find_prefix(prefix), sys.prefix)
+        self.assertEqual(_find_prefix(prefix), sys.prefix)
 
 if __name__ == '__main__':
     unittest_main()
--- a/test/unittest_dbapi.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/test/unittest_dbapi.py	Fri Sep 24 18:20:59 2010 +0200
@@ -29,40 +29,40 @@
 
     def test_public_repo_api(self):
         cnx = self.login('anon')
-        self.assertEquals(cnx.get_schema(), self.repo.schema)
-        self.assertEquals(cnx.source_defs(), {'system': {'adapter': 'native', 'uri': 'system'}})
+        self.assertEqual(cnx.get_schema(), self.repo.schema)
+        self.assertEqual(cnx.source_defs(), {'system': {'adapter': 'native', 'uri': 'system'}})
         self.restore_connection() # proper way to close cnx
         self.assertRaises(ProgrammingError, cnx.get_schema)
         self.assertRaises(ProgrammingError, cnx.source_defs)
 
     def test_db_api(self):
         cnx = self.login('anon')
-        self.assertEquals(cnx.rollback(), None)
-        self.assertEquals(cnx.commit(), None)
+        self.assertEqual(cnx.rollback(), None)
+        self.assertEqual(cnx.commit(), None)
         self.restore_connection() # proper way to close cnx
-        #self.assertEquals(cnx.close(), None)
+        #self.assertEqual(cnx.close(), None)
         self.assertRaises(ProgrammingError, cnx.rollback)
         self.assertRaises(ProgrammingError, cnx.commit)
         self.assertRaises(ProgrammingError, cnx.close)
 
     def test_api(self):
         cnx = self.login('anon')
-        self.assertEquals(cnx.user(None).login, 'anon')
-        self.assertEquals(cnx.describe(1), (u'CWGroup', u'system', None))
+        self.assertEqual(cnx.user(None).login, 'anon')
+        self.assertEqual(cnx.describe(1), (u'CWGroup', u'system', None))
         self.restore_connection() # proper way to close cnx
         self.assertRaises(ProgrammingError, cnx.user, None)
         self.assertRaises(ProgrammingError, cnx.describe, 1)
 
     def test_shared_data_api(self):
         cnx = self.login('anon')
-        self.assertEquals(cnx.get_shared_data('data'), None)
+        self.assertEqual(cnx.get_shared_data('data'), None)
         cnx.set_shared_data('data', 4)
-        self.assertEquals(cnx.get_shared_data('data'), 4)
+        self.assertEqual(cnx.get_shared_data('data'), 4)
         cnx.get_shared_data('data', pop=True)
         cnx.get_shared_data('whatever', pop=True)
-        self.assertEquals(cnx.get_shared_data('data'), None)
+        self.assertEqual(cnx.get_shared_data('data'), None)
         cnx.set_shared_data('data', 4)
-        self.assertEquals(cnx.get_shared_data('data'), 4)
+        self.assertEqual(cnx.get_shared_data('data'), 4)
         self.restore_connection() # proper way to close cnx
         self.assertRaises(ProgrammingError, cnx.check)
         self.assertRaises(ProgrammingError, cnx.set_shared_data, 'data', 0)
--- a/test/unittest_entity.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/test/unittest_entity.py	Fri Sep 24 18:20:59 2010 +0200
@@ -42,14 +42,14 @@
 
     def test_has_eid(self):
         e = self.vreg['etypes'].etype_class('CWUser')(self.request())
-        self.assertEquals(e.eid, None)
-        self.assertEquals(e.has_eid(), False)
+        self.assertEqual(e.eid, None)
+        self.assertEqual(e.has_eid(), False)
         e.eid = 'X'
-        self.assertEquals(e.has_eid(), False)
+        self.assertEqual(e.has_eid(), False)
         e.eid = 0
-        self.assertEquals(e.has_eid(), True)
+        self.assertEqual(e.has_eid(), True)
         e.eid = 2
-        self.assertEquals(e.has_eid(), True)
+        self.assertEqual(e.has_eid(), True)
 
     def test_copy(self):
         req = self.request()
@@ -61,11 +61,11 @@
         self.execute('SET TAG tags X WHERE X eid %(x)s', {'x': oe.eid})
         e = req.create_entity('Note', type=u'z')
         e.copy_relations(oe.eid)
-        self.assertEquals(len(e.ecrit_par), 1)
-        self.assertEquals(e.ecrit_par[0].eid, p.eid)
-        self.assertEquals(len(e.reverse_tags), 1)
+        self.assertEqual(len(e.ecrit_par), 1)
+        self.assertEqual(e.ecrit_par[0].eid, p.eid)
+        self.assertEqual(len(e.reverse_tags), 1)
         # check meta-relations are not copied, set on commit
-        self.assertEquals(len(e.created_by), 0)
+        self.assertEqual(len(e.created_by), 0)
 
     def test_copy_with_nonmeta_composite_inlined(self):
         req = self.request()
@@ -83,8 +83,8 @@
         user = self.user()
         adeleid = self.execute('INSERT EmailAddress X: X address "toto@logilab.org", U use_email X WHERE U login "admin"')[0][0]
         e = self.execute('Any X WHERE X eid %(x)s', {'x': user.eid}).get_entity(0, 0)
-        self.assertEquals(e.use_email[0].address, "toto@logilab.org")
-        self.assertEquals(e.use_email[0].eid, adeleid)
+        self.assertEqual(e.use_email[0].address, "toto@logilab.org")
+        self.assertEqual(e.use_email[0].eid, adeleid)
         usereid = self.execute('INSERT CWUser X: X login "toto", X upassword "toto", X in_group G '
                                'WHERE G name "users"')[0][0]
         e = self.execute('Any X WHERE X eid %(x)s', {'x': usereid}).get_entity(0, 0)
@@ -104,18 +104,18 @@
         e.copy_relations(user.eid)
         self.commit()
         e.cw_clear_relation_cache('in_state', 'subject')
-        self.assertEquals(e.cw_adapt_to('IWorkflowable').state, 'activated')
+        self.assertEqual(e.cw_adapt_to('IWorkflowable').state, 'activated')
 
     def test_related_cache_both(self):
         user = self.execute('Any X WHERE X eid %(x)s', {'x':self.user().eid}).get_entity(0, 0)
         adeleid = self.execute('INSERT EmailAddress X: X address "toto@logilab.org", U use_email X WHERE U login "admin"')[0][0]
         self.commit()
-        self.assertEquals(user._cw_related_cache, {})
+        self.assertEqual(user._cw_related_cache, {})
         email = user.primary_email[0]
-        self.assertEquals(sorted(user._cw_related_cache), ['primary_email_subject'])
-        self.assertEquals(email._cw_related_cache.keys(), ['primary_email_object'])
+        self.assertEqual(sorted(user._cw_related_cache), ['primary_email_subject'])
+        self.assertEqual(email._cw_related_cache.keys(), ['primary_email_object'])
         groups = user.in_group
-        self.assertEquals(sorted(user._cw_related_cache), ['in_group_subject', 'primary_email_subject'])
+        self.assertEqual(sorted(user._cw_related_cache), ['in_group_subject', 'primary_email_subject'])
         for group in groups:
             self.failIf('in_group_subject' in group._cw_related_cache, group._cw_related_cache.keys())
 
@@ -125,8 +125,8 @@
         for tag in u'abcd':
             req.create_entity('Tag', name=tag)
         self.execute('SET X tags Y WHERE X is Tag, Y is Personne')
-        self.assertEquals(len(p.related('tags', 'object', limit=2)), 2)
-        self.assertEquals(len(p.related('tags', 'object')), 4)
+        self.assertEqual(len(p.related('tags', 'object', limit=2)), 2)
+        self.assertEqual(len(p.related('tags', 'object')), 4)
 
 
     def test_fetch_rql(self):
@@ -141,7 +141,7 @@
         peschema.subjrels['evaluee'].rdef(peschema, Note.e_schema).cardinality = '1*'
         seschema.subjrels['evaluee'].rdef(seschema, Note.e_schema).cardinality = '1*'
         # testing basic fetch_attrs attribute
-        self.assertEquals(Personne.fetch_rql(user),
+        self.assertEqual(Personne.fetch_rql(user),
                           'Any X,AA,AB,AC ORDERBY AA ASC '
                           'WHERE X is Personne, X nom AA, X prenom AB, X modification_date AC')
         pfetch_attrs = Personne.fetch_attrs
@@ -149,39 +149,39 @@
         try:
             # testing unknown attributes
             Personne.fetch_attrs = ('bloug', 'beep')
-            self.assertEquals(Personne.fetch_rql(user), 'Any X WHERE X is Personne')
+            self.assertEqual(Personne.fetch_rql(user), 'Any X WHERE X is Personne')
             # testing one non final relation
             Personne.fetch_attrs = ('nom', 'prenom', 'travaille')
-            self.assertEquals(Personne.fetch_rql(user),
+            self.assertEqual(Personne.fetch_rql(user),
                               'Any X,AA,AB,AC,AD ORDERBY AA ASC '
                               'WHERE X is Personne, X nom AA, X prenom AB, X travaille AC?, AC nom AD')
             # testing two non final relations
             Personne.fetch_attrs = ('nom', 'prenom', 'travaille', 'evaluee')
-            self.assertEquals(Personne.fetch_rql(user),
+            self.assertEqual(Personne.fetch_rql(user),
                               'Any X,AA,AB,AC,AD,AE,AF ORDERBY AA ASC,AF DESC '
                               'WHERE X is Personne, X nom AA, X prenom AB, X travaille AC?, AC nom AD, '
                               'X evaluee AE?, AE modification_date AF')
             # testing one non final relation with recursion
             Personne.fetch_attrs = ('nom', 'prenom', 'travaille')
             Societe.fetch_attrs = ('nom', 'evaluee')
-            self.assertEquals(Personne.fetch_rql(user),
+            self.assertEqual(Personne.fetch_rql(user),
                               'Any X,AA,AB,AC,AD,AE,AF ORDERBY AA ASC,AF DESC '
                               'WHERE X is Personne, X nom AA, X prenom AB, X travaille AC?, AC nom AD, '
                               'AC evaluee AE?, AE modification_date AF'
                               )
             # testing symmetric relation
             Personne.fetch_attrs = ('nom', 'connait')
-            self.assertEquals(Personne.fetch_rql(user), 'Any X,AA,AB ORDERBY AA ASC '
+            self.assertEqual(Personne.fetch_rql(user), 'Any X,AA,AB ORDERBY AA ASC '
                               'WHERE X is Personne, X nom AA, X connait AB?')
             # testing optional relation
             peschema.subjrels['travaille'].rdef(peschema, seschema).cardinality = '?*'
             Personne.fetch_attrs = ('nom', 'prenom', 'travaille')
             Societe.fetch_attrs = ('nom',)
-            self.assertEquals(Personne.fetch_rql(user),
+            self.assertEqual(Personne.fetch_rql(user),
                               'Any X,AA,AB,AC,AD ORDERBY AA ASC WHERE X is Personne, X nom AA, X prenom AB, X travaille AC?, AC nom AD')
             # testing relation with cardinality > 1
             peschema.subjrels['travaille'].rdef(peschema, seschema).cardinality = '**'
-            self.assertEquals(Personne.fetch_rql(user),
+            self.assertEqual(Personne.fetch_rql(user),
                               'Any X,AA,AB ORDERBY AA ASC WHERE X is Personne, X nom AA, X prenom AB')
             # XXX test unauthorized attribute
         finally:
@@ -197,20 +197,20 @@
         Note.fetch_attrs, Note.fetch_order = fetch_config(('type',))
         SubNote.fetch_attrs, SubNote.fetch_order = fetch_config(('type',))
         p = self.request().create_entity('Personne', nom=u'pouet')
-        self.assertEquals(p.cw_related_rql('evaluee'),
+        self.assertEqual(p.cw_related_rql('evaluee'),
                           'Any X,AA,AB ORDERBY AA ASC WHERE E eid %(x)s, E evaluee X, '
                           'X type AA, X modification_date AB')
         Personne.fetch_attrs, Personne.fetch_order = fetch_config(('nom', ))
         # XXX
-        self.assertEquals(p.cw_related_rql('evaluee'),
+        self.assertEqual(p.cw_related_rql('evaluee'),
                           'Any X,AA ORDERBY AA DESC '
                           'WHERE E eid %(x)s, E evaluee X, X modification_date AA')
 
         tag = self.vreg['etypes'].etype_class('Tag')(self.request())
-        self.assertEquals(tag.cw_related_rql('tags', 'subject'),
+        self.assertEqual(tag.cw_related_rql('tags', 'subject'),
                           'Any X,AA ORDERBY AA DESC '
                           'WHERE E eid %(x)s, E tags X, X modification_date AA')
-        self.assertEquals(tag.cw_related_rql('tags', 'subject', ('Personne',)),
+        self.assertEqual(tag.cw_related_rql('tags', 'subject', ('Personne',)),
                           'Any X,AA,AB ORDERBY AA ASC '
                           'WHERE E eid %(x)s, E tags X, X is IN (Personne), X nom AA, '
                           'X modification_date AB')
@@ -219,20 +219,20 @@
         tag = self.vreg['etypes'].etype_class('Tag')(self.request())
         for ttype in self.schema['tags'].objects():
             self.vreg['etypes'].etype_class(ttype).fetch_attrs = ('modification_date',)
-        self.assertEquals(tag.cw_related_rql('tags', 'subject'),
+        self.assertEqual(tag.cw_related_rql('tags', 'subject'),
                           'Any X,AA ORDERBY AA DESC '
                           'WHERE E eid %(x)s, E tags X, X modification_date AA')
 
     def test_unrelated_rql_security_1(self):
         user = self.request().user
         rql = user.cw_unrelated_rql('use_email', 'EmailAddress', 'subject')[0]
-        self.assertEquals(rql, 'Any O,AA,AB,AC ORDERBY AC DESC '
+        self.assertEqual(rql, 'Any O,AA,AB,AC ORDERBY AC DESC '
                           'WHERE NOT S use_email O, S eid %(x)s, O is EmailAddress, O address AA, O alias AB, O modification_date AC')
         self.create_user('toto')
         self.login('toto')
         user = self.request().user
         rql = user.cw_unrelated_rql('use_email', 'EmailAddress', 'subject')[0]
-        self.assertEquals(rql, 'Any O,AA,AB,AC ORDERBY AC DESC '
+        self.assertEqual(rql, 'Any O,AA,AB,AC ORDERBY AC DESC '
                           'WHERE NOT S use_email O, S eid %(x)s, O is EmailAddress, O address AA, O alias AB, O modification_date AC')
         user = self.execute('Any X WHERE X login "admin"').get_entity(0, 0)
         self.assertRaises(Unauthorized, user.cw_unrelated_rql, 'use_email', 'EmailAddress', 'subject')
@@ -243,24 +243,24 @@
     def test_unrelated_rql_security_2(self):
         email = self.execute('INSERT EmailAddress X: X address "hop"').get_entity(0, 0)
         rql = email.cw_unrelated_rql('use_email', 'CWUser', 'object')[0]
-        self.assertEquals(rql, 'Any S,AA,AB,AC,AD ORDERBY AA ASC '
+        self.assertEqual(rql, 'Any S,AA,AB,AC,AD ORDERBY AA ASC '
                           'WHERE NOT S use_email O, O eid %(x)s, S is CWUser, S login AA, S firstname AB, S surname AC, S modification_date AD')
         #rql = email.cw_unrelated_rql('use_email', 'Person', 'object')[0]
-        #self.assertEquals(rql, '')
+        #self.assertEqual(rql, '')
         self.login('anon')
         email = self.execute('Any X WHERE X eid %(x)s', {'x': email.eid}).get_entity(0, 0)
         rql = email.cw_unrelated_rql('use_email', 'CWUser', 'object')[0]
-        self.assertEquals(rql, 'Any S,AA,AB,AC,AD ORDERBY AA '
+        self.assertEqual(rql, 'Any S,AA,AB,AC,AD ORDERBY AA '
                           'WHERE NOT EXISTS(S use_email O), O eid %(x)s, S is CWUser, S login AA, S firstname AB, S surname AC, S modification_date AD, '
                           'A eid %(B)s, EXISTS(S identity A, NOT A in_group C, C name "guests", C is CWGroup)')
         #rql = email.cw_unrelated_rql('use_email', 'Person', 'object')[0]
-        #self.assertEquals(rql, '')
+        #self.assertEqual(rql, '')
 
     def test_unrelated_rql_security_nonexistant(self):
         self.login('anon')
         email = self.vreg['etypes'].etype_class('EmailAddress')(self.request())
         rql = email.cw_unrelated_rql('use_email', 'CWUser', 'object')[0]
-        self.assertEquals(rql, 'Any S,AA,AB,AC,AD ORDERBY AA '
+        self.assertEqual(rql, 'Any S,AA,AB,AC,AD ORDERBY AA '
                           'WHERE S is CWUser, S login AA, S firstname AB, S surname AC, S modification_date AD, '
                           'A eid %(B)s, EXISTS(S identity A, NOT A in_group C, C name "guests", C is CWGroup)')
 
@@ -282,53 +282,53 @@
         e = req.create_entity('Tag', name=u'x')
         req.create_entity('Personne', nom=u'di mascio', prenom=u'adrien')
         req.create_entity('Personne', nom=u'thenault', prenom=u'sylvain')
-        self.assertEquals(len(e.unrelated('tags', 'Personne', 'subject', limit=1)),
+        self.assertEqual(len(e.unrelated('tags', 'Personne', 'subject', limit=1)),
                           1)
 
     def test_unrelated_security(self):
         email = self.execute('INSERT EmailAddress X: X address "hop"').get_entity(0, 0)
         rset = email.unrelated('use_email', 'CWUser', 'object')
-        self.assertEquals([x.login for x in rset.entities()], [u'admin', u'anon'])
+        self.assertEqual([x.login for x in rset.entities()], [u'admin', u'anon'])
         user = self.request().user
         rset = user.unrelated('use_email', 'EmailAddress', 'subject')
-        self.assertEquals([x.address for x in rset.entities()], [u'hop'])
+        self.assertEqual([x.address for x in rset.entities()], [u'hop'])
         self.create_user('toto')
         self.login('toto')
         email = self.execute('Any X WHERE X eid %(x)s', {'x': email.eid}).get_entity(0, 0)
         rset = email.unrelated('use_email', 'CWUser', 'object')
-        self.assertEquals([x.login for x in rset.entities()], ['toto'])
+        self.assertEqual([x.login for x in rset.entities()], ['toto'])
         user = self.request().user
         rset = user.unrelated('use_email', 'EmailAddress', 'subject')
-        self.assertEquals([x.address for x in rset.entities()], ['hop'])
+        self.assertEqual([x.address for x in rset.entities()], ['hop'])
         user = self.execute('Any X WHERE X login "admin"').get_entity(0, 0)
         rset = user.unrelated('use_email', 'EmailAddress', 'subject')
-        self.assertEquals([x.address for x in rset.entities()], [])
+        self.assertEqual([x.address for x in rset.entities()], [])
         self.login('anon')
         email = self.execute('Any X WHERE X eid %(x)s', {'x': email.eid}).get_entity(0, 0)
         rset = email.unrelated('use_email', 'CWUser', 'object')
-        self.assertEquals([x.login for x in rset.entities()], [])
+        self.assertEqual([x.login for x in rset.entities()], [])
         user = self.request().user
         rset = user.unrelated('use_email', 'EmailAddress', 'subject')
-        self.assertEquals([x.address for x in rset.entities()], [])
+        self.assertEqual([x.address for x in rset.entities()], [])
 
     def test_unrelated_new_entity(self):
         e = self.vreg['etypes'].etype_class('CWUser')(self.request())
         unrelated = [r[0] for r in e.unrelated('in_group', 'CWGroup', 'subject')]
         # should be default groups but owners, i.e. managers, users, guests
-        self.assertEquals(len(unrelated), 3)
+        self.assertEqual(len(unrelated), 3)
 
     def test_printable_value_string(self):
         e = self.request().create_entity('Card', title=u'rest test', content=u'du :eid:`1:*ReST*`',
                             content_format=u'text/rest')
-        self.assertEquals(e.printable_value('content'),
+        self.assertEqual(e.printable_value('content'),
                           '<p>du <a class="reference" href="http://testing.fr/cubicweb/cwgroup/guests">*ReST*</a></p>\n')
         e['content'] = 'du <em>html</em> <ref rql="CWUser X">users</ref>'
         e['content_format'] = 'text/html'
-        self.assertEquals(e.printable_value('content'),
+        self.assertEqual(e.printable_value('content'),
                           'du <em>html</em> <a href="http://testing.fr/cubicweb/view?rql=CWUser%20X">users</a>')
         e['content'] = 'du *texte*'
         e['content_format'] = 'text/plain'
-        self.assertEquals(e.printable_value('content'),
+        self.assertEqual(e.printable_value('content'),
                           '<p>\ndu *texte*<br/>\n</p>')
         e['title'] = 'zou'
         e['content'] = '''\
@@ -336,17 +336,17 @@
 =======
 du :eid:`1:*ReST*`'''
         e['content_format'] = 'text/rest'
-        self.assertEquals(e.printable_value('content', format='text/plain'),
+        self.assertEqual(e.printable_value('content', format='text/plain'),
                           e['content'])
 
         e['content'] = u'<b>yo (zou éà ;)</b>'
         e['content_format'] = 'text/html'
-        self.assertEquals(e.printable_value('content', format='text/plain').strip(),
+        self.assertEqual(e.printable_value('content', format='text/plain').strip(),
                           u'**yo (zou éà ;)**')
         if HAS_TAL:
             e['content'] = '<h1 tal:content="self/title">titre</h1>'
             e['content_format'] = 'text/cubicweb-page-template'
-            self.assertEquals(e.printable_value('content'),
+            self.assertEqual(e.printable_value('content'),
                               '<h1>zou</h1>')
 
 
@@ -358,17 +358,17 @@
         if mttransforms.HAS_PYGMENTS_TRANSFORMS:
             import pygments
             if tuple(int(i) for i in pygments.__version__.split('.')[:2]) >= (1, 3):
-                self.assertEquals(e.printable_value('data'),
+                self.assertEqual(e.printable_value('data'),
                                   '''<div class="highlight"><pre><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="mi">1</span>
 </pre></div>
 ''')
             else:
-                self.assertEquals(e.printable_value('data'),
+                self.assertEqual(e.printable_value('data'),
                                   '''<div class="highlight"><pre><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="mf">1</span>
 </pre></div>
 ''')
         else:
-            self.assertEquals(e.printable_value('data'),
+            self.assertEqual(e.printable_value('data'),
                               '''<pre class="python">
 <span style="color: #C00000;">lambda</span> <span style="color: #000000;">x</span><span style="color: #0000C0;">:</span> <span style="color: #0080C0;">1</span>
 </pre>
@@ -376,7 +376,7 @@
 
         e = req.create_entity('File', data=Binary('*héhéhé*'), data_format=u'text/rest',
                             data_encoding=u'utf-8', data_name=u'toto.txt')
-        self.assertEquals(e.printable_value('data'),
+        self.assertEqual(e.printable_value('data'),
                           u'<p><em>héhéhé</em></p>\n')
 
     def test_printable_value_bad_html(self):
@@ -385,42 +385,42 @@
         e = req.create_entity('Card', title=u'bad html', content=u'<div>R&D<br>',
                             content_format=u'text/html')
         tidy = lambda x: x.replace('\n', '')
-        self.assertEquals(tidy(e.printable_value('content')),
+        self.assertEqual(tidy(e.printable_value('content')),
                           '<div>R&amp;D<br/></div>')
         e['content'] = u'yo !! R&D <div> pas fermé'
-        self.assertEquals(tidy(e.printable_value('content')),
+        self.assertEqual(tidy(e.printable_value('content')),
                           u'yo !! R&amp;D <div> pas fermé</div>')
         e['content'] = u'R&D'
-        self.assertEquals(tidy(e.printable_value('content')), u'R&amp;D')
+        self.assertEqual(tidy(e.printable_value('content')), u'R&amp;D')
         e['content'] = u'R&D;'
-        self.assertEquals(tidy(e.printable_value('content')), u'R&amp;D;')
+        self.assertEqual(tidy(e.printable_value('content')), u'R&amp;D;')
         e['content'] = u'yo !! R&amp;D <div> pas fermé'
-        self.assertEquals(tidy(e.printable_value('content')),
+        self.assertEqual(tidy(e.printable_value('content')),
                           u'yo !! R&amp;D <div> pas fermé</div>')
         e['content'] = u'été <div> été'
-        self.assertEquals(tidy(e.printable_value('content')),
+        self.assertEqual(tidy(e.printable_value('content')),
                           u'été <div> été</div>')
         e['content'] = u'C&apos;est un exemple s&eacute;rieux'
-        self.assertEquals(tidy(e.printable_value('content')),
+        self.assertEqual(tidy(e.printable_value('content')),
                           u"C'est un exemple sérieux")
         # make sure valid xhtml is left untouched
         e['content'] = u'<div>R&amp;D<br/></div>'
-        self.assertEquals(e.printable_value('content'), e['content'])
+        self.assertEqual(e.printable_value('content'), e['content'])
         e['content'] = u'<div>été</div>'
-        self.assertEquals(e.printable_value('content'), e['content'])
+        self.assertEqual(e.printable_value('content'), e['content'])
         e['content'] = u'été'
-        self.assertEquals(e.printable_value('content'), e['content'])
+        self.assertEqual(e.printable_value('content'), e['content'])
         e['content'] = u'hop\r\nhop\nhip\rmomo'
-        self.assertEquals(e.printable_value('content'), u'hop\nhop\nhip\nmomo')
+        self.assertEqual(e.printable_value('content'), u'hop\nhop\nhip\nmomo')
 
     def test_printable_value_bad_html_ms(self):
-        self.skip('fix soup2xhtml to handle this test')
+        self.skipTest('fix soup2xhtml to handle this test')
         req = self.request()
         e = req.create_entity('Card', title=u'bad html', content=u'<div>R&D<br>',
                             content_format=u'text/html')
         tidy = lambda x: x.replace('\n', '')
         e['content'] = u'<div x:foo="bar">ms orifice produces weird html</div>'
-        self.assertEquals(tidy(e.printable_value('content')),
+        self.assertEqual(tidy(e.printable_value('content')),
                           u'<div>ms orifice produces weird html</div>')
         import tidy as tidymod # apt-get install python-tidy
         tidy = lambda x: str(tidymod.parseString(x.encode('utf-8'),
@@ -429,7 +429,7 @@
                                                     'show_body_only' : True,
                                                     'quote-nbsp' : False,
                                                     'char_encoding' : 'utf8'})).decode('utf-8').strip()
-        self.assertEquals(tidy(e.printable_value('content')),
+        self.assertEqual(tidy(e.printable_value('content')),
                           u'<div>ms orifice produces weird html</div>')
 
 
@@ -442,7 +442,7 @@
         e['data_format'] = 'text/html'
         e['data_encoding'] = 'ascii'
         e._cw.transaction_data = {} # XXX req should be a session
-        self.assertEquals(e.cw_adapt_to('IFTIndexable').get_words(),
+        self.assertEqual(e.cw_adapt_to('IFTIndexable').get_words(),
                           {'C': [u'du', u'html', 'an', 'html', 'file', u'some', u'data']})
 
 
@@ -451,7 +451,7 @@
         p1 = req.create_entity('Personne', nom=u'di mascio', prenom=u'adrien')
         p2 = req.create_entity('Personne', nom=u'toto')
         self.execute('SET X evaluee Y WHERE X nom "di mascio", Y nom "toto"')
-        self.assertEquals(p1.evaluee[0].nom, "toto")
+        self.assertEqual(p1.evaluee[0].nom, "toto")
         self.failUnless(not p1.reverse_evaluee)
 
     def test_complete_relation(self):
@@ -465,7 +465,7 @@
         self.failUnless(trinfo.cw_relation_cached('from_state', 'subject'))
         self.failUnless(trinfo.cw_relation_cached('to_state', 'subject'))
         self.failUnless(trinfo.cw_relation_cached('wf_info_for', 'subject'))
-        self.assertEquals(trinfo.by_transition, ())
+        self.assertEqual(trinfo.by_transition, ())
 
     def test_request_cache(self):
         req = self.request()
@@ -477,55 +477,55 @@
     def test_rest_path(self):
         req = self.request()
         note = req.create_entity('Note', type=u'z')
-        self.assertEquals(note.rest_path(), 'note/%s' % note.eid)
+        self.assertEqual(note.rest_path(), 'note/%s' % note.eid)
         # unique attr
         tag = req.create_entity('Tag', name=u'x')
-        self.assertEquals(tag.rest_path(), 'tag/x')
+        self.assertEqual(tag.rest_path(), 'tag/x')
         # test explicit rest_attr
         person = req.create_entity('Personne', prenom=u'john', nom=u'doe')
-        self.assertEquals(person.rest_path(), 'personne/doe')
+        self.assertEqual(person.rest_path(), 'personne/doe')
         # ambiguity test
         person2 = req.create_entity('Personne', prenom=u'remi', nom=u'doe')
         person.clear_all_caches()
-        self.assertEquals(person.rest_path(), 'personne/eid/%s' % person.eid)
-        self.assertEquals(person2.rest_path(), 'personne/eid/%s' % person2.eid)
+        self.assertEqual(person.rest_path(), 'personne/eid/%s' % person.eid)
+        self.assertEqual(person2.rest_path(), 'personne/eid/%s' % person2.eid)
         # unique attr with None value (wikiid in this case)
         card1 = req.create_entity('Card', title=u'hop')
-        self.assertEquals(card1.rest_path(), 'card/eid/%s' % card1.eid)
+        self.assertEqual(card1.rest_path(), 'card/eid/%s' % card1.eid)
         # don't use rest if we have /, ? or & in the path (breaks mod_proxy)
         card2 = req.create_entity('Card', title=u'pod', wikiid=u'zo/bi')
-        self.assertEquals(card2.rest_path(), 'card/eid/%d' % card2.eid)
+        self.assertEqual(card2.rest_path(), 'card/eid/%d' % card2.eid)
         card3 = req.create_entity('Card', title=u'pod', wikiid=u'zo&bi')
-        self.assertEquals(card3.rest_path(), 'card/eid/%d' % card3.eid)
+        self.assertEqual(card3.rest_path(), 'card/eid/%d' % card3.eid)
         card4 = req.create_entity('Card', title=u'pod', wikiid=u'zo?bi')
-        self.assertEquals(card4.rest_path(), 'card/eid/%d' % card4.eid)
+        self.assertEqual(card4.rest_path(), 'card/eid/%d' % card4.eid)
         
 
     def test_set_attributes(self):
         req = self.request()
         person = req.create_entity('Personne', nom=u'di mascio', prenom=u'adrien')
-        self.assertEquals(person.prenom, u'adrien')
-        self.assertEquals(person.nom, u'di mascio')
+        self.assertEqual(person.prenom, u'adrien')
+        self.assertEqual(person.nom, u'di mascio')
         person.set_attributes(prenom=u'sylvain', nom=u'thénault')
         person = self.execute('Personne P').get_entity(0, 0) # XXX retreival needed ?
-        self.assertEquals(person.prenom, u'sylvain')
-        self.assertEquals(person.nom, u'thénault')
+        self.assertEqual(person.prenom, u'sylvain')
+        self.assertEqual(person.nom, u'thénault')
 
     def test_metainformation_and_external_absolute_url(self):
         req = self.request()
         note = req.create_entity('Note', type=u'z')
         metainf = note.cw_metainformation()
-        self.assertEquals(metainf, {'source': {'adapter': 'native', 'uri': 'system'}, 'type': u'Note', 'extid': None})
-        self.assertEquals(note.absolute_url(), 'http://testing.fr/cubicweb/note/%s' % note.eid)
+        self.assertEqual(metainf, {'source': {'adapter': 'native', 'uri': 'system'}, 'type': u'Note', 'extid': None})
+        self.assertEqual(note.absolute_url(), 'http://testing.fr/cubicweb/note/%s' % note.eid)
         metainf['source'] = metainf['source'].copy()
         metainf['source']['base-url']  = 'http://cubicweb2.com/'
         metainf['extid']  = 1234
-        self.assertEquals(note.absolute_url(), 'http://cubicweb2.com/note/1234')
+        self.assertEqual(note.absolute_url(), 'http://cubicweb2.com/note/1234')
 
     def test_absolute_url_empty_field(self):
         req = self.request()
         card = req.create_entity('Card', wikiid=u'', title=u'test')
-        self.assertEquals(card.absolute_url(),
+        self.assertEqual(card.absolute_url(),
                           'http://testing.fr/cubicweb/card/eid/%s' % card.eid)
 
     def test_create_entity(self):
@@ -537,10 +537,10 @@
         p = req.create_entity('Personne', nom=u'di mascio', prenom=u'adrien',
                               connait=p1, evaluee=[p1, p2],
                               reverse_ecrit_par=note)
-        self.assertEquals(p.nom, 'di mascio')
-        self.assertEquals([c.nom for c in p.connait], ['fayolle'])
-        self.assertEquals(sorted([c.nom for c in p.evaluee]), ['campeas', 'fayolle'])
-        self.assertEquals([c.type for c in p.reverse_ecrit_par], ['z'])
+        self.assertEqual(p.nom, 'di mascio')
+        self.assertEqual([c.nom for c in p.connait], ['fayolle'])
+        self.assertEqual(sorted([c.nom for c in p.evaluee]), ['campeas', 'fayolle'])
+        self.assertEqual([c.type for c in p.reverse_ecrit_par], ['z'])
 
 
 
--- a/test/unittest_mail.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/test/unittest_mail.py	Fri Sep 24 18:20:59 2010 +0200
@@ -51,7 +51,7 @@
         mail = format_mail({'name': 'oim', 'email': 'oim@logilab.fr'},
                            ['test@logilab.fr'], u'un petit cöucou', u'bïjour',
                            config=self.config)
-        self.assertLinesEquals(mail.as_string(), """\
+        self.assertMultiLineEqual(mail.as_string(), """\
 MIME-Version: 1.0
 Content-Type: text/plain; charset="utf-8"
 Content-Transfer-Encoding: base64
@@ -64,17 +64,17 @@
 dW4gcGV0aXQgY8O2dWNvdQ==
 """)
         msg = message_from_string(mail.as_string())
-        self.assertEquals(msg.get('subject'), u'bïjour')
-        self.assertEquals(msg.get('from'), u'oim <oim@logilab.fr>')
-        self.assertEquals(msg.get('to'), u'test@logilab.fr')
-        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')
+        self.assertEqual(msg.get('subject'), u'bïjour')
+        self.assertEqual(msg.get('from'), u'oim <oim@logilab.fr>')
+        self.assertEqual(msg.get('to'), u'test@logilab.fr')
+        self.assertEqual(msg.get('reply-to'), u'oim <oim@logilab.fr>, BimBam <bim@boum.fr>')
+        self.assertEqual(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 €')
-        self.assertLinesEquals(mail.as_string(), """\
+        self.assertMultiLineEqual(mail.as_string(), """\
 MIME-Version: 1.0
 Content-Type: text/plain; charset="utf-8"
 Content-Transfer-Encoding: base64
@@ -86,11 +86,11 @@
 dW4gcGV0aXQgY8O2dWNvdSDigqw=
 """)
         msg = message_from_string(mail.as_string())
-        self.assertEquals(msg.get('subject'), u'bïjour €')
-        self.assertEquals(msg.get('from'), u'oîm <oim@logilab.fr>')
-        self.assertEquals(msg.get('to'), u'test@logilab.fr')
-        self.assertEquals(msg.get('reply-to'), u'oîm <oim@logilab.fr>')
-        self.assertEquals(msg.get_payload(decode=True), u'un petit cöucou €')
+        self.assertEqual(msg.get('subject'), u'bïjour €')
+        self.assertEqual(msg.get('from'), u'oîm <oim@logilab.fr>')
+        self.assertEqual(msg.get('to'), u'test@logilab.fr')
+        self.assertEqual(msg.get('reply-to'), u'oîm <oim@logilab.fr>')
+        self.assertEqual(msg.get_payload(decode=True), u'un petit cöucou €')
 
 
     def test_format_mail_from_reply_to(self):
@@ -100,19 +100,19 @@
         msg = format_mail({'name': u'', 'email': u''},
                           ['test@logilab.fr'], u'un petit cöucou €', u'bïjour €',
                           config=self.config)
-        self.assertEquals(msg.get('from'), u'')
-        self.assertEquals(msg.get('reply-to'), None)
+        self.assertEqual(msg.get('from'), u'')
+        self.assertEqual(msg.get('reply-to'), None)
         msg = format_mail({'name': u'tutu', 'email': u'tutu@logilab.fr'},
                           ['test@logilab.fr'], u'un petit cöucou €', u'bïjour €',
                           config=self.config)
         msg = message_from_string(msg.as_string())
-        self.assertEquals(msg.get('from'), u'tutu <tutu@logilab.fr>')
-        self.assertEquals(msg.get('reply-to'), u'tutu <tutu@logilab.fr>')
+        self.assertEqual(msg.get('from'), u'tutu <tutu@logilab.fr>')
+        self.assertEqual(msg.get('reply-to'), u'tutu <tutu@logilab.fr>')
         msg = format_mail({'name': u'tutu', 'email': u'tutu@logilab.fr'},
                           ['test@logilab.fr'], u'un petit cöucou €', u'bïjour €')
         msg = message_from_string(msg.as_string())
-        self.assertEquals(msg.get('from'), u'tutu <tutu@logilab.fr>')
-        self.assertEquals(msg.get('reply-to'), u'tutu <tutu@logilab.fr>')
+        self.assertEqual(msg.get('from'), u'tutu <tutu@logilab.fr>')
+        self.assertEqual(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')
@@ -121,22 +121,22 @@
                            ['test@logilab.fr'], u'un petit cöucou €', u'bïjour €',
                            config=self.config)
         msg = message_from_string(msg.as_string())
-        self.assertEquals(msg.get('from'), u'cubicweb-test <cubicweb-test@logilab.fr>')
-        self.assertEquals(msg.get('reply-to'), u'cubicweb-test <cubicweb-test@logilab.fr>')
+        self.assertEqual(msg.get('from'), u'cubicweb-test <cubicweb-test@logilab.fr>')
+        self.assertEqual(msg.get('reply-to'), u'cubicweb-test <cubicweb-test@logilab.fr>')
         # anonymous notification: only email specified
         msg = format_mail({'email': u'tutu@logilab.fr'},
                            ['test@logilab.fr'], u'un petit cöucou €', u'bïjour €',
                            config=self.config)
         msg = message_from_string(msg.as_string())
-        self.assertEquals(msg.get('from'), u'cubicweb-test <tutu@logilab.fr>')
-        self.assertEquals(msg.get('reply-to'), u'cubicweb-test <tutu@logilab.fr>, cubicweb-test <cubicweb-test@logilab.fr>')
+        self.assertEqual(msg.get('from'), u'cubicweb-test <tutu@logilab.fr>')
+        self.assertEqual(msg.get('reply-to'), u'cubicweb-test <tutu@logilab.fr>, cubicweb-test <cubicweb-test@logilab.fr>')
         # anonymous notification: only name specified
         msg = format_mail({'name': u'tutu'},
                           ['test@logilab.fr'], u'un petit cöucou €', u'bïjour €',
                           config=self.config)
         msg = message_from_string(msg.as_string())
-        self.assertEquals(msg.get('from'), u'tutu <cubicweb-test@logilab.fr>')
-        self.assertEquals(msg.get('reply-to'), u'tutu <cubicweb-test@logilab.fr>')
+        self.assertEqual(msg.get('from'), u'tutu <cubicweb-test@logilab.fr>')
+        self.assertEqual(msg.get('reply-to'), u'tutu <cubicweb-test@logilab.fr>')
 
 
 
--- a/test/unittest_migration.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/test/unittest_migration.py	Fri Sep 24 18:20:59 2010 +0200
@@ -52,26 +52,26 @@
         self.config.__class__.cube_appobject_path = frozenset()
 
     def test_filter_scripts_base(self):
-        self.assertListEquals(filter_scripts(self.config, SMIGRDIR, (2,3,0), (2,4,0)),
+        self.assertListEqual(filter_scripts(self.config, SMIGRDIR, (2,3,0), (2,4,0)),
                               [])
-        self.assertListEquals(filter_scripts(self.config, SMIGRDIR, (2,4,0), (2,5,0)),
+        self.assertListEqual(filter_scripts(self.config, SMIGRDIR, (2,4,0), (2,5,0)),
                               [((2, 5, 0), SMIGRDIR+'2.5.0_Any.sql')])
-        self.assertListEquals(filter_scripts(self.config, SMIGRDIR, (2,5,0), (2,6,0)),
+        self.assertListEqual(filter_scripts(self.config, SMIGRDIR, (2,5,0), (2,6,0)),
                               [((2, 6, 0), SMIGRDIR+'2.6.0_Any.sql')])
-        self.assertListEquals(filter_scripts(self.config, SMIGRDIR, (2,4,0), (2,6,0)),
+        self.assertListEqual(filter_scripts(self.config, SMIGRDIR, (2,4,0), (2,6,0)),
                               [((2, 5, 0), SMIGRDIR+'2.5.0_Any.sql'),
                                ((2, 6, 0), SMIGRDIR+'2.6.0_Any.sql')])
-        self.assertListEquals(filter_scripts(self.config, SMIGRDIR, (2,5,0), (2,5,1)),
+        self.assertListEqual(filter_scripts(self.config, SMIGRDIR, (2,5,0), (2,5,1)),
                               [])
-        self.assertListEquals(filter_scripts(self.config, SMIGRDIR, (2,5,0), (2,10,2)),
+        self.assertListEqual(filter_scripts(self.config, SMIGRDIR, (2,5,0), (2,10,2)),
                               [((2, 6, 0), SMIGRDIR+'2.6.0_Any.sql'),
                                ((2, 10, 2), SMIGRDIR+'2.10.2_Any.sql')])
-        self.assertListEquals(filter_scripts(self.config, SMIGRDIR, (2,5,1), (2,6,0)),
+        self.assertListEqual(filter_scripts(self.config, SMIGRDIR, (2,5,1), (2,6,0)),
                               [((2, 6, 0), SMIGRDIR+'2.6.0_Any.sql')])
 
-        self.assertListEquals(filter_scripts(self.config, TMIGRDIR, (0,0,2), (0,0,3)),
+        self.assertListEqual(filter_scripts(self.config, TMIGRDIR, (0,0,2), (0,0,3)),
                               [((0, 0, 3), TMIGRDIR+'0.0.3_Any.py')])
-        self.assertListEquals(filter_scripts(self.config, TMIGRDIR, (0,0,2), (0,0,4)),
+        self.assertListEqual(filter_scripts(self.config, TMIGRDIR, (0,0,2), (0,0,4)),
                               [((0, 0, 3), TMIGRDIR+'0.0.3_Any.py'),
                                ((0, 0, 4), TMIGRDIR+'0.0.4_Any.py')])
 
@@ -82,16 +82,16 @@
         self.assertIsInstance(config.migration_handler(), MigrationHelper)
         config = self.config
         config.__class__.name = 'twisted'
-        self.assertListEquals(filter_scripts(config, TMIGRDIR, (0,0,4), (0,1,0)),
+        self.assertListEqual(filter_scripts(config, TMIGRDIR, (0,0,4), (0,1,0)),
                               [((0, 1 ,0), TMIGRDIR+'0.1.0_common.py'),
                                ((0, 1 ,0), TMIGRDIR+'0.1.0_web.py')])
         config.__class__.name = 'repository'
-        self.assertListEquals(filter_scripts(config, TMIGRDIR, (0,0,4), (0,1,0)),
+        self.assertListEqual(filter_scripts(config, TMIGRDIR, (0,0,4), (0,1,0)),
                               [((0, 1 ,0), TMIGRDIR+'0.1.0_Any.py'),
                                ((0, 1 ,0), TMIGRDIR+'0.1.0_common.py'),
                                ((0, 1 ,0), TMIGRDIR+'0.1.0_repository.py')])
         config.__class__.name = 'all-in-one'
-        self.assertListEquals(filter_scripts(config, TMIGRDIR, (0,0,4), (0,1,0)),
+        self.assertListEqual(filter_scripts(config, TMIGRDIR, (0,0,4), (0,1,0)),
                               [((0, 1 ,0), TMIGRDIR+'0.1.0_Any.py'),
                                ((0, 1 ,0), TMIGRDIR+'0.1.0_common.py'),
                                ((0, 1 ,0), TMIGRDIR+'0.1.0_repository.py'),
@@ -107,7 +107,7 @@
         """make sure database can be created"""
         config = ApptestConfiguration('data')
         source = config.sources()['system']
-        self.assertEquals(source['db-driver'], 'sqlite')
+        self.assertEqual(source['db-driver'], 'sqlite')
         cleanup_sqlite(source['db-name'], removetemplate=True)
         init_test_database(config=config)
 
--- a/test/unittest_req.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/test/unittest_req.py	Fri Sep 24 18:20:59 2010 +0200
@@ -23,11 +23,11 @@
 class RebuildURLTC(TestCase):
     def test_rebuild_url(self):
         rebuild_url = RequestSessionBase(None).rebuild_url
-        self.assertEquals(rebuild_url('http://logilab.fr?__message=pouet', __message='hop'),
+        self.assertEqual(rebuild_url('http://logilab.fr?__message=pouet', __message='hop'),
                           'http://logilab.fr?__message=hop')
-        self.assertEquals(rebuild_url('http://logilab.fr', __message='hop'),
+        self.assertEqual(rebuild_url('http://logilab.fr', __message='hop'),
                           'http://logilab.fr?__message=hop')
-        self.assertEquals(rebuild_url('http://logilab.fr?vid=index', __message='hop'),
+        self.assertEqual(rebuild_url('http://logilab.fr?vid=index', __message='hop'),
                           'http://logilab.fr?__message=hop&vid=index')
 
     def test_build_url(self):
--- a/test/unittest_rqlrewrite.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/test/unittest_rqlrewrite.py	Fri Sep 24 18:20:59 2010 +0200
@@ -107,7 +107,7 @@
         rqlst = parse('Any S WHERE S documented_by C, C eid %(u)s')
         rewrite(rqlst, {('C', 'X'): (card_constraint,), ('S', 'X'): affaire_constraints},
                 kwargs)
-        self.assertTextEquals(rqlst.as_string(),
+        self.assertMultiLineEqual(rqlst.as_string(),
                              "Any S WHERE S documented_by C, C eid %(u)s, B eid %(D)s, "
                              "EXISTS(C in_state A, B in_group E, F require_state A, "
                              "F name 'read', F require_group E, A is State, E is CWGroup, F is CWPermission), "
@@ -270,7 +270,7 @@
                              "EXISTS(U in_group B, B name 'managers', B is CWGroup), T is TrInfo")
 
     def test_unsupported_constraint_3(self):
-        self.skip('raise unauthorized for now')
+        self.skipTest('raise unauthorized for now')
         trinfo_constraint = ('X wf_info_for Y, Y require_permission P, P name "read"')
         rqlst = parse('Any T WHERE T wf_info_for X')
         rewrite(rqlst, {('T', 'X'): (trinfo_constraint, 'X in_group G, G name "managers"')}, {})
--- a/test/unittest_rset.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/test/unittest_rset.py	Fri Sep 24 18:20:59 2010 +0200
@@ -52,7 +52,7 @@
             }
         for rql, relations in queries.items():
             result = list(attr_desc_iterator(parse(rql).children[0]))
-            self.assertEquals((rql, result), (rql, relations))
+            self.assertEqual((rql, result), (rql, relations))
 
     def test_relations_description_indexed(self):
         """tests relations_description() function"""
@@ -63,7 +63,7 @@
         for rql, results in queries.items():
             for var_index, relations in results.items():
                 result = list(attr_desc_iterator(parse(rql).children[0], var_index))
-                self.assertEquals(result, relations)
+                self.assertEqual(result, relations)
 
 
 
@@ -79,15 +79,15 @@
     def compare_urls(self, url1, url2):
         info1 = urlsplit(url1)
         info2 = urlsplit(url2)
-        self.assertEquals(info1[:3], info2[:3])
+        self.assertEqual(info1[:3], info2[:3])
         if info1[3] != info2[3]:
             params1 = dict(pair.split('=') for pair in info1[3].split('&'))
             params2 = dict(pair.split('=') for pair in info1[3].split('&'))
-            self.assertDictEquals(params1, params2)
+            self.assertDictEqual(params1, params2)
 
     def test_pickle(self):
         del self.rset.req
-        self.assertEquals(len(pickle.dumps(self.rset)), 392)
+        self.assertEqual(len(pickle.dumps(self.rset)), 392)
 
     def test_build_url(self):
         req = self.request()
@@ -105,9 +105,9 @@
     def test_resultset_build(self):
         """test basic build of a ResultSet"""
         rs = ResultSet([1,2,3], 'CWGroup X', description=['CWGroup', 'CWGroup', 'CWGroup'])
-        self.assertEquals(rs.rowcount, 3)
-        self.assertEquals(rs.rows, [1,2,3])
-        self.assertEquals(rs.description, ['CWGroup', 'CWGroup', 'CWGroup'])
+        self.assertEqual(rs.rowcount, 3)
+        self.assertEqual(rs.rows, [1,2,3])
+        self.assertEqual(rs.description, ['CWGroup', 'CWGroup', 'CWGroup'])
 
 
     def test_resultset_limit(self):
@@ -117,12 +117,12 @@
         rs.req = self.request()
         rs.vreg = self.vreg
 
-        self.assertEquals(rs.limit(2).rows, [[12000, 'adim'], [13000, 'syt']])
+        self.assertEqual(rs.limit(2).rows, [[12000, 'adim'], [13000, 'syt']])
         rs2 = rs.limit(2, offset=1)
-        self.assertEquals(rs2.rows, [[13000, 'syt'], [14000, 'nico']])
-        self.assertEquals(rs2.get_entity(0, 0).cw_row, 0)
-        self.assertEquals(rs.limit(2, offset=2).rows, [[14000, 'nico']])
-        self.assertEquals(rs.limit(2, offset=3).rows, [])
+        self.assertEqual(rs2.rows, [[13000, 'syt'], [14000, 'nico']])
+        self.assertEqual(rs2.get_entity(0, 0).cw_row, 0)
+        self.assertEqual(rs.limit(2, offset=2).rows, [[14000, 'nico']])
+        self.assertEqual(rs.limit(2, offset=3).rows, [])
 
 
     def test_resultset_filter(self):
@@ -135,8 +135,8 @@
             return entity.login != 'nico'
 
         rs2 = rs.filtered_rset(test_filter)
-        self.assertEquals(len(rs2), 2)
-        self.assertEquals([login for _, login in rs2], ['adim', 'syt'])
+        self.assertEqual(len(rs2), 2)
+        self.assertEqual([login for _, login in rs2], ['adim', 'syt'])
 
     def test_resultset_transform(self):
         rs = ResultSet([[12, 'adim'], [13, 'syt'], [14, 'nico']],
@@ -147,8 +147,8 @@
             return row[1:], desc[1:]
         rs2 = rs.transformed_rset(test_transform)
 
-        self.assertEquals(len(rs2), 3)
-        self.assertEquals(list(rs2), [['adim'],['syt'],['nico']])
+        self.assertEqual(len(rs2), 3)
+        self.assertEqual(list(rs2), [['adim'],['syt'],['nico']])
 
     def test_resultset_sort(self):
         rs = ResultSet([[12000, 'adim'], [13000, 'syt'], [14000, 'nico']],
@@ -158,22 +158,22 @@
         rs.vreg = self.vreg
 
         rs2 = rs.sorted_rset(lambda e:e['login'])
-        self.assertEquals(len(rs2), 3)
-        self.assertEquals([login for _, login in rs2], ['adim', 'nico', 'syt'])
+        self.assertEqual(len(rs2), 3)
+        self.assertEqual([login for _, login in rs2], ['adim', 'nico', 'syt'])
         # make sure rs is unchanged
-        self.assertEquals([login for _, login in rs], ['adim', 'syt', 'nico'])
+        self.assertEqual([login for _, login in rs], ['adim', 'syt', 'nico'])
 
         rs2 = rs.sorted_rset(lambda e:e['login'], reverse=True)
-        self.assertEquals(len(rs2), 3)
-        self.assertEquals([login for _, login in rs2], ['syt', 'nico', 'adim'])
+        self.assertEqual(len(rs2), 3)
+        self.assertEqual([login for _, login in rs2], ['syt', 'nico', 'adim'])
         # make sure rs is unchanged
-        self.assertEquals([login for _, login in rs], ['adim', 'syt', 'nico'])
+        self.assertEqual([login for _, login in rs], ['adim', 'syt', 'nico'])
 
         rs3 = rs.sorted_rset(lambda row: row[1], col=-1)
-        self.assertEquals(len(rs3), 3)
-        self.assertEquals([login for _, login in rs3], ['adim', 'nico', 'syt'])
+        self.assertEqual(len(rs3), 3)
+        self.assertEqual([login for _, login in rs3], ['adim', 'nico', 'syt'])
         # make sure rs is unchanged
-        self.assertEquals([login for _, login in rs], ['adim', 'syt', 'nico'])
+        self.assertEqual([login for _, login in rs], ['adim', 'syt', 'nico'])
 
     def test_resultset_split(self):
         rs = ResultSet([[12000, 'adim', u'Adim chez les pinguins'],
@@ -188,32 +188,32 @@
         rs.vreg = self.vreg
 
         rsets = rs.split_rset(lambda e:e['login'])
-        self.assertEquals(len(rsets), 3)
-        self.assertEquals([login for _, login,_ in rsets[0]], ['adim', 'adim'])
-        self.assertEquals([login for _, login,_ in rsets[1]], ['syt'])
-        self.assertEquals([login for _, login,_ in rsets[2]], ['nico', 'nico'])
+        self.assertEqual(len(rsets), 3)
+        self.assertEqual([login for _, login,_ in rsets[0]], ['adim', 'adim'])
+        self.assertEqual([login for _, login,_ in rsets[1]], ['syt'])
+        self.assertEqual([login for _, login,_ in rsets[2]], ['nico', 'nico'])
         # make sure rs is unchanged
-        self.assertEquals([login for _, login,_ in rs], ['adim', 'adim', 'syt', 'nico', 'nico'])
+        self.assertEqual([login for _, login,_ in rs], ['adim', 'adim', 'syt', 'nico', 'nico'])
 
         rsets = rs.split_rset(lambda e:e['login'], return_dict=True)
-        self.assertEquals(len(rsets), 3)
-        self.assertEquals([login for _, login,_ in rsets['nico']], ['nico', 'nico'])
-        self.assertEquals([login for _, login,_ in rsets['adim']], ['adim', 'adim'])
-        self.assertEquals([login for _, login,_ in rsets['syt']], ['syt'])
+        self.assertEqual(len(rsets), 3)
+        self.assertEqual([login for _, login,_ in rsets['nico']], ['nico', 'nico'])
+        self.assertEqual([login for _, login,_ in rsets['adim']], ['adim', 'adim'])
+        self.assertEqual([login for _, login,_ in rsets['syt']], ['syt'])
         # make sure rs is unchanged
-        self.assertEquals([login for _, login,_ in rs], ['adim', 'adim', 'syt', 'nico', 'nico'])
+        self.assertEqual([login for _, login,_ in rs], ['adim', 'adim', 'syt', 'nico', 'nico'])
 
         rsets = rs.split_rset(lambda s: s.count('d'), col=2)
-        self.assertEquals(len(rsets), 2)
-        self.assertEquals([title for _, _, title in rsets[0]],
+        self.assertEqual(len(rsets), 2)
+        self.assertEqual([title for _, _, title in rsets[0]],
                           [u"Adim chez les pinguins",
                            u"Jardiner facile",
                            u"L'épluchage du castor commun",])
-        self.assertEquals([title for _, _, title in rsets[1]],
+        self.assertEqual([title for _, _, title in rsets[1]],
                           [u"Le carrelage en 42 leçons",
                            u"La tarte tatin en 15 minutes",])
         # make sure rs is unchanged
-        self.assertEquals([title for _, _, title in rs],
+        self.assertEqual([title for _, _, title in rs],
                           [u'Adim chez les pinguins',
                            u'Jardiner facile',
                            u'Le carrelage en 42 leçons',
@@ -228,15 +228,15 @@
 
     def test_get_entity_simple(self):
         self.request().create_entity('CWUser', login=u'adim', upassword='adim',
-                        surname=u'di mascio', firstname=u'adrien')
+                                     surname=u'di mascio', firstname=u'adrien')
         e = self.execute('Any X,T WHERE X login "adim", X surname T').get_entity(0, 0)
-        self.assertEquals(e['surname'], 'di mascio')
+        self.assertEqual(e['surname'], 'di mascio')
         self.assertRaises(KeyError, e.__getitem__, 'firstname')
         self.assertRaises(KeyError, e.__getitem__, 'creation_date')
-        self.assertEquals(pprelcachedict(e._cw_related_cache), [])
+        self.assertEqual(pprelcachedict(e._cw_related_cache), [])
         e.complete()
-        self.assertEquals(e['firstname'], 'adrien')
-        self.assertEquals(pprelcachedict(e._cw_related_cache), [])
+        self.assertEqual(e['firstname'], 'adrien')
+        self.assertEqual(pprelcachedict(e._cw_related_cache), [])
 
     def test_get_entity_advanced(self):
         self.request().create_entity('Bookmark', title=u'zou', path=u'/view')
@@ -244,24 +244,24 @@
         rset = self.execute('Any X,Y,XT,YN WHERE X bookmarked_by Y, X title XT, Y login YN')
 
         e = rset.get_entity(0, 0)
-        self.assertEquals(e.cw_row, 0)
-        self.assertEquals(e.cw_col, 0)
-        self.assertEquals(e['title'], 'zou')
+        self.assertEqual(e.cw_row, 0)
+        self.assertEqual(e.cw_col, 0)
+        self.assertEqual(e['title'], 'zou')
         self.assertRaises(KeyError, e.__getitem__, 'path')
-        self.assertEquals(e.view('text'), 'zou')
-        self.assertEquals(pprelcachedict(e._cw_related_cache), [])
+        self.assertEqual(e.view('text'), 'zou')
+        self.assertEqual(pprelcachedict(e._cw_related_cache), [])
 
         e = rset.get_entity(0, 1)
-        self.assertEquals(e.cw_row, 0)
-        self.assertEquals(e.cw_col, 1)
-        self.assertEquals(e['login'], 'anon')
+        self.assertEqual(e.cw_row, 0)
+        self.assertEqual(e.cw_col, 1)
+        self.assertEqual(e['login'], 'anon')
         self.assertRaises(KeyError, e.__getitem__, 'firstname')
-        self.assertEquals(pprelcachedict(e._cw_related_cache),
+        self.assertEqual(pprelcachedict(e._cw_related_cache),
                           [])
         e.complete()
-        self.assertEquals(e['firstname'], None)
-        self.assertEquals(e.view('text'), 'anon')
-        self.assertEquals(pprelcachedict(e._cw_related_cache),
+        self.assertEqual(e['firstname'], None)
+        self.assertEqual(e.view('text'), 'anon')
+        self.assertEqual(pprelcachedict(e._cw_related_cache),
                           [])
 
         self.assertRaises(NotAnEntity, rset.get_entity, 0, 2)
@@ -273,7 +273,7 @@
         seid = self.execute('State X WHERE X name "activated"')[0][0]
         # for_user / in_group are prefetched in CWUser __init__, in_state should
         # be filed from our query rset
-        self.assertEquals(pprelcachedict(e._cw_related_cache),
+        self.assertEqual(pprelcachedict(e._cw_related_cache),
                           [('in_state_subject', [seid])])
 
     def test_get_entity_advanced_prefilled_cache(self):
@@ -282,16 +282,16 @@
         rset = self.execute('Any X,U,S,XT,UL,SN WHERE X created_by U, U in_state S, '
                             'X title XT, S name SN, U login UL, X eid %s' % e.eid)
         e = rset.get_entity(0, 0)
-        self.assertEquals(e['title'], 'zou')
-        self.assertEquals(pprelcachedict(e._cw_related_cache),
+        self.assertEqual(e['title'], 'zou')
+        self.assertEqual(pprelcachedict(e._cw_related_cache),
                           [('created_by_subject', [5])])
         # first level of recursion
         u = e.created_by[0]
-        self.assertEquals(u['login'], 'admin')
+        self.assertEqual(u['login'], 'admin')
         self.assertRaises(KeyError, u.__getitem__, 'firstname')
         # second level of recursion
         s = u.in_state[0]
-        self.assertEquals(s['name'], 'activated')
+        self.assertEqual(s['name'], 'activated')
         self.assertRaises(KeyError, s.__getitem__, 'description')
 
 
@@ -302,11 +302,11 @@
         e = rset.get_entity(0, 0)
         # if any of the assertion below fails with a KeyError, the relation is not cached
         # related entities should be an empty list
-        self.assertEquals(e._cw_relation_cache('primary_email', 'subject', True), ())
+        self.assertEqual(e._cw_relation_cache('primary_email', 'subject', True), ())
         # related rset should be an empty rset
         cached = e._cw_relation_cache('primary_email', 'subject', False)
         self.assertIsInstance(cached, ResultSet)
-        self.assertEquals(cached.rowcount, 0)
+        self.assertEqual(cached.rowcount, 0)
 
 
     def test_get_entity_union(self):
@@ -320,16 +320,16 @@
                     ('CWGroup', 'users'))
         for entity in rset.entities(): # test get_entity for each row actually
             etype, n = expected[entity.cw_row]
-            self.assertEquals(entity.__regid__, etype)
+            self.assertEqual(entity.__regid__, etype)
             attr = etype == 'Bookmark' and 'title' or 'name'
-            self.assertEquals(entity[attr], n)
+            self.assertEqual(entity[attr], n)
 
     def test_related_entity_optional(self):
         e = self.request().create_entity('Bookmark', title=u'aaaa', path=u'path')
         rset = self.execute('Any B,U,L WHERE B bookmarked_by U?, U login L')
         entity, rtype = rset.related_entity(0, 2)
-        self.assertEquals(entity, None)
-        self.assertEquals(rtype, None)
+        self.assertEqual(entity, None)
+        self.assertEqual(rtype, None)
 
     def test_related_entity_union_subquery(self):
         e = self.request().create_entity('Bookmark', title=u'aaaa', path=u'path')
@@ -338,27 +338,27 @@
                             ' UNION '
                             ' (Any X,N WHERE X is Bookmark, X title N))')
         entity, rtype = rset.related_entity(0, 1)
-        self.assertEquals(entity.eid, e.eid)
-        self.assertEquals(rtype, 'title')
+        self.assertEqual(entity.eid, e.eid)
+        self.assertEqual(rtype, 'title')
         entity, rtype = rset.related_entity(1, 1)
-        self.assertEquals(entity.__regid__, 'CWGroup')
-        self.assertEquals(rtype, 'name')
+        self.assertEqual(entity.__regid__, 'CWGroup')
+        self.assertEqual(rtype, 'name')
         #
         rset = self.execute('Any X,N ORDERBY N WHERE X is Bookmark WITH X,N BEING '
                             '((Any X,N WHERE X is CWGroup, X name N)'
                             ' UNION '
                             ' (Any X,N WHERE X is Bookmark, X title N))')
         entity, rtype = rset.related_entity(0, 1)
-        self.assertEquals(entity.eid, e.eid)
-        self.assertEquals(rtype, 'title')
+        self.assertEqual(entity.eid, e.eid)
+        self.assertEqual(rtype, 'title')
         #
         rset = self.execute('Any X,N ORDERBY N WITH N,X BEING '
                             '((Any N,X WHERE X is CWGroup, X name N)'
                             ' UNION '
                             ' (Any N,X WHERE X is Bookmark, X title N))')
         entity, rtype = rset.related_entity(0, 1)
-        self.assertEquals(entity.eid, e.eid)
-        self.assertEquals(rtype, 'title')
+        self.assertEqual(entity.eid, e.eid)
+        self.assertEqual(rtype, 'title')
 
     def test_related_entity_trap_subquery(self):
         req = self.request()
@@ -372,7 +372,7 @@
         rset = self.execute('Any X,S,L WHERE X in_state S '
                             'WITH X, L BEING (Any X,MAX(L) GROUPBY X '
                             'WHERE X is CWUser, T? wf_info_for X, T creation_date L)')
-        self.assertEquals(len(rset), 2)
+        self.assertEqual(len(rset), 2)
         rset.related_entity(0, 1)
         rset.related_entity(0, 2)
 
@@ -380,28 +380,28 @@
         rset = self.execute('Any U,G WHERE U in_group G')
         # make sure we have at least one element
         self.failUnless(rset)
-        self.assertEquals(set(e.e_schema.type for e in rset.entities(0)),
+        self.assertEqual(set(e.e_schema.type for e in rset.entities(0)),
                           set(['CWUser',]))
-        self.assertEquals(set(e.e_schema.type for e in rset.entities(1)),
+        self.assertEqual(set(e.e_schema.type for e in rset.entities(1)),
                           set(['CWGroup',]))
 
     def test_printable_rql(self):
         rset = self.execute(u'CWEType X WHERE X final FALSE')
-        self.assertEquals(rset.printable_rql(),
+        self.assertEqual(rset.printable_rql(),
                           'Any X WHERE X final FALSE, X is CWEType')
 
     def test_searched_text(self):
         rset = self.execute(u'Any X WHERE X has_text "foobar"')
-        self.assertEquals(rset.searched_text(), 'foobar')
+        self.assertEqual(rset.searched_text(), 'foobar')
         rset = self.execute(u'Any X WHERE X has_text %(text)s', {'text' : 'foo'})
-        self.assertEquals(rset.searched_text(), 'foo')
+        self.assertEqual(rset.searched_text(), 'foo')
 
     def test_union_limited_rql(self):
         rset = self.execute('(Any X,N WHERE X is Bookmark, X title N)'
                             ' UNION '
                             '(Any X,N WHERE X is CWGroup, X name N)')
         rset.limit(2, 10, inplace=True)
-        self.assertEquals(rset.limited_rql(),
+        self.assertEqual(rset.limited_rql(),
                           'Any A,B LIMIT 2 OFFSET 10 '
                           'WITH A,B BEING ('
                           '(Any X,N WHERE X is Bookmark, X title N) '
@@ -411,12 +411,12 @@
 
     def test_count_users_by_date(self):
         rset = self.execute('Any D, COUNT(U) GROUPBY D WHERE U is CWUser, U creation_date D')
-        self.assertEquals(rset.related_entity(0,0), (None, None))
+        self.assertEqual(rset.related_entity(0,0), (None, None))
 
     def test_str(self):
         rset = self.execute('(Any X,N WHERE X is CWGroup, X name N)')
         self.assertIsInstance(str(rset), basestring)
-        self.assertEquals(len(str(rset).splitlines()), 1)
+        self.assertEqual(len(str(rset).splitlines()), 1)
 
     def test_repr(self):
         rset = self.execute('(Any X,N WHERE X is CWGroup, X name N)')
@@ -425,7 +425,7 @@
 
         rset = self.execute('(Any X WHERE X is CWGroup, X name "managers")')
         self.assertIsInstance(str(rset), basestring)
-        self.assertEquals(len(str(rset).splitlines()), 1)
+        self.assertEqual(len(str(rset).splitlines()), 1)
 
 if __name__ == '__main__':
     unittest_main()
--- a/test/unittest_rtags.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/test/unittest_rtags.py	Fri Sep 24 18:20:59 2010 +0200
@@ -28,25 +28,25 @@
         rtags.tag_subject_of(('Societe', 'travaille', '*'), 'primary')
         rtags.tag_subject_of(('*', 'evaluee', '*'), 'secondary')
         rtags.tag_object_of(('*', 'tags', '*'), 'generated')
-        self.assertEquals(rtags.get('Note', 'evaluee', '*', 'subject'),
+        self.assertEqual(rtags.get('Note', 'evaluee', '*', 'subject'),
                           'secondary')
-        self.assertEquals(rtags.get('Societe', 'travaille', '*', 'subject'),
+        self.assertEqual(rtags.get('Societe', 'travaille', '*', 'subject'),
                           'primary')
-        self.assertEquals(rtags.get('Note', 'travaille', '*', 'subject'),
+        self.assertEqual(rtags.get('Note', 'travaille', '*', 'subject'),
                           None)
-        self.assertEquals(rtags.get('Note', 'tags', '*', 'subject'),
+        self.assertEqual(rtags.get('Note', 'tags', '*', 'subject'),
                           None)
-        self.assertEquals(rtags.get('*', 'tags', 'Note', 'object'),
+        self.assertEqual(rtags.get('*', 'tags', 'Note', 'object'),
                           'generated')
-        self.assertEquals(rtags.get('Tag', 'tags', '*', 'object'),
+        self.assertEqual(rtags.get('Tag', 'tags', '*', 'object'),
                           'generated')
 
-#         self.assertEquals(rtags.rtag('evaluee', 'Note', 'subject'), set(('secondary', 'link')))
-#         self.assertEquals(rtags.is_inlined('evaluee', 'Note', 'subject'), False)
-#         self.assertEquals(rtags.rtag('evaluee', 'Personne', 'subject'), set(('secondary', 'link')))
-#         self.assertEquals(rtags.is_inlined('evaluee', 'Personne', 'subject'), False)
-#         self.assertEquals(rtags.rtag('ecrit_par', 'Note', 'object'), set(('inlineview', 'link')))
-#         self.assertEquals(rtags.is_inlined('ecrit_par', 'Note', 'object'), True)
+#         self.assertEqual(rtags.rtag('evaluee', 'Note', 'subject'), set(('secondary', 'link')))
+#         self.assertEqual(rtags.is_inlined('evaluee', 'Note', 'subject'), False)
+#         self.assertEqual(rtags.rtag('evaluee', 'Personne', 'subject'), set(('secondary', 'link')))
+#         self.assertEqual(rtags.is_inlined('evaluee', 'Personne', 'subject'), False)
+#         self.assertEqual(rtags.rtag('ecrit_par', 'Note', 'object'), set(('inlineview', 'link')))
+#         self.assertEqual(rtags.is_inlined('ecrit_par', 'Note', 'object'), True)
 #         class Personne2(Personne):
 #             id = 'Personne'
 #             __rtags__ = {
@@ -54,21 +54,21 @@
 #                 }
 #         self.vreg.register(Personne2)
 #         rtags = Personne2.rtags
-#         self.assertEquals(rtags.rtag('evaluee', 'Note', 'subject'), set(('inlineview', 'link')))
-#         self.assertEquals(rtags.is_inlined('evaluee', 'Note', 'subject'), True)
-#         self.assertEquals(rtags.rtag('evaluee', 'Personne', 'subject'), set(('secondary', 'link')))
-#         self.assertEquals(rtags.is_inlined('evaluee', 'Personne', 'subject'), False)
+#         self.assertEqual(rtags.rtag('evaluee', 'Note', 'subject'), set(('inlineview', 'link')))
+#         self.assertEqual(rtags.is_inlined('evaluee', 'Note', 'subject'), True)
+#         self.assertEqual(rtags.rtag('evaluee', 'Personne', 'subject'), set(('secondary', 'link')))
+#         self.assertEqual(rtags.is_inlined('evaluee', 'Personne', 'subject'), False)
 
 
     def test_rtagset_expansion(self):
         rtags = RelationTagsSet()
         rtags.tag_subject_of(('Societe', 'travaille', '*'), 'primary')
         rtags.tag_subject_of(('*', 'travaille', '*'), 'secondary')
-        self.assertEquals(rtags.get('Societe', 'travaille', '*', 'subject'),
+        self.assertEqual(rtags.get('Societe', 'travaille', '*', 'subject'),
                           set(('primary', 'secondary')))
-        self.assertEquals(rtags.get('Note', 'travaille', '*', 'subject'),
+        self.assertEqual(rtags.get('Note', 'travaille', '*', 'subject'),
                           set(('secondary',)))
-        self.assertEquals(rtags.get('Note', 'tags', "*", 'subject'),
+        self.assertEqual(rtags.get('Note', 'tags', "*", 'subject'),
                           set())
 
     def test_rtagdict_expansion(self):
@@ -79,16 +79,16 @@
                              {'key1': 'val0', 'key3': 'val0'})
         rtags.tag_subject_of(('Societe', 'travaille', '*'),
                              {'key2': 'val2'})
-        self.assertEquals(rtags.get('Societe', 'travaille', '*', 'subject'),
+        self.assertEqual(rtags.get('Societe', 'travaille', '*', 'subject'),
                           {'key1': 'val1', 'key2': 'val2', 'key3': 'val0'})
-        self.assertEquals(rtags.get('Note', 'travaille', '*', 'subject'),
+        self.assertEqual(rtags.get('Note', 'travaille', '*', 'subject'),
                           {'key1': 'val0', 'key3': 'val0'})
-        self.assertEquals(rtags.get('Note', 'tags', "*", 'subject'),
+        self.assertEqual(rtags.get('Note', 'tags', "*", 'subject'),
                           {})
 
         rtags.setdefault(('Societe', 'travaille', '*', 'subject'), 'key1', 'val4')
         rtags.setdefault(('Societe', 'travaille', '*', 'subject'), 'key4', 'val4')
-        self.assertEquals(rtags.get('Societe', 'travaille', '*', 'subject'),
+        self.assertEqual(rtags.get('Societe', 'travaille', '*', 'subject'),
                           {'key1': 'val1', 'key2': 'val2', 'key3': 'val0', 'key4': 'val4'})
 
 if __name__ == '__main__':
--- a/test/unittest_schema.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/test/unittest_schema.py	Fri Sep 24 18:20:59 2010 +0200
@@ -142,13 +142,13 @@
     def test_erqlexpression(self):
         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')
+        self.assertEqual(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,U WHERE U has_update_permission O, O eid %(o)s, U eid %(u)s')
+        self.assertEqual(str(expr), 'Any O,U WHERE U has_update_permission O, O eid %(o)s, U eid %(u)s')
 
 loader = CubicWebSchemaLoader()
 config = TestConfiguration('data')
@@ -158,15 +158,15 @@
 
     def test_order_eschemas(self):
         schema = loader.load(config)
-        self.assertEquals(order_eschemas([schema['Note'], schema['SubNote']]),
+        self.assertEqual(order_eschemas([schema['Note'], schema['SubNote']]),
                                          [schema['Note'], schema['SubNote']])
-        self.assertEquals(order_eschemas([schema['SubNote'], schema['Note']]),
+        self.assertEqual(order_eschemas([schema['SubNote'], schema['Note']]),
                                          [schema['Note'], schema['SubNote']])
 
     def test_knownValues_load_schema(self):
         schema = loader.load(config)
         self.assert_(isinstance(schema, CubicWebSchema))
-        self.assertEquals(schema.name, 'data')
+        self.assertEqual(schema.name, 'data')
         entities = [str(e) for e in schema.entities()]
         entities.sort()
         expected_entities = ['BaseTransition', 'Bookmark', 'Boolean', 'Bytes', 'Card',
@@ -181,7 +181,7 @@
                              'Societe', 'State', 'String', 'SubNote', 'SubWorkflowExitPoint',
                              'Tag', 'Time', 'Transition', 'TrInfo',
                              'Workflow', 'WorkflowTransition']
-        self.assertListEquals(entities, sorted(expected_entities))
+        self.assertListEqual(entities, sorted(expected_entities))
         relations = [str(r) for r in schema.relations()]
         relations.sort()
         expected_relations = ['add_permission', 'address', 'alias', 'allowed_transition',
@@ -227,11 +227,11 @@
 
                               'wf_info_for', 'wikiid', 'workflow_of']
 
-        self.assertListEquals(relations, expected_relations)
+        self.assertListEqual(relations, expected_relations)
 
         eschema = schema.eschema('CWUser')
         rels = sorted(str(r) for r in eschema.subject_relations())
-        self.assertListEquals(rels, ['created_by', 'creation_date', 'custom_workflow', 'cwuri', 'eid',
+        self.assertListEqual(rels, ['created_by', 'creation_date', 'custom_workflow', 'cwuri', 'eid',
                                      'evaluee', 'firstname', 'has_text', 'identity',
                                      'in_group', 'in_state', 'is',
                                      'is_instance_of', 'last_login_time',
@@ -239,11 +239,11 @@
                                      'primary_email', 'surname', 'upassword',
                                      'use_email'])
         rels = sorted(r.type for r in eschema.object_relations())
-        self.assertListEquals(rels, ['bookmarked_by', 'created_by', 'for_user',
+        self.assertListEqual(rels, ['bookmarked_by', 'created_by', 'for_user',
                                      'identity', 'owned_by', 'wf_info_for'])
         rschema = schema.rschema('relation_type')
         properties = rschema.rdef('CWAttribute', 'CWRType')
-        self.assertEquals(properties.cardinality, '1*')
+        self.assertEqual(properties.cardinality, '1*')
         constraints = properties.constraints
         self.failUnlessEqual(len(constraints), 1, constraints)
         constraint = constraints[0]
@@ -258,13 +258,13 @@
     def test_permission_settings(self):
         schema = loader.load(config)
         aschema = schema['TrInfo'].rdef('comment')
-        self.assertEquals(aschema.get_groups('read'),
+        self.assertEqual(aschema.get_groups('read'),
                           set(('managers', 'users', 'guests')))
-        self.assertEquals(aschema.get_rqlexprs('read'),
+        self.assertEqual(aschema.get_rqlexprs('read'),
                           ())
-        self.assertEquals(aschema.get_groups('update'),
+        self.assertEqual(aschema.get_groups('update'),
                           set(('managers',)))
-        self.assertEquals([x.expression for x in aschema.get_rqlexprs('update')],
+        self.assertEqual([x.expression for x in aschema.get_rqlexprs('update')],
                           ['U has_update_permission X'])
 
 class BadSchemaRQLExprTC(TestCase):
@@ -279,7 +279,7 @@
         self.loader.handle_file(join(DATADIR, schemafile))
         ex = self.assertRaises(BadSchemaDefinition,
                                self.loader._build_schema, 'toto', False)
-        self.assertEquals(str(ex), msg)
+        self.assertEqual(str(ex), msg)
 
     def test_rrqlexpr_on_etype(self):
         self._test('rrqlexpr_on_eetype.py',
@@ -301,12 +301,12 @@
 class NormalizeExpressionTC(TestCase):
 
     def test(self):
-        self.assertEquals(normalize_expression('X  bla Y,Y blur Z  ,  Z zigoulou   X '),
+        self.assertEqual(normalize_expression('X  bla Y,Y blur Z  ,  Z zigoulou   X '),
                                                'X bla Y, Y blur Z, Z zigoulou X')
 
 class RQLExpressionTC(TestCase):
     def test_comparison(self):
-        self.assertEquals(ERQLExpression('X is CWUser', 'X', 0),
+        self.assertEqual(ERQLExpression('X is CWUser', 'X', 0),
                           ERQLExpression('X is CWUser', 'X', 0))
         self.assertNotEquals(ERQLExpression('X is CWUser', 'X', 0),
                              ERQLExpression('X is CWGroup', 'X', 0))
@@ -314,7 +314,7 @@
 class GuessRrqlExprMainVarsTC(TestCase):
     def test_exists(self):
         mainvars = guess_rrqlexpr_mainvars(normalize_expression('NOT EXISTS(O team_competition C, C level < 3)'))
-        self.assertEquals(mainvars, 'O')
+        self.assertEqual(mainvars, 'O')
 
 
 if __name__ == '__main__':
--- a/test/unittest_selectors.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/test/unittest_selectors.py	Fri Sep 24 18:20:59 2010 +0200
@@ -41,55 +41,55 @@
 class SelectorsTC(TestCase):
     def test_basic_and(self):
         selector = _1_() & _1_()
-        self.assertEquals(selector(None), 2)
+        self.assertEqual(selector(None), 2)
         selector = _1_() & _0_()
-        self.assertEquals(selector(None), 0)
+        self.assertEqual(selector(None), 0)
         selector = _0_() & _1_()
-        self.assertEquals(selector(None), 0)
+        self.assertEqual(selector(None), 0)
 
     def test_basic_or(self):
         selector = _1_() | _1_()
-        self.assertEquals(selector(None), 1)
+        self.assertEqual(selector(None), 1)
         selector = _1_() | _0_()
-        self.assertEquals(selector(None), 1)
+        self.assertEqual(selector(None), 1)
         selector = _0_() | _1_()
-        self.assertEquals(selector(None), 1)
+        self.assertEqual(selector(None), 1)
         selector = _0_() | _0_()
-        self.assertEquals(selector(None), 0)
+        self.assertEqual(selector(None), 0)
 
     def test_selector_and_function(self):
         selector = _1_() & _2_
-        self.assertEquals(selector(None), 3)
+        self.assertEqual(selector(None), 3)
         selector = _2_ & _1_()
-        self.assertEquals(selector(None), 3)
+        self.assertEqual(selector(None), 3)
 
     def test_three_and(self):
         selector = _1_() & _1_() & _1_()
-        self.assertEquals(selector(None), 3)
+        self.assertEqual(selector(None), 3)
         selector = _1_() & _0_() & _1_()
-        self.assertEquals(selector(None), 0)
+        self.assertEqual(selector(None), 0)
         selector = _0_() & _1_() & _1_()
-        self.assertEquals(selector(None), 0)
+        self.assertEqual(selector(None), 0)
 
     def test_three_or(self):
         selector = _1_() | _1_() | _1_()
-        self.assertEquals(selector(None), 1)
+        self.assertEqual(selector(None), 1)
         selector = _1_() | _0_() | _1_()
-        self.assertEquals(selector(None), 1)
+        self.assertEqual(selector(None), 1)
         selector = _0_() | _1_() | _1_()
-        self.assertEquals(selector(None), 1)
+        self.assertEqual(selector(None), 1)
         selector = _0_() | _0_() | _0_()
-        self.assertEquals(selector(None), 0)
+        self.assertEqual(selector(None), 0)
 
     def test_composition(self):
         selector = (_1_() & _1_()) & (_1_() & _1_())
         self.failUnless(isinstance(selector, AndSelector))
-        self.assertEquals(len(selector.selectors), 4)
-        self.assertEquals(selector(None), 4)
+        self.assertEqual(len(selector.selectors), 4)
+        self.assertEqual(selector(None), 4)
         selector = (_1_() & _0_()) | (_1_() & _1_())
         self.failUnless(isinstance(selector, OrSelector))
-        self.assertEquals(len(selector.selectors), 2)
-        self.assertEquals(selector(None), 2)
+        self.assertEqual(len(selector.selectors), 2)
+        self.assertEqual(selector(None), 2)
 
     def test_search_selectors(self):
         sel = is_instance('something')
@@ -103,37 +103,37 @@
         selector = _1_()
         selector &= _1_()
         selector &= _1_()
-        self.assertEquals(selector(None), 3)
+        self.assertEqual(selector(None), 3)
         selector = _1_()
         selector &= _0_()
         selector &= _1_()
-        self.assertEquals(selector(None), 0)
+        self.assertEqual(selector(None), 0)
         selector = _0_()
         selector &= _1_()
         selector &= _1_()
-        self.assertEquals(selector(None), 0)
+        self.assertEqual(selector(None), 0)
         selector = _0_()
         selector &= _0_()
         selector &= _0_()
-        self.assertEquals(selector(None), 0)
+        self.assertEqual(selector(None), 0)
 
     def test_inplace_or(self):
         selector = _1_()
         selector |= _1_()
         selector |= _1_()
-        self.assertEquals(selector(None), 1)
+        self.assertEqual(selector(None), 1)
         selector = _1_()
         selector |= _0_()
         selector |= _1_()
-        self.assertEquals(selector(None), 1)
+        self.assertEqual(selector(None), 1)
         selector = _0_()
         selector |= _1_()
         selector |= _1_()
-        self.assertEquals(selector(None), 1)
+        self.assertEqual(selector(None), 1)
         selector = _0_()
         selector |= _0_()
         selector |= _0_()
-        self.assertEquals(selector(None), 0)
+        self.assertEqual(selector(None), 0)
 
 
 class ImplementsSelectorTC(CubicWebTC):
@@ -153,7 +153,7 @@
 
     def test_yams_inheritance(self):
         cls = self.vreg['etypes'].etype_class('Transition')
-        self.assertEquals(is_instance('BaseTransition').score_class(cls, self.request()),
+        self.assertEqual(is_instance('BaseTransition').score_class(cls, self.request()),
                           3)
 
 
--- a/test/unittest_spa2rql.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/test/unittest_spa2rql.py	Fri Sep 24 18:20:59 2010 +0200
@@ -37,7 +37,7 @@
 
     def _test(self, sparql, rql, args={}):
         qi = self.tr.translate(sparql)
-        self.assertEquals(qi.finalize(), (rql, args))
+        self.assertEqual(qi.finalize(), (rql, args))
 
     def XXX_test_base_01(self):
         self._test('SELECT * WHERE { }', 'Any X')
--- a/test/unittest_uilib.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/test/unittest_uilib.py	Fri Sep 24 18:20:59 2010 +0200
@@ -39,22 +39,22 @@
             ]
         for text, expected in data:
             got = uilib.remove_html_tags(text)
-            self.assertEquals(got, expected)
+            self.assertEqual(got, expected)
 
     def test_fallback_safe_cut(self):
-        self.assertEquals(uilib.fallback_safe_cut(u'ab <a href="hello">cd</a>', 4), u'ab c...')
-        self.assertEquals(uilib.fallback_safe_cut(u'ab <a href="hello">cd</a>', 5), u'ab <a href="hello">cd</a>')
-        self.assertEquals(uilib.fallback_safe_cut(u'ab <a href="hello">&amp;d</a>', 4), u'ab &amp;...')
-        self.assertEquals(uilib.fallback_safe_cut(u'ab <a href="hello">&amp;d</a> ef', 5), u'ab &amp;d...')
-        self.assertEquals(uilib.fallback_safe_cut(u'ab <a href="hello">&igrave;d</a>', 4), u'ab ì...')
-        self.assertEquals(uilib.fallback_safe_cut(u'&amp; <a href="hello">&amp;d</a> ef', 4), u'&amp; &amp;d...')
+        self.assertEqual(uilib.fallback_safe_cut(u'ab <a href="hello">cd</a>', 4), u'ab c...')
+        self.assertEqual(uilib.fallback_safe_cut(u'ab <a href="hello">cd</a>', 5), u'ab <a href="hello">cd</a>')
+        self.assertEqual(uilib.fallback_safe_cut(u'ab <a href="hello">&amp;d</a>', 4), u'ab &amp;...')
+        self.assertEqual(uilib.fallback_safe_cut(u'ab <a href="hello">&amp;d</a> ef', 5), u'ab &amp;d...')
+        self.assertEqual(uilib.fallback_safe_cut(u'ab <a href="hello">&igrave;d</a>', 4), u'ab ì...')
+        self.assertEqual(uilib.fallback_safe_cut(u'&amp; <a href="hello">&amp;d</a> ef', 4), u'&amp; &amp;d...')
 
     def test_lxml_safe_cut(self):
-        self.assertEquals(uilib.safe_cut(u'aaa<div>aaad</div> ef', 4), u'<p>aaa</p><div>a...</div>')
-        self.assertEquals(uilib.safe_cut(u'aaa<div>aaad</div> ef', 7), u'<p>aaa</p><div>aaad</div>...')
-        self.assertEquals(uilib.safe_cut(u'aaa<div>aaad</div>', 7), u'<p>aaa</p><div>aaad</div>')
+        self.assertEqual(uilib.safe_cut(u'aaa<div>aaad</div> ef', 4), u'<p>aaa</p><div>a...</div>')
+        self.assertEqual(uilib.safe_cut(u'aaa<div>aaad</div> ef', 7), u'<p>aaa</p><div>aaad</div>...')
+        self.assertEqual(uilib.safe_cut(u'aaa<div>aaad</div>', 7), u'<p>aaa</p><div>aaad</div>')
         # Missing ellipsis due to space management but we don't care
-        self.assertEquals(uilib.safe_cut(u'ab <a href="hello">&amp;d</a>', 4), u'<p>ab <a href="hello">&amp;...</a></p>')
+        self.assertEqual(uilib.safe_cut(u'ab <a href="hello">&amp;d</a>', 4), u'<p>ab <a href="hello">&amp;...</a></p>')
 
     def test_cut(self):
         """tests uilib.cut() behaviour"""
@@ -65,7 +65,7 @@
             ]
         for text, expected in data:
             got = uilib.cut(text, 8)
-            self.assertEquals(got, expected)
+            self.assertEqual(got, expected)
 
     def test_text_cut(self):
         """tests uilib.text_cut() behaviour with no text"""
@@ -92,62 +92,62 @@
                 ]
         for text, expected in data:
             got = uilib.text_cut(text, 30)
-            self.assertEquals(got, expected)
+            self.assertEqual(got, expected)
 
     def test_soup2xhtml_1_1(self):
-        self.assertEquals(uilib.soup2xhtml('hop <div>', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('hop <div>', 'ascii'),
                           'hop <div/>')
-        self.assertEquals(uilib.soup2xhtml('<div> hop', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('<div> hop', 'ascii'),
                           '<div> hop</div>')
-        self.assertEquals(uilib.soup2xhtml('hop <div> hop', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('hop <div> hop', 'ascii'),
                           'hop <div> hop</div>')
 
     def test_soup2xhtml_1_2(self):
-        self.assertEquals(uilib.soup2xhtml('hop </div>', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('hop </div>', 'ascii'),
                           'hop ')
-        self.assertEquals(uilib.soup2xhtml('</div> hop', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('</div> hop', 'ascii'),
                           '<div/> hop')
-        self.assertEquals(uilib.soup2xhtml('hop </div> hop', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('hop </div> hop', 'ascii'),
                           '<div>hop </div> hop')
 
     def test_soup2xhtml_2_1(self):
-        self.assertEquals(uilib.soup2xhtml('hop <body>', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('hop <body>', 'ascii'),
                           'hop ')
-        self.assertEquals(uilib.soup2xhtml('<body> hop', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('<body> hop', 'ascii'),
                           ' hop')
-        self.assertEquals(uilib.soup2xhtml('hop <body> hop', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('hop <body> hop', 'ascii'),
                           'hop  hop')
 
     def test_soup2xhtml_2_2(self):
-        self.assertEquals(uilib.soup2xhtml('hop </body>', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('hop </body>', 'ascii'),
                           'hop ')
-        self.assertEquals(uilib.soup2xhtml('</body> hop', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('</body> hop', 'ascii'),
                           ' hop')
-        self.assertEquals(uilib.soup2xhtml('hop </body> hop', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('hop </body> hop', 'ascii'),
                           'hop  hop')
 
     def test_soup2xhtml_3_1(self):
-        self.assertEquals(uilib.soup2xhtml('hop <html>', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('hop <html>', 'ascii'),
                           'hop ')
-        self.assertEquals(uilib.soup2xhtml('<html> hop', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('<html> hop', 'ascii'),
                           ' hop')
-        self.assertEquals(uilib.soup2xhtml('hop <html> hop', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('hop <html> hop', 'ascii'),
                           'hop  hop')
 
     def test_soup2xhtml_3_2(self):
-        self.assertEquals(uilib.soup2xhtml('hop </html>', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('hop </html>', 'ascii'),
                           'hop ')
-        self.assertEquals(uilib.soup2xhtml('</html> hop', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('</html> hop', 'ascii'),
                           ' hop')
-        self.assertEquals(uilib.soup2xhtml('hop </html> hop', 'ascii'),
+        self.assertEqual(uilib.soup2xhtml('hop </html> hop', 'ascii'),
                           'hop  hop')
 
     def test_js(self):
-        self.assertEquals(str(uilib.js.pouet(1, "2")),
+        self.assertEqual(str(uilib.js.pouet(1, "2")),
                           'pouet(1,"2")')
-        self.assertEquals(str(uilib.js.cw.pouet(1, "2")),
+        self.assertEqual(str(uilib.js.cw.pouet(1, "2")),
                           'cw.pouet(1,"2")')
-        self.assertEquals(str(uilib.js.cw.pouet(1, "2").pouet(None)),
+        self.assertEqual(str(uilib.js.cw.pouet(1, "2").pouet(None)),
                           'cw.pouet(1,"2").pouet(null)')
 
 if __name__ == '__main__':
--- a/test/unittest_utils.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/test/unittest_utils.py	Fri Sep 24 18:20:59 2010 +0200
@@ -57,47 +57,47 @@
 
     def test_base(self):
         l = RepeatList(3, (1, 3))
-        self.assertEquals(l[0], (1, 3))
-        self.assertEquals(l[2], (1, 3))
-        self.assertEquals(l[-1], (1, 3))
-        self.assertEquals(len(l), 3)
+        self.assertEqual(l[0], (1, 3))
+        self.assertEqual(l[2], (1, 3))
+        self.assertEqual(l[-1], (1, 3))
+        self.assertEqual(len(l), 3)
         # XXX
-        self.assertEquals(l[4], (1, 3))
+        self.assertEqual(l[4], (1, 3))
 
         self.failIf(RepeatList(0, None))
 
     def test_slice(self):
         l = RepeatList(3, (1, 3))
-        self.assertEquals(l[0:1], [(1, 3)])
-        self.assertEquals(l[0:4], [(1, 3)]*3)
-        self.assertEquals(l[:], [(1, 3)]*3)
+        self.assertEqual(l[0:1], [(1, 3)])
+        self.assertEqual(l[0:4], [(1, 3)]*3)
+        self.assertEqual(l[:], [(1, 3)]*3)
 
     def test_iter(self):
-        self.assertEquals(list(RepeatList(3, (1, 3))),
+        self.assertEqual(list(RepeatList(3, (1, 3))),
                           [(1, 3)]*3)
 
     def test_add(self):
         l = RepeatList(3, (1, 3))
-        self.assertEquals(l + [(1, 4)], [(1, 3)]*3  + [(1, 4)])
-        self.assertEquals([(1, 4)] + l, [(1, 4)] + [(1, 3)]*3)
-        self.assertEquals(l + RepeatList(2, (2, 3)), [(1, 3)]*3 + [(2, 3)]*2)
+        self.assertEqual(l + [(1, 4)], [(1, 3)]*3  + [(1, 4)])
+        self.assertEqual([(1, 4)] + l, [(1, 4)] + [(1, 3)]*3)
+        self.assertEqual(l + RepeatList(2, (2, 3)), [(1, 3)]*3 + [(2, 3)]*2)
 
         x = l + RepeatList(2, (1, 3))
         self.assertIsInstance(x, RepeatList)
-        self.assertEquals(len(x), 5)
-        self.assertEquals(x[0], (1, 3))
+        self.assertEqual(len(x), 5)
+        self.assertEqual(x[0], (1, 3))
 
         x = l + [(1, 3)] * 2
-        self.assertEquals(x, [(1, 3)] * 5)
+        self.assertEqual(x, [(1, 3)] * 5)
 
     def test_eq(self):
-        self.assertEquals(RepeatList(3, (1, 3)),
+        self.assertEqual(RepeatList(3, (1, 3)),
                           [(1, 3)]*3)
 
     def test_pop(self):
         l = RepeatList(3, (1, 3))
         l.pop(2)
-        self.assertEquals(l, [(1, 3)]*2)
+        self.assertEqual(l, [(1, 3)]*2)
 
 
 class SizeConstrainedListTC(TestCase):
@@ -106,7 +106,7 @@
         l = SizeConstrainedList(10)
         for i in xrange(12):
             l.append(i)
-        self.assertEquals(l, range(2, 12))
+        self.assertEqual(l, range(2, 12))
 
     def test_extend(self):
         testdata = [(range(5), range(5)),
@@ -116,44 +116,44 @@
         for extension, expected in testdata:
             l = SizeConstrainedList(10)
             l.extend(extension)
-            yield self.assertEquals, l, expected
+            yield self.assertEqual, l, expected
 
 
 class JSONEncoderTC(TestCase):
     def setUp(self):
         if json is None:
-            self.skip('json not available')
+            self.skipTest('json not available')
 
     def encode(self, value):
         return json.dumps(value, cls=CubicWebJsonEncoder)
 
     def test_encoding_dates(self):
-        self.assertEquals(self.encode(datetime.datetime(2009, 9, 9, 20, 30)),
+        self.assertEqual(self.encode(datetime.datetime(2009, 9, 9, 20, 30)),
                           '"2009/09/09 20:30:00"')
-        self.assertEquals(self.encode(datetime.date(2009, 9, 9)),
+        self.assertEqual(self.encode(datetime.date(2009, 9, 9)),
                           '"2009/09/09"')
-        self.assertEquals(self.encode(datetime.time(20, 30)),
+        self.assertEqual(self.encode(datetime.time(20, 30)),
                           '"20:30:00"')
 
     def test_encoding_decimal(self):
-        self.assertEquals(self.encode(decimal.Decimal('1.2')), '1.2')
+        self.assertEqual(self.encode(decimal.Decimal('1.2')), '1.2')
 
     def test_encoding_bare_entity(self):
         e = Entity(None)
         e['pouet'] = 'hop'
         e.eid = 2
-        self.assertEquals(json.loads(self.encode(e)),
+        self.assertEqual(json.loads(self.encode(e)),
                           {'pouet': 'hop', 'eid': 2})
 
     def test_encoding_entity_in_list(self):
         e = Entity(None)
         e['pouet'] = 'hop'
         e.eid = 2
-        self.assertEquals(json.loads(self.encode([e])),
+        self.assertEqual(json.loads(self.encode([e])),
                           [{'pouet': 'hop', 'eid': 2}])
 
     def test_encoding_unknown_stuff(self):
-        self.assertEquals(self.encode(TestCase), 'null')
+        self.assertEqual(self.encode(TestCase), 'null')
 
 
 if __name__ == '__main__':
--- a/test/unittest_vregistry.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/test/unittest_vregistry.py	Fri Sep 24 18:20:59 2010 +0200
@@ -48,9 +48,9 @@
         self.vreg.load_file(join(BASE, 'entities', '__init__.py'), 'cubicweb.entities.__init__')
         self.vreg.load_file(join(WEBVIEWSDIR, 'idownloadable.py'), 'cubicweb.web.views.idownloadable')
         self.vreg.load_file(join(WEBVIEWSDIR, 'primary.py'), 'cubicweb.web.views.primary')
-        self.assertEquals(len(self.vreg['views']['primary']), 2)
+        self.assertEqual(len(self.vreg['views']['primary']), 2)
         self.vreg.initialization_completed()
-        self.assertEquals(len(self.vreg['views']['primary']), 1)
+        self.assertEqual(len(self.vreg['views']['primary']), 1)
 
 
     def test_load_subinterface_based_appobjects(self):
@@ -70,7 +70,7 @@
         self.vreg.register(CardIProgressAdapter)
         self.vreg.initialization_completed()
         # check progressbar isn't kicked
-        self.assertEquals(len(self.vreg['views']['progressbar']), 1)
+        self.assertEqual(len(self.vreg['views']['progressbar']), 1)
 
     def test_properties(self):
         self.vreg.reset()
@@ -84,7 +84,7 @@
     def test_property_default_overriding(self):
         # see data/views.py
         from cubicweb.web.views.xmlrss import RSSIconBox
-        self.assertEquals(self.vreg.property_info(RSSIconBox._cwpropkey('visible'))['default'], True)
+        self.assertEqual(self.vreg.property_info(RSSIconBox._cwpropkey('visible'))['default'], True)
 
 if __name__ == '__main__':
     unittest_main()
--- a/web/test/test_views.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/test_views.py	Fri Sep 24 18:20:59 2010 +0200
@@ -66,7 +66,7 @@
         self.vreg.register(SomeView)
         rset = self.execute('CWUser X')
         source = self.view('someview', rset).source
-        self.assertEquals(source.count('spam.js'), 1)
+        self.assertEqual(source.count('spam.js'), 1)
 
 
 
--- a/web/test/unittest_application.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_application.py	Fri Sep 24 18:20:59 2010 +0200
@@ -69,32 +69,32 @@
     def test_list_arg(self):
         """tests the list_arg() function"""
         list_arg = self._cw.list_form_param
-        self.assertEquals(list_arg('arg3', {}), [])
+        self.assertEqual(list_arg('arg3', {}), [])
         d = {'arg1' : "value1",
              'arg2' : ('foo', INTERNAL_FIELD_VALUE,),
              'arg3' : ['bar']}
-        self.assertEquals(list_arg('arg1', d, True), ['value1'])
-        self.assertEquals(d, {'arg2' : ('foo', INTERNAL_FIELD_VALUE), 'arg3' : ['bar'],})
-        self.assertEquals(list_arg('arg2', d, True), ['foo'])
-        self.assertEquals({'arg3' : ['bar'],}, d)
-        self.assertEquals(list_arg('arg3', d), ['bar',])
-        self.assertEquals({'arg3' : ['bar'],}, d)
+        self.assertEqual(list_arg('arg1', d, True), ['value1'])
+        self.assertEqual(d, {'arg2' : ('foo', INTERNAL_FIELD_VALUE), 'arg3' : ['bar'],})
+        self.assertEqual(list_arg('arg2', d, True), ['foo'])
+        self.assertEqual({'arg3' : ['bar'],}, d)
+        self.assertEqual(list_arg('arg3', d), ['bar',])
+        self.assertEqual({'arg3' : ['bar'],}, d)
 
 
     def test_from_controller(self):
         self._cw.vreg['controllers'] = {'view': 1, 'login': 1}
-        self.assertEquals(self._cw.from_controller(), 'view')
+        self.assertEqual(self._cw.from_controller(), 'view')
         req = FakeRequest(url='project?vid=list')
         req.vreg['controllers'] = {'view': 1, 'login': 1}
         # this assertion is just to make sure that relative_path can be
         # correctly computed as it is used in from_controller()
-        self.assertEquals(req.relative_path(False), 'project')
-        self.assertEquals(req.from_controller(), 'view')
+        self.assertEqual(req.relative_path(False), 'project')
+        self.assertEqual(req.from_controller(), 'view')
         # test on a valid non-view controller
         req = FakeRequest(url='login?x=1&y=2')
         req.vreg['controllers'] = {'view': 1, 'login': 1}
-        self.assertEquals(req.relative_path(False), 'login')
-        self.assertEquals(req.from_controller(), 'login')
+        self.assertEqual(req.relative_path(False), 'login')
+        self.assertEqual(req.from_controller(), 'login')
 
 
 class UtilsTC(TestCase):
@@ -107,22 +107,22 @@
     #    """tests which mapping is used (application or core)"""
     #    init_mapping()
     #    from cubicweb.common import mapping
-    #    self.assertEquals(mapping.MAPPING_USED, 'core')
+    #    self.assertEqual(mapping.MAPPING_USED, 'core')
     #    sys.modules['mapping'] = FakeMapping()
     #    init_mapping()
-    #    self.assertEquals(mapping.MAPPING_USED, 'application')
+    #    self.assertEqual(mapping.MAPPING_USED, 'application')
     #    del sys.modules['mapping']
 
     def test_execute_linkto(self):
         """tests the execute_linkto() function"""
-        self.assertEquals(self.ctrl.execute_linkto(), None)
-        self.assertEquals(self.ctrl._cursor.executed,
+        self.assertEqual(self.ctrl.execute_linkto(), None)
+        self.assertEqual(self.ctrl._cursor.executed,
                           [])
 
         self.ctrl.set_form({'__linkto' : 'works_for:12_13_14:object',
                               'eid': 8})
         self.ctrl.execute_linkto()
-        self.assertEquals(self.ctrl._cursor.executed,
+        self.assertEqual(self.ctrl._cursor.executed,
                           ['SET Y works_for X WHERE X eid 8, Y eid %s' % i
                            for i in (12, 13, 14)])
 
@@ -130,7 +130,7 @@
         self.ctrl.set_form({'__linkto' : 'works_for:12_13_14:subject',
                               'eid': 8})
         self.ctrl.execute_linkto()
-        self.assertEquals(self.ctrl._cursor.executed,
+        self.assertEqual(self.ctrl._cursor.executed,
                           ['SET X works_for Y WHERE X eid 8, Y eid %s' % i
                            for i in (12, 13, 14)])
 
@@ -138,14 +138,14 @@
         self.ctrl.new_cursor()
         self.ctrl._cw.form = {'__linkto' : 'works_for:12_13_14:object'}
         self.ctrl.execute_linkto(eid=8)
-        self.assertEquals(self.ctrl._cursor.executed,
+        self.assertEqual(self.ctrl._cursor.executed,
                           ['SET Y works_for X WHERE X eid 8, Y eid %s' % i
                            for i in (12, 13, 14)])
 
         self.ctrl.new_cursor()
         self.ctrl.set_form({'__linkto' : 'works_for:12_13_14:subject'})
         self.ctrl.execute_linkto(eid=8)
-        self.assertEquals(self.ctrl._cursor.executed,
+        self.assertEqual(self.ctrl._cursor.executed,
                           ['SET X works_for Y WHERE X eid 8, Y eid %s' % i
                            for i in (12, 13, 14)])
 
@@ -159,13 +159,13 @@
 
     def test_cnx_user_groups_sync(self):
         user = self.user()
-        self.assertEquals(user.groups, set(('managers',)))
+        self.assertEqual(user.groups, set(('managers',)))
         self.execute('SET X in_group G WHERE X eid %s, G name "guests"' % user.eid)
         user = self.user()
-        self.assertEquals(user.groups, set(('managers',)))
+        self.assertEqual(user.groups, set(('managers',)))
         self.commit()
         user = self.user()
-        self.assertEquals(user.groups, set(('managers', 'guests')))
+        self.assertEqual(user.groups, set(('managers', 'guests')))
         # cleanup
         self.execute('DELETE X in_group G WHERE X eid %s, G name "guests"' % user.eid)
         self.commit()
@@ -193,13 +193,13 @@
         path, params = self.expect_redirect(lambda x: self.app_publish(x, 'edit'), req)
         forminfo = req.session.data['view?vid=edition...']
         eidmap = forminfo['eidmap']
-        self.assertEquals(eidmap, {})
+        self.assertEqual(eidmap, {})
         values = forminfo['values']
-        self.assertEquals(values['login-subject:'+eid], '')
-        self.assertEquals(values['eid'], eid)
+        self.assertEqual(values['login-subject:'+eid], '')
+        self.assertEqual(values['eid'], eid)
         error = forminfo['error']
-        self.assertEquals(error.entity, user.eid)
-        self.assertEquals(error.errors['login-subject'], 'required field')
+        self.assertEqual(error.entity, user.eid)
+        self.assertEqual(error.errors['login-subject'], 'required field')
 
 
     def test_validation_error_dont_loose_subentity_data_ctrl(self):
@@ -222,13 +222,13 @@
                     }
         path, params = self.expect_redirect(lambda x: self.app_publish(x, 'edit'), req)
         forminfo = req.session.data['view?vid=edition...']
-        self.assertEquals(set(forminfo['eidmap']), set('XY'))
-        self.assertEquals(forminfo['eidmap']['X'], None)
+        self.assertEqual(set(forminfo['eidmap']), set('XY'))
+        self.assertEqual(forminfo['eidmap']['X'], None)
         self.assertIsInstance(forminfo['eidmap']['Y'], int)
-        self.assertEquals(forminfo['error'].entity, 'X')
-        self.assertEquals(forminfo['error'].errors,
+        self.assertEqual(forminfo['error'].entity, 'X')
+        self.assertEqual(forminfo['error'].errors,
                           {'login-subject': 'required field'})
-        self.assertEquals(forminfo['values'], req.form)
+        self.assertEqual(forminfo['values'], req.form)
 
 
     def test_validation_error_dont_loose_subentity_data_repo(self):
@@ -251,13 +251,13 @@
                     }
         path, params = self.expect_redirect(lambda x: self.app_publish(x, 'edit'), req)
         forminfo = req.session.data['view?vid=edition...']
-        self.assertEquals(set(forminfo['eidmap']), set('XY'))
+        self.assertEqual(set(forminfo['eidmap']), set('XY'))
         self.assertIsInstance(forminfo['eidmap']['X'], int)
         self.assertIsInstance(forminfo['eidmap']['Y'], int)
-        self.assertEquals(forminfo['error'].entity, forminfo['eidmap']['X'])
-        self.assertEquals(forminfo['error'].errors,
+        self.assertEqual(forminfo['error'].entity, forminfo['eidmap']['X'])
+        self.assertEqual(forminfo['error'].errors,
                           {'login-subject': u'the value "admin" is already used, use another one'})
-        self.assertEquals(forminfo['values'], req.form)
+        self.assertEqual(forminfo['values'], req.form)
 
 
     def _test_cleaned(self, kwargs, injected, cleaned):
@@ -282,24 +282,24 @@
         # protocol
         vreg = self.app.vreg
         # default value
-        self.assertEquals(vreg.property_value('ui.language'), 'en')
+        self.assertEqual(vreg.property_value('ui.language'), 'en')
         self.execute('INSERT CWProperty X: X value "fr", X pkey "ui.language"')
-        self.assertEquals(vreg.property_value('ui.language'), 'en')
+        self.assertEqual(vreg.property_value('ui.language'), 'en')
         self.commit()
-        self.assertEquals(vreg.property_value('ui.language'), 'fr')
+        self.assertEqual(vreg.property_value('ui.language'), 'fr')
         self.execute('SET X value "de" WHERE X pkey "ui.language"')
-        self.assertEquals(vreg.property_value('ui.language'), 'fr')
+        self.assertEqual(vreg.property_value('ui.language'), 'fr')
         self.commit()
-        self.assertEquals(vreg.property_value('ui.language'), 'de')
+        self.assertEqual(vreg.property_value('ui.language'), 'de')
         self.execute('DELETE CWProperty X WHERE X pkey "ui.language"')
-        self.assertEquals(vreg.property_value('ui.language'), 'de')
+        self.assertEqual(vreg.property_value('ui.language'), 'de')
         self.commit()
-        self.assertEquals(vreg.property_value('ui.language'), 'en')
+        self.assertEqual(vreg.property_value('ui.language'), 'en')
 
     def test_login_not_available_to_authenticated(self):
         req = self.request()
         ex = self.assertRaises(Unauthorized, self.app_publish, req, 'login')
-        self.assertEquals(str(ex), 'log out first')
+        self.assertEqual(str(ex), 'log out first')
 
     def test_fb_login_concept(self):
         """see data/views.py"""
@@ -311,7 +311,7 @@
         req.form['__fblogin'] = u'turlututu'
         page = self.app_publish(req)
         self.failIf(req.cnx is origcnx)
-        self.assertEquals(req.user.login, 'turlututu')
+        self.assertEqual(req.user.login, 'turlututu')
         self.failUnless('turlututu' in page, page)
 
     # authentication tests ####################################################
@@ -320,13 +320,13 @@
         req, origsession = self.init_authentication('http')
         self.assertAuthFailure(req)
         self.assertRaises(AuthenticationError, self.app_publish, req, 'login')
-        self.assertEquals(req.cnx, None)
+        self.assertEqual(req.cnx, None)
         authstr = base64.encodestring('%s:%s' % (origsession.login, origsession.authinfo['password']))
         req._headers['Authorization'] = 'basic %s' % authstr
         self.assertAuthSuccess(req, origsession)
-        self.assertEquals(req.session.authinfo, {'password': origsession.authinfo['password']})
+        self.assertEqual(req.session.authinfo, {'password': origsession.authinfo['password']})
         self.assertRaises(LogOut, self.app_publish, req, 'logout')
-        self.assertEquals(len(self.open_sessions), 0)
+        self.assertEqual(len(self.open_sessions), 0)
 
     def test_cookie_auth_no_anon(self):
         req, origsession = self.init_authentication('cookie')
@@ -334,13 +334,13 @@
         form = self.app_publish(req, 'login')
         self.failUnless('__login' in form)
         self.failUnless('__password' in form)
-        self.assertEquals(req.cnx, None)
+        self.assertEqual(req.cnx, None)
         req.form['__login'] = origsession.login
         req.form['__password'] = origsession.authinfo['password']
         self.assertAuthSuccess(req, origsession)
-        self.assertEquals(req.session.authinfo, {'password': origsession.authinfo['password']})
+        self.assertEqual(req.session.authinfo, {'password': origsession.authinfo['password']})
         self.assertRaises(LogOut, self.app_publish, req, 'logout')
-        self.assertEquals(len(self.open_sessions), 0)
+        self.assertEqual(len(self.open_sessions), 0)
 
     def test_login_by_email(self):
         login = self.request().user.login
@@ -359,9 +359,9 @@
         req.form['__login'] = address
         req.form['__password'] = origsession.authinfo['password']
         self.assertAuthSuccess(req, origsession)
-        self.assertEquals(req.session.authinfo, {'password': origsession.authinfo['password']})
+        self.assertEqual(req.session.authinfo, {'password': origsession.authinfo['password']})
         self.assertRaises(LogOut, self.app_publish, req, 'logout')
-        self.assertEquals(len(self.open_sessions), 0)
+        self.assertEqual(len(self.open_sessions), 0)
 
     def _reset_cookie(self, req):
         # preparing the suite of the test
@@ -376,18 +376,18 @@
     def _test_auth_anon(self, req):
         self.app.connect(req)
         asession = req.session
-        self.assertEquals(len(self.open_sessions), 1)
-        self.assertEquals(asession.login, 'anon')
-        self.assertEquals(asession.authinfo['password'], 'anon')
+        self.assertEqual(len(self.open_sessions), 1)
+        self.assertEqual(asession.login, 'anon')
+        self.assertEqual(asession.authinfo['password'], 'anon')
         self.failUnless(asession.anonymous_session)
         self._reset_cookie(req)
 
     def _test_anon_auth_fail(self, req):
-        self.assertEquals(len(self.open_sessions), 1)
+        self.assertEqual(len(self.open_sessions), 1)
         self.app.connect(req)
-        self.assertEquals(req.message, 'authentication failure')
-        self.assertEquals(req.session.anonymous_session, True)
-        self.assertEquals(len(self.open_sessions), 1)
+        self.assertEqual(req.message, 'authentication failure')
+        self.assertEqual(req.session.anonymous_session, True)
+        self.assertEqual(len(self.open_sessions), 1)
         self._reset_cookie(req)
 
     def test_http_auth_anon_allowed(self):
@@ -399,9 +399,9 @@
         authstr = base64.encodestring('%s:%s' % (origsession.login, origsession.authinfo['password']))
         req._headers['Authorization'] = 'basic %s' % authstr
         self.assertAuthSuccess(req, origsession)
-        self.assertEquals(req.session.authinfo, {'password': origsession.authinfo['password']})
+        self.assertEqual(req.session.authinfo, {'password': origsession.authinfo['password']})
         self.assertRaises(LogOut, self.app_publish, req, 'logout')
-        self.assertEquals(len(self.open_sessions), 0)
+        self.assertEqual(len(self.open_sessions), 0)
 
     def test_cookie_auth_anon_allowed(self):
         req, origsession = self.init_authentication('cookie', 'anon')
@@ -412,10 +412,10 @@
         req.form['__login'] = origsession.login
         req.form['__password'] = origsession.authinfo['password']
         self.assertAuthSuccess(req, origsession)
-        self.assertEquals(req.session.authinfo,
+        self.assertEqual(req.session.authinfo,
                           {'password': origsession.authinfo['password']})
         self.assertRaises(LogOut, self.app_publish, req, 'logout')
-        self.assertEquals(len(self.open_sessions), 0)
+        self.assertEqual(len(self.open_sessions), 0)
 
     def test_non_regr_optional_first_var(self):
         req = self.request()
--- a/web/test/unittest_breadcrumbs.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_breadcrumbs.py	Fri Sep 24 18:20:59 2010 +0200
@@ -28,11 +28,11 @@
         self.execute('SET F2 filed_under F1 WHERE F1 eid %(f1)s, F2 eid %(f2)s',
                      {'f1' : f1.eid, 'f2' : f2.eid})
         self.commit()
-        self.assertEquals(f2.view('breadcrumbs'),
+        self.assertEqual(f2.view('breadcrumbs'),
                           '<a href="http://testing.fr/cubicweb/folder/%s" title="">chi&amp;ld</a>' % f2.eid)
         childrset = f2.as_rset()
         ibc = self.vreg['components'].select('breadcrumbs', self.request(), rset=childrset)
-        self.assertEquals(ibc.render(),
+        self.assertEqual(ibc.render(),
                           """<span id="breadcrumbs" class="pathbar">&#160;&gt;&#160;<a href="http://testing.fr/cubicweb/Folder">folder_plural</a>&#160;&gt;&#160;<a href="http://testing.fr/cubicweb/folder/%s" title="">par&amp;ent</a>&#160;&gt;&#160;
 <a href="http://testing.fr/cubicweb/folder/%s" title="">chi&amp;ld</a></span>""" % (f1.eid, f2.eid))
 
--- a/web/test/unittest_facet.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_facet.py	Fri Sep 24 18:20:59 2010 +0200
@@ -9,9 +9,9 @@
         rqlst = rset.syntax_tree().copy()
         req.vreg.rqlhelper.annotate(rqlst)
         mainvar, baserql = facet.prepare_facets_rqlst(rqlst, rset.args)
-        self.assertEquals(mainvar.name, 'X')
-        self.assertEquals(baserql, 'Any X WHERE X is CWUser')
-        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
+        self.assertEqual(mainvar.name, 'X')
+        self.assertEqual(baserql, 'Any X WHERE X is CWUser')
+        self.assertEqual(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
         return req, rset, rqlst, mainvar
 
     def test_relation_simple(self):
@@ -24,20 +24,20 @@
         f.target_attr = 'name'
         guests, managers = [eid for eid, in self.execute('CWGroup G ORDERBY GN '
                                                          'WHERE G name GN, G name IN ("guests", "managers")')]
-        self.assertEquals(f.vocabulary(),
+        self.assertEqual(f.vocabulary(),
                           [(u'guests', guests), (u'managers', managers)])
         # ensure rqlst is left unmodified
-        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
+        self.assertEqual(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
         #rqlst = rset.syntax_tree()
-        self.assertEquals(f.possible_values(),
+        self.assertEqual(f.possible_values(),
                           [str(guests), str(managers)])
         # ensure rqlst is left unmodified
-        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
+        self.assertEqual(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
         req.form[f.__regid__] = str(guests)
         f.add_rql_restrictions()
         # selection is cluttered because rqlst has been prepared for facet (it
         # is not in real life)
-        self.assertEquals(f.rqlst.as_string(),
+        self.assertEqual(f.rqlst.as_string(),
                           'DISTINCT Any  WHERE X is CWUser, X in_group D, D eid %s' % guests)
 
     def test_relation_optional_rel(self):
@@ -56,20 +56,20 @@
         f.target_attr = 'name'
         guests, managers = [eid for eid, in self.execute('CWGroup G ORDERBY GN '
                                                          'WHERE G name GN, G name IN ("guests", "managers")')]
-        self.assertEquals(f.vocabulary(),
+        self.assertEqual(f.vocabulary(),
                           [(u'guests', guests), (u'managers', managers)])
         # ensure rqlst is left unmodified
-        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  GROUPBY X WHERE X in_group G?, G name GN, NOT G name "users"')
+        self.assertEqual(rqlst.as_string(), 'DISTINCT Any  GROUPBY X WHERE X in_group G?, G name GN, NOT G name "users"')
         #rqlst = rset.syntax_tree()
-        self.assertEquals(sorted(f.possible_values()),
+        self.assertEqual(sorted(f.possible_values()),
                           [str(guests), str(managers)])
         # ensure rqlst is left unmodified
-        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  GROUPBY X WHERE X in_group G?, G name GN, NOT G name "users"')
+        self.assertEqual(rqlst.as_string(), 'DISTINCT Any  GROUPBY X WHERE X in_group G?, G name GN, NOT G name "users"')
         req.form[f.__regid__] = str(guests)
         f.add_rql_restrictions()
         # selection is cluttered because rqlst has been prepared for facet (it
         # is not in real life)
-        self.assertEquals(f.rqlst.as_string(),
+        self.assertEqual(f.rqlst.as_string(),
                           'DISTINCT Any  GROUPBY X WHERE X in_group G?, G name GN, NOT G name "users", X in_group D, D eid %s' % guests)
 
 
@@ -81,20 +81,20 @@
         f.rtype = 'in_group'
         f.role = 'subject'
         f.target_attr = 'name'
-        self.assertEquals(f.vocabulary(),
+        self.assertEqual(f.vocabulary(),
                           [(u'guests', u'guests'), (u'managers', u'managers')])
         # ensure rqlst is left unmodified
-        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
+        self.assertEqual(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
         #rqlst = rset.syntax_tree()
-        self.assertEquals(f.possible_values(),
+        self.assertEqual(f.possible_values(),
                           ['guests', 'managers'])
         # ensure rqlst is left unmodified
-        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
+        self.assertEqual(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
         req.form[f.__regid__] = 'guests'
         f.add_rql_restrictions()
         # selection is cluttered because rqlst has been prepared for facet (it
         # is not in real life)
-        self.assertEquals(f.rqlst.as_string(),
+        self.assertEqual(f.rqlst.as_string(),
                           "DISTINCT Any  WHERE X is CWUser, X in_group E, E name 'guests'")
 
 
@@ -104,18 +104,18 @@
                                  rqlst=rqlst.children[0],
                                  filtered_variable=mainvar)
         f.rtype = 'login'
-        self.assertEquals(f.vocabulary(),
+        self.assertEqual(f.vocabulary(),
                           [(u'admin', u'admin'), (u'anon', u'anon')])
         # ensure rqlst is left unmodified
-        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
+        self.assertEqual(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
         #rqlst = rset.syntax_tree()
-        self.assertEquals(f.possible_values(),
+        self.assertEqual(f.possible_values(),
                           ['admin', 'anon'])
         # ensure rqlst is left unmodified
-        self.assertEquals(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
+        self.assertEqual(rqlst.as_string(), 'DISTINCT Any  WHERE X is CWUser')
         req.form[f.__regid__] = 'admin'
         f.add_rql_restrictions()
         # selection is cluttered because rqlst has been prepared for facet (it
         # is not in real life)
-        self.assertEquals(f.rqlst.as_string(),
+        self.assertEqual(f.rqlst.as_string(),
                           "DISTINCT Any  WHERE X is CWUser, X login 'admin'")
--- a/web/test/unittest_form.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_form.py	Fri Sep 24 18:20:59 2010 +0200
@@ -36,10 +36,10 @@
 
     def test_form_field_format(self):
         form = FieldsForm(self.request(), None)
-        self.assertEquals(StringField().format(form), 'text/html')
+        self.assertEqual(StringField().format(form), 'text/html')
         self.execute('INSERT CWProperty X: X pkey "ui.default-text-format", X value "text/rest", X for_user U WHERE U login "admin"')
         self.commit()
-        self.assertEquals(StringField().format(form), 'text/rest')
+        self.assertEqual(StringField().format(form), 'text/rest')
 
 
 class EntityFieldsFormTC(CubicWebTC):
@@ -70,7 +70,7 @@
         form = self.vreg['forms'].select('edition', self.req, entity=e)
         unrelated = [rview for rview, reid in form.field_by_name('in_group', 'subject').choices(form)]
         # should be default groups but owners, i.e. managers, users, guests
-        self.assertEquals(unrelated, [u'guests', u'managers', u'users'])
+        self.assertEqual(unrelated, [u'guests', u'managers', u'users'])
 
     def test_consider_req_form_params(self):
         e = self.vreg['etypes'].etype_class('CWUser')(self.request())
@@ -79,7 +79,7 @@
         field = StringField(name='login', role='subject', eidparam=True)
         form.append_field(field)
         form.build_context({})
-        self.assertEquals(field.widget.values(form, field), (u'toto',))
+        self.assertEqual(field.widget.values(form, field), (u'toto',))
 
 
     def test_linkto_field_duplication(self):
@@ -144,7 +144,7 @@
         form = RTFForm(self.req, redirect_path='perdu.com', entity=state)
         # make it think it can use fck editor anyway
         form.field_by_name('description', 'subject').format = lambda x: 'text/html'
-        self.assertTextEquals(self._render_entity_field('description', form),
+        self.assertMultiLineEqual(self._render_entity_field('description', form),
                               expected % {'eid': state.eid})
 
 
@@ -174,7 +174,7 @@
         file = self.req.create_entity('File', data_name=u"pouet.txt", data_encoding=u'UTF-8',
                                data=Binary('new widgets system'))
         form = FFForm(self.req, redirect_path='perdu.com', entity=file)
-        self.assertTextEquals(self._render_entity_field('data', form),
+        self.assertMultiLineEqual(self._render_entity_field('data', form),
                               '''<input id="data-subject:%(eid)s" name="data-subject:%(eid)s" tabindex="1" type="file" value="" />
 <a href="javascript: toggleVisibility(&#39;data-subject:%(eid)s-advanced&#39;)" title="show advanced fields"><img src="http://testing.fr/cubicweb/data/puce_down.png" alt="show advanced fields"/></a>
 <div id="data-subject:%(eid)s-advanced" class="hidden">
@@ -183,8 +183,7 @@
 </div>
 <br/>
 <input name="data-subject__detach:%(eid)s" type="checkbox" />
-detach attached file
-''' % {'eid': file.eid})
+detach attached file''' % {'eid': file.eid})
 
 
     def test_editablefilefield(self):
@@ -198,7 +197,7 @@
         file = self.req.create_entity('File', data_name=u"pouet.txt", data_encoding=u'UTF-8',
                                data=Binary('new widgets system'))
         form = EFFForm(self.req, redirect_path='perdu.com', entity=file)
-        self.assertTextEquals(self._render_entity_field('data', form),
+        self.assertMultiLineEqual(self._render_entity_field('data', form),
                               '''<input id="data-subject:%(eid)s" name="data-subject:%(eid)s" tabindex="1" type="file" value="" />
 <a href="javascript: toggleVisibility(&#39;data-subject:%(eid)s-advanced&#39;)" title="show advanced fields"><img src="http://testing.fr/cubicweb/data/puce_down.png" alt="show advanced fields"/></a>
 <div id="data-subject:%(eid)s-advanced" class="hidden">
@@ -216,7 +215,7 @@
         class PFForm(EntityFieldsForm):
             upassword = PasswordField(eidparam=True, role='subject')
         form = PFForm(self.req, redirect_path='perdu.com', entity=self.entity)
-        self.assertTextEquals(self._render_entity_field('upassword', form),
+        self.assertMultiLineEqual(self._render_entity_field('upassword', form),
                               '''<input id="upassword-subject:%(eid)s" name="upassword-subject:%(eid)s" tabindex="1" type="password" value="" />
 <br/>
 <input name="upassword-subject-confirm:%(eid)s" tabindex="1" type="password" value="" />
@@ -230,7 +229,7 @@
     #     form = DFForm(self.req, entity=self.entity)
     #     init, cur = (fromstring(self._render_entity_field(attr, form)).get('value')
     #                  for attr in ('edits-creation_date', 'creation_date'))
-    #     self.assertEquals(init, cur)
+    #     self.assertEqual(init, cur)
 
 if __name__ == '__main__':
     unittest_main()
--- a/web/test/unittest_formfields.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_formfields.py	Fri Sep 24 18:20:59 2010 +0200
@@ -38,64 +38,64 @@
     def test_state_fields(self):
         title_field = guess_field(schema['State'], schema['name'])
         self.assertIsInstance(title_field, StringField)
-        self.assertEquals(title_field.required, True)
+        self.assertEqual(title_field.required, True)
 
 #         synopsis_field = guess_field(schema['State'], schema['synopsis'])
 #         self.assertIsInstance(synopsis_field, StringField)
 #         self.assertIsInstance(synopsis_field.widget, TextArea)
-#         self.assertEquals(synopsis_field.required, False)
-#         self.assertEquals(synopsis_field.help, 'an abstract for this state')
+#         self.assertEqual(synopsis_field.required, False)
+#         self.assertEqual(synopsis_field.help, 'an abstract for this state')
 
         description_field = guess_field(schema['State'], schema['description'])
         self.assertIsInstance(description_field, RichTextField)
-        self.assertEquals(description_field.required, False)
-        self.assertEquals(description_field.format_field, None)
+        self.assertEqual(description_field.required, False)
+        self.assertEqual(description_field.format_field, None)
 
         # description_format_field = guess_field(schema['State'], schema['description_format'])
-        # self.assertEquals(description_format_field, None)
+        # self.assertEqual(description_format_field, None)
 
         description_format_field = guess_field(schema['State'], schema['description_format'])
-        self.assertEquals(description_format_field.internationalizable, True)
-        self.assertEquals(description_format_field.sort, True)
+        self.assertEqual(description_format_field.internationalizable, True)
+        self.assertEqual(description_format_field.sort, True)
 
 #         wikiid_field = guess_field(schema['State'], schema['wikiid'])
 #         self.assertIsInstance(wikiid_field, StringField)
-#         self.assertEquals(wikiid_field.required, False)
+#         self.assertEqual(wikiid_field.required, False)
 
 
     def test_cwuser_fields(self):
         upassword_field = guess_field(schema['CWUser'], schema['upassword'])
         self.assertIsInstance(upassword_field, StringField)
         self.assertIsInstance(upassword_field.widget, PasswordInput)
-        self.assertEquals(upassword_field.required, True)
+        self.assertEqual(upassword_field.required, True)
 
         last_login_time_field = guess_field(schema['CWUser'], schema['last_login_time'])
         self.assertIsInstance(last_login_time_field, DateTimeField)
-        self.assertEquals(last_login_time_field.required, False)
+        self.assertEqual(last_login_time_field.required, False)
 
         in_group_field = guess_field(schema['CWUser'], schema['in_group'])
         self.assertIsInstance(in_group_field, RelationField)
-        self.assertEquals(in_group_field.required, True)
-        self.assertEquals(in_group_field.role, 'subject')
-        self.assertEquals(in_group_field.help, 'groups grant permissions to the user')
+        self.assertEqual(in_group_field.required, True)
+        self.assertEqual(in_group_field.role, 'subject')
+        self.assertEqual(in_group_field.help, 'groups grant permissions to the user')
 
         owned_by_field = guess_field(schema['CWUser'], schema['owned_by'], 'object')
         self.assertIsInstance(owned_by_field, RelationField)
-        self.assertEquals(owned_by_field.required, False)
-        self.assertEquals(owned_by_field.role, 'object')
+        self.assertEqual(owned_by_field.required, False)
+        self.assertEqual(owned_by_field.role, 'object')
 
 
     def test_file_fields(self):
         # data_format_field = guess_field(schema['File'], schema['data_format'])
-        # self.assertEquals(data_format_field, None)
+        # self.assertEqual(data_format_field, None)
         # data_encoding_field = guess_field(schema['File'], schema['data_encoding'])
-        # self.assertEquals(data_encoding_field, None)
+        # self.assertEqual(data_encoding_field, None)
         # data_name_field = guess_field(schema['File'], schema['data_name'])
-        # self.assertEquals(data_name_field, None)
+        # self.assertEqual(data_name_field, None)
 
         data_field = guess_field(schema['File'], schema['data'])
         self.assertIsInstance(data_field, FileField)
-        self.assertEquals(data_field.required, True)
+        self.assertEqual(data_field.required, True)
         self.assertIsInstance(data_field.format_field, StringField)
         self.assertIsInstance(data_field.encoding_field, StringField)
         self.assertIsInstance(data_field.name_field, StringField)
@@ -103,7 +103,7 @@
     def test_constraints_priority(self):
         salesterm_field = guess_field(schema['Salesterm'], schema['reason'])
         constraints = schema['reason'].rdef('Salesterm', 'String').constraints
-        self.assertEquals([c.__class__ for c in constraints],
+        self.assertEqual([c.__class__ for c in constraints],
                           [SizeConstraint, StaticVocabularyConstraint])
         self.assertIsInstance(salesterm_field, StringField)
         self.assertIsInstance(salesterm_field.widget, Select)
@@ -112,16 +112,16 @@
     def test_bool_field_base(self):
         field = guess_field(schema['CWAttribute'], schema['indexed'])
         self.assertIsInstance(field, BooleanField)
-        self.assertEquals(field.required, False)
+        self.assertEqual(field.required, False)
         self.assertIsInstance(field.widget, Radio)
-        self.assertEquals(field.vocabulary(mock(_cw=mock(_=unicode))),
+        self.assertEqual(field.vocabulary(mock(_cw=mock(_=unicode))),
                           [(u'yes', '1'), (u'no', '')])
 
     def test_bool_field_explicit_choices(self):
         field = guess_field(schema['CWAttribute'], schema['indexed'],
                             choices=[(u'maybe', '1'), (u'no', '')])
         self.assertIsInstance(field.widget, Radio)
-        self.assertEquals(field.vocabulary(mock(req=mock(_=unicode))),
+        self.assertEqual(field.vocabulary(mock(req=mock(_=unicode))),
                           [(u'maybe', '1'), (u'no', '')])
 
 
@@ -133,18 +133,18 @@
         form = EntityFieldsForm(req, entity=e)
         description_field = guess_field(schema['State'], schema['description'])
         description_format_field = description_field.get_format_field(form)
-        self.assertEquals(description_format_field.internationalizable, True)
-        self.assertEquals(description_format_field.sort, True)
+        self.assertEqual(description_format_field.internationalizable, True)
+        self.assertEqual(description_format_field.sort, True)
         # unlike below, initial is bound to form.form_field_format
-        self.assertEquals(description_format_field.value(form), 'text/html')
+        self.assertEqual(description_format_field.value(form), 'text/html')
         self.execute('INSERT CWProperty X: X pkey "ui.default-text-format", X value "text/rest", X for_user U WHERE U login "admin"')
         self.commit()
-        self.assertEquals(description_format_field.value(form), 'text/rest')
+        self.assertEqual(description_format_field.value(form), 'text/rest')
 
 
 class UtilsTC(TestCase):
     def test_vocab_sort(self):
-        self.assertEquals(vocab_sort([('Z', 1), ('A', 2),
+        self.assertEqual(vocab_sort([('Z', 1), ('A', 2),
                                       ('Group 1', None), ('Y', 3), ('B', 4),
                                       ('Group 2', None), ('X', 5), ('C', 6)]),
                           [('A', 2), ('Z', 1),
--- a/web/test/unittest_magicsearch.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_magicsearch.py	Fri Sep 24 18:20:59 2010 +0200
@@ -61,16 +61,16 @@
         """tests basic translations (no ambiguities)"""
         rql = "Any C WHERE C is Adresse, P adel C, C adresse 'Logilab'"
         rql, = self.proc.preprocess_query(rql)
-        self.assertEquals(rql, "Any C WHERE C is EmailAddress, P use_email C, C address 'Logilab'")
+        self.assertEqual(rql, "Any C WHERE C is EmailAddress, P use_email C, C address 'Logilab'")
 
     def test_ambiguous_translations(self):
         """tests possibly ambiguous translations"""
         rql = "Any P WHERE P adel C, C is EmailAddress, C nom 'Logilab'"
         rql, = self.proc.preprocess_query(rql)
-        self.assertEquals(rql, "Any P WHERE P use_email C, C is EmailAddress, C alias 'Logilab'")
+        self.assertEqual(rql, "Any P WHERE P use_email C, C is EmailAddress, C alias 'Logilab'")
         rql = "Any P WHERE P is Utilisateur, P adel C, P nom 'Smith'"
         rql, = self.proc.preprocess_query(rql)
-        self.assertEquals(rql, "Any P WHERE P is CWUser, P use_email C, P surname 'Smith'")
+        self.assertEqual(rql, "Any P WHERE P is CWUser, P use_email C, P surname 'Smith'")
 
 
 class QSPreProcessorTC(CubicWebTC):
@@ -86,21 +86,21 @@
     def test_entity_translation(self):
         """tests QSPreProcessor._get_entity_name()"""
         translate = self.proc._get_entity_type
-        self.assertEquals(translate(u'EmailAddress'), "EmailAddress")
-        self.assertEquals(translate(u'emailaddress'), "EmailAddress")
-        self.assertEquals(translate(u'Adresse'), "EmailAddress")
-        self.assertEquals(translate(u'adresse'), "EmailAddress")
+        self.assertEqual(translate(u'EmailAddress'), "EmailAddress")
+        self.assertEqual(translate(u'emailaddress'), "EmailAddress")
+        self.assertEqual(translate(u'Adresse'), "EmailAddress")
+        self.assertEqual(translate(u'adresse'), "EmailAddress")
         self.assertRaises(BadRQLQuery, translate, 'whatever')
 
     def test_attribute_translation(self):
         """tests QSPreProcessor._get_attribute_name"""
         translate = self.proc._get_attribute_name
         eschema = self.schema.eschema('CWUser')
-        self.assertEquals(translate(u'prénom', eschema), "firstname")
-        self.assertEquals(translate(u'nom', eschema), 'surname')
+        self.assertEqual(translate(u'prénom', eschema), "firstname")
+        self.assertEqual(translate(u'nom', eschema), 'surname')
         eschema = self.schema.eschema('EmailAddress')
-        self.assertEquals(translate(u'adresse', eschema), "address")
-        self.assertEquals(translate(u'nom', eschema), 'alias')
+        self.assertEqual(translate(u'adresse', eschema), "address")
+        self.assertEqual(translate(u'nom', eschema), 'alias')
         # should fail if the name is not an attribute for the given entity schema
         self.assertRaises(BadRQLQuery, translate, 'whatever', eschema)
         self.assertRaises(BadRQLQuery, translate, 'prénom', eschema)
@@ -108,50 +108,50 @@
     def test_one_word_query(self):
         """tests the 'one word shortcut queries'"""
         transform = self.proc._one_word_query
-        self.assertEquals(transform('123'),
+        self.assertEqual(transform('123'),
                           ('Any X WHERE X eid %(x)s', {'x': 123}, 'x'))
-        self.assertEquals(transform('CWUser'),
+        self.assertEqual(transform('CWUser'),
                           ('CWUser C',))
-        self.assertEquals(transform('Utilisateur'),
+        self.assertEqual(transform('Utilisateur'),
                           ('CWUser C',))
-        self.assertEquals(transform('Adresse'),
+        self.assertEqual(transform('Adresse'),
                           ('EmailAddress E',))
-        self.assertEquals(transform('adresse'),
+        self.assertEqual(transform('adresse'),
                           ('EmailAddress E',))
         self.assertRaises(BadRQLQuery, transform, 'Workcases')
 
     def test_two_words_query(self):
         """tests the 'two words shortcut queries'"""
         transform = self.proc._two_words_query
-        self.assertEquals(transform('CWUser', 'E'),
+        self.assertEqual(transform('CWUser', 'E'),
                           ("CWUser E",))
-        self.assertEquals(transform('CWUser', 'Smith'),
+        self.assertEqual(transform('CWUser', 'Smith'),
                           ('CWUser C ORDERBY FTIRANK(C) DESC WHERE C has_text %(text)s', {'text': 'Smith'}))
-        self.assertEquals(transform('utilisateur', 'Smith'),
+        self.assertEqual(transform('utilisateur', 'Smith'),
                           ('CWUser C ORDERBY FTIRANK(C) DESC WHERE C has_text %(text)s', {'text': 'Smith'}))
-        self.assertEquals(transform(u'adresse', 'Logilab'),
+        self.assertEqual(transform(u'adresse', 'Logilab'),
                           ('EmailAddress E ORDERBY FTIRANK(E) DESC WHERE E has_text %(text)s', {'text': 'Logilab'}))
-        self.assertEquals(transform(u'adresse', 'Logi%'),
+        self.assertEqual(transform(u'adresse', 'Logi%'),
                           ('EmailAddress E WHERE E alias LIKE %(text)s', {'text': 'Logi%'}))
         self.assertRaises(BadRQLQuery, transform, "pers", "taratata")
 
     def test_three_words_query(self):
         """tests the 'three words shortcut queries'"""
         transform = self.proc._three_words_query
-        self.assertEquals(transform('utilisateur', u'prénom', 'cubicweb'),
+        self.assertEqual(transform('utilisateur', u'prénom', 'cubicweb'),
                           ('CWUser C WHERE C firstname %(text)s', {'text': 'cubicweb'}))
-        self.assertEquals(transform('utilisateur', 'nom', 'cubicweb'),
+        self.assertEqual(transform('utilisateur', 'nom', 'cubicweb'),
                           ('CWUser C WHERE C surname %(text)s', {'text': 'cubicweb'}))
-        self.assertEquals(transform(u'adresse', 'nom', 'cubicweb'),
+        self.assertEqual(transform(u'adresse', 'nom', 'cubicweb'),
                           ('EmailAddress E WHERE E alias %(text)s', {'text': 'cubicweb'}))
-        self.assertEquals(transform('EmailAddress', 'nom', 'cubicweb'),
+        self.assertEqual(transform('EmailAddress', 'nom', 'cubicweb'),
                           ('EmailAddress E WHERE E alias %(text)s', {'text': 'cubicweb'}))
-        self.assertEquals(transform('utilisateur', u'prénom', 'cubicweb%'),
+        self.assertEqual(transform('utilisateur', u'prénom', 'cubicweb%'),
                           ('CWUser C WHERE C firstname LIKE %(text)s', {'text': 'cubicweb%'}))
         # expanded shortcuts
-        self.assertEquals(transform('CWUser', 'use_email', 'Logilab'),
+        self.assertEqual(transform('CWUser', 'use_email', 'Logilab'),
                           ('CWUser C ORDERBY FTIRANK(C1) DESC WHERE C use_email C1, C1 has_text %(text)s', {'text': 'Logilab'}))
-        self.assertEquals(transform('CWUser', 'use_email', '%Logilab'),
+        self.assertEqual(transform('CWUser', 'use_email', '%Logilab'),
                           ('CWUser C WHERE C use_email C1, C1 alias LIKE %(text)s', {'text': '%Logilab'}))
         self.assertRaises(BadRQLQuery, transform, 'word1', 'word2', 'word3')
 
@@ -165,7 +165,7 @@
             ]
         transform = self.proc._quoted_words_query
         for query, expected in queries:
-            self.assertEquals(transform(query), expected)
+            self.assertEqual(transform(query), expected)
         self.assertRaises(BadRQLQuery, transform, "unquoted rql")
         self.assertRaises(BadRQLQuery, transform, 'pers "Jean Paul"')
         self.assertRaises(BadRQLQuery, transform, 'CWUser firstname other "Jean Paul"')
@@ -179,7 +179,7 @@
             (u'CWUser prénom cubicweb', (u'CWUser C WHERE C firstname %(text)s', {'text': 'cubicweb'},)),
             ]
         for query, expected in queries:
-            self.assertEquals(self.proc.preprocess_query(query), expected)
+            self.assertEqual(self.proc.preprocess_query(query), expected)
         self.assertRaises(BadRQLQuery,
                           self.proc.preprocess_query, 'Any X WHERE X is Something')
 
@@ -213,13 +213,13 @@
             ]
         for query, expected in queries:
             rset = self.proc.process_query(query)
-            self.assertEquals((rset.rql, rset.args), expected)
+            self.assertEqual((rset.rql, rset.args), expected)
 
     def test_accentuated_fulltext(self):
         """we must be able to type accentuated characters in the search field"""
         rset = self.proc.process_query(u'écrire')
-        self.assertEquals(rset.rql, "Any X ORDERBY FTIRANK(X) DESC WHERE X has_text %(text)s")
-        self.assertEquals(rset.args, {'text': u'écrire'})
+        self.assertEqual(rset.rql, "Any X ORDERBY FTIRANK(X) DESC WHERE X has_text %(text)s")
+        self.assertEqual(rset.args, {'text': u'écrire'})
 
     def test_explicit_component(self):
         self.assertRaises(RQLSyntaxError,
@@ -227,8 +227,8 @@
         self.assertRaises(BadRQLQuery,
                           self.proc.process_query, u'rql: CWUser E WHERE E noattr "Smith"')
         rset = self.proc.process_query(u'text: utilisateur Smith')
-        self.assertEquals(rset.rql, 'Any X ORDERBY FTIRANK(X) DESC WHERE X has_text %(text)s')
-        self.assertEquals(rset.args, {'text': u'utilisateur Smith'})
+        self.assertEqual(rset.rql, 'Any X ORDERBY FTIRANK(X) DESC WHERE X has_text %(text)s')
+        self.assertEqual(rset.args, {'text': u'utilisateur Smith'})
 
 if __name__ == '__main__':
     unittest_main()
--- a/web/test/unittest_propertysheet.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_propertysheet.py	Fri Sep 24 18:20:59 2010 +0200
@@ -19,21 +19,21 @@
         ps.load(join(DATADIR, 'sheet1.py'))
         ps.load(join(DATADIR, 'sheet2.py'))
         # defined by sheet1
-        self.assertEquals(ps['logo'], 'http://cwtest.com/logo.png')
+        self.assertEqual(ps['logo'], 'http://cwtest.com/logo.png')
         # defined by sheet1, overriden by sheet2
-        self.assertEquals(ps['bgcolor'], '#FFFFFF')
+        self.assertEqual(ps['bgcolor'], '#FFFFFF')
         # defined by sheet2
-        self.assertEquals(ps['fontcolor'], 'black')
+        self.assertEqual(ps['fontcolor'], 'black')
         # defined by sheet1, extended by sheet2
-        self.assertEquals(ps['stylesheets'], ['http://cwtest.com/cubicweb.css',
+        self.assertEqual(ps['stylesheets'], ['http://cwtest.com/cubicweb.css',
                                               'http://cwtest.com/mycube.css'])
         # lazy string defined by sheet1
         self.assertIsInstance(ps['lazy'], lazystr)
-        self.assertEquals(str(ps['lazy']), '#FFFFFF')
+        self.assertEqual(str(ps['lazy']), '#FFFFFF')
         # test compilation
-        self.assertEquals(ps.compile('a {bgcolor: %(bgcolor)s; size: 1%;}'),
+        self.assertEqual(ps.compile('a {bgcolor: %(bgcolor)s; size: 1%;}'),
                           'a {bgcolor: #FFFFFF; size: 1%;}')
-        self.assertEquals(ps.process_resource(DATADIR, 'pouet.css'),
+        self.assertEqual(ps.process_resource(DATADIR, 'pouet.css'),
                           CACHEDIR)
         self.failUnless('pouet.css' in ps._cache)
         self.failIf(ps.need_reload())
--- a/web/test/unittest_reledit.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_reledit.py	Fri Sep 24 18:20:59 2010 +0200
@@ -43,7 +43,7 @@
             if rschema not in reledit:
                 continue
             rtype = rschema.type
-            self.assertTextEquals(reledit[rtype] % {'eid': self.proj.eid}, self.proj.view('reledit', rtype=rtype, role=role), rtype)
+            self.assertMultiLineEqual(reledit[rtype] % {'eid': self.proj.eid}, self.proj.view('reledit', rtype=rtype, role=role), rtype)
 
     def test_default_forms(self):
         doreledit = {'title': """<div id="title-subject-%(eid)s-reledit" onmouseout="jQuery('#title-subject-%(eid)s').addClass('hidden')" onmouseover="jQuery('#title-subject-%(eid)s').removeClass('hidden')" class="releditField"><div id="title-subject-%(eid)s-value" class="editableFieldValue">cubicweb-world-domination</div><form action="http://testing.fr/cubicweb/validateform?__onsuccess=window.parent.cw.reledit.onSuccess" method="post" enctype="application/x-www-form-urlencoded" id="title-subject-%(eid)s-form" onsubmit="return freezeFormButtons(&#39;title-subject-%(eid)s-form&#39;);" class="releditForm" cubicweb:target="eformframe">
@@ -177,7 +177,7 @@
             if rschema not in doreledit:
                 continue
             rtype = rschema.type
-            self.assertTextEquals(doreledit[rtype] % {'eid': self.proj.eid, 'toto': self.toto.eid},
+            self.assertMultiLineEqual(doreledit[rtype] % {'eid': self.proj.eid, 'toto': self.toto.eid},
                                   self.proj.view('doreledit', rtype=rtype, role=role,
                                                  formid='edition' if rtype == 'long_desc' else 'base'),
                                   rtype)
@@ -213,7 +213,7 @@
             if rschema not in reledit:
                 continue
             rtype = rschema.type
-            self.assertTextEquals(reledit[rtype] % {'eid': self.proj.eid, 'toto': self.toto.eid, 'tick': self.tick.eid},
+            self.assertMultiLineEqual(reledit[rtype] % {'eid': self.proj.eid, 'toto': self.toto.eid, 'tick': self.tick.eid},
                                   self.proj.view('reledit', rtype=rtype, role=role),
                                   rtype)
         reledit_ctrl.clear()
--- a/web/test/unittest_session.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_session.py	Fri Sep 24 18:20:59 2010 +0200
@@ -15,8 +15,8 @@
         # make is if the web session has been opened by the session manager
         sm._sessions[self.cnx.sessionid] = self.websession
         sessionid = self.websession.sessionid
-        self.assertEquals(len(sm._sessions), 1)
-        self.assertEquals(self.websession.sessionid, self.websession.cnx.sessionid)
+        self.assertEqual(len(sm._sessions), 1)
+        self.assertEqual(self.websession.sessionid, self.websession.cnx.sessionid)
         # fake the repo session is expiring
         self.repo.close(sessionid)
         try:
@@ -24,9 +24,9 @@
             # don't use self.request() which try to call req.set_session
             req = self.requestcls(self.vreg)
             websession = sm.get_session(req, sessionid)
-            self.assertEquals(len(sm._sessions), 1)
+            self.assertEqual(len(sm._sessions), 1)
             self.assertIs(websession, self.websession)
-            self.assertEquals(websession.sessionid, sessionid)
+            self.assertEqual(websession.sessionid, sessionid)
             self.assertNotEquals(websession.sessionid, websession.cnx.sessionid)
         finally:
             # avoid error in tearDown by telling this connection is closed...
--- a/web/test/unittest_uicfg.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_uicfg.py	Fri Sep 24 18:20:59 2010 +0200
@@ -62,7 +62,7 @@
     def test_definition_order_hidden(self):
         result = uicfg.autoform_section.get('CWUser', 'login', 'String', 'subject')
         expected = set(['main_inlined', 'muledit_attributes', 'inlined_attributes'])
-        self.assertSetEquals(result, expected)
+        self.assertSetEqual(result, expected)
 
     def tearDown(self):
         super(DefinitionOrderTC, self).tearDown()
--- a/web/test/unittest_urlpublisher.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_urlpublisher.py	Fri Sep 24 18:20:59 2010 +0200
@@ -45,51 +45,51 @@
 
     def test_raw_path(self):
         """tests raw path resolution'"""
-        self.assertEquals(self.process('view'), ('view', None))
-        self.assertEquals(self.process('edit'), ('edit', None))
+        self.assertEqual(self.process('view'), ('view', None))
+        self.assertEqual(self.process('edit'), ('edit', None))
         self.assertRaises(NotFound, self.process, 'whatever')
 
     def test_eid_path(self):
         """tests eid path resolution"""
         self.assertIsInstance(self.process('123')[1], ResultSet)
-        self.assertEquals(len(self.process('123')[1]), 1)
+        self.assertEqual(len(self.process('123')[1]), 1)
         self.assertRaises(NotFound, self.process, '123/345')
         self.assertRaises(NotFound, self.process, 'not_eid')
 
     def test_rest_path(self):
         """tests the rest path resolution"""
         ctrl, rset = self.process('CWUser')
-        self.assertEquals(ctrl, 'view')
-        self.assertEquals(rset.description[0][0], 'CWUser')
-        self.assertEquals(rset.printable_rql(),
+        self.assertEqual(ctrl, 'view')
+        self.assertEqual(rset.description[0][0], 'CWUser')
+        self.assertEqual(rset.printable_rql(),
                           "Any X,AA,AB,AC,AD ORDERBY AA WHERE X is CWUser, X login AA, X firstname AB, X surname AC, X modification_date AD")
         ctrl, rset = self.process('CWUser/login/admin')
-        self.assertEquals(ctrl, 'view')
-        self.assertEquals(len(rset), 1)
-        self.assertEquals(rset.description[0][0], 'CWUser')
-        self.assertEquals(rset.printable_rql(), 'Any X,AA,AB,AC,AD WHERE X login "admin", X is CWUser, X login AA, X firstname AB, X surname AC, X modification_date AD')
+        self.assertEqual(ctrl, 'view')
+        self.assertEqual(len(rset), 1)
+        self.assertEqual(rset.description[0][0], 'CWUser')
+        self.assertEqual(rset.printable_rql(), 'Any X,AA,AB,AC,AD WHERE X login "admin", X is CWUser, X login AA, X firstname AB, X surname AC, X modification_date AD')
         ctrl, rset = self.process('cwuser/admin')
-        self.assertEquals(ctrl, 'view')
-        self.assertEquals(len(rset), 1)
-        self.assertEquals(rset.description[0][0], 'CWUser')
-        self.assertEquals(rset.printable_rql(), 'Any X,AA,AB,AC,AD WHERE X login "admin", X is CWUser, X login AA, X firstname AB, X surname AC, X modification_date AD')
+        self.assertEqual(ctrl, 'view')
+        self.assertEqual(len(rset), 1)
+        self.assertEqual(rset.description[0][0], 'CWUser')
+        self.assertEqual(rset.printable_rql(), 'Any X,AA,AB,AC,AD WHERE X login "admin", X is CWUser, X login AA, X firstname AB, X surname AC, X modification_date AD')
         ctrl, rset = self.process('cwuser/eid/%s'%rset[0][0])
-        self.assertEquals(ctrl, 'view')
-        self.assertEquals(len(rset), 1)
-        self.assertEquals(rset.description[0][0], 'CWUser')
-        self.assertEquals(rset.printable_rql(), 'Any X,AA,AB,AC,AD WHERE X eid 5, X is CWUser, X login AA, X firstname AB, X surname AC, X modification_date AD')
+        self.assertEqual(ctrl, 'view')
+        self.assertEqual(len(rset), 1)
+        self.assertEqual(rset.description[0][0], 'CWUser')
+        self.assertEqual(rset.printable_rql(), 'Any X,AA,AB,AC,AD WHERE X eid 5, X is CWUser, X login AA, X firstname AB, X surname AC, X modification_date AD')
         # test non-ascii paths
         ctrl, rset = self.process('CWUser/login/%C3%BFsa%C3%BFe')
-        self.assertEquals(ctrl, 'view')
-        self.assertEquals(len(rset), 1)
-        self.assertEquals(rset.description[0][0], 'CWUser')
-        self.assertEquals(rset.printable_rql(), u'Any X,AA,AB,AC,AD WHERE X login "\xffsa\xffe", X is CWUser, X login AA, X firstname AB, X surname AC, X modification_date AD')
+        self.assertEqual(ctrl, 'view')
+        self.assertEqual(len(rset), 1)
+        self.assertEqual(rset.description[0][0], 'CWUser')
+        self.assertEqual(rset.printable_rql(), u'Any X,AA,AB,AC,AD WHERE X login "\xffsa\xffe", X is CWUser, X login AA, X firstname AB, X surname AC, X modification_date AD')
         # test quoted paths
         ctrl, rset = self.process('BlogEntry/title/hell%27o')
-        self.assertEquals(ctrl, 'view')
-        self.assertEquals(len(rset), 1)
-        self.assertEquals(rset.description[0][0], 'BlogEntry')
-        self.assertEquals(rset.printable_rql(), u'Any X,AA,AB,AC WHERE X title "hell\'o", X is BlogEntry, X creation_date AA, X title AB, X modification_date AC')
+        self.assertEqual(ctrl, 'view')
+        self.assertEqual(len(rset), 1)
+        self.assertEqual(rset.description[0][0], 'BlogEntry')
+        self.assertEqual(rset.printable_rql(), u'Any X,AA,AB,AC WHERE X title "hell\'o", X is BlogEntry, X creation_date AA, X title AB, X modification_date AC')
         # errors
         self.assertRaises(NotFound, self.process, 'CWUser/eid/30000')
         self.assertRaises(NotFound, self.process, 'Workcases')
@@ -108,9 +108,9 @@
     def test_regexp_path(self):
         """tests the regexp path resolution"""
         ctrl, rset = self.process('add/Task')
-        self.assertEquals(ctrl, 'view')
-        self.assertEquals(rset, None)
-        self.assertEquals(self.req.form, {'etype' : "Task", 'vid' : "creation"})
+        self.assertEqual(ctrl, 'view')
+        self.assertEqual(rset, None)
+        self.assertEqual(self.req.form, {'etype' : "Task", 'vid' : "creation"})
         self.assertRaises(NotFound, self.process, 'add/foo/bar')
 
 
@@ -120,8 +120,8 @@
         try:
             path = str(FakeRequest().url_quote(u'été'))
             ctrl, rset = self.process(path)
-            self.assertEquals(rset, None)
-            self.assertEquals(self.req.form, {'vid' : "foo"})
+            self.assertEqual(rset, None)
+            self.assertEqual(self.req.form, {'vid' : "foo"})
         finally:
             SimpleReqRewriter.rules = oldrules
 
--- a/web/test/unittest_urlrewrite.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_urlrewrite.py	Fri Sep 24 18:20:59 2010 +0200
@@ -39,7 +39,7 @@
             if hasattr(pattern, 'pattern'):
                 pattern = pattern.pattern
             rules.append((pattern, values))
-        self.assertListEquals(rules, [
+        self.assertListEqual(rules, [
             ('foo' , dict(rql='Foo F')),
             ('/index' , dict(vid='index2')),
             ('/_', dict(vid='manage')),
@@ -71,7 +71,7 @@
                 ('foo', dict(rql='Foo F')),
                 ('/index', dict(vid='index2')),
                 ]
-        self.assertListEquals(Rewriter.rules, [
+        self.assertListEqual(Rewriter.rules, [
             ('foo' , dict(rql='Foo F')),
             ('/index' , dict(vid='index2')),
             ])
@@ -81,19 +81,19 @@
         req = FakeRequest()
         rewriter = SimpleReqRewriter(req)
         self.assertRaises(KeyError, rewriter.rewrite, req, '/view?vid=whatever')
-        self.assertEquals(req.form, {})
+        self.assertEqual(req.form, {})
         rewriter.rewrite(req, '/index')
-        self.assertEquals(req.form, {'vid' : "index"})
+        self.assertEqual(req.form, {'vid' : "index"})
 
     def test_regexp_transformation(self):
         """test regexp-based rewrite"""
         req = FakeRequest()
         rewriter = SimpleReqRewriter(req)
         rewriter.rewrite(req, '/add/Task')
-        self.assertEquals(req.form, {'vid' : "creation", 'etype' : "Task"})
+        self.assertEqual(req.form, {'vid' : "creation", 'etype' : "Task"})
         req = FakeRequest()
         rewriter.rewrite(req, '/add/Task/')
-        self.assertEquals(req.form, {'vid' : "creation", 'etype' : "Task"})
+        self.assertEqual(req.form, {'vid' : "creation", 'etype' : "Task"})
 
 
 
@@ -117,8 +117,8 @@
         req = self.request()
         rewriter = TestSchemaBasedRewriter(req)
         pmid, rset = rewriter.rewrite(req, u'/DaLToN/JoE')
-        self.assertEquals(len(rset), 1)
-        self.assertEquals(rset[0][0], self.p1.eid)
+        self.assertEqual(len(rset), 1)
+        self.assertEqual(rset[0][0], self.p1.eid)
 
     def test_inheritance_precedence(self):
         RQL1 = 'Any C WHERE C is CWEType'
@@ -142,17 +142,17 @@
         req = self.request()
         rewriter = Rewriter(req)
         pmid, rset = rewriter.rewrite(req, '/collector')
-        self.assertEquals(rset.rql, RQL1)
-        self.assertEquals(req.form, {'vid' : "baseindex"})
+        self.assertEqual(rset.rql, RQL1)
+        self.assertEqual(req.form, {'vid' : "baseindex"})
         pmid, rset = rewriter.rewrite(req, '/collector/something')
-        self.assertEquals(rset.rql, RQL2)
-        self.assertEquals(req.form, {'vid' : "index"})
+        self.assertEqual(rset.rql, RQL2)
+        self.assertEqual(req.form, {'vid' : "index"})
         pmid, rset = rewriter.rewrite(req, '/collector/something/')
-        self.assertEquals(req.form, {'vid' : "index"})
-        self.assertEquals(rset.rql, RQL2)
+        self.assertEqual(req.form, {'vid' : "index"})
+        self.assertEqual(rset.rql, RQL2)
         pmid, rset = rewriter.rewrite(req, '/collector/somethingelse/')
-        self.assertEquals(rset.rql, RQL1)
-        self.assertEquals(req.form, {'vid' : "baseindex"})
+        self.assertEqual(rset.rql, RQL1)
+        self.assertEqual(req.form, {'vid' : "baseindex"})
 
     def test_inheritance_precedence_same_rgx(self):
         RQL1 = 'Any C WHERE C is CWEType'
@@ -176,17 +176,17 @@
         req = self.request()
         rewriter = Rewriter(req)
         pmid, rset = rewriter.rewrite(req, '/collector')
-        self.assertEquals(rset.rql, RQL2)
-        self.assertEquals(req.form, {'vid' : "index"})
+        self.assertEqual(rset.rql, RQL2)
+        self.assertEqual(req.form, {'vid' : "index"})
         pmid, rset = rewriter.rewrite(req, '/collector/something')
-        self.assertEquals(rset.rql, RQL2)
-        self.assertEquals(req.form, {'vid' : "index"})
+        self.assertEqual(rset.rql, RQL2)
+        self.assertEqual(req.form, {'vid' : "index"})
         pmid, rset = rewriter.rewrite(req, '/collector/something/')
-        self.assertEquals(req.form, {'vid' : "index"})
-        self.assertEquals(rset.rql, RQL2)
+        self.assertEqual(req.form, {'vid' : "index"})
+        self.assertEqual(rset.rql, RQL2)
         pmid, rset = rewriter.rewrite(req, '/collector/somethingelse/')
-        self.assertEquals(rset.rql, RQL2)
-        self.assertEquals(req.form, {'vid' : "index"})
+        self.assertEqual(rset.rql, RQL2)
+        self.assertEqual(req.form, {'vid' : "index"})
 
 
 if __name__ == '__main__':
--- a/web/test/unittest_views_actions.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_views_actions.py	Fri Sep 24 18:20:59 2010 +0200
@@ -28,7 +28,7 @@
         rset = self.execute('CWUser X')
         actions = self.vreg['actions'].poss_visible_objects(req, rset=rset)
         vaction = [action for action in actions if action.__regid__ == 'view'][0]
-        self.assertEquals(vaction.url(), 'http://testing.fr/cubicweb/view?rql=CWUser%20X')
+        self.assertEqual(vaction.url(), 'http://testing.fr/cubicweb/view?rql=CWUser%20X')
 
     def test_sendmail_action(self):
         req = self.request()
--- a/web/test/unittest_views_apacherewrite.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_views_apacherewrite.py	Fri Sep 24 18:20:59 2010 +0200
@@ -41,18 +41,18 @@
             urlrewriter.rewrite('logilab.fr', '/whatever', req)
             self.fail('redirect exception expected')
         except Redirect, ex:
-            self.assertEquals(ex.location, 'http://www.logilab.fr/whatever')
-        self.assertEquals(urlrewriter.rewrite('www.logilab.fr', '/whatever', req),
+            self.assertEqual(ex.location, 'http://www.logilab.fr/whatever')
+        self.assertEqual(urlrewriter.rewrite('www.logilab.fr', '/whatever', req),
                           '/whatever')
-        self.assertEquals(urlrewriter.rewrite('www.logilab.fr', '/json/bla', req),
+        self.assertEqual(urlrewriter.rewrite('www.logilab.fr', '/json/bla', req),
                           '/json/bla')
-        self.assertEquals(urlrewriter.rewrite('abcd.logilab.fr', '/json/bla', req),
+        self.assertEqual(urlrewriter.rewrite('abcd.logilab.fr', '/json/bla', req),
                           '/json/bla')
-        self.assertEquals(urlrewriter.rewrite('abcd.logilab.fr', '/data/bla', req),
+        self.assertEqual(urlrewriter.rewrite('abcd.logilab.fr', '/data/bla', req),
                           '/data/bla')
-        self.assertEquals(urlrewriter.rewrite('abcd.logilab.fr', '/whatever', req),
+        self.assertEqual(urlrewriter.rewrite('abcd.logilab.fr', '/whatever', req),
                           '/m_abcd/whatever')
-        self.assertEquals(urlrewriter.rewrite('abcd.fr', '/whatever', req),
+        self.assertEqual(urlrewriter.rewrite('abcd.fr', '/whatever', req),
                           '/whatever')
 
 
--- a/web/test/unittest_views_basecontrollers.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_views_basecontrollers.py	Fri Sep 24 18:20:59 2010 +0200
@@ -48,7 +48,7 @@
         """check behaviour of this controller without any form parameter
         """
         ex = self.assertRaises(ValidationError, self.ctrl_publish, self.request())
-        self.assertEquals(ex.errors, {None: u'no selected entities'})
+        self.assertEqual(ex.errors, {None: u'no selected entities'})
 
     def test_validation_unique(self):
         """test creation of two linked entities
@@ -62,7 +62,7 @@
                     'upassword-subject-confirm:X': u'toto',
                     }
         ex = self.assertRaises(ValidationError, self.ctrl_publish, req)
-        self.assertEquals(ex.errors, {'login-subject': 'the value "admin" is already used, use another one'})
+        self.assertEqual(ex.errors, {'login-subject': 'the value "admin" is already used, use another one'})
 
     def test_user_editing_itself(self):
         """checking that a manager user can edit itself
@@ -83,10 +83,10 @@
             }
         path, params = self.expect_redirect_publish(req, 'edit')
         e = self.execute('Any X WHERE X eid %(x)s', {'x': user.eid}).get_entity(0, 0)
-        self.assertEquals(e.firstname, u'Sylvain')
-        self.assertEquals(e.surname, u'Th\xe9nault')
-        self.assertEquals(e.login, user.login)
-        self.assertEquals([g.eid for g in e.in_group], groupeids)
+        self.assertEqual(e.firstname, u'Sylvain')
+        self.assertEqual(e.surname, u'Th\xe9nault')
+        self.assertEqual(e.login, user.login)
+        self.assertEqual([g.eid for g in e.in_group], groupeids)
 
     def test_user_can_change_its_password(self):
         user = self.create_user('user')
@@ -102,7 +102,7 @@
             }
         path, params = self.expect_redirect_publish(req, 'edit')
         cnx.commit() # commit to check we don't get late validation error for instance
-        self.assertEquals(path, 'cwuser/user')
+        self.assertEqual(path, 'cwuser/user')
         self.failIf('vid' in params)
 
     def test_user_editing_itself_no_relation(self):
@@ -123,11 +123,11 @@
             }
         path, params = self.expect_redirect_publish(req, 'edit')
         e = self.execute('Any X WHERE X eid %(x)s', {'x': user.eid}).get_entity(0, 0)
-        self.assertEquals(e.login, user.login)
-        self.assertEquals(e.firstname, u'Th\xe9nault')
-        self.assertEquals(e.surname, u'Sylvain')
-        self.assertEquals([g.eid for g in e.in_group], groupeids)
-        self.assertEquals(e.cw_adapt_to('IWorkflowable').state, 'activated')
+        self.assertEqual(e.login, user.login)
+        self.assertEqual(e.firstname, u'Th\xe9nault')
+        self.assertEqual(e.surname, u'Sylvain')
+        self.assertEqual([g.eid for g in e.in_group], groupeids)
+        self.assertEqual(e.cw_adapt_to('IWorkflowable').state, 'activated')
 
 
     def test_create_multiple_linked(self):
@@ -149,11 +149,11 @@
                     }
         path, params = self.expect_redirect_publish(req, 'edit')
         # should be redirected on the created person
-        self.assertEquals(path, 'cwuser/adim')
+        self.assertEqual(path, 'cwuser/adim')
         e = self.execute('Any P WHERE P surname "Di Mascio"').get_entity(0, 0)
-        self.assertEquals(e.surname, 'Di Mascio')
+        self.assertEqual(e.surname, 'Di Mascio')
         email = e.use_email[0]
-        self.assertEquals(email.address, 'dima@logilab.fr')
+        self.assertEqual(email.address, 'dima@logilab.fr')
 
     def test_edit_multiple_linked(self):
         peid = u(self.create_user('adim').eid)
@@ -171,10 +171,10 @@
                     }
         path, params = self.expect_redirect_publish(req, 'edit')
         # should be redirected on the created person
-        self.assertEquals(path, 'cwuser/adim')
+        self.assertEqual(path, 'cwuser/adim')
         e = self.execute('Any P WHERE P surname "Di Masci"').get_entity(0, 0)
         email = e.use_email[0]
-        self.assertEquals(email.address, 'dima@logilab.fr')
+        self.assertEqual(email.address, 'dima@logilab.fr')
 
         emaileid = u(email.eid)
         req = self.request()
@@ -191,7 +191,7 @@
                     }
         path, params = self.expect_redirect_publish(req, 'edit')
         email.clear_all_caches()
-        self.assertEquals(email.address, 'adim@logilab.fr')
+        self.assertEqual(email.address, 'adim@logilab.fr')
 
 
     def test_password_confirm(self):
@@ -206,7 +206,7 @@
                     'upassword-subject:X': u'toto',
                     }
         ex = self.assertRaises(ValidationError, self.ctrl_publish, req)
-        self.assertEquals(ex.errors, {'upassword-subject': u'password and confirmation don\'t match'})
+        self.assertEqual(ex.errors, {'upassword-subject': u'password and confirmation don\'t match'})
         req = self.request()
         req.form = {'__cloned_eid:X': u(user.eid),
                     'eid': 'X', '__type:X': 'CWUser',
@@ -216,7 +216,7 @@
                     'upassword-subject-confirm:X': u'tutu',
                     }
         ex = self.assertRaises(ValidationError, self.ctrl_publish, req)
-        self.assertEquals(ex.errors, {'upassword-subject': u'password and confirmation don\'t match'})
+        self.assertEqual(ex.errors, {'upassword-subject': u'password and confirmation don\'t match'})
 
 
     def test_interval_bound_constraint_success(self):
@@ -230,7 +230,7 @@
                     'described_by_test-subject:X': u(feid),
                 }
         ex = self.assertRaises(ValidationError, self.ctrl_publish, req)
-        self.assertEquals(ex.errors, {'amount-subject': 'value must be >= 0'})
+        self.assertEqual(ex.errors, {'amount-subject': 'value must be >= 0'})
         req = self.request()
         req.form = {'eid': ['X'],
                     '__type:X': 'Salesterm',
@@ -239,7 +239,7 @@
                     'described_by_test-subject:X': u(feid),
                     }
         ex = self.assertRaises(ValidationError, self.ctrl_publish, req)
-        self.assertEquals(ex.errors, {'amount-subject': 'value must be <= 100'})
+        self.assertEqual(ex.errors, {'amount-subject': 'value must be <= 100'})
         req = self.request()
         req.form = {'eid': ['X'],
                     '__type:X': 'Salesterm',
@@ -251,7 +251,7 @@
         # should be redirected on the created
         #eid = params['rql'].split()[-1]
         e = self.execute('Salesterm X').get_entity(0, 0)
-        self.assertEquals(e.amount, 10)
+        self.assertEqual(e.amount, 10)
 
     def test_req_pending_insert(self):
         """make sure req's pending insertions are taken into account"""
@@ -262,8 +262,8 @@
         path, params = self.expect_redirect_publish(req, 'edit')
         usergroups = [gname for gname, in
                       self.execute('Any N WHERE G name N, U in_group G, U eid %(u)s', {'u': user.eid})]
-        self.assertUnorderedIterableEquals(usergroups, ['managers', 'test'])
-        self.assertEquals(get_pending_inserts(req), [])
+        self.assertItemsEqual(usergroups, ['managers', 'test'])
+        self.assertEqual(get_pending_inserts(req), [])
 
 
     def test_req_pending_delete(self):
@@ -274,15 +274,15 @@
         usergroups = [gname for gname, in
                       self.execute('Any N WHERE G name N, U in_group G, U eid %(u)s', {'u': user.eid})]
         # just make sure everything was set correctly
-        self.assertUnorderedIterableEquals(usergroups, ['managers', 'test'])
+        self.assertItemsEqual(usergroups, ['managers', 'test'])
         # now try to delete the relation
         req = self.request(**req_form(user))
         req.session.data['pending_delete'] = set([(user.eid, 'in_group', groupeid)])
         path, params = self.expect_redirect_publish(req, 'edit')
         usergroups = [gname for gname, in
                       self.execute('Any N WHERE G name N, U in_group G, U eid %(u)s', {'u': user.eid})]
-        self.assertUnorderedIterableEquals(usergroups, ['managers'])
-        self.assertEquals(get_pending_deletes(req), [])
+        self.assertItemsEqual(usergroups, ['managers'])
+        self.assertEqual(get_pending_deletes(req), [])
 
     # def test_custom_attribute_handler(self):
     #     def custom_login_edit(self, formparams, value, relations):
@@ -300,7 +300,7 @@
     #             }
     #         path, params = self.expect_redirect_publish(req, 'edit')
     #         rset = self.execute('Any L WHERE X eid %(x)s, X login L', {'x': user.eid}, 'x')
-    #         self.assertEquals(rset[0][0], 'FOO')
+    #         self.assertEqual(rset[0][0], 'FOO')
     #     finally:
     #         del CWUser.custom_login_edit
 
@@ -321,11 +321,11 @@
         path, params = self.expect_redirect_publish(req, 'edit')
         self.failUnless(path.startswith('blogentry/'))
         eid = path.split('/')[1]
-        self.assertEquals(params['vid'], 'edition')
+        self.assertEqual(params['vid'], 'edition')
         self.assertNotEquals(int(eid), 4012)
-        self.assertEquals(params['__redirectrql'], redirectrql)
-        self.assertEquals(params['__redirectvid'], 'primary')
-        self.assertEquals(params['__redirectparams'], 'toto=tutu&tata=titi')
+        self.assertEqual(params['__redirectrql'], redirectrql)
+        self.assertEqual(params['__redirectvid'], 'primary')
+        self.assertEqual(params['__redirectparams'], 'toto=tutu&tata=titi')
 
     def test_redirect_ok_button(self):
         redirectrql = rql_for_eid(4012) # whatever
@@ -341,11 +341,11 @@
             '__form_id': 'edition',
             }
         path, params = self.expect_redirect_publish(req, 'edit')
-        self.assertEquals(path, 'view')
-        self.assertEquals(params['rql'], redirectrql)
-        self.assertEquals(params['vid'], 'primary')
-        self.assertEquals(params['tata'], 'titi')
-        self.assertEquals(params['toto'], 'tutu')
+        self.assertEqual(path, 'view')
+        self.assertEqual(params['rql'], redirectrql)
+        self.assertEqual(params['vid'], 'primary')
+        self.assertEqual(params['tata'], 'titi')
+        self.assertEqual(params['toto'], 'tutu')
 
     def test_redirect_delete_button(self):
         req = self.request()
@@ -353,7 +353,7 @@
         req.form = {'eid': u(eid), '__type:%s'%eid: 'BlogEntry',
                     '__action_delete': ''}
         path, params = self.expect_redirect_publish(req, 'edit')
-        self.assertEquals(path, 'blogentry')
+        self.assertEqual(path, 'blogentry')
         self.assertIn('_cwmsgid', params)
         eid = req.create_entity('EmailAddress', address=u'hop@logilab.fr').eid
         self.execute('SET X use_email E WHERE E eid %(e)s, X eid %(x)s',
@@ -363,7 +363,7 @@
         req.form = {'eid': u(eid), '__type:%s'%eid: 'EmailAddress',
                     '__action_delete': ''}
         path, params = self.expect_redirect_publish(req, 'edit')
-        self.assertEquals(path, 'cwuser/admin')
+        self.assertEqual(path, 'cwuser/admin')
         self.assertIn('_cwmsgid', params)
         eid1 = req.create_entity('BlogEntry', title=u'hop', content=u'hop').eid
         eid2 = req.create_entity('EmailAddress', address=u'hop@logilab.fr').eid
@@ -373,7 +373,7 @@
                     '__type:%s'%eid2: 'EmailAddress',
                     '__action_delete': ''}
         path, params = self.expect_redirect_publish(req, 'edit')
-        self.assertEquals(path, 'view')
+        self.assertEqual(path, 'view')
         self.assertIn('_cwmsgid', params)
 
     def test_nonregr_eetype_etype_editing(self):
@@ -397,8 +397,8 @@
         try:
             path, params = self.expect_redirect_publish(req, 'edit')
             e = self.execute('Any X WHERE X eid %(x)s', {'x': cwetypeeid}).get_entity(0, 0)
-            self.assertEquals(e.name, 'CWEType')
-            self.assertEquals(sorted(g.eid for g in e.read_permission), groupeids)
+            self.assertEqual(e.name, 'CWEType')
+            self.assertEqual(sorted(g.eid for g in e.read_permission), groupeids)
         finally:
             # restore
             self.execute('SET X read_permission Y WHERE X name "CWEType", Y eid IN (%s), NOT X read_permission Y' % (','.join(basegroups)))
@@ -419,8 +419,8 @@
         self.failUnless(path.startswith('blogentry/'))
         eid = path.split('/')[1]
         e = self.execute('Any C, T WHERE C eid %(x)s, C content T', {'x': eid}).get_entity(0, 0)
-        self.assertEquals(e.title, '"13:03:40"')
-        self.assertEquals(e.content, '"13:03:43"')
+        self.assertEqual(e.title, '"13:03:40"')
+        self.assertEqual(e.content, '"13:03:43"')
 
 
     def test_nonregr_multiple_empty_email_addr(self):
@@ -441,7 +441,7 @@
                     'use_email-object:Y': 'X',
                     }
         ex = self.assertRaises(ValidationError, self.ctrl_publish, req)
-        self.assertEquals(ex.errors, {'address-subject': u'required field'})
+        self.assertEqual(ex.errors, {'address-subject': u'required field'})
 
     def test_nonregr_copy(self):
         user = self.user()
@@ -453,10 +453,10 @@
                     'upassword-subject:X': u'toto', 'upassword-subject-confirm:X': u'toto',
                     }
         path, params = self.expect_redirect_publish(req, 'edit')
-        self.assertEquals(path, 'cwuser/toto')
+        self.assertEqual(path, 'cwuser/toto')
         e = self.execute('Any X WHERE X is CWUser, X login "toto"').get_entity(0, 0)
-        self.assertEquals(e.login, 'toto')
-        self.assertEquals(e.in_group[0].name, 'managers')
+        self.assertEqual(e.login, 'toto')
+        self.assertEqual(e.in_group[0].name, 'managers')
 
 
     def test_nonregr_rollback_on_validation_error(self):
@@ -488,7 +488,7 @@
                 req.form['vid'] = 'copy'
                 self.app_publish(req, 'view')
             rset = self.execute('CWUser P WHERE P surname "Boom"')
-            self.assertEquals(len(rset), 0)
+            self.assertEqual(len(rset), 0)
         finally:
             p.__class__.skip_copy_for = old_skips
 
@@ -560,95 +560,95 @@
 #     def test_json_exec(self):
 #         rql = 'Any T,N WHERE T is Tag, T name N'
 #         ctrl = self.ctrl(self.request(mode='json', rql=rql, pageid='123'))
-#         self.assertEquals(ctrl.publish(),
+#         self.assertEqual(ctrl.publish(),
 #                           json_dumps(self.execute(rql).rows))
 
     def test_remote_add_existing_tag(self):
         self.remote_call('tag_entity', self.john.eid, ['python'])
-        self.assertUnorderedIterableEquals(
+        self.assertItemsEqual(
             [tname for tname, in self.execute('Any N WHERE T is Tag, T name N')],
             ['python', 'cubicweb'])
-        self.assertEquals(
+        self.assertEqual(
             self.execute('Any N WHERE T tags P, P is CWUser, T name N').rows,
             [['python']])
 
     def test_remote_add_new_tag(self):
         self.remote_call('tag_entity', self.john.eid, ['javascript'])
-        self.assertUnorderedIterableEquals(
+        self.assertItemsEqual(
             [tname for tname, in self.execute('Any N WHERE T is Tag, T name N')],
             ['python', 'cubicweb', 'javascript'])
-        self.assertEquals(
+        self.assertEqual(
             self.execute('Any N WHERE T tags P, P is CWUser, T name N').rows,
             [['javascript']])
 
     def test_pending_insertion(self):
         res, req = self.remote_call('add_pending_inserts', [['12', 'tags', '13']])
         deletes = get_pending_deletes(req)
-        self.assertEquals(deletes, [])
+        self.assertEqual(deletes, [])
         inserts = get_pending_inserts(req)
-        self.assertEquals(inserts, ['12:tags:13'])
+        self.assertEqual(inserts, ['12:tags:13'])
         res, req = self.remote_call('add_pending_inserts', [['12', 'tags', '14']])
         deletes = get_pending_deletes(req)
-        self.assertEquals(deletes, [])
+        self.assertEqual(deletes, [])
         inserts = get_pending_inserts(req)
-        self.assertEquals(inserts, ['12:tags:13', '12:tags:14'])
+        self.assertEqual(inserts, ['12:tags:13', '12:tags:14'])
         inserts = get_pending_inserts(req, 12)
-        self.assertEquals(inserts, ['12:tags:13', '12:tags:14'])
+        self.assertEqual(inserts, ['12:tags:13', '12:tags:14'])
         inserts = get_pending_inserts(req, 13)
-        self.assertEquals(inserts, ['12:tags:13'])
+        self.assertEqual(inserts, ['12:tags:13'])
         inserts = get_pending_inserts(req, 14)
-        self.assertEquals(inserts, ['12:tags:14'])
+        self.assertEqual(inserts, ['12:tags:14'])
         req.remove_pending_operations()
 
     def test_pending_deletion(self):
         res, req = self.remote_call('add_pending_delete', ['12', 'tags', '13'])
         inserts = get_pending_inserts(req)
-        self.assertEquals(inserts, [])
+        self.assertEqual(inserts, [])
         deletes = get_pending_deletes(req)
-        self.assertEquals(deletes, ['12:tags:13'])
+        self.assertEqual(deletes, ['12:tags:13'])
         res, req = self.remote_call('add_pending_delete', ['12', 'tags', '14'])
         inserts = get_pending_inserts(req)
-        self.assertEquals(inserts, [])
+        self.assertEqual(inserts, [])
         deletes = get_pending_deletes(req)
-        self.assertEquals(deletes, ['12:tags:13', '12:tags:14'])
+        self.assertEqual(deletes, ['12:tags:13', '12:tags:14'])
         deletes = get_pending_deletes(req, 12)
-        self.assertEquals(deletes, ['12:tags:13', '12:tags:14'])
+        self.assertEqual(deletes, ['12:tags:13', '12:tags:14'])
         deletes = get_pending_deletes(req, 13)
-        self.assertEquals(deletes, ['12:tags:13'])
+        self.assertEqual(deletes, ['12:tags:13'])
         deletes = get_pending_deletes(req, 14)
-        self.assertEquals(deletes, ['12:tags:14'])
+        self.assertEqual(deletes, ['12:tags:14'])
         req.remove_pending_operations()
 
     def test_remove_pending_operations(self):
         self.remote_call('add_pending_delete', ['12', 'tags', '13'])
         _, req = self.remote_call('add_pending_inserts', [['12', 'tags', '14']])
         inserts = get_pending_inserts(req)
-        self.assertEquals(inserts, ['12:tags:14'])
+        self.assertEqual(inserts, ['12:tags:14'])
         deletes = get_pending_deletes(req)
-        self.assertEquals(deletes, ['12:tags:13'])
+        self.assertEqual(deletes, ['12:tags:13'])
         req.remove_pending_operations()
-        self.assertEquals(get_pending_deletes(req), [])
-        self.assertEquals(get_pending_inserts(req), [])
+        self.assertEqual(get_pending_deletes(req), [])
+        self.assertEqual(get_pending_inserts(req), [])
 
 
     def test_add_inserts(self):
         res, req = self.remote_call('add_pending_inserts',
                                     [('12', 'tags', '13'), ('12', 'tags', '14')])
         inserts = get_pending_inserts(req)
-        self.assertEquals(inserts, ['12:tags:13', '12:tags:14'])
+        self.assertEqual(inserts, ['12:tags:13', '12:tags:14'])
         req.remove_pending_operations()
 
 
     # silly tests
     def test_external_resource(self):
-        self.assertEquals(self.remote_call('external_resource', 'RSS_LOGO')[0],
+        self.assertEqual(self.remote_call('external_resource', 'RSS_LOGO')[0],
                           json_dumps(self.config.uiprops['RSS_LOGO']))
     def test_i18n(self):
-        self.assertEquals(self.remote_call('i18n', ['bimboom'])[0],
+        self.assertEqual(self.remote_call('i18n', ['bimboom'])[0],
                           json_dumps(['bimboom']))
 
     def test_format_date(self):
-        self.assertEquals(self.remote_call('format_date', '2007-01-01 12:00:00')[0],
+        self.assertEqual(self.remote_call('format_date', '2007-01-01 12:00:00')[0],
                           json_dumps('2007/01/01'))
 
 
--- a/web/test/unittest_views_basetemplates.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_views_basetemplates.py	Fri Sep 24 18:20:59 2010 +0200
@@ -31,9 +31,9 @@
 
     def test_label(self):
         self.set_option('allow-email-login', 'yes')
-        self.assertEquals(self._login_labels(), ['login or email', 'password'])
+        self.assertEqual(self._login_labels(), ['login or email', 'password'])
         self.set_option('allow-email-login', 'no')
-        self.assertEquals(self._login_labels(), ['login', 'password'])
+        self.assertEqual(self._login_labels(), ['login', 'password'])
 
 if __name__ == '__main__':
     from logilab.common.testlib import unittest_main
--- a/web/test/unittest_views_baseviews.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_views_baseviews.py	Fri Sep 24 18:20:59 2010 +0200
@@ -31,56 +31,56 @@
 
     def test_no_rset(self):
         req = self.request()
-        self.assertEquals(vid_from_rset(req, None, self.schema), 'index')
+        self.assertEqual(vid_from_rset(req, None, self.schema), 'index')
 
     def test_no_entity(self):
         req = self.request()
         rset = self.execute('Any X WHERE X login "blabla"')
-        self.assertEquals(vid_from_rset(req, rset, self.schema), 'noresult')
+        self.assertEqual(vid_from_rset(req, rset, self.schema), 'noresult')
 
     def test_one_entity(self):
         req = self.request()
         rset = self.execute('Any X WHERE X login "admin"')
-        self.assertEquals(vid_from_rset(req, rset, self.schema), 'primary')
+        self.assertEqual(vid_from_rset(req, rset, self.schema), 'primary')
         rset = self.execute('Any X, L WHERE X login "admin", X login L')
-        self.assertEquals(vid_from_rset(req, rset, self.schema), 'primary')
+        self.assertEqual(vid_from_rset(req, rset, self.schema), 'primary')
         req.search_state = ('pasnormal',)
         rset = self.execute('Any X WHERE X login "admin"')
-        self.assertEquals(vid_from_rset(req, rset, self.schema), 'outofcontext-search')
+        self.assertEqual(vid_from_rset(req, rset, self.schema), 'outofcontext-search')
 
     def test_one_entity_eid(self):
         req = self.request()
         rset = self.execute('Any X WHERE X eid 1')
-        self.assertEquals(vid_from_rset(req, rset, self.schema), 'primary')
+        self.assertEqual(vid_from_rset(req, rset, self.schema), 'primary')
 
     def test_more_than_one_entity_same_type(self):
         req = self.request()
         rset = self.execute('Any X WHERE X is CWUser')
-        self.assertEquals(vid_from_rset(req, rset, self.schema), 'sameetypelist')
+        self.assertEqual(vid_from_rset(req, rset, self.schema), 'sameetypelist')
         rset = self.execute('Any X, L WHERE X login L')
-        self.assertEquals(vid_from_rset(req, rset, self.schema), 'sameetypelist')
+        self.assertEqual(vid_from_rset(req, rset, self.schema), 'sameetypelist')
 
     def test_more_than_one_entity_diff_type(self):
         req = self.request()
         rset = self.execute('Any X WHERE X is IN (CWUser, CWGroup)')
-        self.assertEquals(vid_from_rset(req, rset, self.schema), 'list')
+        self.assertEqual(vid_from_rset(req, rset, self.schema), 'list')
 
     def test_more_than_one_entity_by_row(self):
         req = self.request()
         rset = self.execute('Any X, G WHERE X in_group G')
-        self.assertEquals(vid_from_rset(req, rset, self.schema), 'table')
+        self.assertEqual(vid_from_rset(req, rset, self.schema), 'table')
 
     def test_more_than_one_entity_by_row_2(self):
         req = self.request()
         rset = self.execute('Any X, GN WHERE X in_group G, G name GN')
-        self.assertEquals(vid_from_rset(req, rset, self.schema), 'table')
+        self.assertEqual(vid_from_rset(req, rset, self.schema), 'table')
 
     def test_aggregat(self):
         req = self.request()
         rset = self.execute('Any X, COUNT(T) GROUPBY X WHERE X is T')
-        self.assertEquals(vid_from_rset(req, rset, self.schema), 'table')
+        self.assertEqual(vid_from_rset(req, rset, self.schema), 'table')
         rset = self.execute('Any MAX(X) WHERE X is CWUser')
-        self.assertEquals(vid_from_rset(req, rset, self.schema), 'table')
+        self.assertEqual(vid_from_rset(req, rset, self.schema), 'table')
 
     def test_subquery(self):
         rset = self.execute(
@@ -90,7 +90,7 @@
 '       UNION'
 '     (DISTINCT Any W,N WHERE W is CWGroup, W name N))')
         req = self.request()
-        self.assertEquals(vid_from_rset(req, rset, self.schema), 'table')
+        self.assertEqual(vid_from_rset(req, rset, self.schema), 'table')
 
 
 class TableViewTC(CubicWebTC):
@@ -104,7 +104,7 @@
         return e, rset, view
 
     def test_headers(self):
-        self.skip('implement me')
+        self.skipTest('implement me')
 
     def test_sortvalue(self):
         e, _, view = self._prepare_entity()
--- a/web/test/unittest_views_editforms.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_views_editforms.py	Fri Sep 24 18:20:59 2010 +0200
@@ -50,19 +50,19 @@
     def test_cwuser_relations_by_category(self):
         e = self.vreg['etypes'].etype_class('CWUser')(self.request())
         # see custom configuration in views.cwuser
-        self.assertEquals(rbc(e, 'main', 'attributes'),
+        self.assertEqual(rbc(e, 'main', 'attributes'),
                           [('login', 'subject'),
                            ('upassword', 'subject'),
                            ('firstname', 'subject'),
                            ('surname', 'subject'),
                            ('in_group', 'subject'),
                            ])
-        self.assertListEquals(rbc(e, 'muledit', 'attributes'),
+        self.assertListEqual(rbc(e, 'muledit', 'attributes'),
                               [('login', 'subject'),
                                ('upassword', 'subject'),
                                ('in_group', 'subject'),
                                ])
-        self.assertListEquals(rbc(e, 'main', 'metadata'),
+        self.assertListEqual(rbc(e, 'main', 'metadata'),
                               [('last_login_time', 'subject'),
                                ('modification_date', 'subject'),
                                ('created_by', 'subject'),
@@ -74,18 +74,18 @@
         # XXX skip 'tags' relation here and in the hidden category because
         # of some test interdependancy when pytest is launched on whole cw
         # (appears here while expected in hidden
-        self.assertListEquals([x for x in rbc(e, 'main', 'relations')
+        self.assertListEqual([x for x in rbc(e, 'main', 'relations')
                                if x != ('tags', 'object')],
                               [('primary_email', 'subject'),
                                ('custom_workflow', 'subject'),
                                ('connait', 'subject'),
                                ('checked_by', 'object'),
                                ])
-        self.assertListEquals(rbc(e, 'main', 'inlined'),
+        self.assertListEqual(rbc(e, 'main', 'inlined'),
                               [('use_email', 'subject'),
                                ])
         # owned_by is defined both as subject and object relations on CWUser
-        self.assertListEquals(sorted(x for x in rbc(e, 'main', 'hidden')
+        self.assertListEqual(sorted(x for x in rbc(e, 'main', 'hidden')
                                      if x != ('tags', 'object')),
                               sorted([('for_user', 'object'),
                                       ('created_by', 'object'),
@@ -100,7 +100,7 @@
 
     def test_personne_relations_by_category(self):
         e = self.vreg['etypes'].etype_class('Personne')(self.request())
-        self.assertListEquals(rbc(e, 'main', 'attributes'),
+        self.assertListEqual(rbc(e, 'main', 'attributes'),
                               [('nom', 'subject'),
                                ('prenom', 'subject'),
                                ('sexe', 'subject'),
@@ -115,22 +115,22 @@
                                ('description', 'subject'),
                                ('salary', 'subject'),
                                ])
-        self.assertListEquals(rbc(e, 'muledit', 'attributes'),
+        self.assertListEqual(rbc(e, 'muledit', 'attributes'),
                               [('nom', 'subject'),
                                ])
-        self.assertListEquals(rbc(e, 'main', 'metadata'),
+        self.assertListEqual(rbc(e, 'main', 'metadata'),
                               [('creation_date', 'subject'),
                                ('cwuri', 'subject'),
                                ('modification_date', 'subject'),
                                ('created_by', 'subject'),
                                ('owned_by', 'subject'),
                                ])
-        self.assertListEquals(rbc(e, 'main', 'relations'),
+        self.assertListEqual(rbc(e, 'main', 'relations'),
                               [('travaille', 'subject'),
                                ('manager', 'object'),
                                ('connait', 'object'),
                                ])
-        self.assertListEquals(rbc(e, 'main', 'hidden'),
+        self.assertListEqual(rbc(e, 'main', 'hidden'),
                               [])
 
     def test_edition_form(self):
--- a/web/test/unittest_views_embeding.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_views_embeding.py	Fri Sep 24 18:20:59 2010 +0200
@@ -46,7 +46,7 @@
         ]
         for orig_a, expected_a in zip(orig, expected):
             got = prefix_links(orig_a, 'PREFIX', 'http://embedded.com/page1.html')
-            self.assertEquals(got, expected_a)
+            self.assertEqual(got, expected_a)
 
 if __name__ == '__main__':
     unittest_main()
--- a/web/test/unittest_views_navigation.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_views_navigation.py	Fri Sep 24 18:20:59 2010 +0200
@@ -62,10 +62,10 @@
         req = self.request()
         rset = self.execute('Any X,N LIMIT 10 WHERE X name N')
         navcomp = self.vreg['components'].select_or_none('navigation', req, rset=rset)
-        self.assertEquals(navcomp, None)
+        self.assertEqual(navcomp, None)
         req.set_search_state('W:X:Y:Z')
         navcomp = self.vreg['components'].select_or_none('navigation', req, rset=rset)
-        self.assertEquals(navcomp, None)
+        self.assertEqual(navcomp, None)
         req.set_search_state('normal')
 
     def test_navigation_selection_not_enough(self):
--- a/web/test/unittest_views_pyviews.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_views_pyviews.py	Fri Sep 24 18:20:59 2010 +0200
@@ -25,7 +25,7 @@
                                          pyvalue=[[1, 'a'], [2, 'b']])
         content = view.render(pyvalue=[[1, 'a'], [2, 'b']],
                               headers=['num', 'char'])
-        self.assertEquals(content.strip(), '''<table class="listing">
+        self.assertEqual(content.strip(), '''<table class="listing">
 <thead><tr><th>num</th><th>char</th></tr>
 </thead><tbody><tr><td>1</td><td>a</td></tr>
 <tr><td>2</td><td>b</td></tr>
@@ -35,7 +35,7 @@
         view = self.vreg['views'].select('pyvallist', self.request(),
                                          pyvalue=[1, 'a'])
         content = view.render(pyvalue=[1, 'a'])
-        self.assertEquals(content.strip(), '''<ul>
+        self.assertEqual(content.strip(), '''<ul>
 <li>1</li>
 <li>a</li>
 </ul>''')
--- a/web/test/unittest_views_searchrestriction.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_views_searchrestriction.py	Fri Sep 24 18:20:59 2010 +0200
@@ -46,32 +46,32 @@
                           'B in_group P, P name "managers"')
 
     def test_1(self):
-        self.assertEquals(self._generate(self.select, 'in_state', 'subject', 'name'),
+        self.assertEqual(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, B is CWUser, A name C")
 
     def test_2(self):
-        self.assertEquals(self._generate(self.select, 'tags', 'object', 'name'),
+        self.assertEqual(self._generate(self.select, 'tags', 'object', 'name'),
                           "DISTINCT Any A,C ORDERBY C WHERE B in_group P, P name 'managers', "
                           "A tags B, B is CWUser, A name C")
 
     def test_3(self):
-        self.assertEquals(self._generate(self.select, 'created_by', 'subject', 'login'),
+        self.assertEqual(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, B is CWUser, A login C")
 
     def test_4(self):
-        self.assertEquals(self._generate(self.parse('Any X WHERE X is CWUser'), 'created_by', 'subject', 'login'),
+        self.assertEqual(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'),
+        self.assertEqual(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')
-        self.assertEquals(self._generate(select, 'created_by', 'subject', 'login'),
+        self.assertEqual(self._generate(select, 'created_by', 'subject', 'login'),
                           "DISTINCT Any A,B ORDERBY B WHERE T created_by U, "
                           "T created_by A, T is Bookmark, A login B")
 
@@ -83,7 +83,7 @@
         for rdefs in rschema.rdefs.values():
             rdefs.cardinality =  '++'
         try:
-            self.assertEquals(self._generate(select, 'in_state', 'subject', 'name'),
+            self.assertEqual(self._generate(select, 'in_state', 'subject', 'name'),
                               "DISTINCT Any A,B ORDERBY B WHERE V is CWUser, "
                               "NOT EXISTS(V in_state VS), VS name 'published', "
                               "V in_state A, A name B")
@@ -94,7 +94,7 @@
     def test_nonregr3(self):
         #'DISTINCT Any X,TMP,N WHERE P name TMP, X version_of P, P is Project, X is Version, not X in_state S,S name "published", X num N ORDERBY TMP,N'
         select = self.parse('DISTINCT Any X, MAX(Y) GROUPBY X WHERE X is CWUser, Y is Bookmark, X in_group A')
-        self.assertEquals(self._generate(select, 'in_group', 'subject', 'name'),
+        self.assertEqual(self._generate(select, 'in_group', 'subject', 'name'),
                           "DISTINCT Any B,C ORDERBY C WHERE X is CWUser, X in_group B, B name C")
 
 
--- a/web/test/unittest_viewselector.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_viewselector.py	Fri Sep 24 18:20:59 2010 +0200
@@ -65,7 +65,7 @@
         except AttributeError:
             return
         if registry == 'hooks':
-            self.assertEquals(len(content), expected, content)
+            self.assertEqual(len(content), expected, content)
             return
         try:
             self.assertSetEqual(content.keys(), expected)
@@ -467,18 +467,18 @@
 
 
     def test_properties(self):
-        self.assertEquals(sorted(k for k in self.vreg['propertydefs'].keys()
+        self.assertEqual(sorted(k for k in self.vreg['propertydefs'].keys()
                                  if k.startswith('boxes.edit_box')),
                           ['boxes.edit_box.context',
                            'boxes.edit_box.order',
                            'boxes.edit_box.visible'])
-        self.assertEquals([k for k in self.vreg['propertyvalues'].keys()
+        self.assertEqual([k for k in self.vreg['propertyvalues'].keys()
                            if not k.startswith('system.version')],
                           [])
-        self.assertEquals(self.vreg.property_value('boxes.edit_box.visible'), True)
-        self.assertEquals(self.vreg.property_value('boxes.edit_box.order'), 2)
-        self.assertEquals(self.vreg.property_value('boxes.possible_views_box.visible'), False)
-        self.assertEquals(self.vreg.property_value('boxes.possible_views_box.order'), 10)
+        self.assertEqual(self.vreg.property_value('boxes.edit_box.visible'), True)
+        self.assertEqual(self.vreg.property_value('boxes.edit_box.order'), 2)
+        self.assertEqual(self.vreg.property_value('boxes.possible_views_box.visible'), False)
+        self.assertEqual(self.vreg.property_value('boxes.possible_views_box.order'), 10)
         self.assertRaises(UnknownProperty, self.vreg.property_value, 'boxes.actions_box')
 
 
--- a/web/test/unittest_web.py	Fri Sep 24 18:20:57 2010 +0200
+++ b/web/test/unittest_web.py	Fri Sep 24 18:20:59 2010 +0200
@@ -25,9 +25,9 @@
         req = FakeRequest()
         arurl = req.ajax_replace_url
         # NOTE: for the simplest use cases, we could use doctest
-        self.assertEquals(arurl('foo', rql='Person P', vid='list'),
+        self.assertEqual(arurl('foo', rql='Person P', vid='list'),
                           """javascript: $('#foo').loadxhtml("http://testing.fr/cubicweb/json?rql=Person%20P&fname=view&vid=list",null,"get","replace"); noop()""")
-        self.assertEquals(arurl('foo', rql='Person P', vid='oneline', name='bar', age=12),
+        self.assertEqual(arurl('foo', rql='Person P', vid='oneline', name='bar', age=12),
                           """javascript: $('#foo').loadxhtml("http://testing.fr/cubicweb/json?name=bar&age=12&rql=Person%20P&fname=view&vid=oneline",null,"get","replace"); noop()""")