summaryrefslogtreecommitdiff
path: root/odoo/models.py
diff options
context:
space:
mode:
authorxmo-odoo <xmo@odoo.com>2017-05-10 09:39:55 +0200
committerGitHub <noreply@github.com>2017-05-10 09:39:55 +0200
commitfffaf735f58f1ac57781c095eb552de6d1fcdc47 (patch)
tree88ab0ab65430d871862a836524e0ecc890d1674d /odoo/models.py
parent10eee18a047d35305dc46282e610e88936d81ffc (diff)
[FIX] P3: list -> iterable builtins (#16811)
In Python 3: * various builtins and dict methods were changed to return view/iterable objects rather than lists * and the separate Python 2 view/iterable builtins and methods were removed altogether This is problematic when using these items as list (which the happens repeatedly in Odoo), but more viciously when iterating *multiple times* over them (which also happens, which I've messed up multiple times while writing this, and which is a pain to debug even when you've just created the issue). Convert all code using these to semantics-matching cross-version helper functions to get the LCD behaviour between P2 and P3, and forbid the builtins via lint. issue #8530
Diffstat (limited to 'odoo/models.py')
-rw-r--r--odoo/models.py163
1 files changed, 80 insertions, 83 deletions
diff --git a/odoo/models.py b/odoo/models.py
index a1535123c9d..a9448b3ca05 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -108,9 +108,6 @@ def check_method_name(name):
if regex_private.match(name):
raise AccessError(_('Private methods (such as %s) cannot be called remotely.') % (name,))
-def intersect(la, lb):
- return filter(lambda x: x in lb, la)
-
def same_name(f, g):
""" Test whether functions ``f`` and ``g`` are identical or have the same name """
return f == g or getattr(f, '__name__', 0) == getattr(g, '__name__', 1)
@@ -150,7 +147,7 @@ class MetaModel(api.Meta):
self.module_to_models[self._module].append(self)
# check for new-api conversion error: leave comma after field definition
- for key, val in attrs.iteritems():
+ for key, val in pycompat.items(attrs):
if type(val) is tuple and len(val) == 1 and isinstance(val[0], Field):
_logger.error("Trailing comma after field definition: %s.%s", self, key)
if isinstance(val, Field):
@@ -515,7 +512,7 @@ class BaseModel(object):
cls._inherits.update(base._inherits)
- for mname, fnames in base._depends.iteritems():
+ for mname, fnames in pycompat.items(base._depends):
cls._depends[mname] = cls._depends.get(mname, []) + fnames
for cons in base._constraints:
@@ -525,7 +522,7 @@ class BaseModel(object):
cls._sql_constraints += base._sql_constraints
cls._sequence = cls._sequence or (cls._table + '_id_seq')
- cls._constraints = cls._constraints.values()
+ cls._constraints = list(pycompat.values(cls._constraints))
# update _inherits_children of parent models
for parent_name in cls._inherits:
@@ -707,7 +704,7 @@ class BaseModel(object):
This method is used when exporting data via client menu
"""
- fields_to_export = map(fix_import_export_id_paths, fields_to_export)
+ fields_to_export = [fix_import_export_id_paths(f) for f in fields_to_export]
if raw_data:
self = self.with_context(export_raw_data=True)
return {'datas': self._export_rows(fields_to_export)}
@@ -740,7 +737,7 @@ class BaseModel(object):
cr = self._cr
cr.execute('SAVEPOINT model_load')
- fields = map(fix_import_export_id_paths, fields)
+ fields = [fix_import_export_id_paths(f) for f in fields]
fg = self.fields_get()
ids = []
@@ -835,7 +832,7 @@ class BaseModel(object):
# copy non-relational fields to record dict
record = {fnames[0]: value
- for fnames, value in itertools.izip(fields_, row)
+ for fnames, value in pycompat.izip(fields_, row)
if not is_relational(fnames[0])}
# Get all following rows which have relational values attached to
@@ -849,13 +846,13 @@ class BaseModel(object):
# get only cells for this sub-field, should be strictly
# non-empty, field path [None] is for name_get field
- indices, subfields = zip(*((index, fnames[1:] or [None])
+ indices, subfields = pycompat.izip(*((index, fnames[1:] or [None])
for index, fnames in enumerate(fields_)
if fnames[0] == relfield))
# return all rows which have at least one value for the
# subfields of relfield
- relfield_data = filter(any, map(itemgetter_tuple(indices), record_span))
+ relfield_data = [it for it in pycompat.imap(itemgetter_tuple(indices), record_span) if any(it)]
record[relfield] = [
subrecord
for subrecord, _subinfo in comodel._extract_records(subfields, relfield_data, log=log)
@@ -876,7 +873,7 @@ class BaseModel(object):
:returns: a list of triplets of (id, xid, record)
:rtype: list((int|None, str|None, dict))
"""
- field_names = {name: field.string for name, field in self._fields.iteritems()}
+ field_names = {name: field.string for name, field in pycompat.items(self._fields)}
if self.env.lang:
field_names.update(self.env['ir.translation'].get_field_string(self._name))
@@ -1007,7 +1004,7 @@ class BaseModel(object):
defaults = self._convert_to_write(defaults)
# add default values for inherited fields
- for model, names in parent_fields.iteritems():
+ for model, names in pycompat.items(parent_fields):
defaults.update(self.env[model].default_get(names))
return defaults
@@ -1083,7 +1080,7 @@ class BaseModel(object):
:rtype: etree._Element
"""
group = E.group(col="4")
- for fname, field in self._fields.iteritems():
+ for fname, field in pycompat.items(self._fields):
if field.automatic:
continue
elif field.type in ('one2many', 'many2many', 'text', 'html'):
@@ -1500,14 +1497,14 @@ class BaseModel(object):
# avoid overriding inherited values when parent is set
avoid_models = {
parent_model
- for parent_model, parent_field in self._inherits.iteritems()
+ for parent_model, parent_field in pycompat.items(self._inherits)
if parent_field in values
}
# compute missing fields
missing_defaults = {
name
- for name, field in self._fields.iteritems()
+ for name, field in pycompat.items(self._fields)
if name not in values
if name not in MAGIC_COLUMNS
if not (field.inherited and field.related_field.model_name in avoid_models)
@@ -1518,7 +1515,7 @@ class BaseModel(object):
# override defaults with the provided values, never allow the other way around
defaults = self.default_get(list(missing_defaults))
- for name, value in defaults.iteritems():
+ for name, value in pycompat.items(defaults):
if self._fields[name].type == 'many2many' and value and isinstance(value[0], pycompat.integer_types):
# convert a list of ids into a list of commands
defaults[name] = [(6, 0, value)]
@@ -1603,10 +1600,10 @@ class BaseModel(object):
if field.relational and groups._fold_name in groups._fields:
fold = {group.id: group[groups._fold_name]
for group in groups.browse([key for key in result if key])}
- for key, line in result.iteritems():
+ for key, line in pycompat.items(result):
line['__fold'] = fold.get(key, False)
- return result.values()
+ return list(pycompat.values(result))
@api.model
def _read_group_prepare(self, orderby, aggregated_fields, annotated_groupbys, query):
@@ -1840,7 +1837,7 @@ class BaseModel(object):
def _read_group_raw(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
self.check_access_rights('read')
query = self._where_calc(domain)
- fields = fields or [f.name for f in self._fields.itervalues() if f.store]
+ fields = fields or [f.name for f in pycompat.values(self._fields) if f.store]
groupby = [groupby] if isinstance(groupby, basestring) else list(OrderedSet(groupby))
groupby_list = groupby[:1] if lazy else groupby
@@ -1914,7 +1911,7 @@ class BaseModel(object):
self._read_group_resolve_many2one_fields(fetched_data, annotated_groupbys)
- data = map(lambda r: {k: self._read_group_prepare_data(k,v, groupby_dict) for k,v in r.iteritems()}, fetched_data)
+ data = ({k: self._read_group_prepare_data(k,v, groupby_dict) for k,v in pycompat.items(r)} for r in fetched_data)
result = [self._read_group_format_result(d, annotated_groupbys, groupby, domain) for d in data]
if lazy:
# Right now, read_group only fill results in lazy mode (by default).
@@ -2020,7 +2017,7 @@ class BaseModel(object):
# fields which were required but have been removed (or will be added by
# another module)
cr = self._cr
- cols = [name for name, field in self._fields.iteritems()
+ cols = [name for name, field in pycompat.items(self._fields)
if field.store and field.column_type]
cr.execute("SELECT a.attname, a.attnotnull"
" FROM pg_class c, pg_attribute a"
@@ -2120,7 +2117,7 @@ class BaseModel(object):
recs = self.with_context(active_test=False).search([])
recs._recompute_todo(field)
- for field in self._fields.itervalues():
+ for field in pycompat.values(self._fields):
if not field.store:
continue
@@ -2208,9 +2205,9 @@ class BaseModel(object):
""" Determine inherited fields. """
# determine candidate inherited fields
fields = {}
- for parent_model, parent_field in self._inherits.iteritems():
+ for parent_model, parent_field in pycompat.items(self._inherits):
parent = self.env[parent_model]
- for name, field in parent._fields.iteritems():
+ for name, field in pycompat.items(parent._fields):
# inherited fields are implemented as related fields, with the
# following specific properties:
# - reading inherited fields should not bypass access rights
@@ -2223,13 +2220,13 @@ class BaseModel(object):
)
# add inherited fields that are not redefined locally
- for name, field in fields.iteritems():
+ for name, field in pycompat.items(fields):
if name not in self._fields:
self._add_field(name, field)
@api.model
def _inherits_check(self):
- for table, field_name in self._inherits.items():
+ for table, field_name in pycompat.items(self._inherits):
field = self._fields.get(field_name)
if not field:
_logger.info('Missing many2one field definition for _inherits reference "%s" in "%s", using default one.', field_name, self._name)
@@ -2242,7 +2239,7 @@ class BaseModel(object):
field.ondelete = "cascade"
# reflect fields with delegate=True in dictionary self._inherits
- for field in self._fields.itervalues():
+ for field in pycompat.values(self._fields):
if field.type == 'many2one' and not field.related and field.delegate:
if not field.required:
_logger.warning("Field %s with delegate=True must be required.", field)
@@ -2330,7 +2327,7 @@ class BaseModel(object):
# set up fields
bad_fields = []
- for name, field in cls._fields.iteritems():
+ for name, field in pycompat.items(cls._fields):
try:
field.setup_full(self)
except Exception:
@@ -2349,11 +2346,11 @@ class BaseModel(object):
# map each field to the fields computed with the same method
groups = defaultdict(list)
- for field in cls._fields.itervalues():
+ for field in pycompat.values(cls._fields):
if field.compute:
cls._field_computed[field] = group = groups[field.compute]
group.append(field)
- for fields in groups.itervalues():
+ for fields in pycompat.values(groups):
compute_sudo = fields[0].compute_sudo
if not all(field.compute_sudo == compute_sudo for field in fields):
_logger.warning("%s: inconsistent 'compute_sudo' for computed fields: %s",
@@ -2366,7 +2363,7 @@ class BaseModel(object):
if isinstance(self, Model):
# set up field triggers (on database-persisted models only)
- for field in cls._fields.itervalues():
+ for field in pycompat.values(cls._fields):
# dependencies of custom fields may not exist; ignore that case
exceptions = (Exception,) if field.manual else ()
with tools.ignore(*exceptions):
@@ -2405,7 +2402,7 @@ class BaseModel(object):
readonly = not (has_access('write') or has_access('create'))
res = {}
- for fname, field in self._fields.iteritems():
+ for fname, field in pycompat.items(self._fields):
if allfields and fname not in allfields:
continue
if field.groups and not self.user_has_groups(field.groups):
@@ -2417,7 +2414,7 @@ class BaseModel(object):
description['states'] = {}
if attributes:
description = {key: val
- for key, val in description.iteritems()
+ for key, val in pycompat.items(description)
if key in attributes}
res[fname] = description
@@ -2452,9 +2449,9 @@ class BaseModel(object):
return True
if not fields:
- fields = filter(valid, self._fields)
+ fields = [name for name in self._fields if valid(name)]
else:
- invalid_fields = set(filter(lambda name: not valid(name), fields))
+ invalid_fields = {name for name in fields if not valid(name)}
if invalid_fields:
_logger.info('Access Denied by ACLs for operation: %s, uid: %s, model: %s, fields: %s',
operation, self._uid, self._name, ', '.join(invalid_fields))
@@ -2528,7 +2525,7 @@ class BaseModel(object):
if self._context.get('prefetch_fields', True) and field.prefetch:
fs.update(
f
- for f in self._fields.itervalues()
+ for f in pycompat.values(self._fields)
# select fields that can be prefetched
if f.prefetch
# discard fields with groups that the user may not access
@@ -2591,7 +2588,7 @@ class BaseModel(object):
order_str = self._generate_order_by(None, query)
# determine the fields that are stored as columns in tables;
- fields = map(self._fields.get, field_names + inherited_field_names)
+ fields = [self._fields[n] for n in (field_names + inherited_field_names)]
fields_pre = [
field
for field in fields
@@ -2608,7 +2605,7 @@ class BaseModel(object):
res = 'pg_size_pretty(length(%s)::bigint)' % res
return '%s as "%s"' % (res, col)
- qual_names = map(qualify, set(fields_pre + [self._fields['id']]))
+ qual_names = [qualify(name) for name in set(fields_pre + [self._fields['id']])]
# determine the actual query to execute
from_clause, where_clause, params = query.get_sql()
@@ -2666,8 +2663,7 @@ class BaseModel(object):
if extras:
raise AccessError(
_("Database fetch misses ids ({}) and has extra ids ({}), may be caused by a type incoherence in a previous request").format(
- ', '.join(map(repr, missing._ids)),
- ', '.join(map(repr, extras._ids)),
+ missing._ids, extras._ids,
))
# mark non-existing records in missing
forbidden = missing.exists()
@@ -2990,7 +2986,7 @@ class BaseModel(object):
# split up fields into old-style and pure new-style ones
old_vals, new_vals, unknown = {}, {}, []
- for key, val in vals.iteritems():
+ for key, val in pycompat.items(vals):
field = self._fields.get(key)
if field:
if field.store or field.inherited:
@@ -3003,7 +2999,7 @@ class BaseModel(object):
if unknown:
_logger.warning("%s.write() with unknown fields: %s", self._name, ', '.join(sorted(unknown)))
- protected_fields = map(self._fields.get, new_vals)
+ protected_fields = [self._fields[n] for n in new_vals]
with self.env.protecting(protected_fields, self):
# write old-style fields with (low-level) method _write
if old_vals:
@@ -3054,7 +3050,7 @@ class BaseModel(object):
query = "SELECT id FROM %s WHERE id IN %%s AND (%s IS NOT NULL) ORDER BY %s" % \
(self._table, self._parent_name, self._parent_order)
cr.execute(query, (tuple(self.ids),))
- parents_changed = map(operator.itemgetter(0), cr.fetchall())
+ parents_changed = [x[0] for x in cr.fetchall()]
updates = [] # list of (column, expr) or (column, pattern, value)
upd_todo = [] # list of column names to set explicitly
@@ -3062,7 +3058,7 @@ class BaseModel(object):
direct = [] # list of direcly updated columns
has_trans = self.env.lang and self.env.lang != 'en_US'
single_lang = len(self.env['res.lang'].get_installed()) <= 1
- for name, val in vals.iteritems():
+ for name, val in pycompat.items(vals):
field = self._fields[name]
if field and field.deprecated:
_logger.warning('Field %s.%s is deprecated: %s', self._name, name, field.deprecated)
@@ -3124,7 +3120,7 @@ class BaseModel(object):
# defaults in context must be removed when call a one2many or many2many
rel_context = {key: val
- for key, val in self._context.iteritems()
+ for key, val in pycompat.items(self._context)
if not key.startswith('default_')}
# call the 'write' method of fields which are not columns
@@ -3137,7 +3133,7 @@ class BaseModel(object):
# write inherited fields on the corresponding parent records
unknown_fields = set(updend)
- for parent_model, parent_field in self._inherits.iteritems():
+ for parent_model, parent_field in pycompat.items(self._inherits):
parent_ids = []
for sub_ids in cr.split_for_in_conditions(self.ids):
query = "SELECT DISTINCT %s FROM %s WHERE id IN %%s" % (parent_field, self._table)
@@ -3258,7 +3254,7 @@ class BaseModel(object):
# split up fields into old-style and pure new-style ones
old_vals, new_vals, unknown = {}, {}, []
- for key, val in vals.iteritems():
+ for key, val in pycompat.items(vals):
field = self._fields.get(key)
if field:
if field.store or field.inherited:
@@ -3274,7 +3270,7 @@ class BaseModel(object):
# create record with old-style fields
record = self.browse(self._create(old_vals))
- protected_fields = map(self._fields.get, new_vals)
+ protected_fields = [self._fields[n] for n in new_vals]
with self.env.protecting(protected_fields, record):
# put the values of pure new-style fields into cache, and inverse them
record.modified(set(new_vals) - set(old_vals))
@@ -3299,7 +3295,7 @@ class BaseModel(object):
# data of parent records to create or update, by model
tocreate = {
parent_model: {'id': vals.pop(parent_field, None)}
- for parent_model, parent_field in self._inherits.iteritems()
+ for parent_model, parent_field in pycompat.items(self._inherits)
}
# list of column assignments defined as tuples like:
@@ -3314,7 +3310,7 @@ class BaseModel(object):
upd_todo = []
unknown_fields = []
protected_fields = []
- for name, val in vals.items():
+ for name, val in list(pycompat.items(vals)):
field = self._fields.get(name)
if not field:
unknown_fields.append(name)
@@ -3330,7 +3326,7 @@ class BaseModel(object):
_logger.warning('No such field(s) in model %s: %s.', self._name, ', '.join(unknown_fields))
# create or update parent records
- for parent_model, parent_vals in tocreate.iteritems():
+ for parent_model, parent_vals in pycompat.items(tocreate):
parent_id = parent_vals.pop('id')
if not parent_id:
parent_id = self.env[parent_model].create(parent_vals).id
@@ -3339,12 +3335,12 @@ class BaseModel(object):
updates.append((self._inherits[parent_model], '%s', parent_id))
# set boolean fields to False by default (to make search more powerful)
- for name, field in self._fields.iteritems():
+ for name, field in pycompat.items(self._fields):
if field.type == 'boolean' and field.store and name not in vals:
vals[name] = False
# determine SQL values
- for name, val in vals.iteritems():
+ for name, val in pycompat.items(vals):
field = self._fields[name]
if field.store and field.column_type:
updates.append((name, field.column_format, field.convert_to_column(val, self)))
@@ -3375,7 +3371,7 @@ class BaseModel(object):
if self.env.lang and self.env.lang != 'en_US':
# add translations for self.env.lang
- for name, val in vals.iteritems():
+ for name, val in pycompat.items(vals):
field = self._fields[name]
if field.store and field.column_type and field.translate is True:
tname = "%s,%s" % (self._name, name)
@@ -3423,7 +3419,7 @@ class BaseModel(object):
# defaults in context must be removed when call a one2many or many2many
rel_context = {key: val
- for key, val in self._context.iteritems()
+ for key, val in pycompat.items(self._context)
if not key.startswith('default_')}
# call the 'write' method of fields which are not columns
@@ -3728,11 +3724,11 @@ class BaseModel(object):
# build a black list of fields that should not be copied
blacklist = set(MAGIC_COLUMNS + ['parent_left', 'parent_right'])
- whitelist = set(name for name, field in self._fields.iteritems() if not field.inherited)
+ whitelist = set(name for name, field in pycompat.items(self._fields) if not field.inherited)
def blacklist_given_fields(model):
# blacklist the fields that are given by inheritance
- for parent_model, parent_field in model._inherits.items():
+ for parent_model, parent_field in pycompat.items(model._inherits):
blacklist.add(parent_field)
if parent_field in default:
# all the fields of 'parent_model' are given by the record:
@@ -3741,17 +3737,17 @@ class BaseModel(object):
else:
blacklist_given_fields(self.env[parent_model])
# blacklist deprecated fields
- for name, field in model._fields.iteritems():
+ for name, field in pycompat.items(model._fields):
if field.deprecated:
blacklist.add(name)
blacklist_given_fields(self)
fields_to_copy = {name: field
- for name, field in self._fields.iteritems()
+ for name, field in pycompat.items(self._fields)
if field.copy and name not in default and name not in blacklist}
- for name, field in fields_to_copy.iteritems():
+ for name, field in pycompat.items(fields_to_copy):
if field.type == 'one2many':
# duplicate following the order of the ids because we'll rely on
# it later for copying translations in copy_translation()!
@@ -3789,7 +3785,7 @@ class BaseModel(object):
old_wo_lang, new_wo_lang = (old + new).with_context(lang=None)
Translation = old.env['ir.translation']
- for name, field in old._fields.iteritems():
+ for name, field in pycompat.items(old._fields):
if not field.copy:
continue
@@ -3799,7 +3795,7 @@ class BaseModel(object):
# foreseen in copy_data()
old_lines = old[name].sorted(key='id')
new_lines = new[name].sorted(key='id')
- for (old_line, new_line) in zip(old_lines, new_lines):
+ for (old_line, new_line) in pycompat.izip(old_lines, new_lines):
old_line.copy_translations(new_line)
elif field.translate:
@@ -3969,7 +3965,7 @@ class BaseModel(object):
"""
results = self._get_external_ids()
return {key: val[0] if val else ''
- for key, val in results.iteritems()}
+ for key, val in pycompat.items(results)}
# backwards compatibility
get_xml_id = get_external_id
@@ -4236,7 +4232,7 @@ class BaseModel(object):
""" List of actual record ids in this recordset (ignores placeholder
ids for records to create)
"""
- return filter(None, list(self._ids))
+ return [it for it in self._ids if it]
# backward-compatibility with former browse records
_cr = property(lambda self: self.env.cr)
@@ -4342,7 +4338,7 @@ class BaseModel(object):
target = self if update else self.browse([], self._prefetch)
return {
name: fields[name].convert_to_cache(value, target, validate=validate)
- for name, value in values.iteritems()
+ for name, value in pycompat.items(values)
if name in fields
}
@@ -4352,14 +4348,14 @@ class BaseModel(object):
"""
return {
name: self._fields[name].convert_to_record(value, self)
- for name, value in values.iteritems()
+ for name, value in pycompat.items(values)
}
def _convert_to_write(self, values):
""" Convert the ``values`` dictionary into the format of :meth:`write`. """
fields = self._fields
result = {}
- for name, value in values.iteritems():
+ for name, value in pycompat.items(values):
if name in fields:
field = fields[name]
value = field.convert_to_cache(value, self, validate=False)
@@ -4423,7 +4419,7 @@ class BaseModel(object):
"""
if isinstance(func, basestring):
name = func
- func = lambda rec: filter(None, rec.mapped(name))
+ func = lambda rec: any(rec.mapped(name))
return self.browse([rec.id for rec in self if func(rec)])
def sorted(self, key=None, reverse=False):
@@ -4440,13 +4436,13 @@ class BaseModel(object):
return self.browse(reversed(recs._ids)) if reverse else recs
if isinstance(key, basestring):
key = itemgetter(key)
- return self.browse(map(attrgetter('id'), sorted(self, key=key, reverse=reverse)))
+ return self.browse(item.id for item in sorted(self, key=key, reverse=reverse))
@api.multi
def update(self, values):
""" Update the records in ``self`` with ``values``. """
for record in self:
- for name, value in values.iteritems():
+ for name, value in pycompat.items(values):
record[name] = value
#
@@ -4667,7 +4663,7 @@ class BaseModel(object):
the records of model ``self`` in cache that have no value for ``field``
(:class:`Field` instance).
"""
- ids = filter(None, self._prefetch[self._name] - set(self.env.cache[field]))
+ ids = [it for it in self._prefetch[self._name] - set(self.env.cache[field]) if it]
return self.browse(ids)
@api.model
@@ -4690,9 +4686,9 @@ class BaseModel(object):
if fnames is None:
if ids is None:
return self.env.invalidate_all()
- fields = self._fields.values()
+ fields = list(pycompat.values(self._fields))
else:
- fields = map(self._fields.__getitem__, fnames)
+ fields = [self._fields[n] for n in fnames]
# invalidate fields and inverse fields, too
spec = [(f, ids) for f in fields] + \
@@ -4746,10 +4742,11 @@ class BaseModel(object):
updates[frozendict(vals)].add(rec.id)
# update records in batch when possible
with recs.env.norecompute():
- for vals, ids in updates.iteritems():
+ for vals, ids in pycompat.items(updates):
recs.browse(ids)._write(dict(vals))
# mark computed fields as done
- map(recs._recompute_done, fs)
+ for f in fs:
+ recs._recompute_done(f)
#
# Generic onchange method
@@ -4779,7 +4776,7 @@ class BaseModel(object):
if not result.get(names):
result[names] = node.attrib.get('on_change')
# traverse the subviews included in relational fields
- for subinfo in info['fields'][name].get('views', {}).itervalues():
+ for subinfo in pycompat.values(info['fields'][name].get('views', {})):
process(etree.fromstring(subinfo['arch']), subinfo, names)
else:
for child in node:
@@ -4802,19 +4799,19 @@ class BaseModel(object):
return
if res.get('value'):
res['value'].pop('id', None)
- self.update({key: val for key, val in res['value'].iteritems() if key in self._fields})
+ self.update({key: val for key, val in pycompat.items(res['value']) if key in self._fields})
if res.get('domain'):
result.setdefault('domain', {}).update(res['domain'])
if res.get('warning'):
if result.get('warning'):
# Concatenate multiple warnings
warning = result['warning']
- warning['message'] = '\n\n'.join(filter(None, [
+ warning['message'] = '\n\n'.join(s for s in [
warning.get('title'),
warning.get('message'),
res['warning'].get('title'),
res['warning'].get('message'),
- ]))
+ ] if s)
warning['title'] = _('Warnings')
else:
result['warning'] = res['warning']
@@ -4931,7 +4928,7 @@ class BaseModel(object):
record.mapped(field_seq)
# determine which fields have been modified
- for name, oldval in values.iteritems():
+ for name, oldval in pycompat.items(values):
field = self._fields[name]
newval = record[name]
if newval != oldval or (
@@ -5005,7 +5002,7 @@ class RecordCache(MutableMapping):
"""
if args and isinstance(args[0], SpecialValue):
values = dict.fromkeys(self._recs._ids, args[0])
- for name, field in self._recs._fields.iteritems():
+ for name, field in pycompat.items(self._recs._fields):
if name != 'id':
self._recs.env.cache[field].update(values)
else:
@@ -5023,7 +5020,7 @@ class RecordCache(MutableMapping):
""" Iterate over the field names with a regular value in cache. """
cache, id = self._recs.env.cache, self._recs.id
dummy = SpecialValue(None)
- for name, field in self._recs._fields.iteritems():
+ for name, field in pycompat.items(self._recs._fields):
if name != 'id' and not isinstance(cache[field].get(id, dummy), SpecialValue):
yield name