merge stable in default (3.18) branch
authorDavid Douard <david.douard@logilab.fr>
Wed, 07 Aug 2013 09:02:47 +0200
changeset 9217 b4ac21bf6019
parent 9205 ea32e964fbf8 (current diff)
parent 9216 5b440b87cd2d (diff)
child 9218 c027ed79f1ce
merge stable in default (3.18) branch
web/formfields.py
--- a/.hgtags	Tue Jul 30 20:31:57 2013 +0200
+++ b/.hgtags	Wed Aug 07 09:02:47 2013 +0200
@@ -299,3 +299,9 @@
 c7ba8e5d2e45e3d1289c1403df40d7dcb5e62acb cubicweb-version-3.17.4
 c7ba8e5d2e45e3d1289c1403df40d7dcb5e62acb cubicweb-debian-version-3.17.4-1
 c7ba8e5d2e45e3d1289c1403df40d7dcb5e62acb cubicweb-centos-version-3.17.4-1
+15dd5b37998b8ef5e8fab1ea0491e6bd8e9f3355 cubicweb-centos-version-3.17.5-1
+15dd5b37998b8ef5e8fab1ea0491e6bd8e9f3355 cubicweb-version-3.17.5
+15dd5b37998b8ef5e8fab1ea0491e6bd8e9f3355 cubicweb-debian-version-3.17.5-1
+5b9fedf67a2912a80fe315a477df9e3ab104c734 cubicweb-centos-version-3.17.6-1
+5b9fedf67a2912a80fe315a477df9e3ab104c734 cubicweb-version-3.17.6
+5b9fedf67a2912a80fe315a477df9e3ab104c734 cubicweb-debian-version-3.17.6-1
--- a/__pkginfo__.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/__pkginfo__.py	Wed Aug 07 09:02:47 2013 +0200
@@ -22,7 +22,7 @@
 
 modname = distname = "cubicweb"
 
-numversion = (3, 17, 4)
+numversion = (3, 17, 6)
 version = '.'.join(str(num) for num in numversion)
 
 description = "a repository of entities / relations for knowledge management"
--- a/cubicweb.spec	Tue Jul 30 20:31:57 2013 +0200
+++ b/cubicweb.spec	Wed Aug 07 09:02:47 2013 +0200
@@ -7,7 +7,7 @@
 %endif
 
 Name:           cubicweb
-Version:        3.17.4
+Version:        3.17.6
 Release:        logilab.1%{?dist}
 Summary:        CubicWeb is a semantic web application framework
 Source0:        http://download.logilab.org/pub/cubicweb/cubicweb-%{version}.tar.gz
--- a/debian/changelog	Tue Jul 30 20:31:57 2013 +0200
+++ b/debian/changelog	Wed Aug 07 09:02:47 2013 +0200
@@ -1,3 +1,15 @@
+cubicweb (3.17.6-1) unstable; urgency=low
+
+  * new upstream release
+
+ -- David Douard <david.douard@logilab.fr>  Tue, 06 Aug 2013 11:49:04 +0200
+
+cubicweb (3.17.5-1) unstable; urgency=low
+
+  * new upstream release
+
+ -- David Douard <david.douard@logilab.fr>  Wed, 31 Jul 2013 16:58:19 +0200
+
 cubicweb (3.17.4-1) unstable; urgency=low
 
   * new upstream release
