From e9d29e509f40c9bc039bf0fec526e928c2aaca35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 16 Dec 2008 13:50:02 +0100 Subject: [PATCH 1/5] Fix creation of translation in xml import --- trytond/tools/convert.py | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/trytond/tools/convert.py b/trytond/tools/convert.py index 191018fd01..f6e3e107ab 100644 --- a/trytond/tools/convert.py +++ b/trytond/tools/convert.py @@ -563,13 +563,28 @@ class TrytondXmlHandler(sax.handler.ContentHandler): object_ref._inherit_fields[field_name][0])._name res_id = inherit_db_ids[table_name] if field.translate and values.get(field_name): - cursor.execute('INSERT INTO ir_translation ' \ - '(name, lang, type, src, res_id, ' \ - 'value, module, fuzzy) ' \ - 'VALUES (%s, %s, %s, %s, %s, %s, %s, false)', + cursor.execute('SELECT id FROM ir_translation ' \ + 'WHERE name = %s ' \ + 'AND lang = %s ' \ + 'AND type = %s ' \ + 'AND res_id = %s ' \ + 'AND module = %s', (table_name + ',' + field_name, - 'en_US', 'model', values[field_name], - res_id, '', module)) + 'en_US', 'model', res_id, module)) + if cursor.rowcount: + trans_id = cursor.fetchone()[0] + cursor.execute('UPDATE ir_translation ' \ + 'SET src = %s, module = %s ' \ + 'WHERE id = %s', + (values[field_name], module, trans_id)) + else: + cursor.execute('INSERT INTO ir_translation ' \ + '(name, lang, type, src, res_id, ' \ + 'value, module, fuzzy) ' \ + 'VALUES (%s, %s, %s, %s, %s, %s, %s, false)', + (table_name + ',' + field_name, + 'en_US', 'model', values[field_name], + res_id, '', module)) for table in inherit_db_ids.keys(): data_id = self.modeldata_obj.search(cursor, user, [ @@ -680,12 +695,13 @@ class TrytondXmlHandler(sax.handler.ContentHandler): res_id = inherit_db_ids[table_name] if field.translate: cursor.execute('SELECT id FROM ir_translation ' \ - 'WHERE name = %s' \ + 'WHERE name = %s ' \ 'AND lang = %s ' \ 'AND type = %s ' \ - 'AND res_id = %s', + 'AND res_id = %s ' \ + 'AND module = %s', (table_name + ',' + field_name, - 'en_US', 'model', res_id)) + 'en_US', 'model', res_id, module)) if cursor.rowcount: if to_update.get(field_name): trans_id = cursor.fetchone()[0] From b460852a2de95ce0cbf49319109554aeeb4093f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 16 Dec 2008 13:57:19 +0100 Subject: [PATCH 2/5] Improve xml import by using a BrowseRecordList for existing records --- trytond/tools/convert.py | 128 +++++++++++++++++++++++++++------------ 1 file changed, 88 insertions(+), 40 deletions(-) diff --git a/trytond/tools/convert.py b/trytond/tools/convert.py index f6e3e107ab..ed9262526e 100644 --- a/trytond/tools/convert.py +++ b/trytond/tools/convert.py @@ -291,18 +291,28 @@ class Fs2bdAccessor: Provide some helper function to ease cache access and management. """ - def __init__(self, cursor, user, modeldata_obj): + def __init__(self, cursor, user, modeldata_obj, pool): self.fs2db = {} self.fetched_modules = [] self.modeldata_obj = modeldata_obj self.cursor = cursor self.user = user + self.browserecord = {} + self.pool = pool def get(self, module, fs_id): if module not in self.fetched_modules: self.fetch_new_module(module) return self.fs2db[module].get(fs_id, None) + def get_browserecord(self, module, model_name, db_id): + if module not in self.fetched_modules: + self.fetch_new_module(module) + if model_name in self.browserecord[module] \ + and db_id in self.browserecord[module][model_name]: + return self.browserecord[module][model_name][db_id] + return None + def set(self, module, fs_id, values): """ Whe call the prefetch function here to. Like that whe are sure @@ -316,6 +326,23 @@ class Fs2bdAccessor: for key, val in values.items(): fs2db_val[key] = val + def reset_browsercord(self, module, model_name, ids=None): + if module not in self.fetched_modules: + return + if model_name not in self.browserecord[module]: + return + model_obj = self.pool.get(model_name) + if not ids: + object_ids = self.browserecord[module][model_name].keys() + else: + if isinstance(ids, (int, long)): + object_ids = [ids] + else: + object_ids = ids + models = model_obj.browse(self.cursor, self.user, object_ids) + for model in models: + self.browserecord[module][model_name][model.id] = model + def fetch_new_module(self, module): if module == "ir.ui.menu": raise self.fs2db[module] = {} @@ -324,12 +351,27 @@ class Fs2bdAccessor: ('module', '=', module), ('inherit', '=', False), ]) + + record_ids = {} for rec in self.modeldata_obj.browse( self.cursor, self.user, module_data_ids): self.fs2db[rec.module][rec.fs_id] = { "db_id": rec.db_id, "model": rec.model, "id": rec.id, "values": rec.values } + record_ids.setdefault(rec.model, []) + record_ids[rec.model].append(rec.db_id) + + self.browserecord[module] = {} + for model_name in record_ids.keys(): + model_obj = self.pool.get(model_name) + self.browserecord[module][model_name] = {} + ids = model_obj.search(self.cursor, self.user, [ + ('id', 'in', record_ids[model_name]), + ], context={'active_test': False}) + models = model_obj.browse(self.cursor, self.user, ids) + for model in models: + self.browserecord[module][model_name][model.id] = model self.fetched_modules.append(module) @@ -343,7 +385,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler): self.user = 0 self.module = module self.modeldata_obj = pool.get('ir.model.data') - self.fs2db = Fs2bdAccessor(cursor, self.user, self.modeldata_obj) + self.fs2db = Fs2bdAccessor(cursor, self.user, self.modeldata_obj, pool) self.to_delete = self.populate_to_delete() # Tag handlders are used to delegate the processing @@ -541,8 +583,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler): "data with the wrong model: %s (module: %s)" % (fs_id, module)) #Re-create object if it was deleted - if not object_ref.search(cursor, user, [('id', '=', db_id)], - context={'active_test': False}): + if not self.fs2db.get_browserecord(module, object_ref._name, db_id): db_id = object_ref.create(cursor, user, values, context={'module': module}) @@ -617,7 +658,9 @@ class TrytondXmlHandler(sax.handler.ContentHandler): }) self.fs2db.get(module, fs_id)["db_id"] = db_id - db_val = object_ref.browse(cursor, user, db_id) + db_val = self.fs2db.get_browserecord(module, object_ref._name, db_id) + if not db_val: + db_val = object_ref.browse(cursor, user, db_id) to_update = {} for key in values: @@ -665,6 +708,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler): # write the values in the db: object_ref.write(cursor, user, db_id, to_update, context={'module': module}) + self.fs2db.reset_browsercord(module, object_ref._name, db_id) if not inherit_db_ids: @@ -682,46 +726,50 @@ class TrytondXmlHandler(sax.handler.ContentHandler): inherit_mdata_ids.append((table, data_id)) #Update/Create translation record for field translatable - for field_name in object_ref._columns.keys() + \ - object_ref._inherit_fields.keys(): - if field_name in object_ref._columns: - field = object_ref._columns[field_name] - table_name = object_ref._name - res_id = db_id - else: - field = object_ref._inherit_fields[field_name][2] - table_name = self.pool.get( - object_ref._inherit_fields[field_name][0])._name - res_id = inherit_db_ids[table_name] - if field.translate: - cursor.execute('SELECT id FROM ir_translation ' \ - 'WHERE name = %s ' \ - 'AND lang = %s ' \ - 'AND type = %s ' \ - 'AND res_id = %s ' \ - 'AND module = %s', - (table_name + ',' + field_name, - 'en_US', 'model', res_id, module)) - if cursor.rowcount: - if to_update.get(field_name): - trans_id = cursor.fetchone()[0] - cursor.execute('UPDATE ir_translation ' \ - 'SET src = %s, module = %s ' \ - 'WHERE id = %s', - (to_update[field_name], module, trans_id)) - elif values.get(field_name): - cursor.execute('INSERT INTO ir_translation ' \ - '(name, lang, type, src, res_id, ' \ - 'value, module, fuzzy) ' \ - 'VALUES (%s, %s, %s, %s, %s, %s, %s, false)', + if to_update: + for field_name in object_ref._columns.keys() + \ + object_ref._inherit_fields.keys(): + if field_name in object_ref._columns: + field = object_ref._columns[field_name] + table_name = object_ref._name + res_id = db_id + else: + field = object_ref._inherit_fields[field_name][2] + table_name = self.pool.get( + object_ref._inherit_fields[field_name][0])._name + res_id = inherit_db_ids[table_name] + if field.translate: + cursor.execute('SELECT id FROM ir_translation ' \ + 'WHERE name = %s ' \ + 'AND lang = %s ' \ + 'AND type = %s ' \ + 'AND res_id = %s ' \ + 'AND module = %s', (table_name + ',' + field_name, - 'en_US', 'model', values[field_name], - res_id, '', module)) + 'en_US', 'model', res_id, module)) + if cursor.rowcount: + if to_update.get(field_name): + trans_id = cursor.fetchone()[0] + cursor.execute('UPDATE ir_translation ' \ + 'SET src = %s, module = %s ' \ + 'WHERE id = %s', + (to_update[field_name], module, trans_id)) + elif values.get(field_name): + cursor.execute('INSERT INTO ir_translation ' \ + '(name, lang, type, src, res_id, ' \ + 'value, module, fuzzy) ' \ + 'VALUES (%s, %s, %s, %s, %s, %s, %s, false)', + (table_name + ',' + field_name, + 'en_US', 'model', values[field_name], + res_id, '', module)) if to_update: # re-read it: this ensure that we store the real value # in the model_data table: - db_val = object_ref.browse(cursor, user, db_id) + db_val = self.fs2db.get_browserecord(module, object_ref._name, + db_id) + if not db_val: + db_val = object_ref.browse(cursor, user, db_id) for key in to_update: try: values[key] = self._clean_value( From bf44fea46a31e2e0680f242618a453bb5abf9d49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 16 Dec 2008 19:15:11 +0100 Subject: [PATCH 3/5] Fix find_in_path to return the name if not found in path --- trytond/tools/misc.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/trytond/tools/misc.py b/trytond/tools/misc.py index 69287a5fbf..f0695ac925 100644 --- a/trytond/tools/misc.py +++ b/trytond/tools/misc.py @@ -1,4 +1,5 @@ -#This file is part of Tryton. The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. +#This file is part of Tryton. The COPYRIGHT file at the top level of +#this repository contains the full copyright notices and license terms. # -*- coding: utf-8 -*- """ Miscelleanous tools used by tryton @@ -27,7 +28,7 @@ def find_in_path(name): val = os.path.join(directory, name) if os.path.isfile(val) or os.path.islink(val): return val - return None + return name def find_pg_tool(name): if CONFIG['pg_path'] and CONFIG['pg_path'] != 'None': From 9519dd036e6f4408a42d6024ed3297279de98d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 16 Dec 2008 20:46:00 +0100 Subject: [PATCH 4/5] Add migration from 1.0 remove multi on ir.action.act_window.view for issue670 --- trytond/ir/action.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/trytond/ir/action.py b/trytond/ir/action.py index 125fa65dd6..bcb30bab1c 100644 --- a/trytond/ir/action.py +++ b/trytond/ir/action.py @@ -3,6 +3,7 @@ "Action" from trytond.osv import fields, OSV from trytond.tools import file_open +from trytond.sql_db import table_handler class Action(OSV): @@ -411,6 +412,15 @@ class ActionActWindowView(OSV): super(ActionActWindowView, self).__init__() self._order.insert(0, ('sequence', 'ASC')) + def _auto_init(self, cursor, module_name): + super(ActionActWindowView, self)._auto_init(cursor, module_name) + table = table_handler(cursor, self._table, self._name, module_name) + + # Migration from 1.0 remove multi + if 'multi' in table.table: + cursor.execute('ALTER TABLE "' + self._table + '" ' \ + 'DROP COLUMN multi') + ActionActWindowView() From 2fd972b8f93c33a6a1437a9a11aeba4f6d0b6986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 17 Dec 2008 12:59:12 +0100 Subject: [PATCH 5/5] Add replace_attributes for xpath tag --- CHANGELOG | 1 + doc/views.rst | 2 +- trytond/ir/ui/board.rnc | 6 ++++-- trytond/ir/ui/board.rng | 2 ++ trytond/ir/ui/form.rnc | 2 +- trytond/ir/ui/form.rng | 1 + trytond/ir/ui/graph.rnc | 2 +- trytond/ir/ui/graph.rng | 1 + trytond/ir/ui/tree.rnc | 3 ++- trytond/ir/ui/tree.rng | 2 ++ trytond/osv/orm.py | 4 ++++ 11 files changed, 20 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b6b74aaf72..f04f3a08f5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Add replace_attributes for xpath tag * Add email paramter on report action * Allow to inherit views from an other model * Add user warnings diff --git a/doc/views.rst b/doc/views.rst index 12b47968a1..bf2289fc09 100644 --- a/doc/views.rst +++ b/doc/views.rst @@ -430,7 +430,7 @@ xpath * ``expr``: the xpath expression to find a node in the inherited view. - * ``position``: Define the position from the finded node, it can be ``before``, ``after``, ``replace``, ``inside``. + * ``position``: Define the position from the finded node, it can be ``before``, ``after``, ``replace``, ``inside`` or ``replace_attributes`` which will change the attributes. Example +++++++ diff --git a/trytond/ir/ui/board.rnc b/trytond/ir/ui/board.rnc index 9e30c02b21..86dc2cb72b 100644 --- a/trytond/ir/ui/board.rnc +++ b/trytond/ir/ui/board.rnc @@ -149,12 +149,14 @@ xpath = element xpath { attlist.xpath, | action | page | child1 - | child2)* + | child2 + | board + )* } attlist.xpath &= attribute expr { text } attlist.xpath &= [ a:defaultValue = "inside" ] - attribute position { "inside" | "replace" | "after" | "before" }? + attribute position { "inside" | "replace" | "replace_attributes" | "after" | "before" }? action |= notAllowed label |= notAllowed start = data | board | label diff --git a/trytond/ir/ui/board.rng b/trytond/ir/ui/board.rng index e4cf28655d..f66f7bd0c7 100644 --- a/trytond/ir/ui/board.rng +++ b/trytond/ir/ui/board.rng @@ -442,6 +442,7 @@ + @@ -455,6 +456,7 @@ inside replace + replace_attributes after before diff --git a/trytond/ir/ui/form.rnc b/trytond/ir/ui/form.rnc index d64c3211cf..b11d15346f 100644 --- a/trytond/ir/ui/form.rnc +++ b/trytond/ir/ui/form.rnc @@ -272,6 +272,6 @@ xpath = element xpath { attlist.xpath, attlist.xpath &= attribute expr { text } attlist.xpath &= [ a:defaultValue = "inside" ] - attribute position { "inside" | "replace" | "after" | "before" }? + attribute position { "inside" | "replace" | "replace_attributes" | "after" | "before" }? start = data | form diff --git a/trytond/ir/ui/form.rng b/trytond/ir/ui/form.rng index 9c5f00384a..9319a53fb7 100644 --- a/trytond/ir/ui/form.rng +++ b/trytond/ir/ui/form.rng @@ -865,6 +865,7 @@ inside replace + replace_attributes after before diff --git a/trytond/ir/ui/graph.rnc b/trytond/ir/ui/graph.rnc index 526cb6575e..bf0f7f2713 100644 --- a/trytond/ir/ui/graph.rnc +++ b/trytond/ir/ui/graph.rnc @@ -34,5 +34,5 @@ xpath = element xpath { attlist.xpath, attlist.xpath &= attribute expr { text } attlist.xpath &= [ a:defaultValue = "inside" ] - attribute position { "inside" | "replace" | "after" | "before" }? + attribute position { "inside" | "replace" | "replace_attributes" | "after" | "before" }? start = data | graph diff --git a/trytond/ir/ui/graph.rng b/trytond/ir/ui/graph.rng index a7b691bbc8..4b1e6070ed 100644 --- a/trytond/ir/ui/graph.rng +++ b/trytond/ir/ui/graph.rng @@ -152,6 +152,7 @@ inside replace + replace_attributes after before diff --git a/trytond/ir/ui/tree.rnc b/trytond/ir/ui/tree.rnc index 1e4a03789b..f5b0969ac8 100644 --- a/trytond/ir/ui/tree.rnc +++ b/trytond/ir/ui/tree.rnc @@ -67,10 +67,11 @@ attlist.data &= empty xpath = element xpath { attlist.xpath, (field | button + | tree )* } attlist.xpath &= attribute expr { text } attlist.xpath &= [ a:defaultValue = "inside" ] - attribute position { "inside" | "replace" | "after" | "before" }? + attribute position { "inside" | "replace" | "replace_attributes" | "after" | "before" }? start = tree | data diff --git a/trytond/ir/ui/tree.rng b/trytond/ir/ui/tree.rng index 70d92618f3..605ea80632 100644 --- a/trytond/ir/ui/tree.rng +++ b/trytond/ir/ui/tree.rng @@ -211,6 +211,7 @@ + @@ -224,6 +225,7 @@ inside replace + replace_attributes after before diff --git a/trytond/osv/orm.py b/trytond/osv/orm.py index 197a50aede..60a6fa64b1 100644 --- a/trytond/osv/orm.py +++ b/trytond/osv/orm.py @@ -2224,6 +2224,10 @@ class ORM(object): else: parent.extend(element2.getchildren()) parent.remove(element) + elif pos == 'replace_attributes': + child = element2.getchildren()[0] + for attr in child.attrib: + element.set(attr, child.get(attr)) elif pos == 'inside': element.extend(element2.getchildren()) elif pos == 'after':