details:   https://code.tryton.org/tryton/commit/c28c787fd5a2
branch:    default
user:      Cédric Krier <[email protected]>
date:      Thu Apr 23 19:04:43 2026 +0200
description:
        Use defaultdict as result of get method of Field

        This prevents loop to fill the result with default value.
diffstat:

 trytond/trytond/model/fields/binary.py         |  13 ++++++-------
 trytond/trytond/model/fields/dict.py           |   7 ++++---
 trytond/trytond/model/fields/many2many.py      |  13 ++++---------
 trytond/trytond/model/fields/multiselection.py |   7 ++++---
 trytond/trytond/model/fields/one2many.py       |   9 ++++-----
 trytond/trytond/model/fields/one2one.py        |   9 +++++----
 trytond/trytond/model/fields/reference.py      |  24 +++++++++++++-----------
 7 files changed, 40 insertions(+), 42 deletions(-)

diffs (266 lines):

diff -r fb4749715cb6 -r c28c787fd5a2 trytond/trytond/model/fields/binary.py
--- a/trytond/trytond/model/fields/binary.py    Thu Apr 23 00:56:02 2026 +0200
+++ b/trytond/trytond/model/fields/binary.py    Thu Apr 23 19:04:43 2026 +0200
@@ -2,6 +2,7 @@
 # this repository contains the full copyright notices and license terms.
 
 import logging
+from collections import defaultdict
 
 from sql import Column, Literal, Null
 from sql.functions import CurrentTimestamp
@@ -63,7 +64,6 @@
         if values is None:
             values = {}
         transaction = Transaction()
-        res = {}
         converter = self.cast
         default = None
         format_ = Transaction().context.get(
@@ -71,6 +71,7 @@
         if format_ == 'size':
             converter = len
             default = 0
+        result = defaultdict(type(default))
 
         if self.file_id:
             table = model.__table__()
@@ -93,24 +94,22 @@
                     & (Column(table, self.file_id) != '')))
             for record_id, file_id in cursor:
                 try:
-                    res[record_id] = store_func(file_id, prefix)
+                    result[record_id] = store_func(file_id, prefix)
                 except (IOError, OSError):
                     logger.exception(
                         "failed to retrieve %r from filestore at %r",
                         file_id, prefix)
 
         for i in values:
-            if i['id'] in res:
+            if i['id'] in result:
                 continue
             value = i[name]
             if value:
                 value = converter(value)
             else:
                 value = default
-            res[i['id']] = value
-        for i in ids:
-            res.setdefault(i, default)
-        return res
+            result[i['id']] = value
+        return result
 
     def queue_for_removal(self, Model, name, ids):
         pool = Pool()
diff -r fb4749715cb6 -r c28c787fd5a2 trytond/trytond/model/fields/dict.py
--- a/trytond/trytond/model/fields/dict.py      Thu Apr 23 00:56:02 2026 +0200
+++ b/trytond/trytond/model/fields/dict.py      Thu Apr 23 19:04:43 2026 +0200
@@ -1,6 +1,7 @@
 # This file is part of Tryton.  The COPYRIGHT file at the toplevel of this
 # repository contains the full copyright notices and license terms.
 import json
+from collections import defaultdict
 from functools import partial
 
 from sql import Cast, CombiningQuery, Literal, Null, Select, operators
@@ -34,7 +35,7 @@
         self.search_unaccented = True
 
     def get(self, ids, model, name, values=None):
-        dicts = dict((id, None) for id in ids)
+        result = defaultdict(type(None))
         for value in values or []:
             data = value[name]
             if data:
@@ -44,8 +45,8 @@
                 for key, val in data.items():
                     if isinstance(val, list):
                         data[key] = tuple(val)
-                dicts[value['id']] = ImmutableDict(data)
-        return dicts
+                result[value['id']] = ImmutableDict(data)
+        return result
 
     def sql_format(self, value):
         value = super().sql_format(value)
diff -r fb4749715cb6 -r c28c787fd5a2 trytond/trytond/model/fields/many2many.py
--- a/trytond/trytond/model/fields/many2many.py Thu Apr 23 00:56:02 2026 +0200
+++ b/trytond/trytond/model/fields/many2many.py Thu Apr 23 19:04:43 2026 +0200
@@ -128,13 +128,7 @@
         '''
         Return target records ordered.
         '''
-        if values is None:
-            values = {}
-        res = {}
-        if not ids:
-            return res
-        for i in ids:
-            res[i] = []
+        result = defaultdict(list)
 
         Relation = self.get_relation()
         origin_field = Relation._fields[self.origin]
@@ -171,8 +165,9 @@
                 origin_id = int(origin_id)
             else:
                 origin_id = relation[self.origin]
