Use defaultdict as result of get method of Field

This prevents loop to fill the result with default value.
This commit is contained in:
Cédric Krier
2026-04-23 19:04:43 +02:00
parent b99e3b455e
commit 9d032e7a48
7 changed files with 40 additions and 42 deletions
+6 -7
View File
@@ -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 @@ class Binary(Field):
if values is None:
values = {}
transaction = Transaction()
res = {}
converter = self.cast
default = None
format_ = Transaction().context.get(
@@ -71,6 +71,7 @@ class Binary(Field):
if format_ == 'size':
converter = len
default = 0
result = defaultdict(type(default))
if self.file_id:
table = model.__table__()
@@ -93,24 +94,22 @@ class Binary(Field):
& (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()
+4 -3
View File
@@ -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 @@ class Dict(Field):
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 @@ class Dict(Field):
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)
+4 -9
View File
@@ -128,13 +128,7 @@ class Many2Many(Field):
'''
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 @@ class Many2Many(Field):
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):
'''
@@ -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 @@ class MultiSelection(SelectionMixin, Field):
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)
+4 -5
View File
@@ -140,9 +140,7 @@ class One2Many(Field):
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 @@ class One2Many(Field):
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):
'''
+5 -4
View File
@@ -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 @@ class One2One(Many2Many):
: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):
'''
+13 -11
View File
@@ -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 @@ class Reference(SelectionMixin, Field):
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 @@ class Reference(SelectionMixin, Field):
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 @@ class Reference(SelectionMixin, Field):
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 @@ class Reference(SelectionMixin, Field):
], 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