--- a/debian/cubicweb-common.install.in	Tue Jul 30 20:31:57 2013 +0200
+++ b/debian/cubicweb-common.install.in	Wed Aug 07 09:02:47 2013 +0200
@@ -1,4 +1,4 @@
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/entities/ usr/lib/PY_VERSION/site-packages/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/ext/ usr/lib/PY_VERSION/site-packages/cubicweb
-debian/tmp/usr/share/cubicweb/cubes/ usr/share/cubicweb/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/*.py usr/share/pyshared/cubicweb
+usr/lib/PY_VERSION/*-packages/cubicweb/entities/
+usr/lib/PY_VERSION/*-packages/cubicweb/ext/
+usr/share/cubicweb/cubes/
+usr/lib/PY_VERSION/*-packages/cubicweb/*.py
--- a/debian/cubicweb-ctl.dirs	Tue Jul 30 20:31:57 2013 +0200
+++ b/debian/cubicweb-ctl.dirs	Wed Aug 07 09:02:47 2013 +0200
@@ -1,4 +1,3 @@
-usr/lib/python2.4/site-packages/cubicweb/
 etc/init.d
 etc/cubicweb.d
 etc/bash_completion.d
--- a/debian/cubicweb-ctl.install.in	Tue Jul 30 20:31:57 2013 +0200
+++ b/debian/cubicweb-ctl.install.in	Wed Aug 07 09:02:47 2013 +0200
@@ -1,3 +1,3 @@
-debian/tmp/usr/bin/cubicweb-ctl usr/bin/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/cwctl.py usr/lib/PY_VERSION/site-packages/cubicweb
-debian/cubicweb-ctl.bash_completion etc/bash_completion.d/cubicweb-ctl
+usr/bin/cubicweb-ctl usr/bin/
+usr/lib/PY_VERSION/*-packages/cubicweb/cwctl.py
+../cubicweb-ctl.bash_completion etc/bash_completion.d/cubicweb-ctl
--- a/debian/cubicweb-dev.install.in	Tue Jul 30 20:31:57 2013 +0200
+++ b/debian/cubicweb-dev.install.in	Wed Aug 07 09:02:47 2013 +0200
@@ -1,10 +1,10 @@
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/devtools/ usr/lib/PY_VERSION/site-packages/cubicweb/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/skeleton/ usr/lib/PY_VERSION/site-packages/cubicweb/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/test usr/lib/PY_VERSION/site-packages/cubicweb/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/entities/test usr/lib/PY_VERSION/site-packages/cubicweb/entities/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/ext/test usr/lib/PY_VERSION/site-packages/cubicweb/ext/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/server/test usr/lib/PY_VERSION/site-packages/cubicweb/server/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/sobjects/test usr/lib/PY_VERSION/site-packages/cubicweb/sobjects/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/hooks/test usr/lib/PY_VERSION/site-packages/cubicweb/sobjects/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/web/test usr/lib/PY_VERSION/site-packages/cubicweb/web/
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/etwist/test usr/lib/PY_VERSION/site-packages/cubicweb/etwist/
+usr/lib/PY_VERSION/*-packages/cubicweb/devtools/
+usr/lib/PY_VERSION/*-packages/cubicweb/skeleton/
+usr/lib/PY_VERSION/*-packages/cubicweb/test
+usr/lib/PY_VERSION/*-packages/cubicweb/entities/test
+usr/lib/PY_VERSION/*-packages/cubicweb/ext/test
+usr/lib/PY_VERSION/*-packages/cubicweb/server/test
+usr/lib/PY_VERSION/*-packages/cubicweb/sobjects/test
+usr/lib/PY_VERSION/*-packages/cubicweb/hooks/test
+usr/lib/PY_VERSION/*-packages/cubicweb/web/test
+usr/lib/PY_VERSION/*-packages/cubicweb/etwist/test
--- a/debian/cubicweb-documentation.install.in	Tue Jul 30 20:31:57 2013 +0200
+++ b/debian/cubicweb-documentation.install.in	Wed Aug 07 09:02:47 2013 +0200
@@ -1,3 +1,3 @@
-doc/book usr/share/doc/cubicweb-documentation
-doc/html usr/share/doc/cubicweb-documentation
-debian/cubicweb-doc usr/share/doc-base/cubicweb-doc
+../../doc/book usr/share/doc/cubicweb-documentation
+../../doc/html usr/share/doc/cubicweb-documentation
+../../debian/cubicweb-doc usr/share/doc-base/cubicweb-doc
--- a/debian/cubicweb-server.install.in	Tue Jul 30 20:31:57 2013 +0200
+++ b/debian/cubicweb-server.install.in	Wed Aug 07 09:02:47 2013 +0200
@@ -1,5 +1,5 @@
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/server/ usr/lib/PY_VERSION/site-packages/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/hooks/ usr/lib/PY_VERSION/site-packages/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/sobjects/ usr/lib/PY_VERSION/site-packages/cubicweb
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/schemas/ usr/lib/PY_VERSION/site-packages/cubicweb
-debian/tmp/usr/share/cubicweb/migration/ usr/share/cubicweb/
+usr/lib/PY_VERSION/*-packages/cubicweb/server/
+usr/lib/PY_VERSION/*-packages/cubicweb/hooks/
+usr/lib/PY_VERSION/*-packages/cubicweb/sobjects/
+usr/lib/PY_VERSION/*-packages/cubicweb/schemas/
+usr/share/cubicweb/migration/
--- a/debian/cubicweb-twisted.install.in	Tue Jul 30 20:31:57 2013 +0200
+++ b/debian/cubicweb-twisted.install.in	Wed Aug 07 09:02:47 2013 +0200
@@ -1,1 +1,1 @@
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/etwist/ usr/lib/PY_VERSION/site-packages/cubicweb/
+usr/lib/PY_VERSION/*-packages/cubicweb/etwist/
--- a/debian/cubicweb-web.install.in	Tue Jul 30 20:31:57 2013 +0200
+++ b/debian/cubicweb-web.install.in	Wed Aug 07 09:02:47 2013 +0200
@@ -1,3 +1,3 @@
-debian/tmp/usr/lib/PY_VERSION/site-packages/cubicweb/web usr/lib/PY_VERSION/site-packages/cubicweb
-debian/tmp/usr/share/cubicweb/cubes/shared/data usr/share/cubicweb/cubes/shared
-debian/tmp/usr/share/cubicweb/cubes/shared/wdoc usr/share/cubicweb/cubes/shared
+usr/lib/PY_VERSION/*-packages/cubicweb/web
+usr/share/cubicweb/cubes/shared/data
+usr/share/cubicweb/cubes/shared/wdoc
--- a/debian/rules	Tue Jul 30 20:31:57 2013 +0200
+++ b/debian/rules	Wed Aug 07 09:02:47 2013 +0200
@@ -37,27 +37,26 @@
 	dh_clean
 	dh_installdirs
 
-	#python setup.py install_lib --no-compile --install-dir=debian/cubicweb-common/usr/lib/python2.4/site-packages/
 	NO_SETUPTOOLS=1 python setup.py -q install --no-compile --prefix=debian/tmp/usr
 
 	# Put all the python library and data in cubicweb-common
 	# and scripts in cubicweb-server
-	dh_install -vi
+	dh_install -vi --sourcedir=debian/tmp
 	# cwctl in the cubicweb-ctl package
-	rm -f debian/cubicweb-common/usr/share/pyshared/cubicweb/cwctl.py
+	rm -f debian/cubicweb-common/usr/lib/python*/*/cubicweb/cwctl.py
         # wdoc in the cubicweb-web package
 	rm -rf debian/cubicweb-common/usr/share/cubicweb/cubes/shared/wdoc
 	rm -rf debian/cubicweb-common/usr/share/cubicweb/cubes/shared/data
 	dh_lintian
 
 	# Remove unittests directory (should be available in cubicweb-dev only)
