Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package tryton for openSUSE:Factory checked 
in at 2025-06-23 15:03:36
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/tryton (Old)
 and      /work/SRC/openSUSE:Factory/.tryton.new.7067 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "tryton"

Mon Jun 23 15:03:36 2025 rev:29 rq:1287652 version:6.0.54

Changes:
--------
--- /work/SRC/openSUSE:Factory/tryton/tryton.changes    2025-03-12 
20:13:56.348066906 +0100
+++ /work/SRC/openSUSE:Factory/.tryton.new.7067/tryton.changes  2025-06-23 
15:04:06.254808590 +0200
@@ -1,0 +2,15 @@
+Sun Jun 22 09:36:44 UTC 2025 - Axel Braun <axel.br...@gmx.de>
+
+- 000-pygtkcompat.diff removed (adapted in source)
+
+-------------------------------------------------------------------
+Sun Jun 15 07:12:22 UTC 2025 - Axel Braun <axel.br...@gmx.de>
+
+- Version 6.0.54 - Bugfix Release
+
+-------------------------------------------------------------------
+Sat May  3 10:55:10 UTC 2025 - Axel Braun <axel.br...@gmx.de>
+
+- Version 6.0.53 - Bugfix Release
+
+-------------------------------------------------------------------

Old:
----
  000-pygtkcompat.diff
  tryton-6.0.50.tar.gz

New:
----
  tryton-6.0.54.tar.gz

----------(Old B)----------
  Old:
- 000-pygtkcompat.diff removed (adapted in source)
----------(Old E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ tryton.spec ++++++
--- /var/tmp/diff_new_pack.bCK0pK/_old  2025-06-23 15:04:07.166846640 +0200
+++ /var/tmp/diff_new_pack.bCK0pK/_new  2025-06-23 15:04:07.166846640 +0200
@@ -30,7 +30,7 @@
 
 
 Name:           tryton
-Version:        %{majorver}.50
+Version:        %{majorver}.54
 Release:        0
 Summary:        The client of the Tryton application platform
 License:        GPL-3.0-or-later
@@ -40,7 +40,6 @@
 ## Source1:        
http://downloads.tryton.org/%{majorver}/%{name}-%{version}.tar.gz.asc
 ## Source2:        
https://keybase.io/cedrickrier/pgp_keys.asc?fingerprint=7C5A4360F6DF81ABA91FD54D6FF50AFE03489130#/%{name}.keyring
 
-Patch0:         000-pygtkcompat.diff
 Patch1:         001-disable-version-check.diff
 
 BuildRequires:  fdupes

++++++ tryton-6.0.50.tar.gz -> tryton-6.0.54.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tryton-6.0.50/CHANGELOG new/tryton-6.0.54/CHANGELOG
--- old/tryton-6.0.50/CHANGELOG 2025-03-04 22:22:17.000000000 +0100
+++ new/tryton-6.0.54/CHANGELOG 2025-06-04 23:17:22.000000000 +0200
@@ -1,4 +1,24 @@
 
+Version 6.0.54 - 2025-06-04
+---------------------------
+* Bug fixes (see mercurial logs for details)
+
+
+Version 6.0.53 - 2025-05-02
+---------------------------
+* Bug fixes (see mercurial logs for details)
+
+
+Version 6.0.52 - 2025-04-26
+---------------------------
+* Bug fixes (see mercurial logs for details)
+
+
+Version 6.0.51 - 2025-04-02
+---------------------------
+* Bug fixes (see mercurial logs for details)
+
+
 Version 6.0.50 - 2025-03-04
 ---------------------------
 * Bug fixes (see mercurial logs for details)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tryton-6.0.50/COPYRIGHT new/tryton-6.0.54/COPYRIGHT
--- old/tryton-6.0.50/COPYRIGHT 2025-03-04 22:22:17.000000000 +0100
+++ new/tryton-6.0.54/COPYRIGHT 2025-06-04 23:17:22.000000000 +0200
@@ -5,7 +5,7 @@
 Copyright (C) 2008-2011 Udo Spallek.
 Copyright (C) 2008-2011 virtual things - Preisler & Spallek GbR.
 Copyright (C) 2008-2025 B2CK SPRL.
-Copyright (C) 2010-2024 Nicolas Évrard.
+Copyright (C) 2010-2025 Nicolas Évrard.
 Copyright (C) 2011-2012 Rodrigo Hübner.
 Copyright (C) 2012-2013 Antoine Smolders.
 Copyright (C) 2020-2021 Maxime Richez
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tryton-6.0.50/PKG-INFO new/tryton-6.0.54/PKG-INFO
--- old/tryton-6.0.50/PKG-INFO  2025-03-04 22:22:20.595941500 +0100
+++ new/tryton-6.0.54/PKG-INFO  2025-06-04 23:17:25.243063400 +0200
@@ -1,6 +1,6 @@
-Metadata-Version: 2.2
+Metadata-Version: 2.4
 Name: tryton
-Version: 6.0.50
+Version: 6.0.54
 Summary: Tryton desktop client
 Home-page: http://www.tryton.org/
 Download-URL: http://downloads.tryton.org/6.0/
@@ -61,6 +61,7 @@
 Dynamic: home-page
 Dynamic: keywords
 Dynamic: license
+Dynamic: license-file
 Dynamic: platform
 Dynamic: project-url
 Dynamic: provides-extra
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tryton-6.0.50/tryton/__init__.py 
new/tryton-6.0.54/tryton/__init__.py
--- old/tryton-6.0.50/tryton/__init__.py        2025-02-16 12:00:06.000000000 
+0100
+++ new/tryton-6.0.54/tryton/__init__.py        2025-05-02 22:12:57.000000000 
+0200
@@ -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.
-__version__ = "6.0.50"
+__version__ = "6.0.54"
 import gi
 import locale
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tryton-6.0.50/tryton/common/domain_parser.py 
new/tryton-6.0.54/tryton/common/domain_parser.py
--- old/tryton-6.0.50/tryton/common/domain_parser.py    2025-01-11 
02:26:34.000000000 +0100
+++ new/tryton-6.0.54/tryton/common/domain_parser.py    2025-04-30 
00:05:58.000000000 +0200
@@ -1,5 +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.
+import math
 from shlex import shlex
 from types import GeneratorType
 import gettext
@@ -334,17 +335,18 @@
                     or isinstance(value, bool))):
             return ''
         digit = 0
