diff -Nru tryton-client-2.8.7/CHANGELOG tryton-client-2.8.13/CHANGELOG --- tryton-client-2.8.7/CHANGELOG 2014-05-06 16:26:52.000000000 +0000 +++ tryton-client-2.8.13/CHANGELOG 2015-03-30 21:24:57.000000000 +0000 @@ -1,3 +1,21 @@ +Version 2.8.13 - 2015-03-30 +* Bug fixes (see mercurial logs for details) + +Version 2.8.12 - 2015-02-16 +* Bug fixes (see mercurial logs for details) + +Version 2.8.11 - 2014-11-06 +* Bug fixes (see mercurial logs for details) + +Version 2.8.10 - 2014-09-29 +* Bug fixes (see mercurial logs for details) + +Version 2.8.9 - 2014-08-03 +* Bug fixes (see mercurial logs for details) + +Version 2.8.8 - 2014-07-02 +* Bug fixes (see mercurial logs for details) + Version 2.8.7 - 2014-05-06 * Bug fixes (see mercurial logs for details) diff -Nru tryton-client-2.8.7/COPYRIGHT tryton-client-2.8.13/COPYRIGHT --- tryton-client-2.8.7/COPYRIGHT 2014-05-06 16:26:51.000000000 +0000 +++ tryton-client-2.8.13/COPYRIGHT 2015-03-30 21:24:55.000000000 +0000 @@ -1,7 +1,7 @@ -Copyright (C) 2010-2014 Nicolas Évrard. -Copyright (C) 2007-2014 Cédric Krier. +Copyright (C) 2010-2015 Nicolas Évrard. +Copyright (C) 2007-2015 Cédric Krier. Copyright (C) 2007-2013 Bertrand Chenal. -Copyright (C) 2008-2014 B2CK SPRL. +Copyright (C) 2008-2015 B2CK SPRL. Copyright (C) 2008-2011 Udo Spallek. Copyright (C) 2008-2011 virtual things - Preisler & Spallek GbR. Copyright (C) 2011-2012 Rodrigo Hübner. diff -Nru tryton-client-2.8.7/debian/changelog tryton-client-2.8.13/debian/changelog --- tryton-client-2.8.7/debian/changelog 2014-06-26 15:48:45.000000000 +0000 +++ tryton-client-2.8.13/debian/changelog 2015-04-24 08:58:20.000000000 +0000 @@ -1,8 +1,45 @@ -tryton-client (2.8.7-1ubuntu0~ppa2~precise) precise; urgency=low +tryton-client (2.8.13-1ubuntu0~ppa1~precise) precise; urgency=low * Ubuntu build - -- Ilya Melnikov Thu, 26 Jun 2014 21:22:28 +0600 + -- Ilya Melnikov Fri, 24 Apr 2015 12:53:56 +0500 + +tryton-client (2.8.13-1) unstable; urgency=medium + + * Merging upstream version 2.8.13. + + -- Mathias Behrle Tue, 31 Mar 2015 14:17:12 +0200 + +tryton-client (2.8.12-1) unstable; urgency=medium + + * Merging upstream version 2.8.12. + * Updating copyright file. + + -- Mathias Behrle Tue, 17 Feb 2015 21:18:39 +0100 + +tryton-client (2.8.11-1) unstable; urgency=medium + + * Merging upstream version 2.8.11. + + -- Mathias Behrle Wed, 12 Nov 2014 13:51:30 +0100 + +tryton-client (2.8.10-1) unstable; urgency=medium + + * Merging upstream version 2.8.10. + + -- Mathias Behrle Wed, 08 Oct 2014 13:56:18 +0200 + +tryton-client (2.8.9-1) unstable; urgency=medium + + * Merging upstream version 2.8.9. + + -- Mathias Behrle Tue, 26 Aug 2014 14:06:19 +0200 + +tryton-client (2.8.8-1) unstable; urgency=medium + + * Merging upstream version 2.8.8. + + -- Mathias Behrle Wed, 02 Jul 2014 13:55:47 +0200 tryton-client (2.8.7-1) unstable; urgency=medium diff -Nru tryton-client-2.8.7/debian/copyright tryton-client-2.8.13/debian/copyright --- tryton-client-2.8.7/debian/copyright 2014-06-26 14:44:27.000000000 +0000 +++ tryton-client-2.8.13/debian/copyright 2015-04-24 07:45:49.000000000 +0000 @@ -1,10 +1,10 @@ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Files: * -Copyright: 2010-2014 Nicolas Évrard - 2007-2014 Cédric Krier +Copyright: 2010-2015 Nicolas Évrard + 2007-2015 Cédric Krier 2007-2013 Bertrand Chenal - 2008-2014 B2CK SPRL + 2008-2015 B2CK SPRL 2008-2011 Udo Spallek 2008-2011 virtual things - Preisler & Spallek GbR 2011-2012 Rodrigo Hübner diff -Nru tryton-client-2.8.7/PKG-INFO tryton-client-2.8.13/PKG-INFO --- tryton-client-2.8.7/PKG-INFO 2014-05-06 16:26:58.000000000 +0000 +++ tryton-client-2.8.13/PKG-INFO 2015-03-30 21:25:04.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: tryton -Version: 2.8.7 +Version: 2.8.13 Summary: Tryton client Home-page: http://www.tryton.org/ Author: Tryton diff -Nru tryton-client-2.8.7/setup.py tryton-client-2.8.13/setup.py --- tryton-client-2.8.7/setup.py 2014-03-04 23:10:35.000000000 +0000 +++ tryton-client-2.8.13/setup.py 2015-02-14 17:17:23.000000000 +0000 @@ -106,7 +106,8 @@ 'includes': ('pygtk, gtk, glib, cairo, pango, pangocairo, atk, ' 'gobject, gio, gtk.keysyms'), 'resources': 'tryton/plugins', - 'frameworks': 'librsvg-2.2.dylib', + 'frameworks': + 'librsvg-2.2.dylib, libjpeg.8.dylib, libtiff.3.dylib', 'plist': { 'CFBundleIdentifier': 'org.tryton', 'CFBundleName': 'Tryton', diff -Nru tryton-client-2.8.7/tryton/action/main.py tryton-client-2.8.13/tryton/action/main.py --- tryton-client-2.8.7/tryton/action/main.py 2014-03-04 23:10:35.000000000 +0000 +++ tryton-client-2.8.13/tryton/action/main.py 2015-03-30 21:24:36.000000000 +0000 @@ -96,7 +96,7 @@ action.setdefault('pyson_domain', '[]') ctx = { - 'active_model': data.get('res_model'), + 'active_model': data.get('model'), 'active_id': data.get('id', False), 'active_ids': data.get('ids', []), } diff -Nru tryton-client-2.8.7/tryton/common/domain_inversion.py tryton-client-2.8.13/tryton/common/domain_inversion.py --- tryton-client-2.8.7/tryton/common/domain_inversion.py 2014-05-06 16:26:39.000000000 +0000 +++ tryton-client-2.8.13/tryton/common/domain_inversion.py 2015-02-14 17:17:23.000000000 +0000 @@ -47,16 +47,21 @@ and expression[1] in OPERATORS) +def constrained_leaf(part, boolop=operator.and_): + field, operand, value = part[:3] + if operand == '=' and boolop == operator.and_: + # We should consider that other domain inversion will set a correct + # value to this field + return True + return False + + def eval_leaf(part, context, boolop=operator.and_): field, operand, value = part[:3] if '.' in field: # In the case where the leaf concerns a m2o then having a value in the # evaluation context is deemed suffisant return bool(context.get(field.split('.')[0])) - if operand == '=' and not context.get(field) and boolop == operator.and_: - # We should consider that other domain inversion will set a correct - # value to this field - return True context_field = context.get(field) if isinstance(context_field, datetime.date) and not value: if isinstance(context_field, datetime.datetime): @@ -144,6 +149,8 @@ return domain elif domain in ('OR', 'AND'): return domain + elif domain in (['OR'], ['AND']): + return [] elif (isinstance(domain, list) and len(domain) == 1 and not is_leaf(domain[0])): return simplify(domain[0]) @@ -227,7 +234,8 @@ field = part[0] if (field not in context or field in context - and eval_leaf(part, context, operator.and_)): + and (eval_leaf(part, context, operator.and_) + or constrained_leaf(part, operator.and_))): result.append(True) else: return False @@ -270,7 +278,8 @@ field = part[0] field = self.base(field) if (field in context - and eval_leaf(part, context, operator.or_)): + and (eval_leaf(part, context, operator.or_) + or constrained_leaf(part, operator.or_))): return True elif (field in context and not eval_leaf(part, context, operator.or_)): @@ -307,7 +316,7 @@ domain = [['x', '=', 3], ['y', '=', 5]] assert domain_inversion(domain, 'z') is True assert domain_inversion(domain, 'z', {'x': 2, 'y': 7}) is True - assert domain_inversion(domain, 'x', {'y': False}) == [['x', '=', 3]] + assert domain_inversion(domain, 'x', {'y': None}) == [['x', '=', 3]] domain = [['x.id', '>', 5], ['y', '<', 3]] assert domain_inversion(domain, 'y') == [['y', '<', 3]] @@ -327,7 +336,7 @@ assert domain_inversion(domain, 'x', {'y': 4, 'z': 'abc'}) is True domain = ['OR', ['x', '=', 3], ['y', '=', 5]] - assert domain_inversion(domain, 'x', {'y': False}) == [['x', '=', 3]] + assert domain_inversion(domain, 'x', {'y': None}) == [['x', '=', 3]] domain = ['OR', ['x', '=', 3], ['y', '>', 5]] assert domain_inversion(domain, 'z') is True @@ -363,7 +372,7 @@ def test_andand_inversion(): domain = [[['x', '=', 4], ['y', '>', 6]], ['z', '=', 3]] assert domain_inversion(domain, 'z') == [['z', '=', 3]] - assert domain_inversion(domain, 'z', {'x': 5}) is False + assert domain_inversion(domain, 'z', {'x': 5}) == [['z', '=', 3]] assert domain_inversion(domain, 'z', {'y': 5}) is False assert domain_inversion(domain, 'z', {'x': 4, 'y': 7}) == [['z', '=', 3]] @@ -411,6 +420,10 @@ assert simplify(domain) == ['OR', [['x', '=', 3]], [['y', '=', 5]]] domain = ['OR', ['x', '=', 3], ['AND', ['y', '=', 5]]] assert simplify(domain) == ['OR', ['x', '=', 3], [['y', '=', 5]]] + domain = ['AND'] + assert simplify(domain) == [] + domain = ['OR'] + assert simplify(domain) == [] def test_merge(): @@ -474,6 +487,12 @@ assert eval_domain(domain, {'x': -4}) assert not eval_domain(domain, {'x': 5}) + domain = ['OR', ['x', '>', 0], ['x', '=', None]] + assert eval_domain(domain, {'x': 1}) + assert eval_domain(domain, {'x': None}) + assert not eval_domain(domain, {'x': -1}) + assert not eval_domain(domain, {'x': 0}) + domain = [['x', '>', 0], ['OR', ['x', '=', 3], ['x', '=', 2]]] assert not eval_domain(domain, {'x': 1}) assert eval_domain(domain, {'x': 3}) diff -Nru tryton-client-2.8.7/tryton/common/domain_parser.py tryton-client-2.8.13/tryton/common/domain_parser.py --- tryton-client-2.8.7/tryton/common/domain_parser.py 2014-03-04 23:10:35.000000000 +0000 +++ tryton-client-2.8.13/tryton/common/domain_parser.py 2015-03-30 21:24:36.000000000 +0000 @@ -12,7 +12,7 @@ import collections from tryton.translate import date_format -from tryton.common import untimezoned_date, datetime_strftime +from tryton.common import untimezoned_date, timezoned_date, datetime_strftime from tryton.pyson import PYSONDecoder __all__ = ['DomainParser'] @@ -117,12 +117,23 @@ "Quote string if needed" if not isinstance(value, basestring): return value + if '\\' in value: + value = value.replace('\\', '\\\\') + if '"' in value: + value = value.replace('"', '\\"') for test in (':', ' ', '(', ')') + OPERATORS: if test in value: return '"%s"' % value return value +def test_quote(): + assert quote('test') == 'test' + assert quote('foo bar') == '"foo bar"' + assert quote('"foo"') == '\\\"foo\\\"' + assert quote('foo\\bar') == 'foo\\\\bar' + + def ending_clause(domain, deep=0): "Return the ending clause" if not domain: @@ -409,7 +420,10 @@ if (not isinstance(value, datetime.datetime) or value.time() == datetime.time.min): format_ = date_format() - return datetime_strftime(value, format_) + time = value + else: + time = timezoned_date(value) + return datetime_strftime(time, format_) def format_date(): if not value: @@ -530,7 +544,8 @@ for value, result in ( (datetime.date(2002, 12, 4), '12/04/2002'), (datetime.datetime(2002, 12, 4), '12/04/2002'), - (datetime.datetime(2002, 12, 4, 12, 30), '"12/04/2002 12:30:00"'), + (untimezoned_date(datetime.datetime(2002, 12, 4, 12, 30)), + '"12/04/2002 12:30:00"'), (False, ''), (None, ''), ): @@ -584,7 +599,7 @@ def complete_datetime(): yield datetime.date.today() - yield datetime.datetime.now() + yield datetime.datetime.utcnow() def complete_date(): yield datetime.date.today() @@ -1115,6 +1130,9 @@ ('Name', '=', None), ('Name', None, 'Doe'), ] + assert rlist(dom.group(udlex(u'Name: \\"foo\\"'))) == [ + ('Name', None, '"foo"'), + ] def test_parse_clause(): diff -Nru tryton-client-2.8.7/tryton/gui/window/view_form/model/field.py tryton-client-2.8.13/tryton/gui/window/view_form/model/field.py --- tryton-client-2.8.7/tryton/gui/window/view_form/model/field.py 2014-05-06 16:26:39.000000000 +0000 +++ tryton-client-2.8.13/tryton/gui/window/view_form/model/field.py 2015-02-14 17:17:23.000000000 +0000 @@ -196,7 +196,7 @@ _default = None def set_client(self, record, value, force_change=False): - if not isinstance(value, datetime.datetime) and value is not None: + if isinstance(value, basestring): try: value = datetime.datetime(*time.strptime(value, date_format() + ' ' + self.time_format(record))[:6]) @@ -224,7 +224,7 @@ _default = None def set_client(self, record, value, force_change=False): - if not isinstance(value, datetime.date) and value is not None: + if isinstance(value, basestring): try: value = datetime.date(*time.strptime(value, date_format())[:3]) @@ -248,7 +248,7 @@ _default = None def set_client(self, record, value, force_change=False): - if not isinstance(value, datetime.time) and value is not None: + if isinstance(value, basestring): try: value = datetime.time(*time.strptime(value, self.time_format(record))[3:6]) @@ -873,6 +873,9 @@ _default = {} + def get(self, record): + return super(DictField, self).get(record) or self._default + def validation_domains(self, record): screen_domain, attr_domain = self.domains_get(record) return screen_domain, screen_domain diff -Nru tryton-client-2.8.7/tryton/gui/window/view_form/model/group.py tryton-client-2.8.13/tryton/gui/window/view_form/model/group.py --- tryton-client-2.8.7/tryton/gui/window/view_form/model/group.py 2014-03-04 23:10:36.000000000 +0000 +++ tryton-client-2.8.13/tryton/gui/window/view_form/model/group.py 2015-02-14 17:17:23.000000000 +0000 @@ -83,9 +83,13 @@ return [head] + self.clean4inversion(tail) def __get_domain4inversion(self): - if self.__domain4inversion is None: - self.__domain4inversion = self.clean4inversion(self.domain) - return self.__domain4inversion + domain = self.domain + if (self.__domain4inversion is None + or self.__domain4inversion[0] != domain): + self.__domain4inversion = ( + domain, self.clean4inversion(domain)) + domain, domain4inversion = self.__domain4inversion + return domain4inversion domain4inversion = property(__get_domain4inversion) diff -Nru tryton-client-2.8.7/tryton/gui/window/view_form/screen/screen.py tryton-client-2.8.13/tryton/gui/window/view_form/screen/screen.py --- tryton-client-2.8.7/tryton/gui/window/view_form/screen/screen.py 2014-03-04 23:10:36.000000000 +0000 +++ tryton-client-2.8.13/tryton/gui/window/view_form/screen/screen.py 2015-02-14 17:17:23.000000000 +0000 @@ -574,12 +574,13 @@ if delete: for record in records: - if record.parent: - record.parent.save(force_reload=False) if record in record.group.record_deleted: record.group.record_deleted.remove(record) if record in record.group.record_removed: record.group.record_removed.remove(record) + if record.parent: + # Save parent without deleted children + record.parent.save(force_reload=False) record.destroy() if idx > 0: @@ -699,7 +700,9 @@ if view.view_type == 'tree' and len(self.group): start, end = view.widget_tree.get_visible_range() vadjustment = view.widget_tree.get_vadjustment() - vadjustment.value = vadjustment.value + vadjustment.page_increment + vadjustment.value = min( + vadjustment.value + vadjustment.page_increment, + vadjustment.get_upper()) store = view.store iter_ = store.get_iter(end) self.current_record = store.get_value(iter_, 0) @@ -743,7 +746,9 @@ if view.view_type == 'tree' and len(self.group): start, end = view.widget_tree.get_visible_range() vadjustment = view.widget_tree.get_vadjustment() - vadjustment.value = vadjustment.value - vadjustment.page_increment + vadjustment.value = min( + vadjustment.value - vadjustment.page_increment, + vadjustment.get_lower()) store = view.store iter_ = store.get_iter(start) self.current_record = store.get_value(iter_, 0) diff -Nru tryton-client-2.8.7/tryton/gui/window/view_form/view/form_gtk/char.py tryton-client-2.8.13/tryton/gui/window/view_form/view/form_gtk/char.py --- tryton-client-2.8.7/tryton/gui/window/view_form/view/form_gtk/char.py 2014-03-04 23:10:36.000000000 +0000 +++ tryton-client-2.8.13/tryton/gui/window/view_form/view/form_gtk/char.py 2014-07-01 22:06:40.000000000 +0000 @@ -90,7 +90,8 @@ return field.set_client(record, value) def get_value(self): - return self.entry.get_text() + entry = self.entry.get_child() if self.autocomplete else self.entry + return entry.get_text() def display(self, record, field): super(Char, self).display(record, field) diff -Nru tryton-client-2.8.7/tryton/gui/window/view_form/view/form_gtk/many2one.py tryton-client-2.8.13/tryton/gui/window/view_form/view/form_gtk/many2one.py --- tryton-client-2.8.7/tryton/gui/window/view_form/view/form_gtk/many2one.py 2014-03-04 23:10:36.000000000 +0000 +++ tryton-client-2.8.13/tryton/gui/window/view_form/view/form_gtk/many2one.py 2015-02-14 17:17:23.000000000 +0000 @@ -32,7 +32,7 @@ self.wid_text.connect('populate-popup', self._populate_popup) self.wid_text.connect('focus-out-event', lambda x, y: self._focus_out()) - self.wid_text.connect_after('changed', self.sig_changed) + self.wid_text.connect('changed', self.sig_changed) self.changed = True self.focus_out = True @@ -305,15 +305,18 @@ if not self.changed: return False value = self.field.get(self.record) - if self.has_target(value): + if self.has_target(value) and self.modified: def clean(): text = self.wid_text.get_text() position = self.wid_text.get_position() self.field.set_client(self.record, self.value_from_id(None, '')) - # Restore text and position after display - self.wid_text.set_text(text) - self.wid_text.set_position(position) + # The value of the field could be different of None + # in such case, the original text should not be restored + if not self.wid_text.get_text(): + # Restore text and position after display + self.wid_text.set_text(text) + self.wid_text.set_position(position) gobject.idle_add(clean) return False diff -Nru tryton-client-2.8.7/tryton/gui/window/view_form/view/form_gtk/parser.py tryton-client-2.8.13/tryton/gui/window/view_form/view/form_gtk/parser.py --- tryton-client-2.8.7/tryton/gui/window/view_form/view/form_gtk/parser.py 2014-03-04 23:10:36.000000000 +0000 +++ tryton-client-2.8.13/tryton/gui/window/view_form/view/form_gtk/parser.py 2014-07-01 22:06:40.000000000 +0000 @@ -469,13 +469,13 @@ hpaned = gtk.HPaned() container.wid_add(hpaned, colspan=int(attrs.get('colspan', 4)), yexpand=True, yfill=True) - (widget, widgets, state_widgets, spam, notebook_list2, + (widget, widgets, state_widgets2, spam, notebook_list2, cursor_widget2) = self.parse(model_name, node, fields, paned=hpaned, tooltips=tooltips) if not cursor_widget: cursor_widget = cursor_widget2 notebook_list.extend(notebook_list2) - state_widgets += state_widgets + state_widgets += state_widgets2 for widget_name, widgets in widgets.iteritems(): dict_widget.setdefault(widget_name, []) dict_widget[widget_name].extend(widgets) @@ -485,7 +485,7 @@ vpaned = gtk.VPaned() container.wid_add(vpaned, colspan=int(attrs.get('colspan', 4)), yexpand=True, yfill=True) - (widget, widgets, state_widgets2, spam, notebook_list, + (widget, widgets, state_widgets2, spam, notebook_list2, cursor_widget2) = self.parse(model_name, node, fields, paned=vpaned, tooltips=tooltips) if not cursor_widget: diff -Nru tryton-client-2.8.7/tryton/gui/window/view_form/view/list_gtk/parser.py tryton-client-2.8.13/tryton/gui/window/view_form/view/list_gtk/parser.py --- tryton-client-2.8.7/tryton/gui/window/view_form/view/list_gtk/parser.py 2014-05-06 16:26:39.000000000 +0000 +++ tryton-client-2.8.13/tryton/gui/window/view_form/view/list_gtk/parser.py 2015-02-14 17:17:23.000000000 +0000 @@ -67,7 +67,7 @@ column.arrow.hide() store = treeview.get_model() unsaved_records = [x for x in store.group if x.id < 0] - search_string = screen.screen_container.get_text() or None + search_string = screen.screen_container.get_text() or u'' if screen.search_count == len(store) or unsaved_records or screen.parent: ids = screen.search_filter(search_string=search_string, only_ids=True) store.sort(ids) diff -Nru tryton-client-2.8.7/tryton/gui/window/view_form/view/list.py tryton-client-2.8.13/tryton/gui/window/view_form/view/list.py --- tryton-client-2.8.7/tryton/gui/window/view_form/view/list.py 2014-04-07 17:37:30.000000000 +0000 +++ tryton-client-2.8.13/tryton/gui/window/view_form/view/list.py 2015-02-14 17:17:23.000000000 +0000 @@ -99,7 +99,7 @@ group.add(record) if not record.parent_name: record.modified_fields.setdefault(prev_group.parent_name) - record.value[prev_group.parent_name] = False + record.value[prev_group.parent_name] = None else: record.modified_fields.setdefault(record.parent_name) group.move(record, pos) @@ -433,7 +433,9 @@ if not col.get_visible() or not col.name: continue cell = self.widget_tree.cells[col.name] - values.append('"' + str(cell.get_textual_value(record)) + '"') + values.append('"' + + str(cell.get_textual_value(record)).replace('"', '""') + + '"') data.append('\t'.join(values)) return diff -Nru tryton-client-2.8.7/tryton/gui/window/win_export.py tryton-client-2.8.13/tryton/gui/window/win_export.py --- tryton-client-2.8.7/tryton/gui/window/win_export.py 2014-03-04 23:10:36.000000000 +0000 +++ tryton-client-2.8.13/tryton/gui/window/win_export.py 2015-02-14 17:17:23.000000000 +0000 @@ -289,7 +289,7 @@ return try: lines = RPCExecute('model', 'ir.export.line', 'read', - sum((x['export_fields'] for x in exports), []), None) + sum((list(x['export_fields']) for x in exports), []), None) except RPCException: return id2lines = {} diff -Nru tryton-client-2.8.7/tryton/gui/window/win_form.py tryton-client-2.8.13/tryton/gui/window/win_form.py --- tryton-client-2.8.7/tryton/gui/window/win_form.py 2014-03-04 23:10:36.000000000 +0000 +++ tryton-client-2.8.13/tryton/gui/window/win_form.py 2015-02-14 17:17:23.000000000 +0000 @@ -257,7 +257,7 @@ self.screen.screen_container.alternate_viewport.connect( 'key-press-event', self.on_keypress) - if self.save_current: + if self.save_current and not new: self.screen.signal_connect(self, 'record-message', self.activate_save) self.screen.signal_connect(self, 'record-modified', diff -Nru tryton-client-2.8.7/tryton/gui/window/win_import.py tryton-client-2.8.13/tryton/gui/window/win_import.py --- tryton-client-2.8.7/tryton/gui/window/win_import.py 2014-03-04 23:10:36.000000000 +0000 +++ tryton-client-2.8.13/tryton/gui/window/win_import.py 2015-02-14 17:17:23.000000000 +0000 @@ -236,6 +236,9 @@ def on_row_expanded(self, treeview, iter, path): child = self.model1.iter_children(iter) + # autodetect could call for node without children + if child is None: + return if self.model1.get_value(child, 0) is None: prefix_field = self.model1.get_value(iter, 1) name, model = self.fields[prefix_field] diff -Nru tryton-client-2.8.7/tryton/pyson.py tryton-client-2.8.13/tryton/pyson.py --- tryton-client-2.8.7/tryton/pyson.py 2014-03-04 23:10:36.000000000 +0000 +++ tryton-client-2.8.13/tryton/pyson.py 2015-02-14 17:17:23.000000000 +0000 @@ -28,25 +28,25 @@ return Not(self) def __and__(self, other): + if (isinstance(other, PYSON) + and other.types() != set([bool])): + other = Bool(other) if (isinstance(self, And) and not isinstance(self, Or)): self._statements.append(other) return self - if (isinstance(other, PYSON) - and other.types() != set([bool])): - other = Bool(other) if self.types() != set([bool]): return And(Bool(self), other) else: return And(self, other) def __or__(self, other): - if isinstance(self, Or): - self._statements.append(other) - return self if (isinstance(other, PYSON) and other.types() != set([bool])): other = Bool(other) + if isinstance(self, Or): + self._statements.append(other) + return self if self.types() != set([bool]): return Or(Bool(self), other) else: diff -Nru tryton-client-2.8.7/tryton/version.py tryton-client-2.8.13/tryton/version.py --- tryton-client-2.8.7/tryton/version.py 2014-04-07 17:38:07.000000000 +0000 +++ tryton-client-2.8.13/tryton/version.py 2015-02-16 22:26:36.000000000 +0000 @@ -1,6 +1,6 @@ #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 = "tryton" -VERSION = "2.8.7" +VERSION = "2.8.13" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" diff -Nru tryton-client-2.8.7/tryton.egg-info/PKG-INFO tryton-client-2.8.13/tryton.egg-info/PKG-INFO --- tryton-client-2.8.7/tryton.egg-info/PKG-INFO 2014-05-06 16:26:57.000000000 +0000 +++ tryton-client-2.8.13/tryton.egg-info/PKG-INFO 2015-03-30 21:25:03.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: tryton -Version: 2.8.7 +Version: 2.8.13 Summary: Tryton client Home-page: http://www.tryton.org/ Author: Tryton