diff options
| author | xmo-odoo <xmo@odoo.com> | 2017-05-10 09:39:55 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-05-10 09:39:55 +0200 |
| commit | fffaf735f58f1ac57781c095eb552de6d1fcdc47 (patch) | |
| tree | 88ab0ab65430d871862a836524e0ecc890d1674d /odoo/models.py | |
| parent | 10eee18a047d35305dc46282e610e88936d81ffc (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.py | 163 |
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 |