-        if isinstance(value, Decimal):
-            cast = Decimal
-        else:
-            cast = float
-        factor = cast(field.get('factor', 1))
-        string_ = str(value * factor)
+        string_ = str(value)
         if 'e' in string_:
             string_, exp = string_.split('e')
             digit -= int(exp)
         if '.' in string_:
             digit += len(string_.rstrip('0').split('.')[1])
+        if isinstance(value, Decimal):
+            cast = Decimal
+        else:
+            cast = float
+        factor = cast(field.get('factor', 1))
+        digit -= round(math.log10(factor))
         return locale.localize(
             '{0:.{1}f}'.format(value * factor or 0, digit), True)
 
Binary files old/tryton-6.0.50/tryton/data/locale/bg/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/bg/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/ca/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/ca/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/cs/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/cs/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/de/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/de/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/es/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/es/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/es_419/LC_MESSAGES/tryton.mo 
and new/tryton-6.0.54/tryton/data/locale/es_419/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/et/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/et/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/fa/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/fa/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/fi/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/fi/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/fr/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/fr/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/hu/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/hu/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/id/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/id/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/it/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/it/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/ja_JP/LC_MESSAGES/tryton.mo 
and new/tryton-6.0.54/tryton/data/locale/ja_JP/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/lo/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/lo/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/lt/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/lt/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/nl/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/nl/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/pl/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/pl/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/pt/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/pt/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/ro/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/ro/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/ru/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/ru/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/sl/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/sl/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/tr/LC_MESSAGES/tryton.mo and 
new/tryton-6.0.54/tryton/data/locale/tr/LC_MESSAGES/tryton.mo differ
Binary files old/tryton-6.0.50/tryton/data/locale/zh_CN/LC_MESSAGES/tryton.mo 
and new/tryton-6.0.54/tryton/data/locale/zh_CN/LC_MESSAGES/tryton.mo differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tryton-6.0.50/tryton/gui/window/form.py 
new/tryton-6.0.54/tryton/gui/window/form.py
--- old/tryton-6.0.50/tryton/gui/window/form.py 2025-02-28 23:30:06.000000000 
+0100
+++ new/tryton-6.0.54/tryton/gui/window/form.py 2025-05-14 19:05:45.000000000 
+0200
@@ -458,7 +458,7 @@
             delimiter = ';'
         fileno, fname = tempfile.mkstemp(
             '.csv', common.slugify(export['name']) + '_')