-            res[origin_id].append(relation[self.target])
-        return dict((key, tuple(value)) for key, value in res.items())
+            result[origin_id].append(relation[self.target])
+        return defaultdict(
+            tuple, ((key, tuple(value)) for key, value in result.items()))
 
     def set(self, Model, name, ids, values, *args):
         '''
diff -r fb4749715cb6 -r c28c787fd5a2 
trytond/trytond/model/fields/multiselection.py
--- a/trytond/trytond/model/fields/multiselection.py    Thu Apr 23 00:56:02 
2026 +0200
+++ b/trytond/trytond/model/fields/multiselection.py    Thu Apr 23 19:04:43 
2026 +0200
@@ -1,6 +1,7 @@
 # This file is part of Tryton.  The COPYRIGHT file at the toplevel of this
 # repository contains the full copyright notices and license terms.
 import json
+from collections import defaultdict
 from functools import partial
 
 from sql import Literal, operators
@@ -57,15 +58,15 @@
                 self.selection, RPC(instantiate=instantiate, cache=cache))
 
     def get(self, ids, model, name, values=None):
-        lists = {id: () for id in ids}
+        result = defaultdict(tuple)
         for value in values or []:
             data = value[name]
             if data:
                 # If stored as JSON conversion is done on backend
                 if isinstance(data, str):
                     data = json.loads(data)
-                lists[value['id']] = tuple(data)
-        return lists
+                result[value['id']] = tuple(data)
+        return result
 
     def sql_format(self, value):
         value = super().sql_format(value)
diff -r fb4749715cb6 -r c28c787fd5a2 trytond/trytond/model/fields/one2many.py
--- a/trytond/trytond/model/fields/one2many.py  Thu Apr 23 00:56:02 2026 +0200
+++ b/trytond/trytond/model/fields/one2many.py  Thu Apr 23 19:04:43 2026 +0200
@@ -140,9 +140,7 @@
         Target = self.get_target()
         field = Target._fields[self.field]
         reference_key = field._type == 'reference'
-        res = {}
-        for i in ids:
-            res[i] = []
+        result = defaultdict(list)
 
         if field.sortable(Target):
             if reference_key:
@@ -175,8 +173,9 @@
                 origin_id = int(origin_id)
             else:
                 origin_id = target[self.field]
-            res[origin_id].append(target['id'])
-        return dict((key, tuple(value)) for key, value in res.items())
+            result[origin_id].append(target['id'])
+        return defaultdict(
+            tuple, ((key, tuple(value)) for key, value in result.items()))
 
     def set(self, Model, name, ids, values, *args):
         '''
diff -r fb4749715cb6 -r c28c787fd5a2 trytond/trytond/model/fields/one2one.py
--- a/trytond/trytond/model/fields/one2one.py   Thu Apr 23 00:56:02 2026 +0200
+++ b/trytond/trytond/model/fields/one2one.py   Thu Apr 23 19:04:43 2026 +0200
@@ -1,6 +1,8 @@
 # This file is part of Tryton.  The COPYRIGHT file at the top level of
 # this repository contains the full copyright notices and license terms.
 
+from collections import defaultdict
+
 from trytond.model.fields.field import Field, instantiate_context
 from trytond.model.fields.many2many import Many2Many
 from trytond.pool import Pool
@@ -21,10 +23,9 @@
         :param values: a dictionary with the read values
         :return: a dictionary with ids as key and target id as value
         '''
-        res = super().get(ids, model, name, values=values)
-        for i, vals in res.items():
-            res[i] = vals[0] if vals else None
-        return res
+        result = super().get(ids, model, name, values=values)
+        return defaultdict(
+            type(None), ((k, v[0] if v else None) for k, v in result.items()))
 
     def set(self, Model, name, ids, value, *args):
         '''
diff -r fb4749715cb6 -r c28c787fd5a2 trytond/trytond/model/fields/reference.py
--- a/trytond/trytond/model/fields/reference.py Thu Apr 23 00:56:02 2026 +0200
+++ b/trytond/trytond/model/fields/reference.py Thu Apr 23 19:04:43 2026 +0200
@@ -1,6 +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.
 import warnings
+from collections import defaultdict
 
 from sql import Cast, Expression, Literal, Null, Query
 from sql.functions import Position, Substring
@@ -123,17 +124,17 @@
         pool = Pool()
         if values is None:
             values = {}
-        res = {}
+        result = defaultdict(type(None))
         for i in values:
-            res[i['id']] = i[name]
+            result[i['id']] = i[name]
         ref_to_check = {}
         for i in ids:
-            if not (i in res):
-                res[i] = None
+            if not (i in result):
+                result[i] = None
                 continue
-            if not res[i]:
+            if not result[i]:
                 continue
-            ref_model, ref_id = res[i].split(',', 1)
+            ref_model, ref_id = result[i].split(',', 1)
             if not ref_model:
                 continue
             try:
@@ -142,7 +143,7 @@
                 continue
             if ref_id < 0:
                 continue
-            res[i] = ref_model + ',' + str(ref_id)
+            result[i] = ref_model + ',' + str(ref_id)
             ref_to_check.setdefault(ref_model, (set(), []))
             ref_to_check[ref_model][0].add(ref_id)
             ref_to_check[ref_model][1].append(i)
@@ -153,7 +154,8 @@
                 try:
                     pool.get(ref_model)
                 except KeyError:
-                    res.update(dict((i, None) for i in ids))
+                    for i in ids:
+                        result.pop(i, None)
                     continue
                 Ref = pool.get(ref_model)
                 refs = Ref.search([
@@ -161,9 +163,9 @@
                     ], order=[])
                 refs = list(map(str, refs))
                 for i in ids:
-                    if res[i] not in refs:
-                        res[i] = None
-        return res
+                    if result[i] not in refs:
+                        result.pop(i, None)
+        return result
 
     def __set__(self, inst, value):
         from ..model import Model

Reply via email to