From 325f9b72a9096d32c53b34b81d769d7f4b74d155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 27 Apr 2011 23:50:21 +0200 Subject: [PATCH 001/128] Increase version number --- trytond/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/version.py b/trytond/version.py index 684428792e..3728c3be4c 100644 --- a/trytond/version.py +++ b/trytond/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "trytond" -VERSION = "2.0.0" +VERSION = "2.0.1" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From 34b6b447863d9f95562cb2943ff51f943bd4dcc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=C3=89vrard?= Date: Thu, 5 May 2011 10:43:42 +0200 Subject: [PATCH 002/128] Add missing src_md5 report_translation queries (transplanted from afa9acca511d5a9787c49c2cad2f3d94aa40a5dc) --- trytond/ir/translation.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/trytond/ir/translation.py b/trytond/ir/translation.py index ee9277cf34..142b9355c9 100644 --- a/trytond/ir/translation.py +++ b/trytond/ir/translation.py @@ -713,6 +713,7 @@ class ReportTranslationSet(Wizard): strings += self._translate_report(document.documentElement) for string in {}.fromkeys(strings).keys(): + src_md5 = self.get_src_md5(string) done = False if string in trans_reports: del trans_reports[string] @@ -729,22 +730,24 @@ class ReportTranslationSet(Wizard): if seqmatch.ratio() > 0.6: cursor.execute('UPDATE ir_translation ' \ 'SET src = %s, ' \ - 'fuzzy = %s ' \ + 'fuzzy = %s, ' \ + 'src_md5 = %s ' \ 'WHERE name = %s ' \ 'AND type = %s ' \ 'AND src = %s ' \ 'AND module = %s', - (string, True, report.report_name, 'odt', - string_trans, report.module)) + (string, True, src_md5, report.report_name, + 'odt', string_trans, report.module)) del trans_reports[string_trans] done = True break if not done: cursor.execute('INSERT INTO ir_translation ' \ - '(name, lang, type, src, value, module, fuzzy)' \ - 'VALUES (%s, %s, %s, %s, %s, %s, %s)', + '(name, lang, type, src, value, module, fuzzy, '\ + 'src_md5)' \ + 'VALUES (%s, %s, %s, %s, %s, %s, %s, %s)', (report.report_name, 'en_US', 'odt', string, '', - report.module, False)) + report.module, False, src_md5)) if strings: cursor.execute('DELETE FROM ir_translation ' \ 'WHERE name = %s ' \ From 48a274f00cfb1a541bffd74fb8e4514da2c1cd4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 11 May 2011 10:18:10 +0200 Subject: [PATCH 003/128] Add missing icons (transplanted from af1e1890b2b042008337cee12ca4940882fa90e7) --- setup.py | 1 + trytond/ir/ui/icons/__init__.py | 0 2 files changed, 1 insertion(+) create mode 100644 trytond/ir/ui/icons/__init__.py diff --git a/setup.py b/setup.py index 553412e1be..72334deeee 100644 --- a/setup.py +++ b/setup.py @@ -32,6 +32,7 @@ setup(name=PACKAGE, 'trytond.ir': ['*.xml', '*.csv'], 'trytond.ir.module': ['*.xml'], 'trytond.ir.ui': ['*.xml', '*.rng', '*.rnc'], + 'trytond.ir.ui.icons': ['*.svg'], 'trytond.res': ['*.xml', '*.csv'], 'trytond.webdav': ['*.xml', '*.csv'], 'trytond.workflow': ['*.xml', '*.csv'], diff --git a/trytond/ir/ui/icons/__init__.py b/trytond/ir/ui/icons/__init__.py new file mode 100644 index 0000000000..e69de29bb2 From 20916e75f5ed3f2ba9cfbbb0394a78ef11a8ae09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 16 May 2011 12:22:43 +0200 Subject: [PATCH 004/128] Fix missing closing of database cursor (transplanted from 950d36d59250a1f23e23c2245391b2d92e45013e) --- trytond/protocols/dispatcher.py | 7 ++-- trytond/protocols/webdav.py | 9 +++--- trytond/server.py | 57 ++++++++++++++++++--------------- 3 files changed, 41 insertions(+), 32 deletions(-) diff --git a/trytond/protocols/dispatcher.py b/trytond/protocols/dispatcher.py index 2faa8187d8..3767b2799d 100644 --- a/trytond/protocols/dispatcher.py +++ b/trytond/protocols/dispatcher.py @@ -33,6 +33,7 @@ def dispatch(host, port, protocol, database_name, user, session, object_type, try: database = Database(database_name).connect() cursor = database.cursor() + cursor.close() except Exception: return False res = security.login(database_name, user, session) @@ -80,8 +81,10 @@ def dispatch(host, port, protocol, database_name, user, session, object_type, database = Database().connect() try: cursor = database.cursor() - res = database.list(cursor) - cursor.close(close=True) + try: + res = database.list(cursor) + finally: + cursor.close(close=True) except Exception: res = [] return res diff --git a/trytond/protocols/webdav.py b/trytond/protocols/webdav.py index e29fe3d53d..f55d98ec3c 100644 --- a/trytond/protocols/webdav.py +++ b/trytond/protocols/webdav.py @@ -170,12 +170,11 @@ class TrytonDAVInterface(iface.dav_interface): dbname, dburi = self._get_dburi(uri) if not dbname: database = Database().connect() + cursor = database.cursor() try: - try: - cursor = database.cursor() - lists = database.list(cursor) - except Exception: - lists = [] + lists = database.list(cursor) + except Exception: + lists = [] finally: cursor.close() for dbname in lists: diff --git a/trytond/server.py b/trytond/server.py index 419fb11b63..3822042885 100644 --- a/trytond/server.py +++ b/trytond/server.py @@ -87,26 +87,30 @@ class TrytonServer(object): database = Database(db_name).connect() cursor = database.cursor() - if CONFIG['init']: - if not cursor.test(): - self.logger.info("init db") - Database.init(cursor) - init[db_name] = True - cursor.commit() + try: + if CONFIG['init']: + if not cursor.test(): + self.logger.info("init db") + Database.init(cursor) + init[db_name] = True + cursor.commit() + elif not cursor.test(): + raise Exception("'%s' is not a Tryton database!" % db_name) + finally: cursor.close() - elif not cursor.test(): - raise Exception("'%s' is not a Tryton database!" % db_name) Pool.start() for db_name in CONFIG["db_name"]: cursor = Database(db_name).connect().cursor() - if not cursor.test(): - raise Exception("'%s' is not a Tryton database!" % db_name) - cursor.execute('SELECT code FROM ir_lang ' \ - 'WHERE translatable') - lang = [x[0] for x in cursor.fetchall()] - cursor.close() + try: + if not cursor.test(): + raise Exception("'%s' is not a Tryton database!" % db_name) + cursor.execute('SELECT code FROM ir_lang ' \ + 'WHERE translatable') + lang = [x[0] for x in cursor.fetchall()] + finally: + cursor.close() update = bool(CONFIG['init'] or CONFIG['update']) Pool(db_name).init(update=update, lang=lang) @@ -129,17 +133,20 @@ class TrytonServer(object): database = Database(db_name).connect() cursor = database.cursor() - salt = ''.join(random.sample(string.letters + string.digits, 8)) - password += salt - if hashlib: - password = hashlib.sha1(password).hexdigest() - else: - password = sha.new(password).hexdigest() - cursor.execute('UPDATE res_user ' \ - 'SET password = %s, salt = %s ' \ - 'WHERE login = \'admin\'', (password, salt)) - cursor.commit() - cursor.close() + try: + salt = ''.join(random.sample( + string.letters + string.digits, 8)) + password += salt + if hashlib: + password = hashlib.sha1(password).hexdigest() + else: + password = sha.new(password).hexdigest() + cursor.execute('UPDATE res_user ' \ + 'SET password = %s, salt = %s ' \ + 'WHERE login = \'admin\'', (password, salt)) + cursor.commit() + finally: + cursor.close() if update: self.logger.info('Update/Init succeed!') From 06fe85241fd1f42470e4c425da5250381ff02da4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 23 May 2011 17:03:08 +0200 Subject: [PATCH 005/128] Search for zip file not above of root_path (transplanted from 2b1deeccc83884d4f6339a590ae519f9e739e807) --- trytond/tools/misc.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/trytond/tools/misc.py b/trytond/tools/misc.py index 95092baaa2..0639eab3ed 100644 --- a/trytond/tools/misc.py +++ b/trytond/tools/misc.py @@ -119,6 +119,8 @@ def file_open(name, mode="r", subdir='modules'): name2 = False while True: head, tail = os.path.split(head) + if head == root_path: + break if not tail: break if zipname: From c3d3212414d4f7077437acac006ec58c7be3fafc Mon Sep 17 00:00:00 2001 From: Sharoon Thomas Date: Wed, 25 May 2011 20:11:52 -0400 Subject: [PATCH 006/128] Add *.xml in trytond.test which is required for import_data.xml to be copied to site-packages fixes Issue2030 (transplanted from 0fb7dff0e74bc08a68d4a6760e4242376845ba30) --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 72334deeee..5bb69db1e5 100644 --- a/setup.py +++ b/setup.py @@ -36,6 +36,7 @@ setup(name=PACKAGE, 'trytond.res': ['*.xml', '*.csv'], 'trytond.webdav': ['*.xml', '*.csv'], 'trytond.workflow': ['*.xml', '*.csv'], + 'trytond.test': ['*.xml'], }, scripts=['bin/trytond'], classifiers=[ From 35b77bf4aaac6fdeb23277fbac7e75c32f4c0feb Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Sun, 29 May 2011 14:20:45 +0200 Subject: [PATCH 007/128] Prepare release 2.0.1 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index b25add96c6..97ddc4b4dd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.0.1 - 2011-05-29 +* Bug fixes (see mercurial logs for details) + Version 2.0.0 - 2011-04-26 * Bug fixes (see mercurial logs for details) * Use md5 hash for indexing translation From 041d492a2abdf8eafcf3fc05de41f56466d8f8f5 Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Sun, 29 May 2011 14:20:45 +0200 Subject: [PATCH 008/128] Added tag 2.0.1 for changeset b7c3a0a60346 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 393d220fbc..96b2e9600c 100644 --- a/.hgtags +++ b/.hgtags @@ -4,3 +4,4 @@ e2d31d59de7745de70199b7c340d78b7c4775723 1.4.0 64691214959ac19983f3b3d1dbb89ff693d1545c 1.6.0 af3a6063b46bf8739a513a06400fbb9858b5869b 1.8.0 3475040a8fe081b1b8609350186b779cc640fba4 2.0.0 +b7c3a0a6034631032867ba0f33c26b7786ebe89a 2.0.1 From d07c4c12d0f314c01676aea5278459cb97baf567 Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Sun, 29 May 2011 14:21:04 +0200 Subject: [PATCH 009/128] Increase version number --- trytond/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/version.py b/trytond/version.py index 3728c3be4c..0d6af84889 100644 --- a/trytond/version.py +++ b/trytond/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "trytond" -VERSION = "2.0.1" +VERSION = "2.0.2" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From 4c8d468d019c14acdb80abe56df7b7a50bd88f0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 26 May 2011 16:22:10 +0200 Subject: [PATCH 010/128] Fix wrong operator <> in ir.rule for issue2029 (transplanted from 19c028d146c582e733f062e13a2b3b8f149edabf) --- trytond/ir/rule.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/trytond/ir/rule.py b/trytond/ir/rule.py index 9cf62eb525..cce65203ad 100644 --- a/trytond/ir/rule.py +++ b/trytond/ir/rule.py @@ -191,8 +191,11 @@ class Rule(ModelSQL, ModelView): with contextlib.nested(Transaction().set_user(0), Transaction().set_context(user=0)): for rule in self.browse(ids): + operator = rule.operator + if operator == '<>': + operator = '!=' dom = safe_eval("[('%s', '%s', %s)]" % \ - (rule.field.name, rule.operator, + (rule.field.name, operator, operand2query[rule.operand]), { 'user': self.pool.get('res.user').browse(user), 'time': time, From 2b8a411d5f2ccbc6b268e79d63c31b4ae7a3aa10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 31 May 2011 10:49:38 +0200 Subject: [PATCH 011/128] Get default value for inherited field only if there is a default method for issue2027 (transplanted from 296a6ca32553b913d1dacaae51fee7c58d267d04) --- trytond/model/modelsql.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index ba2de45fdd..7c0d204fec 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -253,8 +253,9 @@ class ModelSQL(ModelStorage): 'write_uid', 'write_date'): default.append(i) for i in self._inherit_fields.keys(): - if (not i in values) \ - and (not self._inherit_fields[i][0] in avoid_table): + if ((not i in values) + and (not self._inherit_fields[i][0] in avoid_table) + and i in self._defaults): default.append(i) if len(default): From 3ca89f4729f0359c84b94ed26889a47f3157f550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 7 Jun 2011 11:58:55 +0200 Subject: [PATCH 012/128] Signal is a keyword for MySQL 5.5 issue2037 review30006 (transplanted from 48f2144dd20e65a2478e09e46370c6fba83abf1b) --- trytond/backend/mysql/init.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/backend/mysql/init.sql b/trytond/backend/mysql/init.sql index cbb2a56bc4..bb500939fd 100644 --- a/trytond/backend/mysql/init.sql +++ b/trytond/backend/mysql/init.sql @@ -121,7 +121,7 @@ CREATE TABLE wkf_transition ( act_to BIGINT, `condition` VARCHAR(255), trigger_expr_id VARCHAR(255), - signal VARCHAR(255), + `signal` VARCHAR(255), `group` BIGINT, PRIMARY KEY(id), CONSTRAINT wkf_transition_act_from_fkey FOREIGN KEY (act_from) REFERENCES wkf_activity (id) ON DELETE CASCADE, From 804d2b273896842def2a9bc12b50a592e2a89dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=C3=89vrard?= Date: Wed, 8 Jun 2011 14:41:36 +0200 Subject: [PATCH 013/128] Add missing colspan attribute for action (transplanted from b06ae2c0538400dc6d62bd0aefb47e7a30119219) --- trytond/ir/ui/board.rnc | 1 + trytond/ir/ui/board.rng | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/trytond/ir/ui/board.rnc b/trytond/ir/ui/board.rnc index 06662802c0..19fd9c112a 100644 --- a/trytond/ir/ui/board.rnc +++ b/trytond/ir/ui/board.rnc @@ -144,5 +144,6 @@ attlist.xpath &= attribute position { "inside" | "replace" | "replace_attributes" | "after" | "before" }? action = element action { attlist.action, empty } attlist.action &= attribute name { text } +attlist.action &= [ a:defaultValue = "1" ] attribute colspan { text }? label |= notAllowed start = data | board | label diff --git a/trytond/ir/ui/board.rng b/trytond/ir/ui/board.rng index a0c90e3b8d..06d68504d2 100644 --- a/trytond/ir/ui/board.rng +++ b/trytond/ir/ui/board.rng @@ -447,6 +447,11 @@ + + + + + From f790e0cdf2dce5253d2275b7466a9dfd9741babc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 24 Jun 2011 16:10:31 +0200 Subject: [PATCH 014/128] Use rec_name instead of value of _rec_name when searching on Many2One issue2079 (transplanted from 8d556f0c816dba0c095231832c3514975d97ee39) --- trytond/model/modelsql.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 7c0d204fec..80c8460606 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -1601,7 +1601,7 @@ class ModelSQL(ModelStorage): if isinstance(domain[i][2], basestring): field_obj = self.pool.get(field.model_name) res_ids = field_obj.search([ - (field_obj._rec_name, domain[i][1], domain[i][2]), + ('rec_name', domain[i][1], domain[i][2]), ], order=[]) domain[i] = (domain[i][0], 'in', res_ids, table) else: From 9cf34b52b574d81e0ccfb2ae692c2c49687da690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 30 Jun 2011 14:02:56 +0200 Subject: [PATCH 015/128] Fix wrong call to get_src_md5 in ir.translation.set_report (transplanted from a7fedb291bb4e36fb17c3b3fa6e5534c7e7410f8) --- trytond/ir/translation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/trytond/ir/translation.py b/trytond/ir/translation.py index 142b9355c9..5206264c78 100644 --- a/trytond/ir/translation.py +++ b/trytond/ir/translation.py @@ -652,6 +652,7 @@ class ReportTranslationSet(Wizard): def _set_report_translation(self, data): report_obj = self.pool.get('ir.action.report') + translation_obj = self.pool.get('ir.translation') with Transaction().set_context(active_test=False): report_ids = report_obj.search([]) @@ -713,7 +714,7 @@ class ReportTranslationSet(Wizard): strings += self._translate_report(document.documentElement) for string in {}.fromkeys(strings).keys(): - src_md5 = self.get_src_md5(string) + src_md5 = translation_obj.get_src_md5(string) done = False if string in trans_reports: del trans_reports[string] From a7cfaf66dc65488f5e71f051ecea673786d40fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 6 Jul 2011 13:53:28 +0200 Subject: [PATCH 016/128] Add missing double quote on JOIN for field name review48006 (transplanted from 2fe9209da88ac48ad1eca163dba75fe98cf98191) --- trytond/model/modelsql.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 80c8460606..533cfba073 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -1344,7 +1344,7 @@ class ModelSQL(ModelStorage): table_query = '(' + table_query + ') AS ' table_join = 'LEFT JOIN ' + table_query + \ '"' + itable._table + '" ON ' \ - '"%s".id = "%s".%s' % (itable._table, self._table, + '"%s".id = "%s"."%s"' % (itable._table, self._table, self._inherits[itable._name]) if table_join not in tables: tables.append(table_join) @@ -1836,7 +1836,7 @@ class ModelSQL(ModelStorage): otype) table_join = 'LEFT JOIN "' + table_name + '" AS ' \ '"' + table_name + '.' + link_field + '" ON ' \ - '"%s.%s".id = "%s".%s' % (table_name, link_field, + '"%s.%s".id = "%s"."%s"' % (table_name, link_field, self._table, link_field) for i in range(len(order_by)): if table_name in order_by[i]: @@ -1872,7 +1872,7 @@ class ModelSQL(ModelStorage): table_join = 'LEFT JOIN "' + table_name + '" AS ' \ '"' + table_name + '.' + link_field + '" ON ' \ - '"%s.%s".id = "%s".%s' % \ + '"%s.%s".id = "%s"."%s"' % \ (table_name, link_field, self._table, link_field) for i in range(len(order_by)): if table_name in order_by[i]: @@ -1891,7 +1891,7 @@ class ModelSQL(ModelStorage): table_join2 = 'LEFT JOIN "' + table_name2 + '" AS ' \ '"' + table_name2 + '.' + link_field2 + '" ON ' \ - '"%s.%s".id = "%s.%s".%s' % \ + '"%s.%s".id = "%s.%s"."%s"' % \ (table_name2, link_field2, table_name, link_field, link_field2) for i in range(len(order_by)): @@ -1999,7 +1999,7 @@ class ModelSQL(ModelStorage): link_field = self._inherits[obj._name] order_by, tables, tables_args = obj._order_calc(field, otype) table_join = 'LEFT JOIN "' + table_name + '" ON ' \ - '"%s".id = "%s".%s' % \ + '"%s".id = "%s"."%s"' % \ (table_name, self._table, link_field) if table_join not in tables: tables.insert(0, table_join) From 9c6c5de2058561b1a53dbc449b60528df9e41389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 11 Jul 2011 20:57:10 +0200 Subject: [PATCH 017/128] Fix reduce_domain to keep empty clause review50005 (transplanted from 463420059075c9e080b7bc750c470f234e6b3622) --- trytond/tests/test_tools.py | 2 ++ trytond/tools/misc.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/trytond/tests/test_tools.py b/trytond/tests/test_tools.py index 60005efc3b..c6bb78c8be 100644 --- a/trytond/tests/test_tools.py +++ b/trytond/tests/test_tools.py @@ -118,6 +118,8 @@ class ToolsTestCase(unittest.TestCase): ['OR', clause, ['AND', clause, ['OR', clause, clause]]]), (['OR', [clause]], ['OR', ['AND', clause]]), ([], []), + (['OR', clause, []], ['OR', clause, []]), + (['AND', clause, []], ['AND', clause, []]), ) for i, j in tests: self.assertEqual(reduce_domain(i), j, diff --git a/trytond/tools/misc.py b/trytond/tools/misc.py index 0639eab3ed..186833492c 100644 --- a/trytond/tools/misc.py +++ b/trytond/tools/misc.py @@ -469,4 +469,6 @@ def reduce_domain(domain): result.extend(sub_domain[1:]) else: result.append(sub_domain) + else: + result.append(arg) return result From 6fabaca754e8131f805fa5fec6c51ed8cdae78c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 2 Aug 2011 13:30:43 +0200 Subject: [PATCH 018/128] Fix export row with inherited fields issue2102 (transplanted from 35119698fb1016a6858e573ebc3de980eb65ad4e) --- trytond/model/modelstorage.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/trytond/model/modelstorage.py b/trytond/model/modelstorage.py index b21b40df1d..a1fd99a9e8 100644 --- a/trytond/model/modelstorage.py +++ b/trytond/model/modelstorage.py @@ -532,7 +532,13 @@ class ModelStorage(Model): break field_name = fields_tree[i] model_obj = self.pool.get(value._model_name) - field = model_obj._columns[field_name] + if field_name in model_obj._columns: + field = model_obj._columns[field_name] + elif field_name in model_obj._inherit_fields: + field = model_obj._inherit_fields[field_name][2] + else: + raise Exception('Field %s not available on object "%s"' + % (field_name, model_obj._name)) if field.states and 'invisible' in field.states: pyson_invisible = PYSONEncoder().encode( field.states['invisible']) From cdbc8a83bd24fb126c78095d9332cf97d0dd3f8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 3 Aug 2011 12:11:32 +0200 Subject: [PATCH 019/128] Reset AUTO_INCREMENT of res_user The tests assume that "admin" user will have the id "1" but MySQL increments the sequence number even if an id is given so we have to reset it. (transplanted from 65c24ee332ff72f4035215ff11dafdd0ee24a9c7) --- trytond/backend/mysql/init.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/trytond/backend/mysql/init.sql b/trytond/backend/mysql/init.sql index bb500939fd..853775cf17 100644 --- a/trytond/backend/mysql/init.sql +++ b/trytond/backend/mysql/init.sql @@ -76,6 +76,7 @@ ALTER TABLE res_user ADD CONSTRAINT res_user_login_uniq UNIQUE (login); INSERT INTO res_user (id, login, password, name, active) VALUES (0, 'root', NULL, 'Root', False); UPDATE res_user set id = 0; +ALTER TABLE res_user AUTO_INCREMENT = 1; CREATE TABLE res_group ( id BIGINT AUTO_INCREMENT NOT NULL, From 0ca581fa5e5122d234f24df2608939c93a8e3edf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 22 Aug 2011 19:12:19 +0200 Subject: [PATCH 020/128] Cursor cache must depend of the user review90002 (transplanted from 862af40c1b9c8b98f76b312c26b72390f57302fc) --- trytond/backend/database.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/trytond/backend/database.py b/trytond/backend/database.py index 168d1f9624..f144646174 100644 --- a/trytond/backend/database.py +++ b/trytond/backend/database.py @@ -112,6 +112,8 @@ class CursorInterface(object): :param context: the context :return: the cache dictionary ''' + from trytond.transaction import Transaction + user = Transaction().user if context is None: context = {} cache_ctx = context.copy() @@ -119,7 +121,7 @@ class CursorInterface(object): '_delete_records'): if i in cache_ctx: del cache_ctx[i] - return self.cache.setdefault(repr(cache_ctx), {}) + return self.cache.setdefault((user, repr(cache_ctx)), {}) def execute(self, sql, params=None): ''' From 66c0d69ac09c3c7ec7e8d6d1137a3637796d5b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 27 Aug 2011 16:03:12 +0200 Subject: [PATCH 021/128] Don't store BrowseRecord in cursor cache review93001 (transplanted from 22cc25d44a42aeaf7e416858ff02b55e38e399f3) --- trytond/model/browse.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/trytond/model/browse.py b/trytond/model/browse.py index a23ac30eb4..15e86153e5 100644 --- a/trytond/model/browse.py +++ b/trytond/model/browse.py @@ -172,7 +172,9 @@ class BrowseRecord(object): data[i] = BrowseRecordList(BrowseRecord( x, model, local_cache=self._local_cache) for x in data[i]) - if isinstance(j, fields.Function): + if (isinstance(j, fields.Function) + or isinstance(data[i], (BrowseRecord, + BrowseRecordList))): self._local_data.setdefault(data['id'], {})[i] = data[i] del data[i] self._data[data['id']].update(data) From 1ee47ab73d6a1fd4b227ea7f5dc19cdbfa033bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 27 Aug 2011 16:04:36 +0200 Subject: [PATCH 022/128] Don't try to detect rounding issue with MySQL review74005 (transplanted from fb825597af989fdee01428af56a814ebd161d7dc) --- trytond/model/modelstorage.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/trytond/model/modelstorage.py b/trytond/model/modelstorage.py index a1fd99a9e8..2237562607 100644 --- a/trytond/model/modelstorage.py +++ b/trytond/model/modelstorage.py @@ -21,6 +21,7 @@ from trytond.tools import safe_eval, reduce_domain from trytond.pyson import PYSONEncoder, PYSONDecoder, PYSON from trytond.const import OPERATORS from trytond.transaction import Transaction +from trytond.config import CONFIG class ModelStorage(Model): @@ -1094,7 +1095,7 @@ class ModelStorage(Model): if not (value.quantize(Decimal(str(10.0**-digits[1]))) == value): raise_user_error() - else: + elif CONFIG.options['db_type'] != 'mysql': if not (round(value, digits[1]) == float(value)): raise_user_error() # validate digits From e2d838a09b9c609bcff7ce28cb28ffb754ea7eec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 2 Sep 2011 17:53:10 +0200 Subject: [PATCH 023/128] Fix typo in "add datetime_field" and iter on values intead of keys (transplanted from 5b45ffd9b313926fac29fa1faa8ce4ea2a45e187) --- trytond/model/browse.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/trytond/model/browse.py b/trytond/model/browse.py index 15e86153e5..d37cef18ec 100644 --- a/trytond/model/browse.py +++ b/trytond/model/browse.py @@ -114,12 +114,12 @@ class BrowseRecord(object): ffields = {name: col} # add datetime_field - for field in ffields: + for field in ffields.values(): if hasattr(field, 'datetime_field') and field.datetime_field: if field.datetime_field in self._model._columns: - date_field = self._model._columns[field.datetime_field] + datetime_field = self._model._columns[field.datetime_field] else: - date_field = self._model._inherit_fields[ + datetime_field = self._model._inherit_fields[ field.datetime_field][2] ffields[field.datetime_field] = datetime_field From 6371e1aae2659e08b8df60d35a24d7a57a9c3c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=C3=89vrard?= Date: Tue, 6 Sep 2011 12:00:15 +0200 Subject: [PATCH 024/128] Correctly compute if argument is a condition review100001 (transplanted from 9e6b871d4e288ad9b0f5d6217b440edc441514f0) --- trytond/model/fields/field.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/trytond/model/fields/field.py b/trytond/model/fields/field.py index 93e74edcd3..72f3af404d 100644 --- a/trytond/model/fields/field.py +++ b/trytond/model/fields/field.py @@ -11,11 +11,12 @@ def domain_validate(value): if isinstance(arg, basestring): if arg not in ('AND', 'OR'): return False - elif isinstance(arg, tuple) or \ - (isinstance(arg, list) and len(arg) > 2 and \ - (arg[1] in OPERATORS) or \ - (isinstance(arg[1], PYSON) and \ - arg[1].types() == set([str]))): + elif (isinstance(arg, tuple) + or (isinstance(arg, list) + and len(arg) > 2 + and ((arg[1] in OPERATORS) + or (isinstance(arg[1], PYSON) + and arg[1].types() == set([str]))))): pass elif isinstance(arg, list): if not test_domain(arg): From 2eb687a928b31b8ca3ac70e6c8dad38f5f93bd70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 20 Sep 2011 12:53:25 +0200 Subject: [PATCH 025/128] default_get in create should not override existing values review112001 (transplanted from caaf9ded46ca1340a0f77c3155aafe5f1362709f) --- trytond/model/modelsql.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 533cfba073..b3c1982312 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -266,6 +266,8 @@ class ModelSQL(ModelStorage): if field in ('create_uid', 'create_date', 'write_uid', 'write_date'): del defaults[field] + if field in values: + del defaults[field] values.update(self._clean_defaults(defaults)) (upd0, upd1, upd2) = ('', '', []) From 28a5a7b68ad010f67892a0d485a6e15867b09878 Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Sat, 1 Oct 2011 14:18:54 +0200 Subject: [PATCH 026/128] Prepare release 2.0.2 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 97ddc4b4dd..7f31f31ee9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.0.2 - 2011-10-01 +* Bug fixes (see mercurial logs for details) + Version 2.0.1 - 2011-05-29 * Bug fixes (see mercurial logs for details) From 7076d50afc058c5169a72ead6c6b06f9c56306e0 Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Sat, 1 Oct 2011 14:18:54 +0200 Subject: [PATCH 027/128] Added tag 2.0.2 for changeset 66ba97c0b08e --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 96b2e9600c..d00c7a9a24 100644 --- a/.hgtags +++ b/.hgtags @@ -5,3 +5,4 @@ e2d31d59de7745de70199b7c340d78b7c4775723 1.4.0 af3a6063b46bf8739a513a06400fbb9858b5869b 1.8.0 3475040a8fe081b1b8609350186b779cc640fba4 2.0.0 b7c3a0a6034631032867ba0f33c26b7786ebe89a 2.0.1 +66ba97c0b08e179853b3acb14673c5c87614da33 2.0.2 From e46bef0a85a4db934b1b63f201e77f3b5aef397c Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Sat, 1 Oct 2011 14:19:15 +0200 Subject: [PATCH 028/128] Increase version number --- trytond/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/version.py b/trytond/version.py index 0d6af84889..03cd10968c 100644 --- a/trytond/version.py +++ b/trytond/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "trytond" -VERSION = "2.0.2" +VERSION = "2.0.3" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From 474da40b9b08ce304a58f67a40a239482f6348b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 28 Sep 2011 13:24:42 +0200 Subject: [PATCH 029/128] Don't fail on all keywords if one is not readable review108001 (transplanted from b1f790bcb6dbdb5fd007fdbdc72bce35052d90ef) --- trytond/ir/action.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/trytond/ir/action.py b/trytond/ir/action.py index 6996c13b04..438c27fe5c 100644 --- a/trytond/ir/action.py +++ b/trytond/ir/action.py @@ -174,7 +174,8 @@ class ActionKeyword(ModelSQL, ModelView): ('keyword', '=', keyword), ('model', '=', model + ',0'), ])) - for action_keyword in self.browse(action_keyword_ids): + for action_keyword_id in action_keyword_ids: + action_keyword = self.browse(action_keyword_id) try: action_obj = self.pool.get(action_keyword.action.type) except Exception: From e0c9918a62c72b147884bb0fb744778cb02f594f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 3 Oct 2011 23:31:58 +0200 Subject: [PATCH 030/128] Fix decimal._convert_other to work with Float on Python 2.7 review132001 (transplanted from 301a9694888478b3cccf42e02ba442349916be06) --- trytond/protocols/datatype.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/trytond/protocols/datatype.py b/trytond/protocols/datatype.py index ce2e9a84c9..23984a5fe5 100644 --- a/trytond/protocols/datatype.py +++ b/trytond/protocols/datatype.py @@ -1,7 +1,17 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. +import decimal from decimal import Decimal +_convert_other = decimal._convert_other + +def _convert_Float(other, *args, **kwargs): + if isinstance(other, Float): + return other.decimal + return _convert_other(other, *args, **kwargs) +decimal._convert_other = _convert_Float + + class Float(float): def __init__(self, value): super(Float, self).__init__() From 659d8b81d8bd42dd00fac20d532d62b3d9422e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 7 Oct 2011 21:00:30 +0200 Subject: [PATCH 031/128] on_write method should always return a list issue2166 (transplanted from 3c94b91aa748cd7dd13cffd2d5ce2f0fa07f136a) --- trytond/ir/module/module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/ir/module/module.py b/trytond/ir/module/module.py index 4f3ee3ee57..411286ff09 100644 --- a/trytond/ir/module/module.py +++ b/trytond/ir/module/module.py @@ -97,7 +97,7 @@ class Module(ModelSQL, ModelView): def on_write(self, ids): if not ids: - return + return [] res = [] graph, packages, later = create_graph(get_module_list()) for module in self.browse(ids): From 9628d616a3b6a14f6ca47c998f1ad1116931fa83 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bonicoli Date: Wed, 12 Oct 2011 15:44:00 +0200 Subject: [PATCH 032/128] Put quotes around sequence names Identifiers are quoted in trytond/backend/postgresql/table.py, sequence names must be quoted too (see http://www.postgresql.org/docs/8.4/static/functions-sequence.html) issue2176 review141002 (transplanted from b1fded39290d501414f88fbc0041f60498d82b75) --- trytond/backend/postgresql/table.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/trytond/backend/postgresql/table.py b/trytond/backend/postgresql/table.py index 04f5c3de39..d1c674a36f 100644 --- a/trytond/backend/postgresql/table.py +++ b/trytond/backend/postgresql/table.py @@ -32,7 +32,7 @@ class TableHandler(TableHandlerInterface): if not self.history: self.cursor.execute('ALTER TABLE "%s" ' \ 'ADD COLUMN id INTEGER ' \ - 'DEFAULT nextval(\'%s\') NOT NULL' % \ + 'DEFAULT nextval(\'"%s"\') NOT NULL' % \ (self.table_name, self.sequence_name)) self.cursor.execute('ALTER TABLE "%s" ' \ 'ADD PRIMARY KEY(id)' % self.table_name) @@ -43,17 +43,17 @@ class TableHandler(TableHandlerInterface): if self.history and not '__id' in self._columns: self.cursor.execute('ALTER TABLE "%s" ' \ 'ADD COLUMN __id INTEGER ' \ - 'DEFAULT nextval(\'%s\') NOT NULL' % \ + 'DEFAULT nextval(\'"%s"\') NOT NULL' % \ (self.table_name, self.sequence_name)) self.cursor.execute('ALTER TABLE "%s" ' \ 'ADD PRIMARY KEY(__id)' % self.table_name) if self.history: self.cursor.execute('ALTER TABLE "%s" ' \ - 'ALTER __id SET DEFAULT nextval(\'%s\')' % (self.table_name, + 'ALTER __id SET DEFAULT nextval(\'"%s"\')' % (self.table_name, self.sequence_name)) else: self.cursor.execute('ALTER TABLE "%s" ' \ - 'ALTER id SET DEFAULT nextval(\'%s\')' % (self.table_name, + 'ALTER id SET DEFAULT nextval(\'"%s"\')' % (self.table_name, self.sequence_name)) self._update_definitions() From 2b8bf24f68034216407a957186cfd89073d2431c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 18 Oct 2011 09:50:00 +0200 Subject: [PATCH 033/128] Use a thread-local data to store SQLite memory database issue2195 review153005 (transplanted from c1732056c307fcba27d73ebf86b8ef55274d7fa2) --- trytond/backend/sqlite/database.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/trytond/backend/sqlite/database.py b/trytond/backend/sqlite/database.py index 0c4fa0ae60..2cf494c90d 100644 --- a/trytond/backend/sqlite/database.py +++ b/trytond/backend/sqlite/database.py @@ -9,6 +9,7 @@ import re from decimal import Decimal import datetime import time +import threading _FIX_ROWCOUNT = False try: @@ -88,19 +89,20 @@ def replace(text, pattern, replacement): class Database(DatabaseInterface): - _memory_database = None + _local = threading.local() _conn = None def __new__(cls, database_name=':memory:'): - if database_name == ':memory:' \ - and cls._memory_database: - return cls._memory_database + if (database_name == ':memory:' + and hasattr(cls._local, 'memory_database') + and cls._local.memory_database): + return cls._local.memory_database return DatabaseInterface.__new__(cls, database_name=database_name) def __init__(self, database_name=':memory:'): super(Database, self).__init__(database_name=database_name) if database_name == ':memory:': - Database._memory_database = self + Database._local.memory_database = self def connect(self): if self.database_name == ':memory:': From 7f0579dd0f4a1f8cc1bd98990806274652fe2be5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bonicoli Date: Wed, 19 Oct 2011 04:56:08 +0200 Subject: [PATCH 034/128] add missing field name 'lang' Fix NotSupportedError exception which appears when searching fields by description: NotSupportedError: input of anonymous composite types is not implemented "LINE 1: ...ND ir_translation.res_id = 0 AND ir_translation = E'en_US' A..." issue2210 review158001 (transplanted from 5315ef978e92158ea5460e83ed5f94a4717a463d) --- trytond/model/modelsql.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index b3c1982312..688c0081e8 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -1632,7 +1632,7 @@ class ModelSQL(ModelStorage): 'ON (ir_translation.name = ' \ 'ir_model.model||\',\'||%s.name ' \ 'AND ir_translation.res_id = 0 ' \ - 'AND ir_translation = %%s ' \ + 'AND ir_translation.lang = %%s ' \ 'AND ir_translation.type = \'%s\' ' \ 'AND ir_translation.fuzzy = %s)' % \ (table._table, ttype, From 6baecb1cc81f37a8f2f9771cd5a635c99ab3966e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=C3=89vrard?= Date: Fri, 28 Oct 2011 10:17:05 +0200 Subject: [PATCH 035/128] Add zipfile namespace to except clause (transplanted from 7e4362f4987dc4f04050ec779c45ba236fa1e0b5) --- trytond/ir/translation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/ir/translation.py b/trytond/ir/translation.py index 5206264c78..751d5dcbcd 100644 --- a/trytond/ir/translation.py +++ b/trytond/ir/translation.py @@ -687,7 +687,7 @@ class ReportTranslationSet(Wizard): content_io = StringIO.StringIO(content) try: content_z = zipfile.ZipFile(content_io, mode='r') - except BadZipfile: + except zipfile.BadZipfile: continue content_xml = content_z.read('content.xml') From a8218e208e0f4891d7013a34a636ec80dfd610bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=C3=89vrard?= Date: Fri, 28 Oct 2011 10:18:58 +0200 Subject: [PATCH 036/128] Add exception to except clause (transplanted from 50ecc56d97d637989ce48371e054f468cd151056) --- trytond/model/modelsql.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 688c0081e8..f245109d11 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -1097,7 +1097,7 @@ class ModelSQL(ModelStorage): try: cursor.execute('DELETE FROM "'+self._table+'" ' \ 'WHERE ' + red_sql, red_ids) - except DatabaseIntegrityError: + except DatabaseIntegrityError, exception: with Transaction().new_cursor(): for name, _, error in self._sql_constraints: if name in exception[0]: From a86c32c4596f0aafcc4768e38ccaa97957310502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=C3=89vrard?= Date: Fri, 28 Oct 2011 11:40:20 +0200 Subject: [PATCH 037/128] Also define MANIFEST on ImportError (transplanted from 94d21268fc4a9d7014adb18bff82bfedafdd350f) --- trytond/report/report.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/report/report.py b/trytond/report/report.py index 2138023bef..eb7cd7a6a0 100644 --- a/trytond/report/report.py +++ b/trytond/report/report.py @@ -24,7 +24,7 @@ warnings.resetwarnings() try: from relatorio.templates.opendocument import Manifest, MANIFEST except ImportError: - Manifest = None + Manifest, MANIFEST = None, None from genshi.filters import Translator import lxml.etree from trytond.config import CONFIG From 1791a77bf71933bd01a2dddc45176cacd785fe69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 14 Nov 2011 18:00:46 +0100 Subject: [PATCH 038/128] Add allowed ops in safe_eval for Python 2.7 (transplanted from 1e8b99ec6d2d20933146cf9b866f54cb385905f7) --- trytond/tools/misc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/trytond/tools/misc.py b/trytond/tools/misc.py index 186833492c..adac3a6e4a 100644 --- a/trytond/tools/misc.py +++ b/trytond/tools/misc.py @@ -405,6 +405,7 @@ _ALLOWED_CODES = set(dis.opmap[x] for x in [ 'STORE_MAP', 'LOAD_NAME', 'CALL_FUNCTION', 'COMPARE_OP', 'LOAD_ATTR', 'STORE_NAME', 'GET_ITER', 'FOR_ITER', 'LIST_APPEND', 'JUMP_ABSOLUTE', 'DELETE_NAME', 'JUMP_IF_TRUE', 'JUMP_IF_FALSE', 'JUMP_IF_FALSE_OR_POP', + 'JUMP_IF_TRUE_OR_POP', 'POP_JUMP_IF_FALSE', 'POP_JUMP_IF_TRUE', 'BINARY_SUBSCR', ] if x in dis.opmap) From dee9dd25c5b1e0171a22909909cea3484a8bae40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 21 Nov 2011 22:09:52 +0100 Subject: [PATCH 039/128] Fix corruption of _local_data cache when switching language issue2233 review181001 (transplanted from dd6d9aa5ee216148f4f0df8c17c0d33f2a886a9b) --- trytond/model/browse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/model/browse.py b/trytond/model/browse.py index d37cef18ec..26da4e58ee 100644 --- a/trytond/model/browse.py +++ b/trytond/model/browse.py @@ -223,7 +223,7 @@ class BrowseRecord(object): self._context = self._context.copy() prev_lang = self._context.get('language') or 'en_US' self._context['language'] = lang - for cache in (self._cache, self._local_cache): + for cache in (self._cache, {self._model_name: self._local_data}): language_cache = cache['_language_cache'] for model in cache: if model == '_language_cache': From adf91d572dac7ffcafb13dc2f9efe3402da6a77e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 29 Nov 2011 11:12:29 +0100 Subject: [PATCH 040/128] Backed out changeset 2d593d9dea8e --- trytond/model/browse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/model/browse.py b/trytond/model/browse.py index 26da4e58ee..d37cef18ec 100644 --- a/trytond/model/browse.py +++ b/trytond/model/browse.py @@ -223,7 +223,7 @@ class BrowseRecord(object): self._context = self._context.copy() prev_lang = self._context.get('language') or 'en_US' self._context['language'] = lang - for cache in (self._cache, {self._model_name: self._local_data}): + for cache in (self._cache, self._local_cache): language_cache = cache['_language_cache'] for model in cache: if model == '_language_cache': From 5b896bdf6d1af1d095a78a58fcaf9555dece8b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 15 Dec 2011 11:05:04 +0100 Subject: [PATCH 041/128] Remove unsupported attributes from the doc issue2348 (transplanted from 922b7bab23447e08d4e88149c5fd8a4259e1b461) --- doc/topics/views/index.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/topics/views/index.rst b/doc/topics/views/index.rst index 52d7f3f54d..d8b3af94d6 100644 --- a/doc/topics/views/index.rst +++ b/doc/topics/views/index.rst @@ -171,9 +171,6 @@ Display a field of the object with the value of the current record. * ``widget``: The widget that must be used instead of the default one. - * ``saves``: Only for One2Many fields: it is a boolean that defines if - changes made in the list must be saved directly. - * ``help``: The string that will be displayed when the cursor stays over the widget. From 8a5b3c4386c2bd81388bd4ec1fdc2e09ffc6c9fc Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Mon, 26 Dec 2011 10:39:28 +0100 Subject: [PATCH 042/128] Prepare release 2.0.3 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 7f31f31ee9..937bd106f9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.0.3 - 2011-12-26 +* Bug fixes (see mercurial logs for details) + Version 2.0.2 - 2011-10-01 * Bug fixes (see mercurial logs for details) From 19a43005f92456edff60d8e7bc85a6c24acd50ac Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Mon, 26 Dec 2011 10:39:28 +0100 Subject: [PATCH 043/128] Added tag 2.0.3 for changeset f457ce376aaf --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index d00c7a9a24..07da0572a8 100644 --- a/.hgtags +++ b/.hgtags @@ -6,3 +6,4 @@ af3a6063b46bf8739a513a06400fbb9858b5869b 1.8.0 3475040a8fe081b1b8609350186b779cc640fba4 2.0.0 b7c3a0a6034631032867ba0f33c26b7786ebe89a 2.0.1 66ba97c0b08e179853b3acb14673c5c87614da33 2.0.2 +f457ce376aaf792d4fdafd04bc2fb4d47ddac3cc 2.0.3 From b011bd098e23ae0174b3dcd2feb69e8bbc6127fd Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Mon, 26 Dec 2011 10:39:48 +0100 Subject: [PATCH 044/128] Increase version number --- trytond/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/version.py b/trytond/version.py index 03cd10968c..d70007bef2 100644 --- a/trytond/version.py +++ b/trytond/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "trytond" -VERSION = "2.0.3" +VERSION = "2.0.4" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From c20a30582f922e9b64e8385f73d04e6c586b359f Mon Sep 17 00:00:00 2001 From: Albert Cervera i Areny Date: Sat, 24 Dec 2011 15:35:01 +0100 Subject: [PATCH 045/128] Fix bug in read() operation of ir.model.field that didn't allow the function to receive a single id. issue2336 review204001 (transplanted from 77b7fd5b926bc8abbb2865576baf2a802637c02b) --- trytond/ir/model.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/trytond/ir/model.py b/trytond/ir/model.py index bb36f8df80..60ce590989 100644 --- a/trytond/ir/model.py +++ b/trytond/ir/model.py @@ -133,6 +133,10 @@ class ModelField(ModelSQL, ModelView): fields_names.append('name') to_delete.append('name') + int_id = False + if isinstance(ids, (int, long)): + int_id = True + ids = [ids] res = super(ModelField, self).read(ids, fields_names=fields_names) if (Transaction().context.get('language') @@ -185,6 +189,8 @@ class ModelField(ModelSQL, ModelView): for rec in res: for field in to_delete: del rec[field] + if int_id: + res = res[0] return res ModelField() From 35382fd5eab75340d69fef782a35859e408675b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 28 Dec 2011 11:33:04 +0100 Subject: [PATCH 046/128] Missing global declaration of CACHE (transplanted from f2b8e2b850d2d64491dd80bd92bf88195608b27f) --- trytond/protocols/webdav.py | 1 + 1 file changed, 1 insertion(+) diff --git a/trytond/protocols/webdav.py b/trytond/protocols/webdav.py index f55d98ec3c..2e18af77d9 100644 --- a/trytond/protocols/webdav.py +++ b/trytond/protocols/webdav.py @@ -523,6 +523,7 @@ class WebDAVAuthRequestHandler(AuthServer.BufferedAuthRequestHandler, WebDAVServer.DAVRequestHandler): def finish(self): + global CACHE CACHE = LocalDict() if not Transaction().cursor: return From c933a144dc2479d49239aced6109ee28b2d4e9ec Mon Sep 17 00:00:00 2001 From: Max Holtzberg Date: Wed, 28 Dec 2011 16:03:31 +0100 Subject: [PATCH 047/128] Passing false to SQL query on property field search as parameter issue2351 review206002 (transplanted from a93cd284a8e425c71b2f31740df12ea9caa34155) --- trytond/model/fields/property.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trytond/model/fields/property.py b/trytond/model/fields/property.py index a566c61295..b07e94c714 100644 --- a/trytond/model/fields/property.py +++ b/trytond/model/fields/property.py @@ -97,10 +97,10 @@ class Property(Function): ' THEN ' + \ self.get_condition(sql_type, clause) + \ ' ELSE '\ - 'FALSE '\ + '%s '\ 'END', [model._name, name] + property_val + \ - self.get_condition_args(clause)) + self.get_condition_args(clause) + [False]) props = cursor.fetchall() default = None From 6dd36f8daed43a4be3283d03cadaa18adf195941 Mon Sep 17 00:00:00 2001 From: Max Holtzberg Date: Thu, 29 Dec 2011 11:57:44 +0100 Subject: [PATCH 048/128] Correct handling of NULL values in user defined split_part function on SQLite issue2370 review214001 (transplanted from 81d21490c70b90168877a7a5a7572330b84100f0) --- trytond/backend/sqlite/database.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/trytond/backend/sqlite/database.py b/trytond/backend/sqlite/database.py index 2cf494c90d..f0294b424e 100644 --- a/trytond/backend/sqlite/database.py +++ b/trytond/backend/sqlite/database.py @@ -81,6 +81,8 @@ def date_trunc(_type, date): tm_tuple.tm_mday) def split_part(text, delimiter, count): + if text is None: + return None return (text.split(delimiter) + [''] * (count - 1))[count - 1] def replace(text, pattern, replacement): From 7d7381ab4711a8798dd28b9f453e5b1e38a079d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 11 Jan 2012 01:22:32 +0100 Subject: [PATCH 049/128] Reset columns and update rpc for inherting models review206008 (transplanted from 304af0238099eecf87354d58a8f414e36e6dde6a) --- trytond/model/model.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/trytond/model/model.py b/trytond/model/model.py index 716752a003..58f31095c2 100644 --- a/trytond/model/model.py +++ b/trytond/model/model.py @@ -84,7 +84,9 @@ class Model(WarningErrorMixin): assert (k in self._columns) or (k in self._inherit_fields), \ 'Default function defined in %s but field %s does not exist!' % \ (self._name, k,) + self._update_rpc() + def _update_rpc(self): for field_name in self._columns.keys() + self._inherit_fields.keys(): if field_name in self._columns: field = self._columns[field_name] @@ -124,7 +126,8 @@ class Model(WarningErrorMixin): res[field_name] = (model, self._inherits[model], self.pool.get(model)._inherit_fields[field_name][2]) self._inherit_fields = res - self._reset_xxx2many_targets() + self._reset_columns() + self._update_rpc() # Update objects that uses this one to update their _inherits fields for obj_name in self.pool.object_name_list(): obj = self.pool.get(obj_name) From f572cad4b133612e12f212052e3dd4208b690dae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 17 Jan 2012 13:51:08 +0100 Subject: [PATCH 050/128] Activate SO_KEEPALIVE on socket review221002 (transplanted from 6d452ab04653df521df0ec0180c5fcf94df6b4b5) --- trytond/protocols/jsonrpc.py | 2 ++ trytond/protocols/webdav.py | 2 ++ trytond/protocols/xmlrpc.py | 2 ++ 3 files changed, 6 insertions(+) diff --git a/trytond/protocols/jsonrpc.py b/trytond/protocols/jsonrpc.py index 0f0b0f7ed7..95a8cd45b6 100644 --- a/trytond/protocols/jsonrpc.py +++ b/trytond/protocols/jsonrpc.py @@ -283,6 +283,8 @@ class SimpleThreadedJSONRPCServer(SocketServer.ThreadingMixIn, self.socket.settimeout(1) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.socket.setsockopt(socket.SOL_SOCKET, + socket.SO_KEEPALIVE, 1) SimpleJSONRPCServer.server_bind(self) diff --git a/trytond/protocols/webdav.py b/trytond/protocols/webdav.py index 2e18af77d9..76e13ca98e 100644 --- a/trytond/protocols/webdav.py +++ b/trytond/protocols/webdav.py @@ -88,6 +88,8 @@ class BaseThreadedHTTPServer(SocketServer.ThreadingMixIn, self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.socket.setsockopt(socket.SOL_SOCKET, + socket.SO_KEEPALIVE, 1) BaseHTTPServer.HTTPServer.server_bind(self) diff --git a/trytond/protocols/xmlrpc.py b/trytond/protocols/xmlrpc.py index e786f39c80..1abd06e732 100644 --- a/trytond/protocols/xmlrpc.py +++ b/trytond/protocols/xmlrpc.py @@ -208,6 +208,8 @@ class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, self.socket.settimeout(1) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.socket.setsockopt(socket.SOL_SOCKET, + socket.SO_KEEPALIVE, 1) SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self) From 200d3cf4204759a45937ed9b8dd242e91af872b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 28 Jan 2012 12:46:09 +0100 Subject: [PATCH 051/128] Fix reduce_ids with integer as float review233002 (transplanted from dbf6cdb82929cbfd6e554c482c95c640879501d2) --- trytond/tests/test_tools.py | 10 ++++++++++ trytond/tools/misc.py | 6 ++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/trytond/tests/test_tools.py b/trytond/tests/test_tools.py index c6bb78c8be..154b5d4211 100644 --- a/trytond/tests/test_tools.py +++ b/trytond/tests/test_tools.py @@ -60,6 +60,16 @@ class ToolsTestCase(unittest.TestCase): reduce_ids('id', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 18, 19, 21])) + def test0055reduce_ids_float(self): + ''' + Test reduce_ids with integer as float. + ''' + self.assert_(('(((id >= %s) AND (id <= %s)) OR (id IN (%s,%s,%s,%s)))', + [1.0, 12.0, 15.0, 18.0, 19.0, 21.0]) == \ + reduce_ids('id', [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, + 9.0, 10.0, 11.0, 12.0, 15.0, 18.0, 19.0, 21.0])) + self.assertRaises(AssertionError, reduce_ids, 'id', [1.1]) + def test0060safe_eval_builtin(self): ''' Attempt to access a unsafe builtin. diff --git a/trytond/tools/misc.py b/trytond/tools/misc.py index adac3a6e4a..4a0bf40b3c 100644 --- a/trytond/tools/misc.py +++ b/trytond/tools/misc.py @@ -359,7 +359,9 @@ def reduce_ids(field, ids): ''' if not ids: return '(%s)', [False] - ids = ids[:] + assert all(x.is_integer() for x in ids if isinstance(x, float)), \ + 'ids must be integer' + ids = map(int, ids) ids.sort() prev = ids.pop(0) continue_list = [prev, prev] @@ -382,7 +384,7 @@ def reduce_ids(field, ids): prev = i if continue_list[-1] - continue_list[0] < 5: discontinue_list.extend([continue_list[0] + x for x in - range(int(continue_list[-1] - continue_list[0] + 1))]) + range(continue_list[-1] - continue_list[0] + 1)]) else: sql.append('((' + field + ' >= %s) AND (' + field + ' <= %s))') args.append(continue_list[0]) From 1794dd255425eb280fa2cf459481d2bccbcf0d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 29 Jan 2012 16:23:59 +0100 Subject: [PATCH 052/128] Fix argument types from values issue2393 review232002 (transplanted from 346078fb9f180c53540a320774c9cfce29d9cf1c) --- trytond/ir/translation.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/trytond/ir/translation.py b/trytond/ir/translation.py index 751d5dcbcd..15830c9fc5 100644 --- a/trytond/ir/translation.py +++ b/trytond/ir/translation.py @@ -402,26 +402,26 @@ class Translation(ModelSQL, ModelView, Cacheable): if not vals.get('module'): if vals.get('type', '') in ('odt', 'view', 'wizard_button', 'selection', 'error'): - cursor.execute('SELECT module FROM ir_translation ' \ - 'WHERE name = %s ' \ - 'AND res_id = %s ' \ - 'AND lang = %s ' \ - 'AND type = %s ' \ - 'AND src = %s ', - (vals.get('name', ''), vals.get('res_id', 0), 'en_US', - vals.get('type', ''), vals.get('src', ''))) + cursor.execute('SELECT module FROM ir_translation ' + 'WHERE name = %s ' + 'AND res_id = %s ' + 'AND lang = %s ' + 'AND type = %s ' + 'AND src = %s ', + (vals.get('name') or '', vals.get('res_id') or 0, 'en_US', + vals.get('type') or '', vals.get('src') or '')) fetchone = cursor.fetchone() if fetchone: vals = vals.copy() vals['module'] = fetchone[0] else: - cursor.execute('SELECT module, src FROM ir_translation ' \ - 'WHERE name = %s ' \ - 'AND res_id = %s ' \ - 'AND lang = %s ' \ - 'AND type = %s', - (vals.get('name', ''), vals.get('res_id', 0), 'en_US', - vals.get('type', ''))) + cursor.execute('SELECT module, src FROM ir_translation ' + 'WHERE name = %s ' + 'AND res_id = %s ' + 'AND lang = %s ' + 'AND type = %s', + (vals.get('name') or '', vals.get('res_id') or 0, 'en_US', + vals.get('type') or '')) fetchone = cursor.fetchone() if fetchone: vals = vals.copy() From 2857925c1ef554eea8473e1496d51c0459abf025 Mon Sep 17 00:00:00 2001 From: Max Holtzberg Date: Tue, 28 Feb 2012 12:51:01 +0100 Subject: [PATCH 053/128] Enable False search on property fields by domain inversion issue2345 review203002 (transplanted from b04fc3b8a023e9f4194f71ffa324a6dc6545df22) --- trytond/model/fields/property.py | 43 ++++- trytond/test/test.py | 16 ++ trytond/tests/test_fields.py | 277 +++++++++++++++++++++++++++++++ 3 files changed, 327 insertions(+), 9 deletions(-) diff --git a/trytond/model/fields/property.py b/trytond/model/fields/property.py index b07e94c714..dec26b34ed 100644 --- a/trytond/model/fields/property.py +++ b/trytond/model/fields/property.py @@ -76,6 +76,10 @@ class Property(Function): property_query, property_val = rule_obj.domain_get('ir.property') + property_clause = '' + if property_query: + property_clause = 'AND ' + property_query + #Fetch res ids that comply with the domain cursor.execute( 'SELECT CAST(' \ @@ -92,8 +96,8 @@ class Property(Function): 'WHERE '\ 'CASE WHEN "' +\ model_obj._table + '".model = %s ' \ - 'AND "' + field_obj._table + '".name = %s AND ' \ - + property_query + \ + 'AND "' + field_obj._table + '".name = %s ' \ + + property_clause + \ ' THEN ' + \ self.get_condition(sql_type, clause) + \ ' ELSE '\ @@ -109,8 +113,15 @@ class Property(Function): default = prop[1] break - if not default: - return [('id', 'in', [x[0] for x in props])] + if not default \ + or (clause[2] is False and clause[1] in ['=', '!=']) \ + or (clause[1] in ['not like', 'not ilike', 'not in', '!=']): + operator = 'in' # default operator + if (clause[2] is False and clause[1] == '=') \ + or (clause[2] is not False + and clause[1] in ['not like', 'not ilike', 'not in', '!=']): + operator = 'not in' + return [('id', operator, [x[0] for x in props])] #Fetch the res ids that doesn't use the default value cursor.execute( @@ -136,13 +147,27 @@ class Property(Function): @staticmethod def get_condition(sql_type, clause): + operator = '%s' + if sql_type == 'NUMERIC': + operator = 'CAST(%s AS NUMERIC)' + + # All negative clauses will be negated later if clause[1] in ('in', 'not in'): - return ("(cast(split_part(value,',',2) as %s) %s ("+ \ - ",".join(('%%s',) * len(clause[2])) + ")) ") % \ - (sql_type, clause[1]) + operator = operator % '%%s' + return ("(cast(split_part(value,',',2) as %s) in ("+ \ + ",".join((operator,) * len(clause[2])) + ")) ") % sql_type + elif clause[2] is False and clause[1] in ['=', '!=']: + return "((cast(split_part(value,',',2) as %s) IS NULL " \ + ") = %%s) " % sql_type + elif clause[1] in ['not like', 'not ilike']: + return "(cast(split_part(value,',',2) as %s) %s %s) " % \ + (sql_type, clause[1].split()[1], operator) + elif clause[1] == '!=': + return "(cast(split_part(value,',',2) as %s) = %s) " % \ + (sql_type, operator) else: - return "(cast(split_part(value,',',2) as %s) %s %%s) " % \ - (sql_type, clause[1]) + return "(cast(split_part(value,',',2) as %s) %s %s) " % \ + (sql_type, clause[1], operator) @staticmethod def get_condition_args(clause): diff --git a/trytond/test/test.py b/trytond/test/test.py index abca5df215..af0dfdb5f1 100644 --- a/trytond/test/test.py +++ b/trytond/test/test.py @@ -421,3 +421,19 @@ class One2OneRequiredRelation(ModelSQL): One2OneRequiredRelation() + +class Property(ModelSQL): + 'Property' + _name = 'test.property' + _description = __doc__ + + char = fields.Property(fields.Char('Test Char')) + many2one = fields.Property(fields.Many2One('test.char', + 'Test Many2One')) + numeric = fields.Property(fields.Numeric('Test Numeric')) + selection = fields.Property(fields.Selection([ + ('option_a', 'Option A'), + ('option_b', 'Option B') + ], 'Test Selection')) + +Property() diff --git a/trytond/tests/test_fields.py b/trytond/tests/test_fields.py index fd44d29eee..7a725007ef 100644 --- a/trytond/tests/test_fields.py +++ b/trytond/tests/test_fields.py @@ -64,6 +64,8 @@ class FieldsTestCase(unittest.TestCase): self.one2one_target = POOL.get('test.one2one.target') self.one2one_required = POOL.get('test.one2one_required') + self.property_ = POOL.get('test.property') + def test0010boolean(self): ''' Test Boolean. @@ -2205,6 +2207,281 @@ class FieldsTestCase(unittest.TestCase): transaction.cursor.rollback() + def test0110property(self): + ''' + Test Property with supported field types. + ''' + with Transaction().start(DB_NAME, USER, + context=CONTEXT) as transaction: + + # Test Char + prop_id_a = self.property_.create({'char': 'Test'}) + self.assert_(prop_id_a) + + prop_id_b = self.property_.create({}) + self.assert_(prop_id_b) + + prop_id_c = self.property_.create({'char': 'FooBar'}) + self.assert_(prop_id_c) + + prop_a = self.property_.read(prop_id_a, ['char']) + self.assert_(prop_a['char'] == 'Test') + + prop_ids = self.property_.search([('char', '=', 'Test')]) + self.assert_(prop_ids == [prop_id_a]) + + prop_ids = self.property_.search([('char', '=', False)]) + self.assert_(prop_ids == [prop_id_b]) + + prop_ids = self.property_.search([('char', '!=', False)]) + self.assert_(prop_ids == [prop_id_a, prop_id_c]) + + prop_ids = self.property_.search([('char', 'like', 'Tes%')]) + self.assert_(prop_ids == [prop_id_a]) + + prop_ids = self.property_.search([('char', 'like', '%Bar')]) + self.assert_(prop_ids == [prop_id_c]) + + prop_ids = self.property_.search([('char', 'not like', 'Tes%')]) + self.assert_(prop_ids == [prop_id_b, prop_id_c]) + + prop_ids = self.property_.search([('char', 'ilike', 'tes%')]) + self.assert_(prop_ids == [prop_id_a]) + + prop_ids = self.property_.search([('char', 'ilike', '%bar')]) + self.assert_(prop_ids == [prop_id_c]) + + prop_ids = self.property_.search([('char', 'not ilike', 'tes%')]) + self.assert_(prop_ids == [prop_id_b, prop_id_c]) + + prop_ids = self.property_.search([('char', 'in', ['Test'])]) + self.assert_(prop_ids == [prop_id_a]) + + prop_ids = self.property_.search([ + ('char', 'in', ['Test', 'FooBar'])]) + self.assert_(prop_ids == [prop_id_a, prop_id_c]) + + prop_ids = self.property_.search([ + ('char', 'not in', ['Test', 'FooBar'])]) + self.assert_(prop_ids == [prop_id_b]) + + model_field_obj = POOL.get('ir.model.field') + property_obj = POOL.get('ir.property') + + # Test default value + property_field_id, = model_field_obj.search([ + ('model.model', '=', 'test.property'), + ('name', '=', 'char'), + ], limit=1) + property_obj.create({ + 'field': property_field_id, + 'value': ',DEFAULT_VALUE', + }) + + prop_id_d = self.property_.create({}) + self.assert_(prop_id_d) + + prop = self.property_.read(prop_id_d, ['char']) + self.assert_(prop['char'] == 'DEFAULT_VALUE') + + prop_ids = self.property_.search([('char', '!=', False)]) + self.assert_(prop_ids == [prop_id_a, prop_id_c, prop_id_d]) + + self.property_.write(prop_id_a, {'char': False}) + prop_a = self.property_.read(prop_id_a, ['char']) + self.assert_(prop_a['char'] == False) + + self.property_.write(prop_id_b, {'char': 'Test'}) + prop_b = self.property_.read(prop_id_b, ['char']) + self.assert_(prop_b['char'] == 'Test') + + transaction.cursor.rollback() + + + # Test Many2One + char_id_a = self.char.create({'char': 'Test'}) + self.assert_(char_id_a) + + char_id_b = self.char.create({'char': 'FooBar'}) + self.assert_(char_id_b) + + prop_id_a = self.property_.create({'many2one': char_id_a}) + self.assert_(prop_id_a) + + prop_id_b = self.property_.create({'many2one': char_id_b}) + self.assert_(prop_id_b) + + prop_id_c = self.property_.create({}) + self.assert_(prop_id_c) + + prop_ids = self.property_.search([('many2one', '=', char_id_a)]) + self.assert_(prop_ids == [prop_id_a]) + + prop_ids = self.property_.search([('many2one', '!=', False)]) + self.assert_(prop_ids == [prop_id_a, prop_id_b]) + + prop_ids = self.property_.search([('many2one', '=', False)]) + self.assert_(prop_ids == [prop_id_c]) + + prop_a = self.property_.read(prop_id_a, ['many2one']) + self.assert_(prop_a['many2one'] == char_id_a) + + prop_ids = self.property_.search([ + ('many2one', 'in', [char_id_a, char_id_b])]) + self.assert_(prop_ids == [prop_id_a, prop_id_b]) + + prop_ids = self.property_.search([ + ('many2one', 'not in', [char_id_a, char_id_b])]) + self.assert_(prop_ids == [prop_id_c]) + + self.property_.write(prop_id_b, {'many2one': char_id_a}) + prop_b = self.property_.read(prop_id_b, ['many2one']) + self.assert_(prop_b['many2one'] == char_id_a) + + transaction.cursor.rollback() + + + # Test Numeric + prop_id_a = self.property_.create({'numeric': Decimal('1.1')}) + self.assert_(prop_id_a) + + prop_id_b = self.property_.create({'numeric': Decimal('2.6')}) + self.assert_(prop_id_b) + + prop_id_c = self.property_.create({}) + self.assert_(prop_id_c) + + prop_ids = self.property_.search([('numeric', '!=', False)]) + self.assert_(prop_ids == [prop_id_a, prop_id_b]) + + prop_ids = self.property_.search([('numeric', '=', False)]) + self.assert_(prop_ids == [prop_id_c]) + + prop_ids = self.property_.search([('numeric', '=', Decimal('1.1'))]) + self.assert_(prop_ids == [prop_id_a]) + + prop_ids = self.property_.search([ + ('numeric', '!=', Decimal('1.1'))]) + self.assert_(prop_ids == [prop_id_b, prop_id_c]) + + prop_ids = self.property_.search([('numeric', '<', Decimal('2.6'))]) + self.assert_(prop_ids == [prop_id_a]) + + prop_ids = self.property_.search([ + ('numeric', '<=', Decimal('2.6'))]) + self.assert_(prop_ids == [prop_id_a, prop_id_b]) + + prop_ids = self.property_.search([('numeric', '>', Decimal('1.1'))]) + self.assert_(prop_ids == [prop_id_b]) + + prop_ids = self.property_.search([ + ('numeric', '>=', Decimal('1.1'))]) + self.assert_(prop_ids == [prop_id_a, prop_id_b]) + + prop_ids = self.property_.search([ + ('numeric', 'in', [Decimal('1.1')])]) + self.assert_(prop_ids == [prop_id_a]) + + prop_ids = self.property_.search([ + ('numeric', 'in', [Decimal('1.1'), Decimal('2.6')])]) + self.assert_(prop_ids == [prop_id_a, prop_id_b]) + + prop_ids = self.property_.search([ + ('numeric', 'not in', [Decimal('1.1')])]) + self.assert_(prop_ids == [prop_id_b, prop_id_c]) + + prop_ids = self.property_.search([ + ('numeric', 'not in', [Decimal('1.1'), Decimal('2.6')])]) + self.assert_(prop_ids == [prop_id_c]) + + # Test default value + property_field_id, = model_field_obj.search([ + ('model.model', '=', 'test.property'), + ('name', '=', 'numeric'), + ], limit=1) + property_obj.create({ + 'field': property_field_id, + 'value': ',3.7', + }) + + prop_id_d = self.property_.create({}) + self.assert_(prop_id_d) + + prop_d = self.property_.read(prop_id_d, ['numeric']) + self.assert_(prop_d['numeric'] == Decimal('3.7')) + + self.property_.write(prop_id_a, {'numeric': False}) + prop_a = self.property_.read(prop_id_a, ['numeric']) + self.assert_(prop_a['numeric'] == False) + + self.property_.write(prop_id_b, {'numeric': Decimal('3.11')}) + prop_b = self.property_.read(prop_id_b, ['numeric']) + self.assert_(prop_b['numeric'] == Decimal('3.11')) + + transaction.cursor.rollback() + + + # Test Selection + prop_id_a = self.property_.create({'selection': 'option_a'}) + self.assert_(prop_id_a) + + prop_id_b = self.property_.create({'selection': 'option_b'}) + self.assert_(prop_id_b) + + prop_id_c = self.property_.create({}) + self.assert_(prop_id_c) + + prop_ids = self.property_.search([('selection', '=', 'option_a')]) + self.assert_(prop_ids == [prop_id_a]) + + prop_ids = self.property_.search([('selection', '!=', False)]) + self.assert_(prop_ids == [prop_id_a, prop_id_b]) + + prop_ids = self.property_.search([('selection', '=', False)]) + self.assert_(prop_ids == [prop_id_c]) + + prop_ids = self.property_.search([('selection', '!=', 'option_a')]) + self.assert_(prop_ids == [prop_id_b, prop_id_c]) + + prop_ids = self.property_.search([ + ('selection', 'in', ['option_a'])]) + self.assert_(prop_ids == [prop_id_a]) + + prop_ids = self.property_.search([ + ('selection', 'in', ['option_a', 'option_b'])]) + self.assert_(prop_ids == [prop_id_a, prop_id_b]) + + prop_ids = self.property_.search([ + ('selection', 'not in', ['option_a'])]) + self.assert_(prop_ids == [prop_id_b, prop_id_c]) + + # Test default value + property_field_id, = model_field_obj.search([ + ('model.model', '=', 'test.property'), + ('name', '=', 'selection'), + ], limit=1) + property_obj.create({ + 'field': property_field_id, + 'value': ',option_a', + }) + + prop_id_d = self.property_.create({}) + self.assert_(prop_id_d) + + prop_d = self.property_.read(prop_id_d, ['selection']) + self.assert_(prop_d['selection'] == 'option_a') + + self.property_.write(prop_id_a, {'selection': False}) + prop_a = self.property_.read(prop_id_a, ['selection']) + self.assert_(prop_a['selection'] == False) + + self.property_.write(prop_id_c, {'selection': 'option_b'}) + prop_c = self.property_.read(prop_id_c, ['selection']) + self.assert_(prop_c['selection'] == 'option_b') + + transaction.cursor.rollback() + + def suite(): return unittest.TestLoader().loadTestsFromTestCase(FieldsTestCase) From 69ed18650d30b593e6152ca2a82bf62e5ff1a0f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 1 Mar 2012 10:31:28 +0100 Subject: [PATCH 054/128] Make search_rec_name doesn't fail if _rec_name doesn't exist issue2191 review247002 (transplanted from 3cdf1515608a4aa2587678f47df622d9c5a37c90) --- trytond/model/modelstorage.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/trytond/model/modelstorage.py b/trytond/model/modelstorage.py index 2237562607..ac62617a9f 100644 --- a/trytond/model/modelstorage.py +++ b/trytond/model/modelstorage.py @@ -502,7 +502,11 @@ class ModelStorage(Model): :param clause: a domain clause :return: a list of domain clause ''' - return [(self._rec_name,) + clause[1:]] + rec_name = self._rec_name + if (rec_name not in self._columns + and rec_name not in self._inherit_fields): + return [] + return [(rec_name,) + clause[1:]] def browse(self, ids): ''' From 91e183fd54b6ad676f79eeb06017f252824ac5c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 1 Mar 2012 22:50:47 +0100 Subject: [PATCH 055/128] Fix Browse Cache when module dependencies are deleted (transplanted from 7a75670c2a1ba0eff44825ab20b436286aa8f907) --- trytond/ir/module/module.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/trytond/ir/module/module.py b/trytond/ir/module/module.py index 411286ff09..74fb746916 100644 --- a/trytond/ir/module/module.py +++ b/trytond/ir/module/module.py @@ -318,6 +318,8 @@ class Module(ModelSQL, ModelView): if x.name not in depends]) if depends is None: depends = [] + # Restart Browse Cache for deleted dependencies + module = self.browse(module.id) dependency_names = [x.name for x in module.dependencies] for depend in depends: if depend not in dependency_names: From 22c7b85321aece072e834ec70d2cc5054b32425a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 2 Mar 2012 10:45:35 +0100 Subject: [PATCH 056/128] Convert XML-RPC datetime into date for Date fields issue2464 (transplanted from 7169a01cd5e0576dbad835a1445e547f7cd8fa4f) --- trytond/backend/fields.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/trytond/backend/fields.py b/trytond/backend/fields.py index 0919c26ef1..40c457e407 100644 --- a/trytond/backend/fields.py +++ b/trytond/backend/fields.py @@ -103,6 +103,8 @@ class Date(Field): # subclass of date assert(not isinstance(value, datetime.datetime) or value.time() == datetime.time()) + if isinstance(value, datetime.datetime): + value = value.date() return value From 4098f9f89dcc80b5ec2e1be20edfdf3e570baa56 Mon Sep 17 00:00:00 2001 From: Max Holtzberg Date: Fri, 2 Mar 2012 19:07:42 +0100 Subject: [PATCH 057/128] Substitute CAST types and SPLIT_PART function to according to the MySQL specs issue2345 review267002 (transplanted from aa8a0d838a4c840f57993c704a806fe60e96e5ec) --- trytond/backend/mysql/database.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/trytond/backend/mysql/database.py b/trytond/backend/mysql/database.py index de7fc52785..e20b59cf02 100644 --- a/trytond/backend/mysql/database.py +++ b/trytond/backend/mysql/database.py @@ -17,7 +17,17 @@ import tempfile QUOTE_SEPARATION = re.compile(r"(.*?)('.*?')", re.DOTALL) EXTRACT_EPOCH_PATTERN = re.compile(r'EXTRACT\s*\(\s*EPOCH\s+FROM', re.I) -CAST_VARCHAR_PATTERN = re.compile(r'CAST\s*\((.*)AS VARCHAR\)', re.I) +CAST_VARCHAR_PATTERN = re.compile(r' AS VARCHAR\)', re.I) +CAST_INTEGER_PATTERN = re.compile(r' AS (INTEGER|BIGINT)\)', re.I) +SPLIT_PART_LEFT_PATTERN = re.compile(r'SPLIT_PART\((.*?),', re.I) +SPLIT_PART_RIGHT_PATTERN = re.compile(r'^,(\d)', re.I) +def _replace_split_part_right(mobj): + pos = int(mobj.group(1)) + if pos not in (1, 2): + raise Exception('SPLIT_PART is only partially implemented for MySQL') + if pos == 2: + return ', -1' + return ', 1' DatabaseIntegrityError = None DatabaseOperationalError = None @@ -235,12 +245,22 @@ class Cursor(CursorInterface): def execute(self, sql, params=None): buf = "" + split_part_found = False for nquote, quote in QUOTE_SEPARATION.findall(sql+"''"): nquote = nquote.replace('ilike', 'like') nquote = re.sub(EXTRACT_EPOCH_PATTERN, r'UNIX_TIMESTAMP(', nquote) - nquote = re.sub(CAST_VARCHAR_PATTERN, r'CAST(\1AS CHAR)', + nquote = re.sub(CAST_VARCHAR_PATTERN, r' AS CHAR)', nquote) + nquote = re.sub(CAST_INTEGER_PATTERN, r' AS SIGNED INTEGER)', + nquote) + if split_part_found: + nquote = re.sub(SPLIT_PART_RIGHT_PATTERN, + _replace_split_part_right, nquote) + split_part_found = False + nquote, split_part_found = re.subn(SPLIT_PART_LEFT_PATTERN, + r'SUBSTRING_INDEX(\1, ', nquote) + buf += nquote + quote sql = buf[:-2] try: From b44716107353f65e55a2c85acff518378381adc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 3 Mar 2012 12:25:27 +0100 Subject: [PATCH 058/128] Add missing space before AS issue2345 (transplanted from e9243b10f113c754e2a325c5cc2a89a3f2c33fe2) --- trytond/model/modelsql.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index f245109d11..68e2c7e2df 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -491,7 +491,7 @@ class ModelSQL(ModelStorage): if '_timestamp' in fields_pre: if not self.table_query(): fields_pre2 += ['CAST(EXTRACT(EPOCH FROM ' - '(COALESCE("%s".write_date, "%s".create_date)))' + '(COALESCE("%s".write_date, "%s".create_date))) ' 'AS VARCHAR) AS _timestamp' % (self._table, self._table)] From 63774743f80e6b8895f5a3a9f4da9d370585022b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=C3=89vrard?= Date: Sun, 4 Mar 2012 16:07:16 +0100 Subject: [PATCH 059/128] Do not search for deleted history records review250003 (transplanted from 96962d9f896dbb635ce19c7c92f9b2cdf7e5eae0) --- trytond/model/modelsql.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 68e2c7e2df..2a86de58c2 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -1247,7 +1247,19 @@ class ModelSQL(ModelStorage): res.remove(data['id']) res.append(data['id']) ids_date[data['id']] = data['_datetime'] - return res + to_delete = set() + for i in range(0, len(res), cursor.IN_MAX): + sub_ids = res[i:i + cursor.IN_MAX] + reduced_sql, reduced_ids = reduce_ids('id', sub_ids) + cursor.execute(('SELECT id, write_date ' + 'FROM "%s__history" WHERE %s' + 'AND (write_date IS NOT NULL AND create_date IS NULL)' + ) % (self._table, reduced_sql), + reduced_ids) + for deleted_id, delete_date in cursor.fetchall(): + if ids_date[deleted_id] < delete_date: + to_delete.add(deleted_id) + return filter(lambda x: x not in to_delete, res) return [x['id'] for x in datas] From 95841d166066d1b3c73b44dd5402545e8c7b922e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 5 Mar 2012 10:14:14 +0100 Subject: [PATCH 060/128] Use relativedelta to make all the datetime computation issue2469 review266001 (transplanted from 2f7446cf783b5182fe14b1a6752c7ccad31ca954) --- trytond/pyson.py | 58 +++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/trytond/pyson.py b/trytond/pyson.py index b3d375bb30..d27881db54 100644 --- a/trytond/pyson.py +++ b/trytond/pyson.py @@ -6,6 +6,7 @@ if sys.version_info < (2, 6): else: import json import datetime +from dateutil.relativedelta import relativedelta class PYSON(object): @@ -394,23 +395,14 @@ class Date(PYSON): @staticmethod def eval(dct, context): - date = datetime.date.today() - replace = {} - for i, j in (('y', 'year'), ('M', 'month'), ('d', 'day')): - if dct[i] is not None: - replace[j] = dct[i] - date = date.replace(**replace) - if dct['dy']: - year = date.year + dct['dy'] - date = date.replace(year=year) - if dct['dM']: - month = date.month + dct['dM'] - year = date.year + month / 12 - month = month % 12 - date = date.replace(year=year, month=month) - if dct['dd']: - date += datetime.timedelta(days=dct['dd']) - return date + return datetime.date.today() + relativedelta( + year=dct['y'], + month=dct['M'], + day=dct['d'], + years=dct['dy'], + months=dct['dM'], + days=dct['dd'], + ) class DateTime(Date): @@ -458,22 +450,22 @@ class DateTime(Date): @staticmethod def eval(dct, context): - date = Date.eval(dct, context) - datetime_ = datetime.datetime.combine(date, - datetime.datetime.now().time()) - replace = {} - for i, j in (('h', 'hour'), ('m', 'minute'), ('s', 'second'), - ('ms', 'microsecond')): - if dct[i] is not None: - replace[j] = dct[i] - datetime_ = datetime_.replace(**replace) - delta = {} - for i, j in (('dh', 'hours'), ('dm', 'minutes'), ('ds', 'seconds'), - ('dms', 'microseconds')): - if dct[i]: - delta[j] = dct[i] - datetime_ += datetime.timedelta(**delta) - return datetime_ + return datetime.datetime.now() + relativedelta( + year=dct['y'], + month=dct['M'], + day=dct['d'], + hour=dct['h'], + minute=dct['m'], + second=dct['s'], + microsecond=dct['ms'], + years=dct['dy'], + months=dct['dM'], + days=dct['dd'], + hours=dct['dh'], + minutes=dct['dm'], + seconds=dct['ds'], + microseconds=dct['dms'], + ) CONTEXT = { 'Eval': Eval, From 96a24aa7be09273939e9dcb5a74b90cf94c36f27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 5 Mar 2012 11:45:51 +0100 Subject: [PATCH 061/128] Add missing sql_format in "like" clauses issue2478 review270002 (transplanted from 0fe90cd57f000b9382d9859f47bfea0d62c8e23c) --- trytond/model/modelsql.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 2a86de58c2..fae2d828fa 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -1795,12 +1795,16 @@ class ModelSQL(ModelStorage): qu2.append('%') add_null = True else: - qu2.append(arg[2]) + qu2.append(FIELDS[ + table._columns[arg[0]]._type + ].sql_format(arg[2])) elif arg[1] in ('not like', 'not ilike'): if not arg[2]: qu2.append('') else: - qu2.append(arg[2]) + qu2.append(FIELDS[ + table._columns[arg[0]]._type + ].sql_format(arg[2])) add_null = True else: if arg[0] in table._columns: From 30d95e7595959f74a85c2ea1c11f911080ceb668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 6 Mar 2012 10:24:57 +0100 Subject: [PATCH 062/128] It is not possible to compare Sha fields with hash (transplanted from 314016e72e0a8aa9b86d0ba77d19e48d95b57d7c) --- trytond/tests/test_fields.py | 51 +++--------------------------------- 1 file changed, 3 insertions(+), 48 deletions(-) diff --git a/trytond/tests/test_fields.py b/trytond/tests/test_fields.py index 7a725007ef..c26629842d 100644 --- a/trytond/tests/test_fields.py +++ b/trytond/tests/test_fields.py @@ -1396,12 +1396,7 @@ class FieldsTestCase(unittest.TestCase): self.assert_(sha_ids == [sha1_id]) sha_ids = self.sha.search([ - ('sha', 'like', '640ab2bae07bedc4c163f679a746f7ab7fb5d1fa'), - ]) - self.assert_(sha_ids == [sha1_id]) - - sha_ids = self.sha.search([ - ('sha', 'like', '640a%'), + ('sha', 'like', 'Test'), ]) self.assert_(sha_ids == [sha1_id]) @@ -1411,17 +1406,7 @@ class FieldsTestCase(unittest.TestCase): self.assert_(sha_ids == []) sha_ids = self.sha.search([ - ('sha', 'like', 'F%'), - ]) - self.assert_(sha_ids == []) - - sha_ids = self.sha.search([ - ('sha', 'ilike', '640AB2BAE07BEDC4C163F679A746F7AB7FB5D1FA'), - ]) - self.assert_(sha_ids == [sha1_id]) - - sha_ids = self.sha.search([ - ('sha', 'ilike', '640A%'), + ('sha', 'ilike', 'Test'), ]) self.assert_(sha_ids == [sha1_id]) @@ -1431,17 +1416,7 @@ class FieldsTestCase(unittest.TestCase): self.assert_(sha_ids == []) sha_ids = self.sha.search([ - ('sha', 'ilike', 'f%'), - ]) - self.assert_(sha_ids == []) - - sha_ids = self.sha.search([ - ('sha', 'not like', '640ab2bae07bedc4c163f679a746f7ab7fb5d1fa'), - ]) - self.assert_(sha_ids == []) - - sha_ids = self.sha.search([ - ('sha', 'not like', '640a%'), + ('sha', 'not like', 'Test'), ]) self.assert_(sha_ids == []) @@ -1450,31 +1425,11 @@ class FieldsTestCase(unittest.TestCase): ]) self.assert_(sha_ids == [sha1_id]) - sha_ids = self.sha.search([ - ('sha', 'not like', 'F%'), - ]) - self.assert_(sha_ids == [sha1_id]) - - sha_ids = self.sha.search([ - ('sha', 'not ilike', '640AB2BAE07BEDC4C163F679A746F7AB7FB5D1FA'), - ]) - self.assert_(sha_ids == []) - - sha_ids = self.sha.search([ - ('sha', 'not ilike', '640A%'), - ]) - self.assert_(sha_ids == []) - sha_ids = self.sha.search([ ('sha', 'not ilike', 'foo'), ]) self.assert_(sha_ids == [sha1_id]) - sha_ids = self.sha.search([ - ('sha', 'not ilike', 'f%'), - ]) - self.assert_(sha_ids == [sha1_id]) - sha2_id = self.sha.create({ 'sha': False, }) From e79673f04e499d1e97986b0ef631e2bb1607392b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 28 Mar 2012 19:07:26 +0200 Subject: [PATCH 063/128] Don't allow rpc call on ModelStorage without ModelView CVE-2012-0215 issue2476 review307002 --- CHANGELOG | 2 ++ trytond/model/modelstorage.py | 26 ++++++++++++++------------ trytond/workflow/workflow.py | 5 ----- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 937bd106f9..ea3135493c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +* Don't allow rpc call on ModelStorage without ModelView (CVE-2012-0215) + Version 2.0.3 - 2011-12-26 * Bug fixes (see mercurial logs for details) diff --git a/trytond/model/modelstorage.py b/trytond/model/modelstorage.py index ac62617a9f..863e24d77e 100644 --- a/trytond/model/modelstorage.py +++ b/trytond/model/modelstorage.py @@ -22,6 +22,7 @@ from trytond.pyson import PYSONEncoder, PYSONDecoder, PYSON from trytond.const import OPERATORS from trytond.transaction import Transaction from trytond.config import CONFIG +from trytond.model.modelview import ModelView class ModelStorage(Model): @@ -38,18 +39,19 @@ class ModelStorage(Model): def __init__(self): super(ModelStorage, self).__init__() - self._rpc.update({ - 'create': True, - 'read': False, - 'write': True, - 'delete': True, - 'copy': True, - 'search': False, - 'search_count': False, - 'search_read': False, - 'export_data': False, - 'import_data': True, - }) + if isinstance(self, ModelView): + self._rpc.update({ + 'create': True, + 'read': False, + 'write': True, + 'delete': True, + 'copy': True, + 'search': False, + 'search_count': False, + 'search_read': False, + 'export_data': False, + 'import_data': True, + }) self._constraints = [] def default_create_uid(self): diff --git a/trytond/workflow/workflow.py b/trytond/workflow/workflow.py index c1075b917c..7ee189e594 100644 --- a/trytond/workflow/workflow.py +++ b/trytond/workflow/workflow.py @@ -253,11 +253,6 @@ class WorkflowTransitionInstance(ModelSQL): inst_id = fields.Many2One('workflow.instance', 'Instance', ondelete='CASCADE', select=1, required=True) - def __init__(self): - super(WorkflowTransitionInstance, self).__init__() - for i in ('create', 'write', 'delete', 'copy'): - del self._rpc[i] - def fields_get(self, fields_names=None): res = super(WorkflowTransitionInstance, self).fields_get( fields_names=fields_names) From 13a9b12c6b7be2c7766fc4bf10768d719c67961f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 28 Mar 2012 20:00:10 +0200 Subject: [PATCH 064/128] Prepare release 2.0.4 --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index ea3135493c..9b155e6de9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +Version 2.0.4 - 2012-03-28 +* Bug fixes (see mercurial logs for details) * Don't allow rpc call on ModelStorage without ModelView (CVE-2012-0215) Version 2.0.3 - 2011-12-26 From c1e2d943dc4baf0333380e5f896bf6b698d18601 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 28 Mar 2012 20:00:17 +0200 Subject: [PATCH 065/128] Added tag 2.0.4 for changeset 079bc951ab68 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 07da0572a8..d52f34e696 100644 --- a/.hgtags +++ b/.hgtags @@ -7,3 +7,4 @@ af3a6063b46bf8739a513a06400fbb9858b5869b 1.8.0 b7c3a0a6034631032867ba0f33c26b7786ebe89a 2.0.1 66ba97c0b08e179853b3acb14673c5c87614da33 2.0.2 f457ce376aaf792d4fdafd04bc2fb4d47ddac3cc 2.0.3 +079bc951ab6887d2289e4bd6ee31c6bc5273137c 2.0.4 From 70b819d716b35305b7211f835b9f8f709aebf665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 28 Mar 2012 20:01:20 +0200 Subject: [PATCH 066/128] Increase version number --- trytond/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/version.py b/trytond/version.py index d70007bef2..b8c35e06f4 100644 --- a/trytond/version.py +++ b/trytond/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "trytond" -VERSION = "2.0.4" +VERSION = "2.0.5" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From cd7ddd2c2e6d596708a8c4fb42e20573496ac130 Mon Sep 17 00:00:00 2001 From: Albert Cervera i Areny Date: Sat, 17 Mar 2012 12:46:56 +0100 Subject: [PATCH 067/128] Fix error in convert.py when removing records of a model that no longer exists. Fix error in convert.py when an upgrade needs to remove records of a model which no longer exists. issue2496 review283003 (transplanted from 4661a1c17b453df19e64aec39fafd63e64d2c8bf) --- trytond/convert.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/trytond/convert.py b/trytond/convert.py index 03ba03d2a6..fe57481d44 100644 --- a/trytond/convert.py +++ b/trytond/convert.py @@ -373,8 +373,12 @@ class Fs2bdAccessor: record_ids.setdefault(rec.model, []) record_ids[rec.model].append(rec.db_id) + object_name_list = set(self.pool.object_name_list()) + self.browserecord[module] = {} for model_name in record_ids.keys(): + if model_name not in object_name_list: + continue model_obj = self.pool.get(model_name) self.browserecord[module][model_name] = {} for i in range(0, len(record_ids[model_name]), cursor.IN_MAX): @@ -951,6 +955,7 @@ def post_import(pool, module, to_delete): ('module', '=', module), ], order=[('id', 'DESC')]) + object_name_list = set(pool.object_name_list()) for mrec in modeldata_obj.browse(mdata_ids): mdata_id, model, db_id = mrec.id, mrec.model, mrec.db_id @@ -1000,9 +1005,14 @@ def post_import(pool, module, to_delete): 'Deleting %s@%s' % (db_id, model)) try: # Deletion of the record - model_obj = pool.get(model) - model_obj.delete(db_id) - mdata_delete.append(mdata_id) + if model in object_name_list: + model_obj = pool.get(model) + model_obj.delete(db_id) + mdata_delete.append(mdata_id) + else: + logging.getLogger("convert").warning( + 'Could not delete id %d of model %s because model no ' + 'longer exists.' % (db_id, model)) cursor.commit() except Exception: cursor.rollback() From c64d0e8fda931167fea060181af5a5bf71df4a16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=C3=89vrard?= Date: Thu, 29 Mar 2012 12:19:43 +0200 Subject: [PATCH 068/128] resetting columns should also reset defaults review290001 (transplanted from 1df2e9660cd86658f518d67db367cd7536c885de) --- trytond/model/model.py | 1 + 1 file changed, 1 insertion(+) diff --git a/trytond/model/model.py b/trytond/model/model.py index 58f31095c2..3ec588c6dd 100644 --- a/trytond/model/model.py +++ b/trytond/model/model.py @@ -26,6 +26,7 @@ class Model(WarningErrorMixin): def _reset_columns(self): self.__columns = None + self.__defaults = None self._reset_xxx2many_targets() def _getcolumns(self): From 63656f15e1b05032bc2501f0b1da8eac26b179fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 13 Apr 2012 11:15:10 +0200 Subject: [PATCH 069/128] Sync tree tag definition between form and tree view tree could have no child field issue2535 (transplanted from bf20d12a8c13838509713157a40c02f71b206ce9) --- trytond/ir/ui/form.rnc | 2 +- trytond/ir/ui/form.rng | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/trytond/ir/ui/form.rnc b/trytond/ir/ui/form.rnc index a3c97b8098..3f67962b57 100644 --- a/trytond/ir/ui/form.rnc +++ b/trytond/ir/ui/form.rnc @@ -20,7 +20,7 @@ attlist.form &= attribute on_write { text }? attlist.form &= [ a:defaultValue = "4" ] attribute col { text }? attlist.form &= attribute cursor { text }? -tree = element tree { attlist.tree, field+ } +tree = element tree { attlist.tree, field* } attlist.tree &= [ a:defaultValue = "Unknown" ] attribute string { text }? attlist.tree &= attribute on_write { text }? diff --git a/trytond/ir/ui/form.rng b/trytond/ir/ui/form.rng index 8540f19f96..72e203f82c 100644 --- a/trytond/ir/ui/form.rng +++ b/trytond/ir/ui/form.rng @@ -42,9 +42,9 @@ - + - + From c3880ce3add083336b70e33c4da11d531edafa15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 16 Apr 2012 02:10:50 +0200 Subject: [PATCH 070/128] Fix typo in field name date_send -> date_sent issue2551 (transplanted from 2ceb8c3823e24bd1bf657d20463c3cae45ae8628) --- trytond/res/request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/res/request.py b/trytond/res/request.py index 268106d26b..e4cef89fbf 100644 --- a/trytond/res/request.py +++ b/trytond/res/request.py @@ -120,7 +120,7 @@ class Request(ModelSQL, ModelView): request_history_obj.create(values) self.write(ids, { 'state': 'waiting', - 'date_send': datetime.datetime.now(), + 'date_sent': datetime.datetime.now(), }) return True From 1785bd92fb987833f66def44881896f4ded367d2 Mon Sep 17 00:00:00 2001 From: Antoine Smolders Date: Thu, 19 Apr 2012 19:41:44 +0200 Subject: [PATCH 071/128] DatabaseIntegrityError and DatabaseOperationalError were redefined to None. issue2422 review333002 (transplanted from d0780d2a42c8056a8cda9fe3d16bb219df481b7f) --- trytond/backend/mysql/database.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/trytond/backend/mysql/database.py b/trytond/backend/mysql/database.py index e20b59cf02..6a8184dfae 100644 --- a/trytond/backend/mysql/database.py +++ b/trytond/backend/mysql/database.py @@ -28,8 +28,6 @@ def _replace_split_part_right(mobj): if pos == 2: return ', -1' return ', 1' -DatabaseIntegrityError = None -DatabaseOperationalError = None class Database(DatabaseInterface): From 88169287dbf4d58ff6d73d97b85094dfc56b9787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 25 Apr 2012 17:50:01 +0200 Subject: [PATCH 072/128] Missing quote arround table name in order clause (transplanted from 4929bf1c53d95db2ce2812bafa468093121b744f) --- trytond/model/modelsql.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index fae2d828fa..b8d1c86805 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -2003,7 +2003,7 @@ class ModelSQL(ModelStorage): if field_name: if '%(table)s' in field_name or '%(order)s' in field_name: order_by.append(field_name % { - 'table': table_name, + 'table': '"%s"' % table_name, 'order': otype, }) else: From 9a5e71075fbca40478a85e72285050e7808b3c8f Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Mon, 7 May 2012 11:08:53 +0200 Subject: [PATCH 073/128] Prepare release 2.0.5 --- CHANGELOG | 3 +++ COPYRIGHT | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 9b155e6de9..13b1d95290 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.0.5 - 2012-05-07 +* Bug fixes (see mercurial logs for details) + Version 2.0.4 - 2012-03-28 * Bug fixes (see mercurial logs for details) * Don't allow rpc call on ModelStorage without ModelView (CVE-2012-0215) diff --git a/COPYRIGHT b/COPYRIGHT index 6c994d4a71..a0ccf70937 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,7 +1,7 @@ Copyright (C) 2004-2008 Tiny SPRL. -Copyright (C) 2007-2011 Cédric Krier. +Copyright (C) 2007-2012 Cédric Krier. Copyright (C) 2007-2011 Bertrand Chenal. -Copyright (C) 2008-2011 B2CK SPRL. +Copyright (C) 2008-2012 B2CK SPRL. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by From 8492c3449e2f75428ec1e86fdadcc2e71c1b58dc Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Mon, 7 May 2012 11:08:53 +0200 Subject: [PATCH 074/128] Added tag 2.0.5 for changeset e85fc268cc7d --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index d52f34e696..94c12cc02c 100644 --- a/.hgtags +++ b/.hgtags @@ -8,3 +8,4 @@ b7c3a0a6034631032867ba0f33c26b7786ebe89a 2.0.1 66ba97c0b08e179853b3acb14673c5c87614da33 2.0.2 f457ce376aaf792d4fdafd04bc2fb4d47ddac3cc 2.0.3 079bc951ab6887d2289e4bd6ee31c6bc5273137c 2.0.4 +e85fc268cc7db34cd414ea932df0c08913859739 2.0.5 From d4282640d621080521645760712d01c3efac7d15 Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Mon, 7 May 2012 11:09:15 +0200 Subject: [PATCH 075/128] Increase version number --- trytond/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/version.py b/trytond/version.py index b8c35e06f4..39f6229221 100644 --- a/trytond/version.py +++ b/trytond/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "trytond" -VERSION = "2.0.5" +VERSION = "2.0.6" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From 424aa0aa6880a4b8756ced67df6493f2bcee0605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 5 May 2012 09:28:41 +0200 Subject: [PATCH 076/128] Fix nested order_calc tables_args manipulation issue2572 review340003 (transplanted from 140087fedf85ceeb8be5d12aed23057a1f1bf74b) --- trytond/model/modelsql.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index b8d1c86805..0cff0f3a18 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -1862,8 +1862,7 @@ class ModelSQL(ModelStorage): table_name + '.' + link_field) for i in range(len(tables)): if table_name in tables[i]: - args = tables_args[tables[i]] - del tables_args[tables[i]] + args = tables_args.pop(tables[i], []) tables[i] = tables[i].replace(table_name, table_name + '.' + link_field) tables_args[tables[i]] = args @@ -1898,8 +1897,7 @@ class ModelSQL(ModelStorage): table_name + '.' + link_field) for i in range(len(tables)): if table_name in tables[i]: - args = tables_args[tables[i]] - del tables_args[tables[i]] + args = tables_args.pop(tables[i], []) tables[i] = tables[i].replace(table_name, table_name + '.' + link_field) tables_args[tables[i]] = args @@ -1918,8 +1916,7 @@ class ModelSQL(ModelStorage): table_name2 + '.' + link_field2) for i in range(1, len(tables)): if table_name2 in tables[i]: - args = tables_args[tables[i]] - del tables_args[tables[i]] + args = tables_args.pop(tables[i], []) tables[i] = tables[i].replace(table_name2, table_name2 + '.' + link_field2) tables_args[tables[i]] = args From bc5c20442497b1b685437105b4659bca16b6e31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 12 May 2012 16:50:11 +0200 Subject: [PATCH 077/128] Add missing quote on order field review340005 (transplanted from c1ab49a749912d0a1681ce19a21ed1d9e4b273b9) --- trytond/model/modelsql.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 0cff0f3a18..919789f9b1 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -2004,8 +2004,8 @@ class ModelSQL(ModelStorage): 'order': otype, }) else: - order_by.append('"' + table_name + '".' + field_name + \ - ' ' + otype) + order_by.append('"%s"."%s" %s' + % (table_name, field_name, otype)) return order_by, tables, tables_args if field in self._inherit_fields.keys(): From 842b2d8f148acb94c6029c1bc7b0b868c2b3e1b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 12 May 2012 17:25:00 +0200 Subject: [PATCH 078/128] Add missing empty selection for action in menu issue2599 (transplanted from df2144bfa0200416108beb12c77a7887cec07509) --- trytond/ir/ui/menu.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/trytond/ir/ui/menu.py b/trytond/ir/ui/menu.py index 4e722030e5..4f1d17d4c8 100644 --- a/trytond/ir/ui/menu.py +++ b/trytond/ir/ui/menu.py @@ -75,12 +75,13 @@ class UIMenu(ModelSQL, ModelView): order_field='name'), 'get_full_name') icon = fields.Selection('list_icons', 'Icon') action = fields.Function(fields.Reference('Action', - selection=[ - ('ir.action.report', 'ir.action.report'), - ('ir.action.act_window', 'ir.action.act_window'), - ('ir.action.wizard', 'ir.action.wizard'), - ('ir.action.url', 'ir.action.url'), - ]), 'get_action', setter='set_action') + selection=[ + ('', ''), + ('ir.action.report', 'ir.action.report'), + ('ir.action.act_window', 'ir.action.act_window'), + ('ir.action.wizard', 'ir.action.wizard'), + ('ir.action.url', 'ir.action.url'), + ]), 'get_action', setter='set_action') active = fields.Boolean('Active') def __init__(self): From b9cee09576a2e879618b778c201d02ecef3b7411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 17 May 2012 12:59:58 +0200 Subject: [PATCH 079/128] Fix MySQLdb to use time for TIME instead of timedelta (transplanted from ea54d01020f2bf5eaa9f9d6be6446970cfc9b4d2) --- trytond/backend/mysql/database.py | 1 + 1 file changed, 1 insertion(+) diff --git a/trytond/backend/mysql/database.py b/trytond/backend/mysql/database.py index 6a8184dfae..4fe483403f 100644 --- a/trytond/backend/mysql/database.py +++ b/trytond/backend/mysql/database.py @@ -41,6 +41,7 @@ class Database(DatabaseInterface): def cursor(self, autocommit=False): conv = MySQLdb.converters.conversions.copy() conv[float] = lambda value, _: repr(value) + conv[MySQLdb.constants.FIELD_TYPE.TIME] = MySQLdb.times.Time_or_None args = { 'db': self.database_name, 'sql_mode': 'traditional,postgresql', From e9c9036f1f24f17b97cbc380cce5d39684d7fdf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 20 Jun 2012 18:15:04 +0200 Subject: [PATCH 080/128] Skip empty arch when searching other strings of same model review397006 (transplanted from ab888dad00c295a627962fd0d78b64085d07c772) --- trytond/ir/ui/view.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/trytond/ir/ui/view.py b/trytond/ir/ui/view.py index f2d2b5e95a..b13c08832a 100644 --- a/trytond/ir/ui/view.py +++ b/trytond/ir/ui/view.py @@ -137,7 +137,10 @@ class View(ModelSQL, ModelView): ('module', '=', view.module), ]) for view2 in self.browse(view_ids): - tree2 = etree.fromstring(view2.arch) + xml2 = view2.arch.strip() + if not xml2: + continue + tree2 = etree.fromstring(xml2) root2_element = tree2.getroottree().getroot() strings += self._translate_view(root2_element) if not strings: From 695f39cd9bec9f841e450c5549561e7f8ad14e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 28 Jun 2012 14:59:53 +0200 Subject: [PATCH 081/128] Fix comparison of BrowseRecord when other is not a BrowseRecord review395002 (transplanted from f4f87514514c358a0f010e9e384974f0e125434c) --- trytond/model/browse.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/trytond/model/browse.py b/trytond/model/browse.py index d37cef18ec..91b5cf7095 100644 --- a/trytond/model/browse.py +++ b/trytond/model/browse.py @@ -201,9 +201,13 @@ class BrowseRecord(object): return "BrowseRecord(%s, %d)" % (self._model_name, self._id) def __eq__(self, other): + if not isinstance(other, BrowseRecord): + return False return (self._model_name, self._id) == (other._model_name, other._id) def __ne__(self, other): + if not isinstance(other, BrowseRecord): + return True return (self._model_name, self._id) != (other._model_name, other._id) # we need to define __unicode__ even though we've already defined __str__ From 2338c225a32c99b00d8c36afb42fcd6b3cb5ae6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 25 Jul 2012 20:51:36 +0200 Subject: [PATCH 082/128] Don't fail on unknown database for WebDAV issue2717 review426002 (transplanted from 66dfaa06e7f80da00229b88e9b9aae7fb4a1e70b) --- trytond/protocols/webdav.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/trytond/protocols/webdav.py b/trytond/protocols/webdav.py index 76e13ca98e..86fb4db38d 100644 --- a/trytond/protocols/webdav.py +++ b/trytond/protocols/webdav.py @@ -536,7 +536,11 @@ class WebDAVAuthRequestHandler(AuthServer.BufferedAuthRequestHandler, def get_userinfo(self, user, password, command=''): dbname = urllib.unquote_plus(self.path.split('/', 2)[1]) - if not dbname: + database = Database().connect() + cursor = database.cursor() + databases = database.list(cursor) + cursor.close() + if not dbname or dbname not in databases: database = Database().connect() return 1 user = int(login(dbname, user, password, cache=False)) From fabb4673117be12ccef980601f5f743d0fff1d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 23 Aug 2012 23:17:15 +0200 Subject: [PATCH 083/128] NULL value for boolean fields should be considered like False issue2755 review476002 (transplanted from b348f38d0d9419f742ea9d74f9f206d084c1e359) --- trytond/model/modelsql.py | 14 ++++++++++---- trytond/tests/test_fields.py | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 919789f9b1..815d448b21 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -1773,15 +1773,21 @@ class ModelSQL(ModelStorage): else: if (arg[2] is False) and (arg[1] == '='): if table._columns[arg[0]]._type == 'boolean': - qu1.append('("%s"."%s" = %%s)' % \ - (table._table, arg[0])) + qu1.append('(("%s"."%s" = %%s) OR ("%s"."%s" IS NULL))' + % (table._table, arg[0], table._table, arg[0])) qu2.append(False) else: qu1.append('("%s"."%s" IS NULL)' % \ (table._table, arg[0])) elif (arg[2] is False) and (arg[1] == '!='): - qu1.append('("%s"."%s" IS NOT NULL)' % \ - (table._table, arg[0])) + if table._columns[arg[0]]._type == 'boolean': + qu1.append('(("%s"."%s" != %%s) ' + 'AND ("%s"."%s" IS NOT NULL))' + % (table._table, arg[0], table._table, arg[0])) + qu2.append(False) + else: + qu1.append('("%s"."%s" IS NOT NULL)' % \ + (table._table, arg[0])) else: if arg[0] == 'id': qu1.append('("%s"."%s" %s %%s)' % \ diff --git a/trytond/tests/test_fields.py b/trytond/tests/test_fields.py index c26629842d..f6387f78aa 100644 --- a/trytond/tests/test_fields.py +++ b/trytond/tests/test_fields.py @@ -135,6 +135,23 @@ class FieldsTestCase(unittest.TestCase): boolean3_id = self.boolean.create({}) self.assert_(boolean3_id) + # Test search with NULL value + boolean4_id = self.boolean.create({ + 'boolean': None, + }) + self.assert_(boolean4_id) + + boolean_ids = self.boolean.search([ + ('boolean', '=', False), + ]) + self.assertEqual(boolean_ids, + [boolean2_id, boolean3_id, boolean4_id]) + + boolean_ids = self.boolean.search([ + ('boolean', '!=', False), + ]) + self.assertEqual(boolean_ids, [boolean1_id]) + boolean3 = self.boolean.read(boolean3_id, ['boolean']) self.assert_(boolean3['boolean'] == False) From 89fc5b7eee331874c6531f8c0d5f200c6f271f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 10 Sep 2012 18:07:43 +0200 Subject: [PATCH 084/128] Prepare release 2.0.6 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 13b1d95290..489e9c1e21 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.0.6 - 2012-09-10 +* Bug fixes (see mercurial logs for details) + Version 2.0.5 - 2012-05-07 * Bug fixes (see mercurial logs for details) From edd6ec02366232330cf809a049f457455e76d02c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 10 Sep 2012 18:07:45 +0200 Subject: [PATCH 085/128] Added tag 2.0.6 for changeset b7bb97a13380 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 94c12cc02c..eb1a4795b4 100644 --- a/.hgtags +++ b/.hgtags @@ -9,3 +9,4 @@ b7c3a0a6034631032867ba0f33c26b7786ebe89a 2.0.1 f457ce376aaf792d4fdafd04bc2fb4d47ddac3cc 2.0.3 079bc951ab6887d2289e4bd6ee31c6bc5273137c 2.0.4 e85fc268cc7db34cd414ea932df0c08913859739 2.0.5 +b7bb97a1338090ec3ffff997126a41c039b594b5 2.0.6 From 9a8098315db021477bd0cc472cc2f985a93fa639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 10 Sep 2012 18:08:15 +0200 Subject: [PATCH 086/128] Increase version number --- trytond/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/version.py b/trytond/version.py index 39f6229221..6926f093d8 100644 --- a/trytond/version.py +++ b/trytond/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "trytond" -VERSION = "2.0.6" +VERSION = "2.0.7" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From cca2477107050376aa402fd3db0b7df881ecf88b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 10 Sep 2012 15:09:35 +0200 Subject: [PATCH 087/128] Fix documentation about child child{1,2} was replaced by child (transplanted from 505c165774903bb4595616d2e17370433d982362) --- doc/topics/views/index.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/topics/views/index.rst b/doc/topics/views/index.rst index d8b3af94d6..fcb8d8e51f 100644 --- a/doc/topics/views/index.rst +++ b/doc/topics/views/index.rst @@ -350,10 +350,10 @@ hpaned, vpaned * ``colspan``: see in common-attributes-colspan_. The default for panes is 4 columns. -child1, child2 -^^^^^^^^^^^^^^ +child +^^^^^ -Contains the two childs of a hpaned or vpaned. +Contains the childs of a hpaned or vpaned. .. _example_form_view: From 816aff50952874f7992dcd9125db0854cdfb9718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 20 Sep 2012 23:31:04 +0200 Subject: [PATCH 088/128] Fix domain concatenation between list and tuple (transplanted from 1db3c1f30f2aa694d8ab586a0a95f40d6ff054f1) --- trytond/ir/lang.py | 2 +- trytond/res/user.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/trytond/ir/lang.py b/trytond/ir/lang.py index 6ce101fb87..2d734ad306 100644 --- a/trytond/ir/lang.py +++ b/trytond/ir/lang.py @@ -54,7 +54,7 @@ class Lang(ModelSQL, ModelView, Cacheable): if ids: ids += self.search([('name',) + clause[1:]], order=[]) return [('id', 'in', ids)] - return [('name',) + clause[1:]] + return [('name',) + tuple(clause[1:])] def read(self, ids, fields_names=None): translation_obj = self.pool.get('ir.translation') diff --git a/trytond/res/user.py b/trytond/res/user.py index 3f2e4ac609..1ca198e23f 100644 --- a/trytond/res/user.py +++ b/trytond/res/user.py @@ -219,7 +219,7 @@ class User(ModelSQL, ModelView): ], order=[]) if len(ids) == 1: return [('id', '=', ids[0])] - return [(self._rec_name,) + clause[1:]] + return [(self._rec_name,) + tuple(clause[1:])] def copy(self, ids, default=None): if default is None: From fed064443881dbb827d7ae44db73fc333b0eb676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=C3=89vrard?= Date: Fri, 21 Sep 2012 15:26:35 +0200 Subject: [PATCH 089/128] Set domain_get mode correctly review385001 (transplanted from 8f4010112a95920eb3ae9d45379fb5f8442387d8) --- trytond/ir/rule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/ir/rule.py b/trytond/ir/rule.py index cce65203ad..cfe75284b1 100644 --- a/trytond/ir/rule.py +++ b/trytond/ir/rule.py @@ -151,7 +151,7 @@ class Rule(ModelSQL, ModelView): if not Transaction().context.get('user'): return '', [] with Transaction().set_user(Transaction().context['user']): - return self.domain_get(model_name) + return self.domain_get(model_name, mode=mode) rule_group_obj = self.pool.get('ir.rule.group') model_obj = self.pool.get('ir.model') From bf14f634134b05b099fd57b1b0ab6a410d92833d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 24 Sep 2012 11:36:39 +0200 Subject: [PATCH 090/128] Fix read related values of reference fields By using just only the id to store the related values, it could result a mixing of different model with the same id. So now, it uses the reference value. (transplanted from fb51f5b4aa4c504466cd75db60bf23bc9053209b) --- trytond/model/modelsql.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 815d448b21..97cf1697c5 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -674,7 +674,7 @@ class ModelSQL(ModelStorage): obj = self.pool.get(model_name) record2 = obj.read(record_id, fields_related[field]) del record2['id'] - fields_related2values[field][record_id] = record2 + fields_related2values[field][record[field]] = record2 if to_del or fields_related.keys() or datetime_fields: for record in res: @@ -700,7 +700,7 @@ class ModelSQL(ModelStorage): continue record[field + '.' + related] = \ fields_related2values[field][ - record_id][related] + record[field]][related] for field in to_del: del record[field] From 5b33ab42109d7b8b92c5f75f059fc6c800b6c715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 5 Nov 2012 17:44:20 +0100 Subject: [PATCH 091/128] Prepare release 2.0.7 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 489e9c1e21..b055d90c55 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.0.7 - 2012-11-05 +* Bug fixes (see mercurial logs for details) + Version 2.0.6 - 2012-09-10 * Bug fixes (see mercurial logs for details) From 7833a4541cfba1dfb42a7370edb7ebaed4de34a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 5 Nov 2012 17:44:21 +0100 Subject: [PATCH 092/128] Added tag 2.0.7 for changeset 2f83f580c73b --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index eb1a4795b4..e8776fb58d 100644 --- a/.hgtags +++ b/.hgtags @@ -10,3 +10,4 @@ f457ce376aaf792d4fdafd04bc2fb4d47ddac3cc 2.0.3 079bc951ab6887d2289e4bd6ee31c6bc5273137c 2.0.4 e85fc268cc7db34cd414ea932df0c08913859739 2.0.5 b7bb97a1338090ec3ffff997126a41c039b594b5 2.0.6 +2f83f580c73b159c7cfc78352182b039e78683d0 2.0.7 From 6f937169e68b088939960c87582106fa16b1cee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 5 Nov 2012 17:44:58 +0100 Subject: [PATCH 093/128] Increase version number --- trytond/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/version.py b/trytond/version.py index 6926f093d8..7cf92347d2 100644 --- a/trytond/version.py +++ b/trytond/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "trytond" -VERSION = "2.0.7" +VERSION = "2.0.8" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From 670bd3be1961a824ae642b10c9fee9df03165cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=C3=89vrard?= Date: Tue, 13 Nov 2012 11:26:38 +0100 Subject: [PATCH 094/128] fix use of password not in ASCII review582004 issue2869 (transplanted from 11723f7a90274c0ede62bec51f782aa2efab0eea) --- trytond/protocols/dispatcher.py | 6 ++++-- trytond/security.py | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/trytond/protocols/dispatcher.py b/trytond/protocols/dispatcher.py index 3767b2799d..6be3bca380 100644 --- a/trytond/protocols/dispatcher.py +++ b/trytond/protocols/dispatcher.py @@ -211,9 +211,11 @@ def create(database_name, password, lang, admin_password): 'WHERE code = %s', 1) + ')' \ 'WHERE login <> \'root\'', (lang,)) if hashlib: - admin_password = hashlib.sha1(admin_password).hexdigest() + admin_password = hashlib.sha1(admin_password.encode('utf-8'))\ + .hexdigest() else: - admin_password = sha.new(admin_password).hexdigest() + admin_password = sha.new(admin_password.encode('utf-8'))\ + .hexdigest() cursor.execute('UPDATE res_user ' \ 'SET password = %s ' \ 'WHERE login = \'admin\'', (admin_password,)) diff --git a/trytond/security.py b/trytond/security.py index 1f2ed492a0..a988855332 100644 --- a/trytond/security.py +++ b/trytond/security.py @@ -21,7 +21,6 @@ def login(dbname, loginname, password, cache=True): if not dbname in database_list: pool.init() user_obj = pool.get('res.user') - password = password.decode('utf-8') user_id = user_obj.get_login(loginname, password) transaction.cursor.commit() if user_id: From d2e1a70a4587c2789a1ef237b2c1a68fb3cec0d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 22 Nov 2012 22:49:41 +0100 Subject: [PATCH 095/128] Add missing context when filling cache from search (transplanted from 4a73e09049b47932fede96fcfa1525724e072b1b) --- trytond/model/modelsql.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 97cf1697c5..354d97c8b1 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -1197,7 +1197,7 @@ class ModelSQL(ModelStorage): cursor.execute(query_str, tables_args + qu2) datas = cursor.dictfetchmany(cursor.IN_MAX) - cache = cursor.get_cache() + cache = cursor.get_cache(Transaction().context) cache.setdefault(self._name, {}) delete_records = Transaction().delete_records.setdefault(self._name, set()) From 659a4b345d4444fba4c31650458291b06b2f7e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 23 Dec 2012 17:00:50 +0100 Subject: [PATCH 096/128] Prepare release 2.0.8 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index b055d90c55..647ed2d562 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.0.8 - 2012-12-23 +* Bug fixes (see mercurial logs for details) + Version 2.0.7 - 2012-11-05 * Bug fixes (see mercurial logs for details) From a2918d5d79a30d3dff150672710c84bcaebdabc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 23 Dec 2012 17:00:51 +0100 Subject: [PATCH 097/128] Added tag 2.0.8 for changeset 33fbe0a7f1b1 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index e8776fb58d..71874a171c 100644 --- a/.hgtags +++ b/.hgtags @@ -11,3 +11,4 @@ f457ce376aaf792d4fdafd04bc2fb4d47ddac3cc 2.0.3 e85fc268cc7db34cd414ea932df0c08913859739 2.0.5 b7bb97a1338090ec3ffff997126a41c039b594b5 2.0.6 2f83f580c73b159c7cfc78352182b039e78683d0 2.0.7 +33fbe0a7f1b166bbf8360618970c76dda8b0fc21 2.0.8 From c7feda79de97e45b595fbb28d657e1d58a28f438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 23 Dec 2012 17:01:14 +0100 Subject: [PATCH 098/128] Increase version number --- trytond/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/version.py b/trytond/version.py index 7cf92347d2..1a00eed8b7 100644 --- a/trytond/version.py +++ b/trytond/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "trytond" -VERSION = "2.0.8" +VERSION = "2.0.9" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From b16988208a6fffd7be6945b521f1d8a0ff3397ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 4 Mar 2013 21:30:17 +0100 Subject: [PATCH 099/128] Fix check of _sql_error_messages issue3021 review682002 (transplanted from b0bd4835cfc875baf1bf8124e7e23c4cc45c3483) --- trytond/model/modelsql.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 354d97c8b1..64d4e37cc2 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -372,7 +372,7 @@ class ModelSQL(ModelStorage): for name, _, error in self._sql_constraints: if name in exception[0]: self.raise_user_error(error) - for name, error in self._sql_error_messages: + for name, error in self._sql_error_messages.iteritems(): if name in exception[0]: self.raise_user_error(error) raise @@ -887,7 +887,7 @@ class ModelSQL(ModelStorage): for name, _, error in self._sql_constraints: if name in exception[0]: self.raise_user_error(error) - for name, error in self._sql_error_messages: + for name, error in self._sql_error_messages.iteritems(): if name in exception[0]: self.raise_user_error(error) raise From cd9cd461252a031eb7a549508d97863b1097be58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 6 Mar 2013 13:32:16 +0100 Subject: [PATCH 100/128] Don't use Model from res module in ir module As ir module doesn't depend on res module, it should not use the Model of it. (transplanted from f89e104aad506c06c572c76166431ccbd9953def) --- trytond/ir/model.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/trytond/ir/model.py b/trytond/ir/model.py index 60ce590989..c3617e727b 100644 --- a/trytond/ir/model.py +++ b/trytond/ir/model.py @@ -367,7 +367,6 @@ class ModelFieldAccess(ModelSQL, ModelView): ir_model_obj = self.pool.get('ir.model') ir_model_field_obj = self.pool.get('ir.model.field') - user_group_obj = self.pool.get('res.user-res.group') cursor = Transaction().cursor @@ -378,12 +377,12 @@ class ModelFieldAccess(ModelSQL, ModelView): 'ON (a.field = f.id) ' 'JOIN "%s" AS m ' 'ON (f.model = m.id) ' - 'LEFT JOIN "%s" AS gu ' + 'LEFT JOIN "res_user-res_group" AS gu ' 'ON (gu.gid = a."group") ' 'WHERE m.model = %%s AND (gu.uid = %%s OR a."group" IS NULL) ' 'GROUP BY f.name' % (mode, self._table, ir_model_field_obj._table, - ir_model_obj._table, user_group_obj._table), + ir_model_obj._table), (model_name, Transaction().user)) accesses = dict(cursor.fetchall()) if access: From c93a77daf6af064e2326baa0c89330f31a6ea980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 12 Mar 2013 11:47:14 +0100 Subject: [PATCH 101/128] Fix check of _sql_error_messages (transplanted from 4e5f1c24ce3ddad5f362e734138bc67643bad079) --- trytond/model/modelsql.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 64d4e37cc2..623e9e3b83 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -1102,7 +1102,7 @@ class ModelSQL(ModelStorage): for name, _, error in self._sql_constraints: if name in exception[0]: self.raise_user_error(error) - for name, error in self._sql_error_messages: + for name, error in self._sql_error_messages.iteritems(): if name in exception[0]: self.raise_user_error(error) raise From f21a071ee5c6c6c6a07d8176a298f707eb9e41df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 13 Mar 2013 18:42:30 +0100 Subject: [PATCH 102/128] Fix local variable 'microseconds' referenced before assignment issue3049 (transplanted from cdd7c4de7770e3c69fcb584325c2325d91781c06) --- trytond/backend/sqlite/database.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/trytond/backend/sqlite/database.py b/trytond/backend/sqlite/database.py index f0294b424e..f81e7ac54a 100644 --- a/trytond/backend/sqlite/database.py +++ b/trytond/backend/sqlite/database.py @@ -39,6 +39,8 @@ def extract(lookup_type, date): hours, minutes, seconds = map(int, timepart_full[0].split(":")) if len(timepart_full) == 2: microseconds = int(timepart_full[1]) + else: + microseconds = 0 date = datetime.datetime(year, month, day, hours, minutes, seconds, microseconds) except Exception: From 4353aec95429d2e5c1fb5c5bad31a604750312f0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bonicoli Date: Mon, 8 Apr 2013 10:57:39 +0200 Subject: [PATCH 103/128] View: remove encoding declaration (fix lxml usage) issue3119 review765002 (transplanted from 861d25f41f6232ed43b25cac63ee3892313332e4) --- trytond/model/modelview.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trytond/model/modelview.py b/trytond/model/modelview.py index 55b4fcce5d..56322fcfc7 100644 --- a/trytond/model/modelview.py +++ b/trytond/model/modelview.py @@ -190,7 +190,7 @@ class ModelView(Model): else: if view_type == 'form': res = self.fields_get() - xml = '''''' \ + xml = '''''' \ '''
''' % (self._description,) for i in res: if i in ('create_uid', 'create_date', @@ -206,7 +206,7 @@ class ModelView(Model): field = 'id' if self._rec_name in self._columns: field = self._rec_name - xml = '''''' \ + xml = '''''' \ '''''' \ % (self._description, field) else: From 6403b3664b1af0034333cb66b431c02f137a4f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 16 Apr 2013 15:38:04 +0200 Subject: [PATCH 104/128] Fix clean _language_cache review782002 (transplanted from 2833b069cf76cb603305846fa2bf044ddd0cf286) --- trytond/model/modelstorage.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trytond/model/modelstorage.py b/trytond/model/modelstorage.py index 863e24d77e..7dc1fe475d 100644 --- a/trytond/model/modelstorage.py +++ b/trytond/model/modelstorage.py @@ -150,7 +150,7 @@ class ModelStorage(Model): # Clean cursor cache for cache in Transaction().cursor.cache.values(): - for cache in (cache, cache.get('_language_cache', {}).values()): + for cache in [cache] + cache.get('_language_cache', {}).values(): if self._name in cache: if isinstance(ids, (int, long)): ids = [ids] @@ -220,7 +220,7 @@ class ModelStorage(Model): # Clean cursor cache for cache in Transaction().cursor.cache.values(): - for cache in (cache, cache.get('_language_cache', {}).values()): + for cache in [cache] + cache.get('_language_cache', {}).values(): if self._name in cache: if isinstance(ids, (int, long)): ids = [ids] From d7d3c1177a7c8bcb1679c9c1170e242fd430f277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 2 May 2013 09:40:23 +0200 Subject: [PATCH 105/128] Prepare release 2.0.9 --- CHANGELOG | 3 +++ COPYRIGHT | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 647ed2d562..612d9e8813 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.0.9 - 2013-05-02 +* Bug fixes (see mercurial logs for details) + Version 2.0.8 - 2012-12-23 * Bug fixes (see mercurial logs for details) diff --git a/COPYRIGHT b/COPYRIGHT index a0ccf70937..13d533e119 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,7 +1,7 @@ Copyright (C) 2004-2008 Tiny SPRL. -Copyright (C) 2007-2012 Cédric Krier. +Copyright (C) 2007-2013 Cédric Krier. Copyright (C) 2007-2011 Bertrand Chenal. -Copyright (C) 2008-2012 B2CK SPRL. +Copyright (C) 2008-2013 B2CK SPRL. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by From 24eac6a7253740162d8509802fcb23ce9eb3a671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 2 May 2013 09:40:24 +0200 Subject: [PATCH 106/128] Added tag 2.0.9 for changeset c12bff3c6f5b --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 71874a171c..ff32081971 100644 --- a/.hgtags +++ b/.hgtags @@ -12,3 +12,4 @@ e85fc268cc7db34cd414ea932df0c08913859739 2.0.5 b7bb97a1338090ec3ffff997126a41c039b594b5 2.0.6 2f83f580c73b159c7cfc78352182b039e78683d0 2.0.7 33fbe0a7f1b166bbf8360618970c76dda8b0fc21 2.0.8 +c12bff3c6f5b84788ec57bc8fd947d0af6f0627b 2.0.9 From 5add5857998b01850ecd4d3a5d66850694b9b256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 2 May 2013 09:40:45 +0200 Subject: [PATCH 107/128] Increase version number --- trytond/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/version.py b/trytond/version.py index 1a00eed8b7..52818fef75 100644 --- a/trytond/version.py +++ b/trytond/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "trytond" -VERSION = "2.0.9" +VERSION = "2.0.10" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From 89fe3b8f7d375cb5e714c8f0f18d3a1c02ca5cea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 4 May 2013 11:44:15 +0200 Subject: [PATCH 108/128] Allow None in child_of operator issue3190 review844002 (transplanted from 67208cffb07e8ab82e904a23f135fa8c6308d5a4) --- trytond/model/modelsql.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 623e9e3b83..0290031b55 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -1481,7 +1481,7 @@ class ModelSQL(ModelStorage): ids2 = [x[0] for x in target_obj.search([ ('rec_name', 'ilike', domain[i][2]), ], order=[])] - elif isinstance(domain[i][2], (int, long)): + elif not isinstance(domain[i][2], list): ids2 = [domain[i][2]] else: ids2 = domain[i][2] @@ -1557,7 +1557,7 @@ class ModelSQL(ModelStorage): ids2 = [x[0] for x in field_obj.search([ ('rec_name', 'like', domain[i][2]), ], order=[])] - elif isinstance(domain[i][2], (int, long)): + elif not isinstance(domain[i][2], list): ids2 = [domain[i][2]] else: ids2 = domain[i][2] From c04360bc6137d63682e4d6ba69c8cdfd4994423f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 18 May 2013 19:13:12 +0200 Subject: [PATCH 109/128] Fix validation of domain for One2One fields issue3206 review852003 (transplanted from 3765bc03294580c09839b03fa40ea42459376e2b) --- trytond/model/modelstorage.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trytond/model/modelstorage.py b/trytond/model/modelstorage.py index 7dc1fe475d..dbe4e099f5 100644 --- a/trytond/model/modelstorage.py +++ b/trytond/model/modelstorage.py @@ -1017,7 +1017,7 @@ class ModelStorage(Model): domain = PYSONDecoder(env).decode(pyson_domain) relation_ids = [] if record[field_name]: - if field._type in ('many2one',): + if field._type in ('many2one', 'one2one'): relation_ids.append(record[field_name].id) else: relation_ids.extend( @@ -1035,7 +1035,7 @@ class ModelStorage(Model): relation_ids = [] for record in records: if record[field_name]: - if field._type in ('many2one',): + if field._type in ('many2one', 'one2one'): relation_ids.append(record[field_name].id) else: relation_ids.extend( From ef1b785de2ff1e72cb62a3224e6b78e012b5f15d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 9 Jun 2013 22:37:37 +0200 Subject: [PATCH 110/128] Prepare release 2.0.10 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 612d9e8813..66aa30c326 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.0.10 - 2013-06-09 +* Bug fixes (see mercurial logs for details) + Version 2.0.9 - 2013-05-02 * Bug fixes (see mercurial logs for details) From 5d29b1949f8d1ea9578f5a476b1afa544907ed89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 9 Jun 2013 22:37:38 +0200 Subject: [PATCH 111/128] Added tag 2.0.10 for changeset 64a235ffee62 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index ff32081971..c4ccc73328 100644 --- a/.hgtags +++ b/.hgtags @@ -13,3 +13,4 @@ b7bb97a1338090ec3ffff997126a41c039b594b5 2.0.6 2f83f580c73b159c7cfc78352182b039e78683d0 2.0.7 33fbe0a7f1b166bbf8360618970c76dda8b0fc21 2.0.8 c12bff3c6f5b84788ec57bc8fd947d0af6f0627b 2.0.9 +64a235ffee62cd380e83c118c43287d93e328588 2.0.10 From f868d4b5bb54f5fc550dd89e5c058c55b6cf05d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 9 Jun 2013 22:37:53 +0200 Subject: [PATCH 112/128] Increase version number --- trytond/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/version.py b/trytond/version.py index 52818fef75..c72587c3d3 100644 --- a/trytond/version.py +++ b/trytond/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "trytond" -VERSION = "2.0.10" +VERSION = "2.0.11" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From af92222c7260e270e6c12cffaf01e6177e9db7ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 1 Jun 2013 00:17:33 +0200 Subject: [PATCH 113/128] Fix domain concatenation between list and tuple (transplanted from 83a66e4ae380e5f2d790d1cd4c10a59a714fd6bd) --- trytond/model/modelstorage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/model/modelstorage.py b/trytond/model/modelstorage.py index dbe4e099f5..665b8f52a6 100644 --- a/trytond/model/modelstorage.py +++ b/trytond/model/modelstorage.py @@ -508,7 +508,7 @@ class ModelStorage(Model): if (rec_name not in self._columns and rec_name not in self._inherit_fields): return [] - return [(rec_name,) + clause[1:]] + return [(rec_name,) + tuple(clause[1:])] def browse(self, ids): ''' From 71863e951509b4308a4125a6749293646e4b7cfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 22 Jul 2013 11:34:08 +0200 Subject: [PATCH 114/128] Prepare release 2.0.11 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 66aa30c326..7f1238f65a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.0.11 - 2013-07-22 +* Bug fixes (see mercurial logs for details) + Version 2.0.10 - 2013-06-09 * Bug fixes (see mercurial logs for details) From 35e252e12bd4ba56e69036ae13b69bd8c7b32801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 22 Jul 2013 11:34:09 +0200 Subject: [PATCH 115/128] Added tag 2.0.11 for changeset f11ed54bb218 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index c4ccc73328..31f926d0d8 100644 --- a/.hgtags +++ b/.hgtags @@ -14,3 +14,4 @@ b7bb97a1338090ec3ffff997126a41c039b594b5 2.0.6 33fbe0a7f1b166bbf8360618970c76dda8b0fc21 2.0.8 c12bff3c6f5b84788ec57bc8fd947d0af6f0627b 2.0.9 64a235ffee62cd380e83c118c43287d93e328588 2.0.10 +f11ed54bb218722aa641637fee1dff300e59eca6 2.0.11 From 1febb0e66b6e86c09ccef053e769b0b526b02524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 22 Jul 2013 11:34:40 +0200 Subject: [PATCH 116/128] Increase version number --- trytond/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/version.py b/trytond/version.py index c72587c3d3..cf79d616b0 100644 --- a/trytond/version.py +++ b/trytond/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "trytond" -VERSION = "2.0.11" +VERSION = "2.0.12" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From d8f7ba48663f9652f118973216e336c627f8e733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 29 Jul 2013 10:32:45 +0200 Subject: [PATCH 117/128] Fix missing microseconds initialisation review1000002 (transplanted from 898b5745851610dd4ccd33fdc98a06c393669fc5) --- trytond/ir/trigger.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/trytond/ir/trigger.py b/trytond/ir/trigger.py index 971f29f6c1..73fdf45c81 100644 --- a/trytond/ir/trigger.py +++ b/trytond/ir/trigger.py @@ -200,6 +200,8 @@ class Trigger(ModelSQL, ModelView): hours, minutes, seconds = map(int, timepart_full[0].split(":")) if len(timepart_full) == 2: microseconds = int(timepart_full[1]) + else: + microseconds = 0 delay[record_id] = datetime.datetime(year, month, day, hours, minutes, seconds, microseconds) if datetime.datetime.now() - delay[record_id] \ From 5f2d27f0381d11aa22c6a88d0807baaf45a5b03e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 1 Aug 2013 16:09:41 +0200 Subject: [PATCH 118/128] Remove validation of unused XML attributes Those XML attributes are no more allowed in XML. The domain is not only allowed in dashboard and it is not a field domain. issue3310 review986002 (transplanted from 4eba4934492ab6731626837e5bab3fb19f4cf053) --- trytond/ir/ui/view.py | 7 +------ trytond/model/modelview.py | 3 +-- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/trytond/ir/ui/view.py b/trytond/ir/ui/view.py index b13c08832a..e0bbb3e48e 100644 --- a/trytond/ir/ui/view.py +++ b/trytond/ir/ui/view.py @@ -103,14 +103,9 @@ class View(ModelSQL, ModelView): # validate pyson attributes validates = { 'states': fields.states_validate, - 'domain': fields.domain_validate, - 'context': fields.context_validate, - 'digits': fields.digits_validate, - 'add_remove': fields.add_remove_validate, } def encode(element): - for attr in ('states', 'domain', 'context', 'digits', - 'add_remove', 'spell', 'colors'): + for attr in ('states', 'domain', 'spell', 'colors'): if element.get(attr): try: value = safe_eval(element.get(attr), CONTEXT) diff --git a/trytond/model/modelview.py b/trytond/model/modelview.py index 56322fcfc7..c388f463fb 100644 --- a/trytond/model/modelview.py +++ b/trytond/model/modelview.py @@ -409,8 +409,7 @@ class ModelView(Model): # convert attributes into pyson encoder = PYSONEncoder() - for attr in ('states', 'domain', 'context', 'digits', 'add_remove', - 'spell', 'colors'): + for attr in ('states', 'domain', 'spell', 'colors'): if element.get(attr): element.set(attr, encoder.encode(safe_eval(element.get(attr), CONTEXT))) From e1b3ad8ae9d0107a1eea9d8904a0024d1de74202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 14 Aug 2013 11:31:39 +0200 Subject: [PATCH 119/128] Fix MySQL drop index query "ON" is required for MySQL (transplanted from 0204193c8ed628dbc48dec8d4ec001f66a00f1f8) --- trytond/backend/mysql/table.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/trytond/backend/mysql/table.py b/trytond/backend/mysql/table.py index e66641fa6d..8f8e6b3f3d 100644 --- a/trytond/backend/mysql/table.py +++ b/trytond/backend/mysql/table.py @@ -270,7 +270,8 @@ class TableHandler(TableHandlerInterface): return if index_name in self._indexes: - self.cursor.execute('DROP INDEX `%s` ' % (index_name,)) + self.cursor.execute('DROP INDEX `%s` ON `%s`' + % (index_name, self.table_name)) self._update_definitions() else: raise Exception('Index action not supported!') From 9a0aa5c053ec802da41957ab70fed655cf9934f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 1 Oct 2013 21:36:10 +0200 Subject: [PATCH 120/128] Prepare release 2.0.12 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 7f1238f65a..5e455c19a4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.0.12 - 2013-10-01 +* Bug fixes (see mercurial logs for details) + Version 2.0.11 - 2013-07-22 * Bug fixes (see mercurial logs for details) From cfdef5c1c565a0a1a530b7f610163244d23c7e27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 1 Oct 2013 21:36:11 +0200 Subject: [PATCH 121/128] Added tag 2.0.12 for changeset 32b38d541a05 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 31f926d0d8..3c1c756566 100644 --- a/.hgtags +++ b/.hgtags @@ -15,3 +15,4 @@ b7bb97a1338090ec3ffff997126a41c039b594b5 2.0.6 c12bff3c6f5b84788ec57bc8fd947d0af6f0627b 2.0.9 64a235ffee62cd380e83c118c43287d93e328588 2.0.10 f11ed54bb218722aa641637fee1dff300e59eca6 2.0.11 +32b38d541a05817e8fbedaea32e06331295a2f24 2.0.12 From 56dc7d2f44317f8e452b1c9f499b9902003d0b27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 1 Oct 2013 21:36:49 +0200 Subject: [PATCH 122/128] Increase version number --- trytond/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/version.py b/trytond/version.py index cf79d616b0..7d0ca4da9e 100644 --- a/trytond/version.py +++ b/trytond/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "trytond" -VERSION = "2.0.12" +VERSION = "2.0.13" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From e799934c405a95bd18c303e2458cb214aa2b830d Mon Sep 17 00:00:00 2001 From: Albert Cervera i Areny Date: Sat, 21 Sep 2013 00:34:15 +0200 Subject: [PATCH 123/128] Fix test for None error_args. issue3338 review1029002 (transplanted from 073147d17dc49d250f617025eb251951f214f7d0) --- trytond/error.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/error.py b/trytond/error.py index 1ca8e42b9c..87756de04c 100644 --- a/trytond/error.py +++ b/trytond/error.py @@ -38,7 +38,7 @@ class WarningErrorMixin(object): if res: error = res - if error_args: + if error_args is not None: try: error = error % error_args except TypeError: From 24bf1b027b547aa592c1db5760a2aedc5095a48b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 5 Oct 2013 16:16:02 +0200 Subject: [PATCH 124/128] Fix domain concatenation between list and tuple issue3395 (transplanted from a8f3e29c5dbdf89b2f2f0a845e14e8663bd3a6af) --- trytond/ir/lang.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trytond/ir/lang.py b/trytond/ir/lang.py index 2d734ad306..a3387d5fce 100644 --- a/trytond/ir/lang.py +++ b/trytond/ir/lang.py @@ -50,9 +50,9 @@ class Lang(ModelSQL, ModelView, Cacheable): }) def search_rec_name(self, name, clause): - ids = self.search([('code',) + clause[1:]], order=[]) + ids = self.search([('code',) + tuple(clause[1:])], order=[]) if ids: - ids += self.search([('name',) + clause[1:]], order=[]) + ids += self.search([('name',) + tuple(clause[1:])], order=[]) return [('id', 'in', ids)] return [('name',) + tuple(clause[1:])] From bda1994365465afa4667ce614cbd9e58609b5636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 14 Oct 2013 21:08:06 +0200 Subject: [PATCH 125/128] Fix rec_name search when domain value is a string review1125003 (transplanted from b786cf31e330c8f3288aac9a328ae2f247a1c591) --- trytond/model/modelsql.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 0290031b55..3edf6d907c 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -1421,9 +1421,9 @@ class ModelSQL(ModelStorage): if isinstance(domain[i][2], basestring): # get the ids of the records of the "distant" resource - ids2 = [x[0] for x in field_obj.search([ - ('rec_name', domain[i][1], domain[i][2]), - ], order=[])] + ids2 = field_obj.search([ + ('rec_name', domain[i][1], domain[i][2]), + ], order=[]) else: ids2 = domain[i][2] @@ -1478,9 +1478,9 @@ class ModelSQL(ModelStorage): target_obj = field.get_target(self.pool) if domain[i][1] in ('child_of', 'not child_of'): if isinstance(domain[i][2], basestring): - ids2 = [x[0] for x in target_obj.search([ - ('rec_name', 'ilike', domain[i][2]), - ], order=[])] + ids2 = target_obj.search([ + ('rec_name', 'ilike', domain[i][2]), + ], order=[]) elif not isinstance(domain[i][2], list): ids2 = [domain[i][2]] else: From 0a26402bd571cc099769af9a26d3c2d5df82b007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 4 Dec 2013 18:38:41 +0100 Subject: [PATCH 126/128] Prepare release 2.0.13 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 5e455c19a4..92a16e16f9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.0.13 - 2013-12-04 +* Bug fixes (see mercurial logs for details) + Version 2.0.12 - 2013-10-01 * Bug fixes (see mercurial logs for details) From 8b8a8f24894f42728fd9ef8ac434ea9521838db0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 4 Dec 2013 18:38:42 +0100 Subject: [PATCH 127/128] Added tag 2.0.13 for changeset 70d9682eb7b8 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 3c1c756566..3dbd39f700 100644 --- a/.hgtags +++ b/.hgtags @@ -16,3 +16,4 @@ c12bff3c6f5b84788ec57bc8fd947d0af6f0627b 2.0.9 64a235ffee62cd380e83c118c43287d93e328588 2.0.10 f11ed54bb218722aa641637fee1dff300e59eca6 2.0.11 32b38d541a05817e8fbedaea32e06331295a2f24 2.0.12 +70d9682eb7b8c5daa6216ae8920e41b079578997 2.0.13 From c5dd3d4307742a1833c83a6a5160ae0edf7924bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 4 Dec 2013 18:39:01 +0100 Subject: [PATCH 128/128] Increase version number --- trytond/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trytond/version.py b/trytond/version.py index 7d0ca4da9e..27d4a502b9 100644 --- a/trytond/version.py +++ b/trytond/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "trytond" -VERSION = "2.0.13" +VERSION = "2.0.14" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/"