-        with open(fname, 'w') as fp:
+        with open(fname, 'w', newline='') as fp:
             writer = csv.writer(fp, delimiter=delimiter)
             writer.writerow(fields)
             for row, path in zip_longest(data, paths or []):
@@ -669,12 +669,15 @@
             if value == 'ok':
                 return self.sig_save(None)
             if value == 'ko':
-                record_id = self.screen.current_record.id
+                record_id = None
+                if self.screen.current_record:
+                    record_id = self.screen.current_record.id
                 if self.sig_reload(test_modified=False):
-                    if record_id < 0:
-                        return None
-                    elif self.screen.current_record:
-                        return record_id == self.screen.current_record.id
+                    if record_id is not None:
+                        if record_id < 0:
+                            return None
+                        elif self.screen.current_record:
+                            return record_id == self.screen.current_record.id
             return False
         return True
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/tryton-6.0.50/tryton/gui/window/view_form/model/field.py 
new/tryton-6.0.54/tryton/gui/window/view_form/model/field.py
--- old/tryton-6.0.50/tryton/gui/window/view_form/model/field.py        
2025-01-11 02:26:34.000000000 +0100
+++ new/tryton-6.0.54/tryton/gui/window/view_form/model/field.py        
2025-05-29 17:06:31.000000000 +0200
@@ -798,6 +798,7 @@
                         force_remove=False)
 
         if value and (value.get('add') or value.get('update', [])):
+            vals_to_set = {}
             # First set already added fields to prevent triggering a
             # second on_change call
             for vals in value.get('update', []):
@@ -825,7 +826,10 @@
                     continue
                 record2 = group.get(vals['id'])
                 if record2 is not None:
-                    record2.set_on_change(vals)
+                    to_set = {
+                        k: v for k, v in vals.items()
+                        if k not in vals_to_set}
+                    record2.set_on_change(to_set)
 
     def validation_domains(self, record, pre_validate=None):
         screen_domain, attr_domain = self.domains_get(record, pre_validate)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/tryton-6.0.50/tryton/gui/window/view_form/screen/screen.py 
new/tryton-6.0.54/tryton/gui/window/view_form/screen/screen.py
--- old/tryton-6.0.50/tryton/gui/window/view_form/screen/screen.py      
2025-02-13 19:28:35.000000000 +0100
+++ new/tryton-6.0.54/tryton/gui/window/view_form/screen/screen.py      
2025-04-14 19:20:09.000000000 +0200
@@ -853,7 +853,7 @@
             view.expand_nodes(expanded_nodes)
             view.select_nodes(selected_nodes)
         else:
-            if selected_nodes:
+            if selected_nodes and not self.current_record:
                 record = None
                 for node in selected_nodes[0]:
                     new_record = self.group.get(node)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/tryton-6.0.50/tryton/gui/window/view_form/view/list.py 
new/tryton-6.0.54/tryton/gui/window/view_form/view/list.py
--- old/tryton-6.0.50/tryton/gui/window/view_form/view/list.py  2025-01-11 
02:26:34.000000000 +0100
+++ new/tryton-6.0.54/tryton/gui/window/view_form/view/list.py  2025-04-30 
00:13:21.000000000 +0200
@@ -7,7 +7,6 @@
 from functools import wraps
 
 from gi.repository import Gdk, GLib, GObject, Gtk