-	rm -rf debian/cubicweb-server/usr/lib/${PY_VERSION}/site-packages/cubicweb/server/test
-	rm -rf debian/cubicweb-server/usr/lib/${PY_VERSION}/site-packages/cubicweb/hooks/test
-	rm -rf debian/cubicweb-server/usr/lib/${PY_VERSION}/site-packages/cubicweb/sobjects/test
-	rm -rf debian/cubicweb-web/usr/lib/${PY_VERSION}/site-packages/cubicweb/web/test
-	rm -rf debian/cubicweb-twisted/usr/lib/${PY_VERSION}/site-packages/cubicweb/etwist/test
-	rm -rf debian/cubicweb-common/usr/lib/${PY_VERSION}/site-packages/cubicweb/ext/test
-	rm -rf debian/cubicweb-common/usr/lib/${PY_VERSION}/site-packages/cubicweb/entities/test
+	rm -rf debian/cubicweb-server/usr/lib/${PY_VERSION}/*-packages/cubicweb/server/test
+	rm -rf debian/cubicweb-server/usr/lib/${PY_VERSION}/*-packages/cubicweb/hooks/test
+	rm -rf debian/cubicweb-server/usr/lib/${PY_VERSION}/*-packages/cubicweb/sobjects/test
+	rm -rf debian/cubicweb-web/usr/lib/${PY_VERSION}/*-packages/cubicweb/web/test
+	rm -rf debian/cubicweb-twisted/usr/lib/${PY_VERSION}/*-packages/cubicweb/etwist/test
+	rm -rf debian/cubicweb-common/usr/lib/${PY_VERSION}/*-packages/cubicweb/ext/test
+	rm -rf debian/cubicweb-common/usr/lib/${PY_VERSION}/*-packages/cubicweb/entities/test
 
 
 %: %.in
--- a/devtools/fill.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/devtools/fill.py	Wed Aug 07 09:02:47 2013 +0200
@@ -139,7 +139,7 @@
     def generate_integer(self, entity, attrname, index):
         """generates a consistent value for 'attrname' if it's an integer"""
         return self._constrained_generate(entity, attrname, 0, 1, index)
-    generate_int = generate_integer
+    generate_int = generate_bigint = generate_integer
 
     def generate_float(self, entity, attrname, index):
         """generates a consistent value for 'attrname' if it's a float"""
--- a/devtools/test/unittest_testlib.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/devtools/test/unittest_testlib.py	Wed Aug 07 09:02:47 2013 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -20,7 +20,9 @@
 from cStringIO import StringIO
 
 from unittest import TextTestRunner
+
 from logilab.common.testlib import TestSuite, TestCase, unittest_main
+from logilab.common.registry import yes
 
 from cubicweb.devtools import htmlparser
 from cubicweb.devtools.testlib import CubicWebTC
@@ -172,5 +174,20 @@
             self.assertTrue(rdef.permissions['add'])
         self.assertTrue(rdef.permissions['read'], ())
 
+    def test_temporary_appobjects_registered(self):
+        class AnAppobject(object):
+            __registries__ = ('hip',)
+            __regid__ = 'hop'
+            __select__ = yes()
+            registered = None
+            @classmethod
+            def __registered__(cls, reg):
+                cls.registered = reg
+
+        with self.temporary_appobjects(AnAppobject):
+            self.assertEqual(self.vreg['hip'], AnAppobject.registered)
+            self.assertIn(AnAppobject, self.vreg['hip']['hop'])
+        self.assertNotIn(AnAppobject, self.vreg['hip']['hop'])
+
 if __name__ == '__main__':
     unittest_main()
--- a/devtools/testlib.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/devtools/testlib.py	Wed Aug 07 09:02:47 2013 +0200
@@ -461,6 +461,10 @@
         self.vreg._loadedmods.setdefault(self.__module__, {})
         for obj in appobjects:
             self.vreg.register(obj)
+            registered = getattr(obj, '__registered__', None)
+            if registered:
+                for registry in obj.__registries__:
+                    registered(self.vreg[registry])
         try:
             yield
         finally:
--- a/entities/lib.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/entities/lib.py	Wed Aug 07 09:02:47 2013 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -15,14 +15,15 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""entity classes for optional library entities
+"""entity classes for optional library entities"""
 
-"""
 __docformat__ = "restructuredtext en"
 
 from urlparse import urlsplit, urlunsplit
 from datetime import datetime
 
+from logilab.mtconverter import xml_escape
+
 from cubicweb import UnknownProperty
 from cubicweb.entity import _marker
 from cubicweb.entities import AnyEntity, fetch_config
@@ -81,7 +82,10 @@
                         format='text/html'):
         """overriden to return displayable address when necessary"""
         if attr == 'address':
-            return self.display_address()
+            address = self.display_address()
+            if format == 'text/html':
+                address = xml_escape(address)
+            return address
         return super(EmailAddress, self).printable_value(attr, value, attrtype, format)
 
 
--- a/entities/test/unittest_base.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/entities/test/unittest_base.py	Wed Aug 07 09:02:47 2013 +0200
@@ -82,12 +82,19 @@
         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.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.assertEqual(email.display_address(), 'syt')
-        self.assertEqual(email.printable_value('address'), 'syt')
+        try:
+            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.assertEqual(email.display_address(), 'syt')
+            self.assertEqual(email.printable_value('address'), 'syt')
+        finally:
+            self.vreg.config.global_set_option('mangle-emails', False)
 
+    def test_printable_value_escape(self):
+        email = self.execute('INSERT EmailAddress X: X address "maarten&ter@philips.com"').get_entity(0, 0)
+        self.assertEqual(email.printable_value('address'), 'maarten&amp;ter@philips.com')
+        self.assertEqual(email.printable_value('address', format='text/plain'), 'maarten&ter@philips.com')
 
 class CWUserTC(BaseEntityTC):
 
--- a/server/ssplanner.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/server/ssplanner.py	Wed Aug 07 09:02:47 2013 +0200
@@ -101,23 +101,16 @@
 
     Return None when no query actually needed, else the given select node that
     will be used as substep query.
-
-    When select has nothing selected, search in origrqlst for restriction that
-    should be considered.
     """
     if origrqlst.where is not None and not select.selection:
         # no selection, append one randomly by searching for a relation which is
-        # neither a type restriction (is) nor an eid specification (not neged
-        # eid with constant node)
+        # not neged neither a type restriction (is/is_instance_of)
         for rel in origrqlst.where.iget_nodes(Relation):
-            if rel.neged(strict=True) or not (
-                rel.is_types_restriction() or
-                (rel.r_type == 'eid'
-                 and isinstance(rel.get_variable_parts()[1], Constant))):
+            if not (rel.neged(traverse_scope=True) or rel.is_types_restriction()):
                 select.append_selected(rel.children[0].copy(select))
                 break
         else:
-            return
+            return None
     if select.selection:
         if origrqlst.where is not None:
             select.set_where(origrqlst.where.copy(select))
--- a/server/test/unittest_msplanner.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/server/test/unittest_msplanner.py	Wed Aug 07 09:02:47 2013 +0200
@@ -1772,7 +1772,12 @@
         repo._type_source_cache[999998] = ('State', 'system', None, 'system')
         self._test('INSERT Note X: X in_state S, X type "bla", X migrated_from N WHERE S eid %(s)s, N eid %(n)s',
                    [('InsertStep',
-                      [('InsertRelationsStep', [])]
+                      [('InsertRelationsStep',
+                        [('OneFetchStep',
+                          [('Any 999999', [{}])],
+                          None, None,
+                          [self.system], {},
+                          [])])]
                      )],
                    {'n': 999999, 's': 999998})
 
--- a/server/test/unittest_querier.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/server/test/unittest_querier.py	Wed Aug 07 09:02:47 2013 +0200
@@ -1,5 +1,5 @@
 # -*- coding: iso-8859-1 -*-
-# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -1268,12 +1268,21 @@
         newname = self.execute('Any XN WHERE X eid %(x)s, X title XN', {'x': beid})[0][0]
         self.assertEqual(newname, 'toto-moved')
 
+    def test_update_not_exists(self):
+        rset = self.execute("INSERT Personne X, Societe Y: X nom 'bidule', Y nom 'toto'")
+        eid1, eid2 = rset[0][0], rset[0][1]
+        rset = self.execute("SET X travaille Y WHERE X eid %(x)s, Y eid %(y)s, "
+                            "NOT EXISTS(Z ecrit_par X)",
+                            {'x': unicode(eid1), 'y': unicode(eid2)})
+        self.assertEqual(tuplify(rset.rows), [(eid1, eid2)])
+
     def test_update_query_error(self):
         self.execute("INSERT Personne Y: Y nom 'toto'")
         self.assertRaises(Exception, self.execute, "SET X nom 'toto', X is Personne")
         self.assertRaises(QueryError, self.execute, "SET X nom 'toto', X has_text 'tutu' WHERE X is Personne")
         self.assertRaises(QueryError, self.execute, "SET X login 'tutu', X eid %s" % cnx.user(self.session).eid)
 
+
     # HAVING on write queries test #############################################
 
     def test_update_having(self):
--- a/test/data/entities.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/test/data/entities.py	Wed Aug 07 09:02:47 2013 +0200
@@ -28,6 +28,9 @@
     fetch_attrs, cw_fetch_order = fetch_config(['nom', 'prenom'])
     rest_attr = 'nom'
 
+class Ami(Societe):
+    __regid__ = 'Ami'
+    rest_attr = 'nom'
 
 class Note(AnyEntity):
     __regid__ = 'Note'
--- a/test/data/schema.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/test/data/schema.py	Wed Aug 07 09:02:47 2013 +0200
@@ -44,6 +44,10 @@
     associe = SubjectRelation('Personne', cardinality='1*',
                               constraints=[RQLConstraint('S actionnaire SOC, O actionnaire SOC')])
 
+class Ami(EntityType):
+    """A Person, for which surname is not required"""
+    prenom = String()
+    nom = String()
 
 class Societe(EntityType):
     nom = String()
--- a/test/unittest_entity.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/test/unittest_entity.py	Wed Aug 07 09:02:47 2013 +0200
@@ -692,16 +692,16 @@
         person.cw_clear_all_caches()
         self.assertEqual(person.rest_path(), unicode(person.eid))
         self.assertEqual(person2.rest_path(), unicode(person2.eid))
-        # unique attr with None value (wikiid in this case)
-        card1 = req.create_entity('Card', title=u'hop')
-        self.assertEqual(card1.rest_path(), unicode(card1.eid))
+        # unique attr with None value (nom in this case)
+        friend = req.create_entity('Ami', prenom=u'bob')
+        self.assertEqual(friend.rest_path(), unicode(friend.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.assertEqual(card2.rest_path(), unicode(card2.eid))
-        card3 = req.create_entity('Card', title=u'pod', wikiid=u'zo&bi')
-        self.assertEqual(card3.rest_path(), unicode(card3.eid))
-        card4 = req.create_entity('Card', title=u'pod', wikiid=u'zo?bi')
-        self.assertEqual(card4.rest_path(), unicode(card4.eid))
+        person3 = req.create_entity('Personne', nom=u'zo/bi')
+        self.assertEqual(person3.rest_path(), unicode(person3.eid))
+        person4 = req.create_entity('Personne', nom=u'zo&bi')
+        self.assertEqual(person4.rest_path(), unicode(person4.eid))
+        person5 = req.create_entity('Personne', nom=u'zo?bi')
+        self.assertEqual(person5.rest_path(), unicode(person5.eid))
 
 
     def test_cw_set_attributes(self):
--- a/test/unittest_schema.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/test/unittest_schema.py	Wed Aug 07 09:02:47 2013 +0200
@@ -157,7 +157,7 @@
         self.assert_(isinstance(schema, CubicWebSchema))
         self.assertEqual(schema.name, 'data')
         entities = sorted([str(e) for e in schema.entities()])
-        expected_entities = ['BaseTransition', 'BigInt', 'Bookmark', 'Boolean', 'Bytes', 'Card',
+        expected_entities = ['Ami', 'BaseTransition', 'BigInt', 'Bookmark', 'Boolean', 'Bytes', 'Card',
                              'Date', 'Datetime', 'Decimal',
                              'CWCache', 'CWConstraint', 'CWConstraintType', 'CWDataImport',
                              'CWEType', 'CWAttribute', 'CWGroup', 'EmailAddress', 'CWRelation',
--- a/web/formfields.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/web/formfields.py	Wed Aug 07 09:02:47 2013 +0200
@@ -506,7 +506,7 @@
             if field is self:
                 try:
                     value = field.process_form_value(form)
-                    if value is None and field.required:
+                    if field.no_value(value) and field.required:
                         raise ProcessFormError(form._cw._("required field"))
                     yield field, value
                 except UnmodifiedField:
@@ -517,6 +517,11 @@
                 for field, value in field.process_posted(form):
                     yield field, value
 
+    @staticmethod
+    def no_value(value):
+        """return True if the value can be considered as no value for the field"""
+        return value is None
+
 
 class StringField(Field):
     """Use this field to edit unicode string (`String` yams type). This field
@@ -1170,6 +1175,12 @@
             eids.add(typed_eid)
         return eids
 
+    @staticmethod
+    def no_value(value):
+        """return True if the value can be considered as no value for the field"""
+        # value is None is the 'not yet ready value, consider the empty set
+        return value is not None and not value
+
 
 _AFF_KWARGS = uicfg.autoform_field_kwargs
 
--- a/web/test/data/schema.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/web/test/data/schema.py	Wed Aug 07 09:02:47 2013 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -15,9 +15,6 @@
 #
 # You should have received a copy of the GNU Lesser General Public License along
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
 
 from yams.buildobjs import (EntityType, RelationDefinition, SubjectRelation,
                             String, Int, Datetime, Boolean, Float)
--- a/web/test/unittest_views_basecontrollers.py	Tue Jul 30 20:31:57 2013 +0200
+++ b/web/test/unittest_views_basecontrollers.py	Wed Aug 07 09:02:47 2013 +0200
@@ -645,6 +645,34 @@
         finally:
             p.__class__.skip_copy_for = old_skips
 
+    def test_regr_inlined_forms(self):
+        self.schema['described_by_test'].inlined = False
+        try:
+            req = self.request()
+            req.data['eidmap'] = {}
+            req.data['pending_others'] = set()
+            req.data['pending_inlined'] = {}
+            req.form = {'eid': ['X', 'Y'], '__maineid' : 'X',
+
+                        '__type:X': 'Salesterm',
+                        '_cw_entity_fields:X': 'described_by_test-subject',
+                        'described_by_test-subject:X': 'Y',
+
+                        '__type:Y': 'File',
+                        '_cw_entity_fields:Y': 'data-subject',
+                        'data-subject:Y': (u'coucou.txt', Binary('coucou')),
+                        }
+            values_by_eid = dict((eid, req.extract_entity_params(eid, minparams=2))
+                                 for eid in req.edited_eids())
+            editctrl = self.vreg['controllers'].select('edit', req)
+            # don't call publish to enforce select order
+            editctrl.errors = []
+            editctrl._to_create = {}
+            editctrl.edit_entity(values_by_eid['X']) # #3064653 raise ValidationError
+            editctrl.edit_entity(values_by_eid['Y'])
+        finally:
+            self.schema['described_by_test'].inlined = False
+
 
 class ReportBugControllerTC(CubicWebTC):