diff --git a/bin/addons/base/res/res_user.py b/bin/addons/base/res/res_user.py
index 2b1d39381cc..e49578e9cc6 100644
--- a/bin/addons/base/res/res_user.py
+++ b/bin/addons/base/res/res_user.py
@@ -412,8 +412,14 @@ class users(osv.osv):
return self.name_get(cr, user, ids)
def copy(self, cr, uid, id, default=None, context={}):
- login = self.read(cr, uid, [id], ['login'])[0]['login']
- default.update({'login': login+' (copy)'})
+ user2copy = self.read(cr, uid, [id], ['login','name'])[0]
+ if default is None:
+ default = {}
+ copy_pattern = _("%s (copy)")
+ default.update(login=(copy_pattern % user2copy['login']),
+ name=(copy_pattern % user2copy['name']),
+ address_id=False, # avoid sharing the address of the copied user!
+ )
return super(users, self).copy(cr, uid, id, default, context)
def context_get(self, cr, uid, context=None):
diff --git a/bin/addons/base/rng/board.rng b/bin/addons/base/rng/board.rng
deleted file mode 100644
index 73477113f62..00000000000
--- a/bin/addons/base/rng/board.rng
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/bin/addons/base/rng/calendar.rng b/bin/addons/base/rng/calendar.rng
deleted file mode 100644
index 73477113f62..00000000000
--- a/bin/addons/base/rng/calendar.rng
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/bin/addons/base/rng/form.rng b/bin/addons/base/rng/form.rng
deleted file mode 100644
index b8a93c67549..00000000000
--- a/bin/addons/base/rng/form.rng
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/bin/addons/base/rng/gallery.rng b/bin/addons/base/rng/gallery.rng
deleted file mode 100644
index 73477113f62..00000000000
--- a/bin/addons/base/rng/gallery.rng
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/bin/addons/base/rng/graph.rng b/bin/addons/base/rng/graph.rng
deleted file mode 100644
index 73477113f62..00000000000
--- a/bin/addons/base/rng/graph.rng
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/bin/addons/base/rng/inherit.rng b/bin/addons/base/rng/inherit.rng
deleted file mode 100644
index 73477113f62..00000000000
--- a/bin/addons/base/rng/inherit.rng
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/bin/addons/base/rng/tree.rng b/bin/addons/base/rng/tree.rng
deleted file mode 100644
index 73477113f62..00000000000
--- a/bin/addons/base/rng/tree.rng
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/bin/osv/osv.py b/bin/osv/osv.py
index d75c9af564f..11db4096a9a 100644
--- a/bin/osv/osv.py
+++ b/bin/osv/osv.py
@@ -65,12 +65,19 @@ class osv_pool(netsvc.Service):
for key in self._sql_error.keys():
if key in inst[0]:
self.abortResponse(1, _('Constraint Error'), 'warning', _(self._sql_error[key]))
- if inst.pgcode == errorcodes.NOT_NULL_VIOLATION:
+ if inst.pgcode in (errorcodes.NOT_NULL_VIOLATION, errorcodes.FOREIGN_KEY_VIOLATION, errorcodes.RESTRICT_VIOLATION):
msg = _('The operation cannot be completed, probably due to the following:\n- deletion: you may be trying to delete a record while other records still reference it\n- creation/update: a mandatory field is not correctly set')
self.logger.debug("IntegrityError", exc_info=True)
try:
- context = inst.pgerror.split('"public".')[1]
- model_name = table = context.split('"')[1]
+ errortxt = inst.pgerror.replace('«','"').replace('»','"')
+ if '"public".' in errortxt:
+ context = errortxt.split('"public".')[1]
+ model_name = table = context.split('"')[1]
+ else:
+ last_quote_end = errortxt.rfind('"')
+ last_quote_begin = errortxt.rfind('"', 0, last_quote_end)
+ model_name = table = errortxt[last_quote_begin+1:last_quote_end].strip()
+ print "MODEL", last_quote_begin, last_quote_end, model_name
model = table.replace("_",".")
model_obj = self.get(model)
if model_obj:
diff --git a/bin/tools/convert.py b/bin/tools/convert.py
index a90de107b29..a8749514958 100644
--- a/bin/tools/convert.py
+++ b/bin/tools/convert.py
@@ -68,6 +68,24 @@ def _obj(pool, cr, uid, model_str, context=None):
model = pool.get(model_str)
return lambda x: model.browse(cr, uid, x, context=context)
+def _fix_multiple_roots(node):
+ """
+ Surround the children of the ``node`` element of an XML field with a
+ single root "data" element, to prevent having a document with multiple
+ roots once parsed separately.
+
+ XML nodes should have one root only, but we'd like to support
+ direct multiple roots in our partial documents (like inherited view architectures).
+ As a convention we'll surround multiple root with a container "data" element, to be
+ ignored later when parsing.
+ """
+
+ if len(node) > 1:
+ data_node = etree.Element("data")
+ for child in node:
+ data_node.append(child)
+ node.append(data_node)
+
def _eval_xml(self, node, pool, cr, uid, idref, context=None):
if context is None:
context = {}
@@ -115,6 +133,7 @@ def _eval_xml(self, node, pool, cr, uid, idref, context=None):
if not id in idref:
idref[id]=self.id_get(cr, False, id)
return s % idref
+ _fix_multiple_roots(node)
return '\n'\
+_process("".join([etree.tostring(n, encoding='utf-8')
for n in node]),