-from pygtkcompat.generictreemodel import GenericTreeModel
 
 from tryton.config import CONFIG
 from tryton.common.cellrendererbutton import CellRendererButton
@@ -19,6 +18,7 @@
 import tryton.common as common
 from . import View, XMLViewParser
 from .list_gtk.editabletree import EditableTreeView, TreeView
+from .list_gtk.generictreemodel import GenericTreeModel
 from .list_gtk.widget import (Affix, Char, Text, Int, Boolean, URL, Date,
     Time, Float, TimeDelta, Binary, M2O, O2O, O2M, M2M, Selection,
     MultiSelection, Reference, Dict, ProgressBar, Button, Image)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/tryton-6.0.50/tryton/gui/window/view_form/view/list_gtk/generictreemodel.py 
new/tryton-6.0.54/tryton/gui/window/view_form/view/list_gtk/generictreemodel.py
--- 
old/tryton-6.0.50/tryton/gui/window/view_form/view/list_gtk/generictreemodel.py 
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/tryton-6.0.54/tryton/gui/window/view_form/view/list_gtk/generictreemodel.py 
    2025-04-30 00:12:52.000000000 +0200
@@ -0,0 +1,426 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+# generictreemodel - GenericTreeModel implementation for pygtk compatibility.
+# Copyright (C) 2013 Simon Feltman
+#
+#   generictreemodel.py: GenericTreeModel implementation for pygtk 
compatibility
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+
+# System
+import sys
+import random
+import collections
+import ctypes
+import platform
+import warnings
+
+# GObject
+import gi
+from gi.repository import GObject
+from gi.repository import Gtk
+
+
+class _CTreeIter(ctypes.Structure):
+    _fields_ = [('stamp', ctypes.c_int),
+                ('user_data', ctypes.c_void_p),
+                ('user_data2', ctypes.c_void_p),
+                ('user_data3', ctypes.c_void_p)]
+
+    @classmethod
+    def from_iter(cls, iter):
+        offset = sys.getsizeof(object())  # size of PyObject_HEAD
+        return ctypes.POINTER(cls).from_address(id(iter) + offset)
+
+
+if platform.python_implementation() == "PyPy":
+    def _get_user_data_as_pyobject(iter):
+        raise NotImplementedError("Not yet supported under PyPy")
+else:
+    def _get_user_data_as_pyobject(iter):
+        citer = _CTreeIter.from_iter(iter)
+        return ctypes.cast(citer.contents.user_data, ctypes.py_object).value
+
+
+def handle_exception(default_return):
+    """Returns a function which can act as a decorator for wrapping exceptions 
and
+    returning "default_return" upon an exception being thrown.
+
+    This is used to wrap Gtk.TreeModel "do_" method implementations so we can 
return
+    a proper value from the override upon an exception occurring with client 
code
+    implemented by the "on_" methods.
+    """
+    def decorator(func):
+        def wrapped_func(*args, **kargs):
+            try:
+                return func(*args, **kargs)
+            except:
+                # Use excepthook directly to avoid any printing to the screen
+                # if someone installed an except hook.
+                sys.excepthook(*sys.exc_info())
+            return default_return
+        return wrapped_func
+    return decorator
+
+
+class GenericTreeModel(GObject.GObject, Gtk.TreeModel):
+    """A base implementation of a Gtk.TreeModel for python.
+
+    The GenericTreeModel eases implementing the Gtk.TreeModel interface in 
Python.
+    The class can be subclassed to provide a TreeModel implementation which 
works
+    directly with Python objects instead of iterators.
+
+    All of the on_* methods should be overridden by subclasses to provide the
+    underlying implementation a way to access custom model data. For the 
purposes of
+    this API, all custom model data supplied or handed back through the 
overridable
+    API will use the argument names: node, parent, and child in regards to 
user data
+    python objects.
+
+    The create_tree_iter, set_user_data, invalidate_iters, iter_is_valid 
methods are
+    available to help manage Gtk.TreeIter objects and their Python object 
references.
+
+    GenericTreeModel manages a pool of user data nodes that have been used 
with iters.
+    This pool stores a references to user data nodes as a dictionary value 
with the
+    key being the integer id of the data. This id is what the Gtk.TreeIter 
objects
+    use to reference data in the pool.
+    References will be removed from the pool when the model is deleted or 
explicitly
+    by using the optional "node" argument to the "row_deleted" method when 
notifying
+    the model of row deletion.
+    """
+
+    leak_references = GObject.Property(default=True, type=bool,
+                                       blurb="If True, strong references to 
user data attached to iters are "
+                                       "stored in a dictionary pool (default). 
Otherwise the user data is "
+                                       "stored as a raw pointer to a python 
object without a reference.")
+
+    #
+    # Methods
+    #
+    def __init__(self):
+        """Initialize. Make sure to call this from derived classes if 
overridden."""
+        warnings.warn("pygtkcompat is deprecated, see 
https://pygobject.gnome.org for migration instructions", 
gi.PyGIDeprecationWarning)
+        super(GenericTreeModel, self).__init__()
+        self.stamp = 0
+
+        #: Dictionary of (id(user_data): user_data), used when 
leak-references=False
+        self._held_refs = dict()
+
+        # Set initial stamp
+        self.invalidate_iters()
+
+    def iter_depth_first(self):
+        """Depth-first iteration of the entire TreeModel yielding the python 
nodes."""
+        stack = collections.deque([None])
+        while stack:
+            it = stack.popleft()
+            if it is not None:
+                yield self.get_user_data(it)
+            children = [self.iter_nth_child(it, i) for i in 
range(self.iter_n_children(it))]
+            stack.extendleft(reversed(children))
+
+    def invalidate_iter(self, iter):
+        """Clear user data and its reference from the iter and this model."""
+        iter.stamp = 0
+        if iter.user_data:
+            if iter.user_data in self._held_refs:
+                del self._held_refs[iter.user_data]
+            iter.user_data = None
+
+    def invalidate_iters(self):
+        """
+        This method invalidates all TreeIter objects associated with this 
custom tree model
+        and frees their locally pooled references.
+        """
+        self.stamp = random.randint(-2147483648, 2147483647)
+        self._held_refs.clear()
+
+    def iter_is_valid(self, iter):
+        """
+        :Returns:
+            True if the gtk.TreeIter specified by iter is valid for the custom 
tree model.
+        """
+        return iter.stamp == self.stamp
+
+    def get_user_data(self, iter):
+        """Get the user_data associated with the given TreeIter.
+
+        GenericTreeModel stores arbitrary Python objects mapped to instances 
of Gtk.TreeIter.
+        This method allows to retrieve the Python object held by the given 
iterator.
+        """
+        if self.leak_references:
+            return self._held_refs[iter.user_data]
+        else:
+            return _get_user_data_as_pyobject(iter)
+
+    def set_user_data(self, iter, user_data):
+        """Applies user_data and stamp to the given iter.
+
+        If the models "leak_references" property is set, a reference to the
+        user_data is stored with the model to ensure we don't run into bad
+        memory problems with the TreeIter.
+        """
+        iter.user_data = id(user_data)
+
+        if user_data is None:
+            self.invalidate_iter(iter)
+        else:
+            iter.stamp = self.stamp
+            if self.leak_references:
+                self._held_refs[iter.user_data] = user_data
+
+    def create_tree_iter(self, user_data):
+        """Create a Gtk.TreeIter instance with the given user_data specific 
for this model.
+
+        Use this method to create Gtk.TreeIter instance instead of directly 
calling
+        Gtk.Treeiter(), this will ensure proper reference managment of wrapped 
used_data.
+        """
+        iter = Gtk.TreeIter()
+        self.set_user_data(iter, user_data)
+        return iter
+
+    def _create_tree_iter(self, data):
+        """Internal creation of a (bool, TreeIter) pair for returning directly
+        back to the view interfacing with this model."""
+        if data is None:
+            return (False, None)
+        else:
+            it = self.create_tree_iter(data)
+            return (True, it)
+
+    def row_deleted(self, path, node=None):
+        """Notify the model a row has been deleted.
+
+        Use the node parameter to ensure the user_data reference associated
+        with the path is properly freed by this model.
+
+        :Parameters:
+            path : Gtk.TreePath
+                Path to the row that has been deleted.
+            node : object
+                Python object used as the node returned from "on_get_iter". 
This is
+                optional but ensures the model will not leak references to 
this object.
+        """
+        super(GenericTreeModel, self).row_deleted(path)
+        node_id = id(node)
+        if node_id in self._held_refs:
+            del self._held_refs[node_id]
+
+    #
+    # GtkTreeModel Interface Implementation
+    #
+    @handle_exception(0)
+    def do_get_flags(self):
+        """Internal method."""
+        return self.on_get_flags()
+
+    @handle_exception(0)
+    def do_get_n_columns(self):
+        """Internal method."""
+        return self.on_get_n_columns()
+
+    @handle_exception(GObject.TYPE_INVALID)
+    def do_get_column_type(self, index):
+        """Internal method."""
+        return self.on_get_column_type(index)
+
+    @handle_exception((False, None))
+    def do_get_iter(self, path):
+        """Internal method."""
+        return self._create_tree_iter(self.on_get_iter(path))
+
+    @handle_exception(False)
+    def do_iter_next(self, iter):
+        """Internal method."""
+        if iter is None:
+            next_data = self.on_iter_next(None)
+        else:
+            next_data = self.on_iter_next(self.get_user_data(iter))
+
+        self.set_user_data(iter, next_data)
+        return next_data is not None
+
+    @handle_exception(None)
+    def do_get_path(self, iter):
+        """Internal method."""
+        path = self.on_get_path(self.get_user_data(iter))
+        if path is None:
+            return None
+        else:
+            return Gtk.TreePath(path)
+
+    @handle_exception(None)
+    def do_get_value(self, iter, column):
+        """Internal method."""
+        return self.on_get_value(self.get_user_data(iter), column)
+
+    @handle_exception((False, None))
+    def do_iter_children(self, parent):
+        """Internal method."""
+        data = self.get_user_data(parent) if parent else None
+        return self._create_tree_iter(self.on_iter_children(data))
+
+    @handle_exception(False)
+    def do_iter_has_child(self, parent):
+        """Internal method."""
+        return self.on_iter_has_child(self.get_user_data(parent))
+
+    @handle_exception(0)
+    def do_iter_n_children(self, iter):
+        """Internal method."""
+        if iter is None:
+            return self.on_iter_n_children(None)
+        return self.on_iter_n_children(self.get_user_data(iter))
+
+    @handle_exception((False, None))
+    def do_iter_nth_child(self, parent, n):
+        """Internal method."""
+        if parent is None:
+            data = self.on_iter_nth_child(None, n)
+        else:
+            data = self.on_iter_nth_child(self.get_user_data(parent), n)
+        return self._create_tree_iter(data)
+
+    @handle_exception((False, None))
+    def do_iter_parent(self, child):
+        """Internal method."""
+        return 
self._create_tree_iter(self.on_iter_parent(self.get_user_data(child)))
+
+    @handle_exception(None)
+    def do_ref_node(self, iter):
+        self.on_ref_node(self.get_user_data(iter))
+
+    @handle_exception(None)
+    def do_unref_node(self, iter):
+        self.on_unref_node(self.get_user_data(iter))
+
+    #
+    # Python Subclass Overridables
+    #
+    def on_get_flags(self):
+        """Overridable.
+
+        :Returns Gtk.TreeModelFlags:
+            The flags for this model. See: Gtk.TreeModelFlags
+        """
+        raise NotImplementedError
+
+    def on_get_n_columns(self):
+        """Overridable.
+
+        :Returns:
+            The number of columns for this model.
+        """
+        raise NotImplementedError
+
+    def on_get_column_type(self, index):
+        """Overridable.
+
+        :Returns:
+            The column type for the given index.
+        """
+        raise NotImplementedError
+
+    def on_get_iter(self, path):
+        """Overridable.
+
+        :Returns:
+            A python object (node) for the given TreePath.
+        """
+        raise NotImplementedError
+
+    def on_iter_next(self, node):
+        """Overridable.
+
+        :Parameters:
+            node : object
+                Node at current level.
+
+        :Returns:
+            A python object (node) following the given node at the current 
level.
+        """
+        raise NotImplementedError
+
+    def on_get_path(self, node):
+        """Overridable.
+
+        :Returns:
+            A TreePath for the given node.
+        """
+        raise NotImplementedError
+
+    def on_get_value(self, node, column):
+        """Overridable.
+
+        :Parameters:
+            node : object
+            column : int
+                Column index to get the value from.
+
+        :Returns:
+            The value of the column for the given node."""
+        raise NotImplementedError
+
+    def on_iter_children(self, parent):
+        """Overridable.
+
+        :Returns:
+            The first child of parent or None if parent has no children.
+            If parent is None, return the first node of the model.
+        """
+        raise NotImplementedError
+
+    def on_iter_has_child(self, node):
+        """Overridable.
+
+        :Returns:
+            True if the given node has children.
+        """
+        raise NotImplementedError
+
+    def on_iter_n_children(self, node):
+        """Overridable.
+
+        :Returns:
+            The number of children for the given node. If node is None,
+            return the number of top level nodes.
+        """
+        raise NotImplementedError
+
+    def on_iter_nth_child(self, parent, n):
+        """Overridable.
+
+        :Parameters:
+            parent : object
+            n : int
+                Index of child within parent.
+
+        :Returns:
+            The child for the given parent index starting at 0. If parent None,
+            return the top level node corresponding to "n".
+            If "n" is larger then available nodes, return None.
+        """
+        raise NotImplementedError
+
+    def on_iter_parent(self, child):
+        """Overridable.
+
+        :Returns:
+            The parent node of child or None if child is a top level node."""
+        raise NotImplementedError
+
+    def on_ref_node(self, node):
+        pass
+
+    def on_unref_node(self, node):
+        pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tryton-6.0.50/tryton.egg-info/PKG-INFO 
new/tryton-6.0.54/tryton.egg-info/PKG-INFO
--- old/tryton-6.0.50/tryton.egg-info/PKG-INFO  2025-03-04 22:22:19.000000000 
+0100
+++ new/tryton-6.0.54/tryton.egg-info/PKG-INFO  2025-06-04 23:17:24.000000000 
+0200
@@ -1,6 +1,6 @@
-Metadata-Version: 2.2
+Metadata-Version: 2.4
 Name: tryton
-Version: 6.0.50
+Version: 6.0.54
 Summary: Tryton desktop client
 Home-page: http://www.tryton.org/
 Download-URL: http://downloads.tryton.org/6.0/
@@ -61,6 +61,7 @@
 Dynamic: home-page
 Dynamic: keywords
 Dynamic: license
+Dynamic: license-file
 Dynamic: platform
 Dynamic: project-url
 Dynamic: provides-extra
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tryton-6.0.50/tryton.egg-info/SOURCES.txt 
new/tryton-6.0.54/tryton.egg-info/SOURCES.txt
--- old/tryton-6.0.50/tryton.egg-info/SOURCES.txt       2025-03-04 
22:22:20.000000000 +0100
+++ new/tryton-6.0.54/tryton.egg-info/SOURCES.txt       2025-06-04 
23:17:25.000000000 +0200
@@ -260,6 +260,7 @@
 tryton/gui/window/view_form/view/graph_gtk/pie.py
 tryton/gui/window/view_form/view/list_gtk/__init__.py
 tryton/gui/window/view_form/view/list_gtk/editabletree.py
+tryton/gui/window/view_form/view/list_gtk/generictreemodel.py
 tryton/gui/window/view_form/view/list_gtk/widget.py
 tryton/plugins/__init__.py
 tryton/plugins/translation/__init__.py

Reply via email to