diff options
| author | Olivier Dony <odo@openerp.com> | 2017-08-18 18:43:46 +0200 |
|---|---|---|
| committer | Olivier Dony <odo@openerp.com> | 2017-08-20 23:25:54 +0200 |
| commit | 695716efb0f79f9a0e716952b1dcd433d866371a (patch) | |
| tree | 1b582a3469d12fc716d6252b4f239f0cd40da9e4 /addons | |
| parent | 589c0d7e2c3a44adc5d26aac8af08c0d06b97d5a (diff) | |
[FIX] P3: remove pycompat.{keys,items,values} helpers
Now that we're closer to switching to P3 for good, these helpers have
outlived their usefulness, and mostly add noise.
All remaining dict.iter*() or dict.view*() must be converted to the
normal keys(), values() or items() calls.
Whenever the result is likely to be used for more than the scope of a
loop, or when the dict needs to be modified during iteration, the calls
must be wrapped in a ``list()``, to protect the new P3 semantics.
Those cases are very exceptional.
Also removed some dead code or improved the API to remove unnecessary
conversions.
Diffstat (limited to 'addons')
100 files changed, 248 insertions, 334 deletions
diff --git a/addons/account/models/account.py b/addons/account/models/account.py index 29fcaa17c8e..daa407d636f 100644 --- a/addons/account/models/account.py +++ b/addons/account/models/account.py @@ -5,7 +5,7 @@ import math from odoo.osv import expression from odoo.tools.float_utils import float_round as round -from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, pycompat +from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT from odoo.exceptions import UserError, ValidationError from odoo import api, fields, models, _ diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index 87480662784..ee0d1903fd0 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -395,7 +395,7 @@ class AccountInvoice(models.Model): '_onchange_partner_id': ['account_id', 'payment_term_id', 'fiscal_position_id', 'partner_bank_id'], '_onchange_journal_id': ['currency_id'], } - for onchange_method, changed_fields in pycompat.items(onchanges): + for onchange_method, changed_fields in onchanges.items(): if any(f not in vals for f in changed_fields): invoice = self.new(vals) getattr(invoice, onchange_method)() @@ -516,7 +516,7 @@ class AccountInvoice(models.Model): tax_grouped = invoice.get_taxes_values() # Create new tax lines - for tax in pycompat.values(tax_grouped): + for tax in tax_grouped.values(): account_invoice_tax.create(tax) # dummy write on self to trigger recomputations @@ -535,7 +535,7 @@ class AccountInvoice(models.Model): def _onchange_invoice_line_ids(self): taxes_grouped = self.get_taxes_values() tax_lines = self.tax_line_ids.filtered('manual') - for tax in pycompat.values(taxes_grouped): + for tax in taxes_grouped.values(): tax_lines += tax_lines.new(tax) self.tax_line_ids = tax_lines return @@ -886,7 +886,7 @@ class AccountInvoice(models.Model): else: line2[tmp] = l line = [] - for key, val in pycompat.items(line2): + for key, val in line2.items(): line.append((0, 0, val)) return line @@ -1079,7 +1079,7 @@ class AccountInvoice(models.Model): result = [] for line in lines: values = {} - for name, field in pycompat.items(line._fields): + for name, field in line._fields.items(): if name in MAGIC_COLUMNS: continue elif field.type == 'many2one': @@ -1249,7 +1249,7 @@ class AccountInvoice(models.Model): for line in self.tax_line_ids: res.setdefault(line.tax_id.tax_group_id, 0.0) res[line.tax_id.tax_group_id] += line.amount - res = sorted(pycompat.items(res), key=lambda l: l[0].sequence) + res = sorted(res.items(), key=lambda l: l[0].sequence) res = [(l[0].name, l[1]) for l in res] return res diff --git a/addons/account/models/chart_template.py b/addons/account/models/chart_template.py index 2fe33e02e3a..d99b3fe99ce 100644 --- a/addons/account/models/chart_template.py +++ b/addons/account/models/chart_template.py @@ -7,8 +7,6 @@ from odoo.exceptions import UserError import logging -from odoo.tools import pycompat - _logger = logging.getLogger(__name__) def migrate_set_tags_and_taxes_updatable(cr, registry, module): @@ -327,7 +325,7 @@ class AccountChartTemplate(models.Model): # writing account values after creation of accounts company.transfer_account_id = account_template_ref[transfer_account_id.id] - for key, value in pycompat.items(generated_tax_res['account_dict']): + for key, value in generated_tax_res['account_dict'].items(): if value['refund_account_id'] or value['account_id'] or value['cash_basis_account']: AccountTaxObj.browse(key).write({ 'refund_account_id': account_ref.get(value['refund_account_id'], False), diff --git a/addons/account/models/partner.py b/addons/account/models/partner.py index f2f0f85f7c0..de32aaa5f3d 100644 --- a/addons/account/models/partner.py +++ b/addons/account/models/partner.py @@ -5,7 +5,7 @@ from operator import itemgetter import time from odoo import api, fields, models, _ -from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, pycompat +from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT from odoo.exceptions import ValidationError from odoo.addons.base.res.res_partner import WARNING_MESSAGE, WARNING_HELP @@ -73,7 +73,7 @@ class AccountFiscalPosition(models.Model): ref_dict = {} for line in self.account_ids: ref_dict[line.account_src_id] = line.account_dest_id - for key, acc in list(pycompat.items(accounts)): + for key, acc in accounts.items(): if acc in ref_dict: accounts[key] = ref_dict[acc] return accounts @@ -293,7 +293,7 @@ class ResPartner(models.Model): """ % where_clause self.env.cr.execute(query, where_clause_params) price_totals = self.env.cr.dictfetchall() - for partner, child_ids in pycompat.items(all_partners_and_children): + for partner, child_ids in all_partners_and_children.items(): partner.total_invoiced = sum(price['total'] for price in price_totals if price['partner_id'] in child_ids) @api.multi diff --git a/addons/account/report/account_report_financial.py b/addons/account/report/account_report_financial.py index 01e2080307f..65560736fff 100644 --- a/addons/account/report/account_report_financial.py +++ b/addons/account/report/account_report_financial.py @@ -3,7 +3,6 @@ import time from odoo import api, models, _ from odoo.exceptions import UserError -from odoo.tools import pycompat class ReportFinancial(models.AbstractModel): @@ -28,7 +27,7 @@ class ReportFinancial(models.AbstractModel): if where_clause.strip(): wheres.append(where_clause.strip()) filters = " AND ".join(wheres) - request = "SELECT account_id as id, " + ', '.join(pycompat.values(mapping)) + \ + request = "SELECT account_id as id, " + ', '.join(mapping.values()) + \ " FROM " + tables + \ " WHERE account_id IN %s " \ + filters + \ @@ -55,26 +54,26 @@ class ReportFinancial(models.AbstractModel): if report.type == 'accounts': # it's the sum of the linked accounts res[report.id]['account'] = self._compute_account_balance(report.account_ids) - for value in pycompat.values(res[report.id]['account']): + for value in res[report.id]['account'].values(): for field in fields: res[report.id][field] += value.get(field) elif report.type == 'account_type': # it's the sum the leaf accounts with such an account type accounts = self.env['account.account'].search([('user_type_id', 'in', report.account_type_ids.ids)]) res[report.id]['account'] = self._compute_account_balance(accounts) - for value in pycompat.values(res[report.id]['account']): + for value in res[report.id]['account'].values(): for field in fields: res[report.id][field] += value.get(field) elif report.type == 'account_report' and report.account_report_id: # it's the amount of the linked report res2 = self._compute_report_balance(report.account_report_id) - for key, value in pycompat.items(res2): + for key, value in res2.items(): for field in fields: res[report.id][field] += value[field] elif report.type == 'sum': # it's the sum of the children of this account.report res2 = self._compute_report_balance(report.children_ids) - for key, value in pycompat.items(res2): + for key, value in res2.items(): for field in fields: res[report.id][field] += value[field] return res @@ -86,11 +85,11 @@ class ReportFinancial(models.AbstractModel): res = self.with_context(data.get('used_context'))._compute_report_balance(child_reports) if data['enable_filter']: comparison_res = self.with_context(data.get('comparison_context'))._compute_report_balance(child_reports) - for report_id, value in pycompat.items(comparison_res): + for report_id, value in comparison_res.items(): res[report_id]['comp_bal'] = value['balance'] report_acc = res[report_id].get('account') if report_acc: - for account_id, val in pycompat.items(comparison_res[report_id].get('account')): + for account_id, val in comparison_res[report_id].get('account').items(): report_acc[account_id]['comp_bal'] = val['balance'] for report in child_reports: @@ -115,7 +114,7 @@ class ReportFinancial(models.AbstractModel): if res[report.id].get('account'): sub_lines = [] - for account_id, value in pycompat.items(res[report.id]['account']): + for account_id, value in res[report.id]['account'].items(): #if there are accounts to display, we add them to the lines with a level equals to their level in #the COA + 1 (to avoid having them with a too low level that would conflicts with the level of data #financial reports for Assets, liabilities...) diff --git a/addons/account/tests/test_reconciliation.py b/addons/account/tests/test_reconciliation.py index 0093915eee5..ac2aca16951 100644 --- a/addons/account/tests/test_reconciliation.py +++ b/addons/account/tests/test_reconciliation.py @@ -2,8 +2,6 @@ from odoo.addons.account.tests.account_test_classes import AccountingTestCase import time import unittest -from odoo.tools import pycompat - class TestReconciliation(AccountingTestCase): @@ -339,8 +337,8 @@ class TestReconciliation(AccountingTestCase): self.assertTrue(exchange_loss_line, 'There should be one move line of 0.01 EUR in credit') # The journal items of the reconciliation should have their debit and credit total equal # Besides, the total debit and total credit should be 60.61 EUR (2.00 USD) - self.assertEquals(sum(res['debit'] for res in pycompat.values(result)), 60.61) - self.assertEquals(sum(res['credit'] for res in pycompat.items(result)), 60.61) + self.assertEquals(sum(res['debit'] for res in result.values()), 60.61) + self.assertEquals(sum(res['credit'] for res in result.items()), 60.61) counterpart_exchange_loss_line = None for line in exchange_loss_line.move_id.line_id: if line.account_id.id == self.account_fx_expense_id: diff --git a/addons/account_asset/models/account_asset.py b/addons/account_asset/models/account_asset.py index cc2a29a09a9..15d471301b6 100644 --- a/addons/account_asset/models/account_asset.py +++ b/addons/account_asset/models/account_asset.py @@ -7,7 +7,7 @@ from dateutil.relativedelta import relativedelta from odoo import api, fields, models, _ from odoo.exceptions import UserError, ValidationError -from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF, pycompat +from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF from odoo.tools import float_compare, float_is_zero @@ -374,7 +374,7 @@ class AccountAssetAsset(models.Model): vals = self.onchange_category_id_values(self.category_id.id) # We cannot use 'write' on an object that doesn't exist yet if vals: - for k, v in pycompat.items(vals['value']): + for k, v in vals['value'].items(): setattr(self, k, v) def onchange_category_id_values(self, category_id): @@ -583,7 +583,7 @@ class AccountAssetDepreciationLine(models.Model): message = '' if message_description: message = '<span>%s</span>' % message_description - for name, values in pycompat.items(tracked_values): + for name, values in tracked_values.items(): message += '<div> • <b>%s</b>: ' % name message += '%s</div>' % values return message diff --git a/addons/account_voucher/models/account_voucher.py b/addons/account_voucher/models/account_voucher.py index e394af36296..40ae66c3395 100644 --- a/addons/account_voucher/models/account_voucher.py +++ b/addons/account_voucher/models/account_voucher.py @@ -5,7 +5,6 @@ from odoo import fields, models, api, _ from odoo.addons import decimal_precision as dp from odoo.exceptions import UserError -from odoo.tools import pycompat class AccountVoucher(models.Model): @@ -358,7 +357,7 @@ class AccountVoucherLine(models.Model): self.company_id.id, self.voucher_id.currency_id.id, self.voucher_id.voucher_type) - for fname, fvalue in pycompat.items(onchange_res['value']): + for fname, fvalue in onchange_res['value'].items(): setattr(self, fname, fvalue) def _get_account(self, product, fpos, type): diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py index 8f8db0fab0d..262dfdad86d 100644 --- a/addons/auth_signup/controllers/main.py +++ b/addons/auth_signup/controllers/main.py @@ -8,7 +8,6 @@ from odoo.addons.auth_signup.models.res_users import SignupError from odoo.addons.web.controllers.main import ensure_db, Home from odoo.exceptions import UserError from odoo.http import request -from odoo.tools import pycompat _logger = logging.getLogger(__name__) @@ -106,7 +105,7 @@ class AuthSignupHome(Home): try: # retrieve the user info (name, login or email) corresponding to a signup token token_infos = request.env['res.partner'].sudo().signup_retrieve_info(qcontext.get('token')) - for k, v in pycompat.items(token_infos): + for k, v in token_infos.items(): qcontext.setdefault(k, v) except: qcontext['error'] = _("Invalid signup token") diff --git a/addons/auth_signup/models/res_partner.py b/addons/auth_signup/models/res_partner.py index 0cf5c25b7ff..ecf63246580 100644 --- a/addons/auth_signup/models/res_partner.py +++ b/addons/auth_signup/models/res_partner.py @@ -8,8 +8,6 @@ from collections import defaultdict from datetime import datetime, timedelta from odoo import api, exceptions, fields, models, _ -from odoo.tools import pycompat - class SignupError(Exception): pass diff --git a/addons/base_address_extended/models/base_address_extended.py b/addons/base_address_extended/models/base_address_extended.py index 1d49c1c94c4..9a210dde769 100644 --- a/addons/base_address_extended/models/base_address_extended.py +++ b/addons/base_address_extended/models/base_address_extended.py @@ -5,7 +5,6 @@ import re from odoo import api, fields, models, _ from odoo.exceptions import UserError -from odoo.tools import pycompat STREET_FIELDS = ('street_name', 'street_number', 'street_number2') @@ -135,7 +134,7 @@ class Partner(models.Model): vals[field_name] = street_raw # assign the values to the fields # /!\ Note that a write(vals) would cause a recursion since it would bypass the cache - for k, v in pycompat.items(vals): + for k, v in vals.items(): partner[k] = v diff --git a/addons/base_automation/models/base_automation.py b/addons/base_automation/models/base_automation.py index 061828c161e..9896a9706d8 100644 --- a/addons/base_automation/models/base_automation.py +++ b/addons/base_automation/models/base_automation.py @@ -12,7 +12,6 @@ from dateutil.relativedelta import relativedelta from odoo import api, fields, models, SUPERUSER_ID from odoo.modules.registry import Registry -from odoo.tools import pycompat from odoo.tools.safe_eval import safe_eval _logger = logging.getLogger(__name__) @@ -264,7 +263,7 @@ class BaseAutomation(models.Model): if res: if 'value' in res: res['value'].pop('id', None) - self.update({key: val for key, val in pycompat.items(res['value']) if key in self._fields}) + self.update({key: val for key, val in res['value'].items() if key in self._fields}) if 'domain' in res: result.setdefault('domain', {}).update(res['domain']) if 'warning' in res: diff --git a/addons/base_gengo/wizard/base_gengo_translations.py b/addons/base_gengo/wizard/base_gengo_translations.py index 98df9356576..d6e5ce9176a 100644 --- a/addons/base_gengo/wizard/base_gengo_translations.py +++ b/addons/base_gengo/wizard/base_gengo_translations.py @@ -8,7 +8,6 @@ import uuid from odoo import api, fields, models, tools, _ from odoo.exceptions import UserError, ValidationError -from odoo.tools import pycompat _logger = logging.getLogger(__name__) @@ -194,7 +193,7 @@ class BaseGengoTranslations(models.TransientModel): term_ids.write(vals) jobs = response.get('jobs', []) if jobs: - for t_id, job in pycompat.items(jobs): + for t_id, job in jobs.items(): self._update_terms_job(job) return diff --git a/addons/base_import/models/base_import.py b/addons/base_import/models/base_import.py index 09d2dcb2852..19941858dfa 100644 --- a/addons/base_import/models/base_import.py +++ b/addons/base_import/models/base_import.py @@ -42,7 +42,7 @@ FILE_TYPE_DICT = { } EXTENSIONS = { '.' + ext: handler - for mime, (ext, handler, req) in pycompat.items(FILE_TYPE_DICT) + for mime, (ext, handler, req) in FILE_TYPE_DICT.items() } @@ -114,7 +114,7 @@ class Import(models.TransientModel): }] model_fields = Model.fields_get() blacklist = models.MAGIC_COLUMNS + [Model.CONCURRENCY_CHECK_FIELD] - for name, field in pycompat.items(model_fields): + for name, field in model_fields.items(): if name in blacklist: continue # an empty string means the field is deprecated, @deprecated must @@ -127,7 +127,7 @@ class Import(models.TransientModel): continue # states = {state: [(attr, value), (attr2, value2)], state2:...} if not any(attr == 'readonly' and value is False - for attr, value in itertools.chain.from_iterable(pycompat.values(states))): + for attr, value in itertools.chain.from_iterable(states.values())): continue field_value = { 'id': name, @@ -595,7 +595,7 @@ class Import(models.TransientModel): def _parse_import_data(self, data, import_fields, options): # Get fields of type date/datetime all_fields = self.env[self.res_model].fields_get() - for name, field in pycompat.items(all_fields): + for name, field in all_fields.items(): if field['type'] in ('date', 'datetime') and name in import_fields: # Parse date index = import_fields.index(name) diff --git a/addons/base_import/models/odf_ods_reader.py b/addons/base_import/models/odf_ods_reader.py index c2613c6baa5..daa7d2b16e2 100644 --- a/addons/base_import/models/odf_ods_reader.py +++ b/addons/base_import/models/odf_ods_reader.py @@ -19,8 +19,6 @@ from odf import opendocument from odf.table import Table, TableRow, TableCell from odf.text import P -from odoo.tools import pycompat - class ODSReader(object): @@ -97,4 +95,4 @@ class ODSReader(object): return self.SHEETS[name] def getFirstSheet(self): - return next(iter(pycompat.values(self.SHEETS))) + return next(iter(self.SHEETS.values())) diff --git a/addons/base_import_module/models/ir_module.py b/addons/base_import_module/models/ir_module.py index d6bb62a4d46..5bad5ea53eb 100644 --- a/addons/base_import_module/models/ir_module.py +++ b/addons/base_import_module/models/ir_module.py @@ -9,7 +9,7 @@ from os.path import join as opj from odoo import api, fields, models, _ from odoo.exceptions import UserError from odoo.modules import load_information_from_description_file -from odoo.tools import convert_file, exception_to_unicode, pycompat +from odoo.tools import convert_file, exception_to_unicode from odoo.tools.osutil import tempdir _logger = logging.getLogger(__name__) @@ -119,6 +119,6 @@ class IrModule(models.Model): finally: addons.module.ad_paths.remove(module_dir) r = ["Successfully imported module '%s'" % mod for mod in success] - for mod, error in pycompat.items(errors): + for mod, error in errors.items(): r.append("Error while importing module '%s': %r" % (mod, error)) return '\n'.join(r), module_names diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index 49c87a8e9b9..e80a2727282 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -470,7 +470,7 @@ class Alarm(models.Model): name = fields.Char('Name', required=True) type = fields.Selection([('notification', 'Notification'), ('email', 'Email')], 'Type', required=True, default='email') duration = fields.Integer('Remind Before', required=True, default=1) - interval = fields.Selection(list(pycompat.items(_interval_selection)), 'Unit', required=True, default='hours') + interval = fields.Selection(list(_interval_selection.items()), 'Unit', required=True, default='hours') duration_minutes = fields.Integer('Duration in minutes', compute='_compute_duration_minutes', store=True, help="Duration in minutes") @api.onchange('duration', 'interval') @@ -1292,7 +1292,7 @@ class Meeting(models.Model): @api.multi def _get_message_unread(self): id_map = {x: calendar_id2real_id(x) for x in self.ids} - real = self.browse(set(pycompat.values(id_map))) + real = self.browse(set(id_map.values())) super(Meeting, real)._get_message_unread() for event in self: if event.id == id_map[event.id]: @@ -1304,7 +1304,7 @@ class Meeting(models.Model): @api.multi def _get_message_needaction(self): id_map = {x: calendar_id2real_id(x) for x in self.ids} - real = self.browse(set(pycompat.values(id_map))) + real = self.browse(set(id_map.values())) super(Meeting, real)._get_message_needaction() for event in self: if event.id == id_map[event.id]: diff --git a/addons/event/models/event.py b/addons/event/models/event.py index 95310a67122..c5f7f43915a 100644 --- a/addons/event/models/event.py +++ b/addons/event/models/event.py @@ -5,7 +5,6 @@ import pytz from odoo import _, api, fields, models from odoo.addons.mail.models.mail_template import format_tz from odoo.exceptions import AccessError, UserError, ValidationError -from odoo.tools import pycompat from odoo.tools.translate import html_translate from dateutil.relativedelta import relativedelta @@ -389,7 +388,7 @@ class EventRegistration(models.Model): 'partner_id': partner_id.id, 'event_id': event_id and event_id.id or False, } - data.update({key: value for key, value in pycompat.items(registration) if key in self._fields}) + data.update({key: value for key, value in registration.items() if key in self._fields}) return data @api.one diff --git a/addons/fleet/models/fleet_vehicle_cost.py b/addons/fleet/models/fleet_vehicle_cost.py index 12c6a7d7f2e..827863e3adc 100644 --- a/addons/fleet/models/fleet_vehicle_cost.py +++ b/addons/fleet/models/fleet_vehicle_cost.py @@ -6,8 +6,6 @@ from odoo.exceptions import UserError from dateutil.relativedelta import relativedelta -from odoo.tools import pycompat - class FleetVehicleCost(models.Model): _name = 'fleet.vehicle.cost' @@ -264,7 +262,7 @@ class FleetVehicleLogContract(models.Model): res[contract.vehicle_id.id] = 1 Vehicle = self.env['fleet.vehicle'] - for vehicle, value in pycompat.items(res): + for vehicle, value in res.items(): Vehicle.browse(vehicle).message_post(body=_('%s contract(s) need(s) to be renewed and/or closed!') % value) return contracts.write({'state': 'toclose'}) diff --git a/addons/gamification/models/goal.py b/addons/gamification/models/goal.py index 56c447dd9d4..3c062401662 100644 --- a/addons/gamification/models/goal.py +++ b/addons/gamification/models/goal.py @@ -262,7 +262,7 @@ class Goal(models.Model): for goal in self: goals_by_definition.setdefault(goal.definition_id, []).append(goal) - for definition, goals in pycompat.items(goals_by_definition): + for definition, goals in goals_by_definition.items(): goals_to_write = {} if definition.computation_mode == 'manually': for goal in goals: @@ -307,9 +307,9 @@ class Goal(models.Model): subqueries.setdefault((start_date, end_date), {}).update({goal.id:safe_eval(definition.batch_user_expression, {'user': goal.user_id})}) # the global query should be split by time periods (especially for recurrent goals) - for (start_date, end_date), query_goals in pycompat.items(subqueries): + for (start_date, end_date), query_goals in subqueries.items(): subquery_domain = list(general_domain) - subquery_domain.append((field_name, 'in', list(set(pycompat.values(query_goals))))) + subquery_domain.append((field_name, 'in', list(set(query_goals.values())))) if start_date: subquery_domain.append((field_date_name, '>=', start_date)) if end_date: @@ -353,7 +353,7 @@ class Goal(models.Model): goals_to_write.update(goal._get_write_values(new_value)) - for goal, values in pycompat.items(goals_to_write): + for goal, values in goals_to_write.items(): if not values: continue goal.write(values) diff --git a/addons/google_calendar/models/google_calendar.py b/addons/google_calendar/models/google_calendar.py index 0303dbe5154..ac91835f530 100644 --- a/addons/google_calendar/models/google_calendar.py +++ b/addons/google_calendar/models/google_calendar.py @@ -12,7 +12,7 @@ import pytz from werkzeug import urls from odoo import api, fields, models, tools, _ -from odoo.tools import exception_to_unicode, pycompat +from odoo.tools import exception_to_unicode _logger = logging.getLogger(__name__) @@ -25,15 +25,13 @@ class Meta(type): """ This Meta class allow to define class as a structure, and so instancied variable in __init__ to avoid to have side effect alike 'static' variable """ def __new__(typ, name, parents, attrs): - methods = {k: v for k, v in pycompat.items(attrs) - if callable(v)} - attrs = {k: v for k, v in pycompat.items(attrs) - if not callable(v)} + methods = {k: v for k, v in attrs.items() if callable(v)} + attrs = {k: v for k, v in attrs.items() if not callable(v)} def init(self, **kw): - for key, val in pycompat.items(attrs): + for key, val in attrs.items(): setattr(self, key, val) - for key, val in pycompat.items(kw): + for key, val in kw.items(): assert key in attrs setattr(self, key, val) @@ -161,7 +159,7 @@ class SyncOperation(object): def __init__(self, src, info, **kw): self.src = src self.info = info - for key, val in pycompat.items(kw): + for key, val in kw.items(): setattr(self, key, val) def __str__(self): @@ -689,7 +687,7 @@ class GoogleCalendar(models.AbstractModel): my_google_attendees = CalendarAttendee.with_context(context_novirtual).search([ ('partner_id', '=', my_partner_id), - ('google_internal_event_id', 'in', pycompat.keys(all_event_from_google)) + ('google_internal_event_id', 'in', all_event_from_google.keys()) ]) my_google_att_ids = my_google_attendees.ids @@ -753,7 +751,7 @@ class GoogleCalendar(models.AbstractModel): ev_to_sync.OE.status = event.active ev_to_sync.OE.synchro = att.oe_synchro_date - for event in pycompat.values(all_event_from_google): + for event in all_event_from_google.values(): event_id = event.get('id') base_event_id = event_id.rsplit('_', 1)[0] @@ -788,7 +786,7 @@ class GoogleCalendar(models.AbstractModel): # DO ACTION # ###################### for base_event in event_to_synchronize: - event_to_synchronize[base_event] = sorted(pycompat.items(event_to_synchronize[base_event]), key=operator.itemgetter(0)) + event_to_synchronize[base_event] = sorted(event_to_synchronize[base_event].items(), key=operator.itemgetter(0)) for current_event in event_to_synchronize[base_event]: self.env.cr.commit() event = current_event[1] # event is an Sync Event ! diff --git a/addons/hr/models/hr.py b/addons/hr/models/hr.py index 3e513bb9e5d..d3bb213cb6a 100644 --- a/addons/hr/models/hr.py +++ b/addons/hr/models/hr.py @@ -7,7 +7,6 @@ from odoo import api, fields, models from odoo import tools, _ from odoo.exceptions import ValidationError from odoo.modules.module import get_module_resource -from odoo.tools import pycompat _logger = logging.getLogger(__name__) @@ -250,7 +249,7 @@ class Employee(models.Model): if auto_follow_fields is None: auto_follow_fields = ['user_id'] user_field_lst = [] - for name, field in pycompat.items(self._fields): + for name, field in self._fields.items(): if name in auto_follow_fields and name in updated_fields and field.comodel_name == 'res.users': user_field_lst.append(name) return user_field_lst diff --git a/addons/hr_expense/models/hr_expense.py b/addons/hr_expense/models/hr_expense.py index ce0054a5636..6699dddeb2a 100644 --- a/addons/hr_expense/models/hr_expense.py +++ b/addons/hr_expense/models/hr_expense.py @@ -5,7 +5,7 @@ import re from odoo import api, fields, models, _ from odoo.exceptions import UserError -from odoo.tools import email_split, float_is_zero, pycompat +from odoo.tools import email_split, float_is_zero from odoo.addons import decimal_precision as dp @@ -243,7 +243,7 @@ class HrExpense(models.Model): expense.sheet_id.write({'account_move_id': move.id}) if expense.payment_mode == 'company_account': expense.sheet_id.paid_expense_sheets() - for move in pycompat.values(move_group_by_sheet): + for move in move_group_by_sheet.values(): move.post() return True diff --git a/addons/hr_payroll/models/hr_payslip.py b/addons/hr_payroll/models/hr_payslip.py index fd30b7a1b23..2f310c3456e 100644 --- a/addons/hr_payroll/models/hr_payslip.py +++ b/addons/hr_payroll/models/hr_payslip.py @@ -11,8 +11,6 @@ import babel from odoo import api, fields, models, tools, _ from odoo.addons import decimal_precision as dp from odoo.exceptions import UserError, ValidationError -from odoo.tools import pycompat - class HrPayslip(models.Model): _name = 'hr.payslip' @@ -205,7 +203,7 @@ class HrPayslip(models.Model): } res.append(attendances) - res.extend(pycompat.values(leaves)) + res.extend(leaves.values()) return res @api.model @@ -369,7 +367,7 @@ class HrPayslip(models.Model): #blacklist this rule and its children blacklist += [id for id, seq in rule._recursive_search_of_rules()] - return [value for code, value in pycompat.items(result_dict)] + return list(result_dict.values()) # YTI TODO To rename. This method is not really an onchange, as it is not in any view # employee_id and contract_id could be browse records diff --git a/addons/hr_payroll/report/report_payslip_details.py b/addons/hr_payroll/report/report_payslip_details.py index 23043d2edb9..ffd5b9d913d 100644 --- a/addons/hr_payroll/report/report_payslip_details.py +++ b/addons/hr_payroll/report/report_payslip_details.py @@ -2,8 +2,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import api, models -from odoo.tools import pycompat - class PayslipDetailsReport(models.AbstractModel): _name = 'report.hr_payroll.report_payslipdetails' @@ -38,9 +36,9 @@ class PayslipDetailsReport(models.AbstractModel): result.setdefault(x[2], {}) result[x[2]].setdefault(x[1], []) result[x[2]][x[1]].append(x[0]) - for payslip_id, lines_dict in pycompat.items(result): + for payslip_id, lines_dict in result.items(): res.setdefault(payslip_id, []) - for rule_categ_id, line_ids in pycompat.items(lines_dict): + for rule_categ_id, line_ids in lines_dict.items(): rule_categories = RuleCateg.browse(rule_categ_id) lines = PayslipLine.browse(line_ids) level = 0 @@ -70,9 +68,9 @@ class PayslipDetailsReport(models.AbstractModel): result.setdefault(line.slip_id.id, {}) result[line.slip_id.id].setdefault(line.register_id, line) result[line.slip_id.id][line.register_id] |= line - for payslip_id, lines_dict in pycompat.items(result): + for payslip_id, lines_dict in result.items(): res.setdefault(payslip_id, []) - for register, lines in pycompat.items(lines_dict): + for register, lines in lines_dict.items(): res[payslip_id].append({ 'register_name': register.name, 'total': sum(lines.mapped('total')), diff --git a/addons/hr_recruitment/models/hr_recruitment.py b/addons/hr_recruitment/models/hr_recruitment.py index adec7b15f57..4e4a694e9eb 100644 --- a/addons/hr_recruitment/models/hr_recruitment.py +++ b/addons/hr_recruitment/models/hr_recruitment.py @@ -4,7 +4,6 @@ from datetime import datetime from odoo import api, fields, models, tools, SUPERUSER_ID -from odoo.tools import pycompat from odoo.tools.translate import _ from odoo.exceptions import UserError @@ -251,7 +250,7 @@ class Applicant(models.Model): self = self.with_context(default_department_id=vals.get('department_id')) if vals.get('job_id') or self._context.get('default_job_id'): job_id = vals.get('job_id') or self._context.get('default_job_id') - for key, value in pycompat.items(self._onchange_job_id_internal(job_id)['value']): + for key, value in self._onchange_job_id_internal(job_id)['value'].items(): if key not in vals: vals[key] = value if vals.get('user_id'): diff --git a/addons/im_livechat/models/im_livechat_channel.py b/addons/im_livechat/models/im_livechat_channel.py index a878389913c..c2741fcef92 100644 --- a/addons/im_livechat/models/im_livechat_channel.py +++ b/addons/im_livechat/models/im_livechat_channel.py @@ -6,8 +6,6 @@ import re from datetime import datetime, timedelta from odoo import api, fields, models, modules, tools -from odoo.tools import pycompat - class ImLivechatChannel(models.Model): """ Livechat Channel @@ -96,7 +94,7 @@ class ImLivechatChannel(models.Model): for record in self: dt = fields.Datetime.to_string(datetime.utcnow() - timedelta(days=7)) repartition = record.channel_ids.rating_get_grades([('create_date', '>=', dt)]) - total = sum(pycompat.values(repartition)) + total = sum(repartition.values()) if total > 0: happy = repartition['great'] record.rating_percentage_satisfaction = ((happy*100) / total) if happy > 0 else 0 diff --git a/addons/im_livechat/models/mail_channel.py b/addons/im_livechat/models/mail_channel.py index 32d66a0154c..c64bcd7108c 100644 --- a/addons/im_livechat/models/mail_channel.py +++ b/addons/im_livechat/models/mail_channel.py @@ -2,8 +2,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import api, fields, models, _ -from odoo.tools import pycompat - class ChannelPartner(models.Model): _inherit = 'mail.channel.partner' @@ -78,7 +76,7 @@ class MailChannel(models.Model): last_msg = self.env['mail.message'].search([("channel_ids", "in", [channel.id])], limit=1) if last_msg: channel_infos_dict[channel.id]['last_message_date'] = last_msg.date - return list(pycompat.values(channel_infos_dict)) + return list(channel_infos_dict.values()) @api.model def channel_fetch_slot(self): diff --git a/addons/l10n_in_hr_payroll/report/report_hr_yearly_salary_detail.py b/addons/l10n_in_hr_payroll/report/report_hr_yearly_salary_detail.py index 001a5a782f8..0d26efe9bf5 100644 --- a/addons/l10n_in_hr_payroll/report/report_hr_yearly_salary_detail.py +++ b/addons/l10n_in_hr_payroll/report/report_hr_yearly_salary_detail.py @@ -5,8 +5,6 @@ from datetime import date from odoo import api, models, _ from odoo.exceptions import UserError -from odoo.tools import pycompat - class EmployeesYearlySalaryReport(models.AbstractModel): _name = 'report.l10n_in_hr_payroll.report_hryearlysalary' @@ -99,7 +97,7 @@ class EmployeesYearlySalaryReport(models.AbstractModel): def salary_list(self, salaries): cat_salary_all = [] - for category_name, amount in pycompat.items(salaries): + for category_name, amount in salaries.items(): cat_salary = [] total = 0.0 cat_salary.append(category_name) diff --git a/addons/l10n_lu/scripts/tax2csv.py b/addons/l10n_lu/scripts/tax2csv.py index f4080284064..23fec3c734c 100644 --- a/addons/l10n_lu/scripts/tax2csv.py +++ b/addons/l10n_lu/scripts/tax2csv.py @@ -59,7 +59,7 @@ class LuxTaxGenerator: if tax_code in tax_codes: raise RuntimeError('duplicate tax code %s' % tax_code) tax_codes[tax_code] = row['id'] - writer.writerow([pycompat.to_text(v) for v in pycompat.values(row)]) + writer.writerow([pycompat.to_text(v) for v in row.values()]) # read taxes and add leaf tax codes new_tax_codes = {} # id: parent_code @@ -162,7 +162,7 @@ class LuxTaxGenerator: cur_seq = seq writer.writerow([ pycompat.to_text(v) - for v in list(pycompat.values(row))[3:] + for v in list(row.values())[3:] ] + [cur_seq]) def fiscal_pos_map_to_csv(self): @@ -173,7 +173,7 @@ class LuxTaxGenerator: keys = next(fiscal_pos_map_iterator) writer.writerow(keys) for row in fiscal_pos_map_iterator: - writer.writerow([pycompat.to_text(s) for s in pycompat.values(row)]) + writer.writerow([pycompat.to_text(s) for s in row.values()]) if __name__ == '__main__': diff --git a/addons/link_tracker/models/link_tracker.py b/addons/link_tracker/models/link_tracker.py index da24f66e905..509fc21e153 100644 --- a/addons/link_tracker/models/link_tracker.py +++ b/addons/link_tracker/models/link_tracker.py @@ -12,7 +12,7 @@ from werkzeug import urls, utils from odoo import models, fields, api, _ -from odoo.tools import ustr, pycompat +from odoo.tools import ustr URL_REGEX = r'(\bhref=[\'"](?!mailto:)([^\'"]+)[\'"])' @@ -165,7 +165,7 @@ class link_tracker(models.Model): create_vals['url'] = VALIDATE_URL(vals['url']) search_domain = [] - for fname, value in pycompat.items(create_vals): + for fname, value in create_vals.items(): search_domain.append((fname, '=', value)) result = self.search(search_domain, limit=1) diff --git a/addons/lunch/models/lunch.py b/addons/lunch/models/lunch.py index ee8bba3492e..e9c13060fc3 100644 --- a/addons/lunch/models/lunch.py +++ b/addons/lunch/models/lunch.py @@ -10,8 +10,6 @@ from odoo import api, fields, models, _ from odoo.exceptions import AccessError, ValidationError from odoo.addons import decimal_precision as dp -from odoo.tools import pycompat - class LunchOrder(models.Model): """ @@ -26,10 +24,10 @@ class LunchOrder(models.Model): prev_order = self.env['lunch.order.line'].search([('user_id', '=', self.env.uid), ('product_id.active', '!=', False)], limit=20, order='id desc') # If we return return prev_order.ids, we will have duplicates (identical orders). # Therefore, this following part removes duplicates based on product_id and note. - return list(pycompat.values({ + return list({ (order.product_id, order.note): order.id for order in prev_order - })) + }.values()) user_id = fields.Many2one('res.users', 'User', readonly=True, states={'new': [('readonly', False)]}, @@ -88,10 +86,10 @@ class LunchOrder(models.Model): prev_order = self.env['lunch.order.line'].search([('user_id', '=', self.env.uid), ('product_id.active', '!=', False)], limit=20, order='date desc, id desc') # If we use prev_order.ids, we will have duplicates (identical orders). # Therefore, this following part removes duplicates based on product_id and note. - self.previous_order_ids = list(pycompat.values({ + self.previous_order_ids = list({ (order.product_id, order.note): order.id for order in prev_order - })) + }.values()) if self.previous_order_ids: lunch_data = {} diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py index a2ac768b772..31e03b99081 100644 --- a/addons/mail/models/mail_channel.py +++ b/addons/mail/models/mail_channel.py @@ -9,7 +9,7 @@ import uuid from odoo import _, api, fields, models, modules, tools from odoo.exceptions import UserError from odoo.osv import expression -from odoo.tools import ormcache, pycompat +from odoo.tools import ormcache from odoo.tools.safe_eval import safe_eval @@ -619,7 +619,7 @@ class Channel(models.Model): channel = channels_preview[message['id']] del(channel['message_id']) channel['last_message'] = message - return list(pycompat.values(channels_preview)) + return list(channels_preview.values()) #------------------------------------------------------ # Commands diff --git a/addons/mail/models/mail_followers.py b/addons/mail/models/mail_followers.py index a6bd60f82c9..3edcfa748c3 100644 --- a/addons/mail/models/mail_followers.py +++ b/addons/mail/models/mail_followers.py @@ -2,7 +2,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import api, fields, models -from odoo.tools import pycompat class Followers(models.Model): @@ -42,7 +41,7 @@ class Followers(models.Model): using the subtypes given in the parameters """ res_model_id = self.env['ir.model']._get(res_model).id - force_mode = force or (all(data for data in pycompat.values(partner_data)) and all(data for data in pycompat.values(channel_data))) + force_mode = force or (all(partner_data.values()) and all(channel_data.values())) generic = [] specific = {} existing = {} # {res_id: follower_ids} @@ -71,13 +70,13 @@ class Followers(models.Model): if force_mode: employee_pids = self.env['res.users'].sudo().search([('partner_id', 'in', list(partner_data)), ('share', '=', False)]).mapped('partner_id').ids - for pid, data in pycompat.items(partner_data): + for pid, data in partner_data.items(): if not data: if pid not in employee_pids: partner_data[pid] = external_default_subtypes.ids else: partner_data[pid] = default_subtypes.ids - for cid, data in pycompat.items(channel_data): + for cid, data in channel_data.items(): if not data: channel_data[cid] = default_subtypes.ids diff --git a/addons/mail/models/mail_mail.py b/addons/mail/models/mail_mail.py index e53c24fb176..e723f71bdc6 100644 --- a/addons/mail/models/mail_mail.py +++ b/addons/mail/models/mail_mail.py @@ -13,7 +13,6 @@ from email.utils import formataddr from odoo import _, api, fields, models from odoo import tools from odoo.addons.base.ir.ir_mail_server import MailDeliveryException -from odoo.tools import pycompat from odoo.tools.safe_eval import safe_eval _logger = logging.getLogger(__name__) @@ -205,7 +204,7 @@ class MailMail(models.Model): groups[mail.mail_server_id.id].append(mail.id) sys_params = self.env['ir.config_parameter'].sudo() batch_size = int(sys_params.get_param('mail.session.batch.size', 1000)) - for server_id, record_ids in pycompat.items(groups): + for server_id, record_ids in groups.items(): for mail_batch in tools.split_every(batch_size, record_ids): yield server_id, mail_batch diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py index 2970933e704..3675ca26332 100644 --- a/addons/mail/models/mail_message.py +++ b/addons/mail/models/mail_message.py @@ -9,7 +9,6 @@ from email.utils import formataddr from odoo import _, api, fields, models, modules, SUPERUSER_ID, tools from odoo.exceptions import UserError, AccessError from odoo.osv import expression -from odoo.tools import pycompat _logger = logging.getLogger(__name__) _image_dataurl = re.compile(r'(data:image/[a-z]+?);base64,([a-z0-9+/]{3,}=*)([\'"])', re.I) @@ -282,7 +281,7 @@ class Message(models.Model): partners = self.env['res.partner'].sudo() attachments = self.env['ir.attachment'] trackings = self.env['mail.tracking.value'] - for key, message in pycompat.items(message_tree): + for key, message in message_tree.items(): if message.author_id: partners |= message.author_id if message.subtype_id and message.partner_ids: # take notified people of message with a subtype @@ -446,7 +445,7 @@ class Message(models.Model): def _find_allowed_doc_ids(self, model_ids): IrModelAccess = self.env['ir.model.access'] allowed_ids = set() - for doc_model, doc_dict in pycompat.items(model_ids): + for doc_model, doc_dict in model_ids.items(): if not IrModelAccess.check(doc_model, 'read', False): continue allowed_ids |= self._find_allowed_model_wise(doc_model, doc_dict) @@ -607,17 +606,17 @@ class Message(models.Model): # Author condition (READ, WRITE, CREATE (private)) author_ids = [] if operation == 'read' or operation == 'write': - author_ids = [mid for mid, message in pycompat.items(message_values) + author_ids = [mid for mid, message in message_values.items() if message.get('author_id') and message.get('author_id') == self.env.user.partner_id.id] elif operation == 'create': - author_ids = [mid for mid, message in pycompat.items(message_values) + author_ids = [mid for mid, message in message_values.items() if not message.get('model') and not message.get('res_id')] # Parent condition, for create (check for received notifications for the created message parent) notified_ids = [] if operation == 'create': # TDE: probably clean me - parent_ids = [message.get('parent_id') for mid, message in pycompat.items(message_values) + parent_ids = [message.get('parent_id') for message in message_values.values() if message.get('parent_id')] self._cr.execute("""SELECT DISTINCT m.id, partner_rel.res_partner_id, channel_partner.partner_id FROM "%s" m LEFT JOIN "mail_message_res_partner_rel" partner_rel @@ -630,37 +629,37 @@ class Message(models.Model): ON channel_partner.channel_id = channel.id AND channel_partner.partner_id = (%%s) WHERE m.id = ANY (%%s)""" % self._table, (self.env.user.partner_id.id, self.env.user.partner_id.id, parent_ids,)) not_parent_ids = [mid[0] for mid in self._cr.fetchall() if any([mid[1], mid[2]])] - notified_ids += [mid for mid, message in pycompat.items(message_values) + notified_ids += [mid for mid, message in message_values.items() if message.get('parent_id') in not_parent_ids] # Recipients condition, for read and write (partner_ids) and create (message_follower_ids) other_ids = set(self.ids).difference(set(author_ids), set(notified_ids)) model_record_ids = _generate_model_record_ids(message_values, other_ids) if operation in ['read', 'write']: - notified_ids = [mid for mid, message in pycompat.items(message_values) if message.get('notified')] + notified_ids = [mid for mid, message in message_values.items() if message.get('notified')] elif operation == 'create': - for doc_model, doc_ids in pycompat.items(model_record_ids): + for doc_model, doc_ids in model_record_ids.items(): followers = self.env['mail.followers'].sudo().search([ ('res_model', '=', doc_model), ('res_id', 'in', list(doc_ids)), ('partner_id', '=', self.env.user.partner_id.id), ]) fol_mids = [follower.res_id for follower in followers] - notified_ids += [mid for mid, message in pycompat.items(message_values) + notified_ids += [mid for mid, message in message_values.items() if message.get('model') == doc_model and message.get('res_id') in fol_mids] # CRUD: Access rights related to the document other_ids = other_ids.difference(set(notified_ids)) model_record_ids = _generate_model_record_ids(message_values, other_ids) document_related_ids = [] - for model, doc_ids in pycompat.items(model_record_ids): + for model, doc_ids in model_record_ids.items(): DocumentModel = self.env[model] mids = DocumentModel.browse(doc_ids).exists() if hasattr(DocumentModel, 'check_mail_message_access'): DocumentModel.check_mail_message_access(mids.ids, operation) # ?? mids ? else: self.env['mail.thread'].check_mail_message_access(mids.ids, operation, model_name=model) - document_related_ids += [mid for mid, message in pycompat.items(message_values) + document_related_ids += [mid for mid, message in message_values.items() if message.get('model') == model and message.get('res_id') in mids.ids] # Calculate remaining ids: if not void, raise an error diff --git a/addons/mail/models/mail_template.py b/addons/mail/models/mail_template.py index f3a7acb253b..1bd92aff430 100644 --- a/addons/mail/models/mail_template.py +++ b/addons/mail/models/mail_template.py @@ -379,7 +379,7 @@ class MailTemplate(models.Model): 'user': self.env.user, 'ctx': self._context, # context kw would clash with mako internals } - for res_id, record in pycompat.items(res_to_rec): + for res_id, record in res_to_rec.items(): variables['object'] = record try: render_result = template.render(variables) @@ -391,7 +391,7 @@ class MailTemplate(models.Model): results[res_id] = render_result if post_process: - for res_id, result in pycompat.items(results): + for res_id, result in results.items(): results[res_id] = self.render_post_process(result) return multi_mode and results or results[res_ids[0]] @@ -412,7 +412,7 @@ class MailTemplate(models.Model): self.ensure_one() langs = self.render_template(self.lang, self.model, res_ids) - for res_id, lang in pycompat.items(langs): + for res_id, lang in langs.items(): if lang: template = self.with_context(lang=lang) else: @@ -431,11 +431,11 @@ class MailTemplate(models.Model): if self.use_default_to or self._context.get('tpl_force_default_to'): default_recipients = self.env['mail.thread'].message_get_default_recipients(res_model=self.model, res_ids=res_ids) - for res_id, recipients in pycompat.items(default_recipients): + for res_id, recipients in default_recipients.items(): results[res_id].pop('partner_to', None) results[res_id].update(recipients) - for res_id, values in pycompat.items(results): + for res_id, values in results.items(): partner_ids = values.get('partner_ids', list()) if self._context.get('tpl_partners_only'): mails = tools.email_split(values.pop('email_to', '')) + tools.email_split(values.pop('email_cc', '')) @@ -474,11 +474,11 @@ class MailTemplate(models.Model): # templates: res_id -> template; template -> res_ids templates_to_res_ids = {} - for res_id, template in pycompat.items(res_ids_to_templates): + for res_id, template in res_ids_to_templates.items(): templates_to_res_ids.setdefault(template, []).append(res_id) results = dict() - for template, template_res_ids in pycompat.items(templates_to_res_ids): + for template, template_res_ids in templates_to_res_ids.items(): Template = self.env['mail.template'] # generate fields value for all res_ids linked to the current template if template.lang: @@ -488,7 +488,7 @@ class MailTemplate(models.Model): generated_field_values = Template.render_template( getattr(template, field), template.model, template_res_ids, post_process=(field == 'body_html')) - for res_id, field_value in pycompat.items(generated_field_values): + for res_id, field_value in generated_field_values.items(): results.setdefault(res_id, dict())[field] = field_value # compute recipients if any(field in fields for field in ['email_to', 'partner_to', 'email_cc']): diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 835fd42b5a6..296f79bed14 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -26,7 +26,6 @@ from werkzeug import url_encode from odoo import _, api, exceptions, fields, models, tools from odoo.tools import pycompat -from odoo.tools.pycompat import text_type from odoo.tools.safe_eval import safe_eval @@ -239,7 +238,7 @@ class MailThread(models.AbstractModel): # auto_subscribe: take values and defaults into account create_values = dict(values) - for key, val in pycompat.items(self._context): + for key, val in self._context.items(): if key.startswith('default_') and key[8:] not in create_values: create_values[key[8:]] = val thread.message_auto_subscribe(list(create_values), values=create_values) @@ -389,7 +388,7 @@ class MailThread(models.AbstractModel): always tracked fields and modified on_change fields """ tracked_fields = [] - for name, field in pycompat.items(self._fields): + for name, field in self._fields.items(): if getattr(field, 'track_visibility', False): tracked_fields.append(name) @@ -417,10 +416,10 @@ class MailThread(models.AbstractModel): @api.multi def _message_track_post_template(self, tracking): - if not any(change for rec_id, (change, tracking_value_ids) in pycompat.items(tracking)): + if not any(change for rec_id, (change, tracking_value_ids) in tracking.items()): return True templates = self._track_template(tracking) - for field_name, (template, post_kwargs) in pycompat.items(templates): + for field_name, (template, post_kwargs) in templates.items(): if not template: continue if isinstance(template, pycompat.string_types): @@ -451,7 +450,7 @@ class MailThread(models.AbstractModel): display_values_ids = [] # generate tracked_values data structure: {'col_name': {col_info, new_value, old_value}} - for col_name, col_info in pycompat.items(tracked_fields): + for col_name, col_info in tracked_fields.items(): track_visibility = getattr(self._fields[col_name], 'track_visibility', 'onchange') initial_value = initial[col_name] new_value = getattr(self, col_name) @@ -817,7 +816,7 @@ class MailThread(models.AbstractModel): def message_capable_models(self): """ Used by the plugin addon, based for plugin_outlook and others. """ ret_dict = {} - for model_name, model in pycompat.items(self.env): + for model_name, model in self.env.items(): if hasattr(model, "message_process") and hasattr(model, "message_post"): ret_dict[model_name] = model._description return ret_dict @@ -2057,7 +2056,7 @@ class MailThread(models.AbstractModel): if auto_follow_fields is None: auto_follow_fields = ['user_id'] user_field_lst = [] - for name, field in pycompat.items(self._fields): + for name, field in self._fields.items(): if name in auto_follow_fields and name in updated_fields and getattr(field, 'track_visibility', False) and field.comodel_name == 'res.users': user_field_lst.append(name) return user_field_lst @@ -2153,10 +2152,10 @@ class MailThread(models.AbstractModel): for partner in to_add_users.mapped('partner_id'): new_partners.setdefault(partner.id, None) - for pid, subtypes in pycompat.items(new_partners): + for pid, subtypes in new_partners.items(): subtypes = list(subtypes) if subtypes is not None else None self.message_subscribe(partner_ids=[pid], subtype_ids=subtypes, force=(subtypes != None)) - for cid, subtypes in pycompat.items(new_channels): + for cid, subtypes in new_channels.items(): subtypes = list(subtypes) if subtypes is not None else None self.message_subscribe(channel_ids=[cid], subtype_ids=subtypes, force=(subtypes != None)) diff --git a/addons/mail/models/res_partner.py b/addons/mail/models/res_partner.py index 6379ddb8c42..9140959f89e 100644 --- a/addons/mail/models/res_partner.py +++ b/addons/mail/models/res_partner.py @@ -4,7 +4,6 @@ import logging import threading -from odoo.tools import pycompat from odoo.tools.misc import split_every from odoo import _, api, fields, models, registry, SUPERUSER_ID @@ -175,7 +174,7 @@ class Partner(models.Model): emails = self.env['mail.mail'] recipients_nbr, recipients_max = 0, 50 - for email_type, recipient_template_values in pycompat.items(recipients): + for email_type, recipient_template_values in recipients.items(): if recipient_template_values['followers']: # generate notification email content template_fol_values = dict(base_template_ctx, **recipient_template_values) # fixme: set button_unfollow to none diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 76412ce041c..767462df892 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -140,7 +140,7 @@ class MailComposer(models.TransientModel): for mid, rmod, rid in self._cr.fetchall(): message_values[mid] = {'model': rmod, 'res_id': rid} # remove from the set to check the ids that mail_compose_message accepts - author_ids = [mid for mid, message in pycompat.items(message_values) + author_ids = [mid for mid, message in message_values.items() if message.get('model') and not message.get('res_id')] self = self.browse(list(set(self.ids) - set(author_ids))) # not sure slef = ... @@ -248,7 +248,7 @@ class MailComposer(models.TransientModel): for res_ids in sliced_res_ids: batch_mails = Mail all_mail_values = wizard.get_mail_values(res_ids) - for res_id, mail_values in pycompat.items(all_mail_values): + for res_id, mail_values in all_mail_values.items(): if wizard.composition_mode == 'mass_mail': batch_mails |= Mail.create(mail_values) else: @@ -338,7 +338,7 @@ class MailComposer(models.TransientModel): def onchange_template_id_wrapper(self): self.ensure_one() values = self.onchange_template_id(self.template_id.id, self.composition_mode, self.model, self.res_id)['value'] - for fname, value in pycompat.items(values): + for fname, value in values.items(): setattr(self, fname, value) @api.multi diff --git a/addons/marketing_campaign/models/marketing_campaign.py b/addons/marketing_campaign/models/marketing_campaign.py index 7370633114e..6fea98870d8 100644 --- a/addons/marketing_campaign/models/marketing_campaign.py +++ b/addons/marketing_campaign/models/marketing_campaign.py @@ -9,7 +9,6 @@ import re from odoo import api, fields, models, _ from odoo.exceptions import UserError, ValidationError -from odoo.tools import pycompat from odoo.tools.safe_eval import safe_eval from odoo.addons import decimal_precision as dp @@ -466,7 +465,7 @@ class MarketingCampaignWorkitem(models.Model): matching_workitems = [] for id, res_id, model in res: workitem_map.setdefault(model, {}).setdefault(res_id, set()).add(id) - for model, id_map in pycompat.items(workitem_map): + for model, id_map in workitem_map.items(): Model = self.env[model] condition_name[0] = Model._rec_name condition = [('id', 'in', list(id_map)), condition_name] diff --git a/addons/mrp/models/mrp_workcenter.py b/addons/mrp/models/mrp_workcenter.py index 58226b2e9e8..cc12ec0060b 100644 --- a/addons/mrp/models/mrp_workcenter.py +++ b/addons/mrp/models/mrp_workcenter.py @@ -5,7 +5,6 @@ from dateutil import relativedelta import datetime from odoo import api, exceptions, fields, models, _ -from odoo.tools import pycompat class MrpWorkcenter(models.Model): @@ -74,7 +73,7 @@ class MrpWorkcenter(models.Model): if res_group['state'] in ('pending', 'ready', 'progress'): result_duration_expected[res_group['workcenter_id'][0]] += res_group['duration_expected'] for workcenter in self: - workcenter.workorder_count = sum(count for state, count in pycompat.items(result[workcenter.id]) if state not in ('done', 'cancel')) + workcenter.workorder_count = sum(count for state, count in result[workcenter.id].items() if state not in ('done', 'cancel')) workcenter.workorder_pending_count = result[workcenter.id].get('pending', 0) workcenter.workcenter_load = result_duration_expected[workcenter.id] workcenter.workorder_ready_count = result[workcenter.id].get('ready', 0) diff --git a/addons/mrp_repair/wizard/mrp_repair_make_invoice.py b/addons/mrp_repair/wizard/mrp_repair_make_invoice.py index a659e45e962..03e89da5cd5 100644 --- a/addons/mrp_repair/wizard/mrp_repair_make_invoice.py +++ b/addons/mrp_repair/wizard/mrp_repair_make_invoice.py @@ -2,7 +2,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import api, fields, models -from odoo.tools import pycompat class MakeInvoice(models.TransientModel): @@ -25,7 +24,7 @@ class MakeInvoice(models.TransientModel): # but that second call will not do anything, since the repairs are already invoiced. repairs.action_repair_invoice_create() return { - 'domain': [('id', 'in', list(pycompat.values(new_invoice)))], + 'domain': [('id', 'in', list(new_invoice.values()))], 'name': 'Invoices', 'view_type': 'form', 'view_mode': 'tree,form', diff --git a/addons/pad/models/pad.py b/addons/pad/models/pad.py index 945e24f4308..d0c2055c739 100644 --- a/addons/pad/models/pad.py +++ b/addons/pad/models/pad.py @@ -10,7 +10,7 @@ import requests from odoo import api, models, _ from odoo.exceptions import UserError -from odoo.tools import html2plaintext, pycompat +from odoo.tools import html2plaintext from ..py_etherpad import EtherpadLiteClient @@ -106,7 +106,7 @@ class PadCommon(models.AbstractModel): # In case the pad is created programmatically, the content is not filled in yet since it is # normally initialized by the JS layer - for k, field in pycompat.items(self._fields): + for k, field in self._fields.items(): if hasattr(field, 'pad_content_field') and k not in vals: ctx = { 'model': self._name, @@ -121,7 +121,7 @@ class PadCommon(models.AbstractModel): def _set_pad_value(self, vals): # Update the pad if the `pad_content_field` is modified - for k, field in pycompat.items(self._fields): + for k, field in self._fields.items(): if hasattr(field, 'pad_content_field') and vals.get(field.pad_content_field) and self[k]: company = self.env.user.sudo().company_id myPad = EtherpadLiteClient(company.pad_key, company.pad_server + '/api') @@ -129,7 +129,7 @@ class PadCommon(models.AbstractModel): myPad.setText(path, (html2plaintext(vals[field.pad_content_field]).encode('utf-8'))) # Update the `pad_content_field` if the pad is modified - for k, v in list(pycompat.items(vals)): + for k, v in vals.items(): field = self._fields[k] if hasattr(field, 'pad_content_field'): vals[field.pad_content_field] = self.pad_get_content(v) @@ -139,7 +139,7 @@ class PadCommon(models.AbstractModel): self.ensure_one() if not default: default = {} - for k, field in pycompat.items(self._fields): + for k, field in self._fields.items(): if hasattr(field, 'pad_content_field'): pad = self.pad_generate_url() default[k] = pad.get('url') diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py index 909536ac95c..2e36d891344 100644 --- a/addons/payment/models/payment_acquirer.py +++ b/addons/payment/models/payment_acquirer.py @@ -5,7 +5,7 @@ import logging import datetime from odoo import api, exceptions, fields, models, _ -from odoo.tools import consteq, float_round, image_resize_images, ustr, pycompat +from odoo.tools import consteq, float_round, image_resize_images, ustr from odoo.addons.base.module import module from odoo.exceptions import ValidationError @@ -169,7 +169,7 @@ class PaymentAcquirer(models.Model): """ If the field has 'required_if_provider="<provider>"' attribute, then it required if record.provider is <provider>. """ for acquirer in self: - if any(getattr(f, 'required_if_provider', None) == acquirer.provider and not acquirer[k] for k, f in pycompat.items(self._fields)): + if any(getattr(f, 'required_if_provider', None) == acquirer.provider and not acquirer[k] for k, f in self._fields.items()): return False return True diff --git a/addons/payment_adyen/models/payment.py b/addons/payment_adyen/models/payment.py index 787160fd1ea..dbc24ced0c0 100644 --- a/addons/payment_adyen/models/payment.py +++ b/addons/payment_adyen/models/payment.py @@ -15,8 +15,6 @@ from odoo import api, fields, models, tools, _ from odoo.addons.payment.models.payment_acquirer import ValidationError from odoo.addons.payment_adyen.controllers.main import AdyenController -from odoo.tools import pycompat - _logger = logging.getLogger(__name__) @@ -52,7 +50,7 @@ class AcquirerAdyen(models.Model): def signParams(parms): signing_string = ':'.join( escapeVal(v) - for v in chain(pycompat.keys(parms), pycompat.values(parms)) + for v in chain(parms.keys(), parms.values()) ) hm = hmac.new(hmac_key, signing_string.encode('utf-8'), hashlib.sha256) return base64.b64encode(hm.digest()) @@ -81,7 +79,7 @@ class AcquirerAdyen(models.Model): hmac_key = binascii.a2b_hex(self.adyen_skin_hmac_key.encode('ascii')) raw_values = {k: values.get(k.encode('ascii'), '') for k in keys if k in values} - raw_values_ordered = OrderedDict(sorted(pycompat.items(raw_values), key=lambda t: t[0])) + raw_values_ordered = OrderedDict(sorted(raw_values.items(), key=lambda t: t[0])) return signParams(raw_values_ordered) diff --git a/addons/payment_authorize/tests/test_authorize.py b/addons/payment_authorize/tests/test_authorize.py index 6d3f4244583..59fb401b091 100644 --- a/addons/payment_authorize/tests/test_authorize.py +++ b/addons/payment_authorize/tests/test_authorize.py @@ -11,7 +11,7 @@ import odoo from odoo.addons.payment.models.payment_acquirer import ValidationError from odoo.addons.payment.tests.common import PaymentAcquirerCommon from odoo.addons.payment_authorize.controllers.main import AuthorizeController -from odoo.tools import mute_logger, pycompat +from odoo.tools import mute_logger @odoo.tests.common.at_install(True) @@ -91,7 +91,7 @@ class AuthorizeForm(AuthorizeCommon): tree = objectify.fromstring(res) self.assertEqual(tree.get('action'), 'https://test.authorize.net/gateway/transact.dll', 'Authorize: wrong form POST url') for el in tree.iterfind('input'): - values = list(pycompat.values(el.attrib)) + values = list(el.attrib.values()) if values[1] in ['submit', 'x_fp_hash', 'return_url', 'x_state', 'x_ship_to_state']: continue self.assertEqual( diff --git a/addons/payment_buckaroo/controllers/main.py b/addons/payment_buckaroo/controllers/main.py index 5af6a454b47..40e4ae539e4 100644 --- a/addons/payment_buckaroo/controllers/main.py +++ b/addons/payment_buckaroo/controllers/main.py @@ -6,7 +6,6 @@ import werkzeug from odoo import http from odoo.http import request -from odoo.tools import pycompat _logger = logging.getLogger(__name__) @@ -27,6 +26,6 @@ class BuckarooController(http.Controller): """ Buckaroo.""" _logger.info('Buckaroo: entering form_feedback with post data %s', pprint.pformat(post)) # debug request.env['payment.transaction'].sudo().form_feedback(post, 'buckaroo') - post = {key.upper(): value for key, value in pycompat.items(post)} + post = {key.upper(): value for key, value in post.items()} return_url = post.get('ADD_RETURNDATA') or '/' return werkzeug.utils.redirect(return_url) diff --git a/addons/payment_buckaroo/models/payment.py b/addons/payment_buckaroo/models/payment.py index a07ca83318d..ec0cadfab01 100644 --- a/addons/payment_buckaroo/models/payment.py +++ b/addons/payment_buckaroo/models/payment.py @@ -8,7 +8,6 @@ from odoo import api, fields, models, _ from odoo.addons.payment.models.payment_acquirer import ValidationError from odoo.addons.payment_buckaroo.controllers.main import BuckarooController -from odoo.tools import pycompat from odoo.tools.float_utils import float_compare _logger = logging.getLogger(__name__) @@ -21,7 +20,7 @@ def normalize_keys_upper(data): convert everything to upper case to be able to easily detected the presence of a parameter by checking the uppercase key only """ - return {key.upper(): val for key, val in pycompat.items(data)} + return {key.upper(): val for key, val in data.items()} class AcquirerBuckaroo(models.Model): @@ -73,7 +72,7 @@ class AcquirerBuckaroo(models.Model): del values[key] break - items = sorted(pycompat.items(values), key=lambda pair: pair[0].lower()) + items = sorted(values.items(), key=lambda pair: pair[0].lower()) sign = ''.join('%s=%s' % (k, urls.url_unquote_plus(v)) for k, v in items) else: sign = ''.join('%s=%s' % (k, get_value(k)) for k in keys) diff --git a/addons/payment_ogone/models/payment.py b/addons/payment_ogone/models/payment.py index a5ae46bdcd3..7a2adf37d45 100644 --- a/addons/payment_ogone/models/payment.py +++ b/addons/payment_ogone/models/payment.py @@ -15,7 +15,7 @@ from odoo import api, fields, models, _ from odoo.addons.payment.models.payment_acquirer import ValidationError from odoo.addons.payment_ogone.controllers.main import OgoneController from odoo.addons.payment_ogone.data import ogone -from odoo.tools import float_round, DEFAULT_SERVER_DATE_FORMAT, pycompat +from odoo.tools import float_round, DEFAULT_SERVER_DATE_FORMAT from odoo.tools.float_utils import float_compare, float_repr from odoo.tools.safe_eval import safe_eval @@ -142,7 +142,7 @@ class PaymentAcquirerOgone(models.Model): ] return key.upper() in keys - items = sorted((k.upper(), v) for k, v in pycompat.items(values)) + items = sorted((k.upper(), v) for k, v in values.items()) sign = ''.join('%s=%s%s' % (k, v, key) for k, v in items if v and filter_key(k)) sign = sign.encode("utf-8") shasign = sha1(sign).hexdigest() diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py index 5e059a41cfc..9e730f9a2e5 100644 --- a/addons/point_of_sale/models/pos_order.py +++ b/addons/point_of_sale/models/pos_order.py @@ -8,7 +8,7 @@ import psycopg2 import pytz from odoo import api, fields, models, tools, _ -from odoo.tools import float_is_zero, pycompat +from odoo.tools import float_is_zero from odoo.exceptions import UserError from odoo.http import request from odoo.addons import decimal_precision as dp @@ -333,7 +333,7 @@ class PosOrder(models.Model): # round tax lines per order if rounding_method == 'round_globally': - for group_key, group_value in pycompat.items(grouped_data): + for group_key, group_value in grouped_data.items(): if group_key[0] == 'tax': for line in group_value: line['credit'] = cur.round(line['credit']) @@ -351,7 +351,7 @@ class PosOrder(models.Model): order.write({'state': 'done', 'account_move': move.id}) all_lines = [] - for group_key, group_data in pycompat.items(grouped_data): + for group_key, group_data in grouped_data.items(): for value in group_data: all_lines.append((0, 0, value),) if move: # In case no order was changed @@ -1032,7 +1032,7 @@ class ReportSaleDetails(models.AbstractModel): 'total_paid': user_currency.round(total), 'payments': payments, 'company_name': self.env.user.company_id.name, - 'taxes': list(pycompat.values(taxes)), + 'taxes': list(taxes.values()), 'products': sorted([{ 'product_id': product.id, 'product_name': product.name, @@ -1041,7 +1041,7 @@ class ReportSaleDetails(models.AbstractModel): 'price_unit': price_unit, 'discount': discount, 'uom': product.uom_id.name - } for (product, price_unit, discount), qty in pycompat.items(products_sold)], key=lambda l: l['product_name']) + } for (product, price_unit, discount), qty in products_sold.items()], key=lambda l: l['product_name']) } @api.multi diff --git a/addons/product/models/product_pricelist.py b/addons/product/models/product_pricelist.py index a0457f021ba..392447809f4 100644 --- a/addons/product/models/product_pricelist.py +++ b/addons/product/models/product_pricelist.py @@ -90,7 +90,7 @@ class Pricelist(models.Model): results = {} for pricelist in pricelists: subres = pricelist._compute_price_rule(products_qty_partner, date=date, uom_id=uom_id) - for product_id, price in pycompat.items(subres): + for product_id, price in subres.items(): results.setdefault(product_id, {}) results[product_id][pricelist.id] = price return results @@ -254,11 +254,11 @@ class Pricelist(models.Model): self.ensure_one() return { product_id: res_tuple[0] - for product_id, res_tuple in pycompat.items(self._compute_price_rule( + for product_id, res_tuple in self._compute_price_rule( list(pycompat.izip(products, quantities, partners)), date=date, uom_id=uom_id - )) + ).items() } def get_product_price(self, product, quantity, partner, date=False, uom_id=False): @@ -280,7 +280,7 @@ class Pricelist(models.Model): @api.multi def price_get(self, prod_id, qty, partner=None): """ Multi pricelist, mono product - returns price per pricelist """ - return {key: price[0] for key, price in pycompat.items(self.price_rule_get(prod_id, qty, partner=partner))} + return {key: price[0] for key, price in self.price_rule_get(prod_id, qty, partner=partner).items()} @api.multi def price_rule_get_multi(self, products_by_qty_by_partner): diff --git a/addons/product_expiry/models/production_lot.py b/addons/product_expiry/models/production_lot.py index 89d2a7569ff..6be9a2865dd 100644 --- a/addons/product_expiry/models/production_lot.py +++ b/addons/product_expiry/models/production_lot.py @@ -2,7 +2,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. import datetime from odoo import api, fields, models -from odoo.tools import pycompat class StockProductionLot(models.Model): @@ -54,5 +53,5 @@ class StockProductionLot(models.Model): @api.onchange('product_id') def _onchange_product(self): dates_dict = self._get_dates() - for field, value in pycompat.items(dates_dict): + for field, value in dates_dict.items(): setattr(self, field, value) diff --git a/addons/product_margin/models/product_product.py b/addons/product_margin/models/product_product.py index f203a9e146b..3dd735b26a4 100644 --- a/addons/product_margin/models/product_product.py +++ b/addons/product_margin/models/product_product.py @@ -4,7 +4,6 @@ import time from odoo import api, fields, models -from odoo.tools import pycompat class ProductProduct(models.Model): @@ -139,6 +138,6 @@ class ProductProduct(models.Model): res[val.id]['expected_margin'] = res[val.id]['sale_expected'] - res[val.id]['normal_cost'] res[val.id]['total_margin_rate'] = res[val.id]['turnover'] and res[val.id]['total_margin'] * 100 / res[val.id]['turnover'] or 0.0 res[val.id]['expected_margin_rate'] = res[val.id]['sale_expected'] and res[val.id]['expected_margin'] * 100 / res[val.id]['sale_expected'] or 0.0 - for k, v in pycompat.items(res[val.id]): + for k, v in res[val.id].items(): setattr(val, k, v) return res diff --git a/addons/rating/models/rating.py b/addons/rating/models/rating.py index a5b54afb3ac..f4bd17b48f3 100644 --- a/addons/rating/models/rating.py +++ b/addons/rating/models/rating.py @@ -6,7 +6,6 @@ import uuid from odoo import api, fields, models, tools, _ from odoo.modules.module import get_resource_path -from odoo.tools import pycompat RATING_LIMIT_SATISFIED = 7 RATING_LIMIT_OK = 3 @@ -275,7 +274,7 @@ class RatingMixin(models.AbstractModel): values.update((d['rating'], d['rating_count']) for d in data) # add other stats if add_stats: - rating_number = sum(pycompat.values(values)) + rating_number = sum(values.values()) result = { 'repartition': values, 'avg': sum(float(key * values[key]) for key in values) / rating_number if rating_number > 0 else 0, diff --git a/addons/rating_project/models/project.py b/addons/rating_project/models/project.py index 915c97848ec..8a4f86d3b96 100644 --- a/addons/rating_project/models/project.py +++ b/addons/rating_project/models/project.py @@ -3,7 +3,6 @@ from datetime import timedelta -from odoo.tools import pycompat from odoo import api, fields, models, _ from odoo.tools.safe_eval import safe_eval @@ -80,13 +79,13 @@ class Project(models.Model): domain = [('create_date', '>=', fields.Datetime.to_string(fields.datetime.now() - timedelta(days=30)))] for project in self: activity = project.tasks.rating_get_grades(domain) - project.percentage_satisfaction_project = activity['great'] * 100 / sum(pycompat.values(activity)) if sum(pycompat.values(activity)) else -1 + project.percentage_satisfaction_project = activity['great'] * 100 / sum(activity.values()) if sum(activity.values()) else -1 @api.one @api.depends('tasks.rating_ids.rating') def _compute_percentage_satisfaction_task(self): activity = self.tasks.rating_get_grades() - self.percentage_satisfaction_task = activity['great'] * 100 / sum(pycompat.values(activity)) if sum(pycompat.values(activity)) else -1 + self.percentage_satisfaction_task = activity['great'] * 100 / sum(activity.values()) if sum(activity.values()) else -1 percentage_satisfaction_task = fields.Integer( compute='_compute_percentage_satisfaction_task', string="Happy % on Task", store=True, default=-1) diff --git a/addons/rating_project_issue/models/project_issue.py b/addons/rating_project_issue/models/project_issue.py index 8116c0f50f1..cd3d541d1ef 100644 --- a/addons/rating_project_issue/models/project_issue.py +++ b/addons/rating_project_issue/models/project_issue.py @@ -4,7 +4,6 @@ from datetime import timedelta from odoo import api, fields, models -from odoo.tools import pycompat from odoo.tools.safe_eval import safe_eval @@ -63,11 +62,11 @@ class Project(models.Model): if project.use_tasks: activity_task = project.tasks.rating_get_grades(domain) activity_great = activity_task['great'] - activity_sum = sum(pycompat.values(activity_task)) + activity_sum = sum(activity_task.values()) if project.use_issues: activity_issue = self.env['project.issue'].search([('project_id', '=', project.id)]).rating_get_grades(domain) activity_great += activity_issue['great'] - activity_sum += sum(pycompat.values(activity_issue)) + activity_sum += sum(activity_issue.values()) project.percentage_satisfaction_project = activity_great * 100 / activity_sum if activity_sum else -1 @api.one @@ -75,7 +74,7 @@ class Project(models.Model): def _compute_percentage_satisfaction_issue(self): project_issue = self.env['project.issue'].search([('project_id', '=', self.id)]) activity = project_issue.rating_get_grades() - self.percentage_satisfaction_issue = activity['great'] * 100 / sum(pycompat.values(activity)) if sum(pycompat.values(activity)) else -1 + self.percentage_satisfaction_issue = activity['great'] * 100 / sum(activity.values()) if sum(activity.values()) else -1 percentage_satisfaction_issue = fields.Integer(compute='_compute_percentage_satisfaction_issue', string="Happy % on Issue", store=True, default=-1) diff --git a/addons/sale/models/account_invoice.py b/addons/sale/models/account_invoice.py index 5163f4baa6c..c4ad56d1277 100644 --- a/addons/sale/models/account_invoice.py +++ b/addons/sale/models/account_invoice.py @@ -3,7 +3,6 @@ from itertools import groupby from odoo import api, fields, models, _ -from odoo.tools import pycompat class AccountInvoice(models.Model): @@ -58,7 +57,7 @@ class AccountInvoice(models.Model): result = super(AccountInvoice, self)._refund_cleanup_lines(lines) if self.env.context.get('mode') == 'modify': for i, line in enumerate(lines): - for name, field in pycompat.items(line._fields): + for name, field in line._fields.items(): if name == 'sale_line_ids': result[i][2][name] = [(6, 0, line[name].ids)] line[name] = False diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index 7e554c6af08..8fe5623e339 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -8,7 +8,7 @@ from datetime import datetime, timedelta from odoo import api, fields, models, _ from odoo.exceptions import UserError -from odoo.tools import float_is_zero, float_compare, DEFAULT_SERVER_DATETIME_FORMAT, pycompat +from odoo.tools import float_is_zero, float_compare, DEFAULT_SERVER_DATETIME_FORMAT from odoo.tools.misc import formatLang from odoo.addons import decimal_precision as dp @@ -400,7 +400,7 @@ class SaleOrder(models.Model): if not invoices: raise UserError(_('There is no invoicable line.')) - for invoice in pycompat.values(invoices): + for invoice in invoices.values(): if not invoice.invoice_line_ids: raise UserError(_('There is no invoicable line.')) # If invoice is negative, do a refund invoice instead @@ -417,7 +417,7 @@ class SaleOrder(models.Model): invoice.message_post_with_view('mail.message_origin_link', values={'self': invoice, 'origin': references[invoice]}, subtype_id=self.env.ref('mail.mt_note').id) - return [inv.id for inv in pycompat.values(invoices)] + return [inv.id for inv in invoices.values()] @api.multi def action_draft(self): @@ -557,7 +557,7 @@ class SaleOrder(models.Model): if tax.include_base_amount: base_tax += tax.compute_all(price_reduce + base_tax, quantity=1, product=line.product_id, partner=self.partner_shipping_id)['taxes'][0]['amount'] - res = sorted(pycompat.items(res), key=lambda l: l[0].sequence) + res = sorted(res.items(), key=lambda l: l[0].sequence) res = [(l[0].name, l[1]) for l in res] return res diff --git a/addons/sale/models/sale_analytic.py b/addons/sale/models/sale_analytic.py index 733bd74bc2a..96f2f896f44 100644 --- a/addons/sale/models/sale_analytic.py +++ b/addons/sale/models/sale_analytic.py @@ -3,7 +3,6 @@ from odoo import api, fields, models, _ from odoo.exceptions import UserError -from odoo.tools import pycompat class SaleOrderLine(models.Model): @@ -41,7 +40,7 @@ class SaleOrderLine(models.Model): qty = d['unit_amount'] lines[line] += qty - for line, qty in pycompat.items(lines): + for line, qty in lines.items(): line.qty_delivered = qty return True diff --git a/addons/sale/tests/test_sale_order.py b/addons/sale/tests/test_sale_order.py index 84dbee6a3fd..2b6c082b150 100644 --- a/addons/sale/tests/test_sale_order.py +++ b/addons/sale/tests/test_sale_order.py @@ -2,7 +2,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo.exceptions import UserError, AccessError -from odoo.tools import pycompat from .test_sale_common import TestSale @@ -18,10 +17,10 @@ class TestSaleOrder(TestSale): 'partner_id': self.partner.id, 'partner_invoice_id': self.partner.id, 'partner_shipping_id': self.partner.id, - 'order_line': [(0, 0, {'name': p.name, 'product_id': p.id, 'product_uom_qty': 2, 'product_uom': p.uom_id.id, 'price_unit': p.list_price}) for (_, p) in pycompat.items(self.products)], + 'order_line': [(0, 0, {'name': p.name, 'product_id': p.id, 'product_uom_qty': 2, 'product_uom': p.uom_id.id, 'price_unit': p.list_price}) for p in self.products.values()], 'pricelist_id': self.env.ref('product.list0').id, }) - self.assertEqual(so.amount_total, sum([2 * p.list_price for (k, p) in pycompat.items(self.products)]), 'Sale: total amount is wrong') + self.assertEqual(so.amount_total, sum([2 * p.list_price for p in self.products.values()]), 'Sale: total amount is wrong') # send quotation so.force_quotation_send() @@ -36,7 +35,7 @@ class TestSaleOrder(TestSale): inv_id = so.action_invoice_create() inv = inv_obj.browse(inv_id) self.assertEqual(len(inv.invoice_line_ids), 2, 'Sale: invoice is missing lines') - self.assertEqual(inv.amount_total, sum([2 * p.list_price if p.invoice_policy == 'order' else 0 for (k, p) in pycompat.items(self.products)]), 'Sale: invoice total amount is wrong') + self.assertEqual(inv.amount_total, sum([2 * p.list_price if p.invoice_policy == 'order' else 0 for p in self.products.values()]), 'Sale: invoice total amount is wrong') self.assertTrue(so.invoice_status == 'no', 'Sale: SO status after invoicing should be "nothing to invoice"') self.assertTrue(len(so.invoice_ids) == 1, 'Sale: invoice is missing') @@ -47,7 +46,7 @@ class TestSaleOrder(TestSale): inv_id = so.action_invoice_create() inv = inv_obj.browse(inv_id) self.assertEqual(len(inv.invoice_line_ids), 2, 'Sale: second invoice is missing lines') - self.assertEqual(inv.amount_total, sum([2 * p.list_price if p.invoice_policy == 'delivery' else 0 for (k, p) in pycompat.items(self.products)]), 'Sale: second invoice total amount is wrong') + self.assertEqual(inv.amount_total, sum([2 * p.list_price if p.invoice_policy == 'delivery' else 0 for p in self.products.values()]), 'Sale: second invoice total amount is wrong') self.assertTrue(so.invoice_status == 'invoiced', 'Sale: SO status after invoicing everything should be "invoiced"') self.assertTrue(len(so.invoice_ids) == 2, 'Sale: invoice is missing') # go over the sold quantity @@ -72,7 +71,7 @@ class TestSaleOrder(TestSale): 'partner_id': self.partner.id, 'partner_invoice_id': self.partner.id, 'partner_shipping_id': self.partner.id, - 'order_line': [(0, 0, {'name': p.name, 'product_id': p.id, 'product_uom_qty': 2, 'product_uom': p.uom_id.id, 'price_unit': p.list_price}) for (_, p) in pycompat.items(self.products)], + 'order_line': [(0, 0, {'name': p.name, 'product_id': p.id, 'product_uom_qty': 2, 'product_uom': p.uom_id.id, 'price_unit': p.list_price}) for p in self.products.values()], 'pricelist_id': self.env.ref('product.list0').id, }) diff --git a/addons/sale_stock/tests/test_sale_stock.py b/addons/sale_stock/tests/test_sale_stock.py index 5a4755d2c16..3dd6d5103ca 100644 --- a/addons/sale_stock/tests/test_sale_stock.py +++ b/addons/sale_stock/tests/test_sale_stock.py @@ -3,7 +3,6 @@ from odoo.addons.sale.tests.test_sale_common import TestSale from odoo.exceptions import UserError -from odoo.tools import pycompat class TestSaleStock(TestSale): @@ -17,7 +16,7 @@ class TestSaleStock(TestSale): 'partner_id': self.partner.id, 'partner_invoice_id': self.partner.id, 'partner_shipping_id': self.partner.id, - 'order_line': [(0, 0, {'name': p.name, 'product_id': p.id, 'product_uom_qty': 2, 'product_uom': p.uom_id.id, 'price_unit': p.list_price}) for (_, p) in pycompat.items(self.products)], + 'order_line': [(0, 0, {'name': p.name, 'product_id': p.id, 'product_uom_qty': 2, 'product_uom': p.uom_id.id, 'price_unit': p.list_price}) for p in self.products.values()], 'pricelist_id': self.env.ref('product.list0').id, 'picking_policy': 'direct', }) @@ -74,7 +73,7 @@ class TestSaleStock(TestSale): 'partner_id': self.partner.id, 'partner_invoice_id': self.partner.id, 'partner_shipping_id': self.partner.id, - 'order_line': [(0, 0, {'name': p.name, 'product_id': p.id, 'product_uom_qty': 2, 'product_uom': p.uom_id.id, 'price_unit': p.list_price}) for (_, p) in pycompat.items(self.products)], + 'order_line': [(0, 0, {'name': p.name, 'product_id': p.id, 'product_uom_qty': 2, 'product_uom': p.uom_id.id, 'price_unit': p.list_price}) for p in self.products.values()], 'pricelist_id': self.env.ref('product.list0').id, 'picking_policy': 'direct', }) diff --git a/addons/stock/models/procurement.py b/addons/stock/models/procurement.py index 8ac7fc638d7..8d5e419fb90 100644 --- a/addons/stock/models/procurement.py +++ b/addons/stock/models/procurement.py @@ -9,8 +9,7 @@ from psycopg2 import OperationalError from odoo import api, fields, models, registry, _ from odoo.osv import expression -from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, float_compare, \ - float_round, pycompat +from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, float_compare, float_round import logging @@ -311,7 +310,7 @@ class ProcurementOrder(models.Model): location_data[key]['orderpoints'] += orderpoint location_data[key]['groups'] = self._procurement_from_orderpoint_get_groups([orderpoint.id]) - for location_id, location_data in pycompat.items(location_data): + for location_id, location_data in location_data.items(): location_orderpoints = location_data['orderpoints'] product_context = dict(self._context, location=location_orderpoints[0].location_id.id) substract_quantity = location_orderpoints.subtract_procurements_from_orderpoints() diff --git a/addons/stock/models/stock_inventory.py b/addons/stock/models/stock_inventory.py index 866f3e2104c..bb14b839d32 100644 --- a/addons/stock/models/stock_inventory.py +++ b/addons/stock/models/stock_inventory.py @@ -4,7 +4,7 @@ from odoo import api, fields, models, _ from odoo.addons import decimal_precision as dp from odoo.exceptions import UserError -from odoo.tools import float_utils, pycompat +from odoo.tools import float_utils class Inventory(models.Model): @@ -251,7 +251,7 @@ class Inventory(models.Model): for product_data in self.env.cr.dictfetchall(): # replace the None the dictionary by False, because falsy values are tested later on - for void_field in [item[0] for item in pycompat.items(product_data) if item[1] is None]: + for void_field in [item[0] for item in product_data.items() if item[1] is None]: product_data[void_field] = False product_data['theoretical_qty'] = product_data['product_qty'] if product_data['product_id']: diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index 5eab237011e..6b7b74f5143 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -10,7 +10,7 @@ from odoo import api, fields, models, _ from odoo.addons import decimal_precision as dp from odoo.addons.procurement.models import procurement from odoo.exceptions import UserError -from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, pycompat +from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT from odoo.tools.float_utils import float_compare, float_round, float_is_zero @@ -595,7 +595,7 @@ class StockMove(models.Model): (move_waiting | move_create_proc).write({'state': 'waiting'}) # assign picking in batch for all confirmed move that share the same details - for key, moves in pycompat.items(to_assign): + for moves in to_assign.values(): moves.assign_picking() self._push_apply() return self diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py index 536ac2a5e6d..de736ef0bcf 100644 --- a/addons/stock/models/stock_picking.py +++ b/addons/stock/models/stock_picking.py @@ -7,7 +7,7 @@ import time from itertools import groupby from odoo import api, fields, models, _ -from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, pycompat +from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT from odoo.tools.float_utils import float_compare, float_round from odoo.addons.procurement.models import procurement from odoo.exceptions import UserError @@ -665,7 +665,7 @@ class Picking(models.Model): self.ensure_one() moves = self.env['stock.move'] for move_line in self.move_line_ids: - for product, remaining_qty in pycompat.items(move_line._get_remaining_prod_quantities()): + for product, remaining_qty in move_line._get_remaining_prod_quantities().items(): if float_compare(remaining_qty, 0, precision_rounding=product.uom_id.rounding) > 0: vals = self._prepare_values_extra_move(move_line, product, remaining_qty) moves |= moves.create(vals) diff --git a/addons/stock/models/stock_quant.py b/addons/stock/models/stock_quant.py index 5609f5be6a6..f2ebb9d0c87 100644 --- a/addons/stock/models/stock_quant.py +++ b/addons/stock/models/stock_quant.py @@ -5,7 +5,6 @@ from psycopg2 import OperationalError from odoo import api, fields, models, _ from odoo.exceptions import UserError, ValidationError -from odoo.tools import pycompat from odoo.osv import expression @@ -274,7 +273,7 @@ class QuantPackage(models.Model): @api.multi def name_get(self): - return list(pycompat.items(self._compute_complete_name())) + return list(self._compute_complete_name().items()) def _compute_complete_name(self): """ Forms complete name of location from parent location to child location. """ diff --git a/addons/stock/models/stock_warehouse.py b/addons/stock/models/stock_warehouse.py index 1f7e44f23ea..d8bd64253c6 100644 --- a/addons/stock/models/stock_warehouse.py +++ b/addons/stock/models/stock_warehouse.py @@ -8,7 +8,7 @@ from dateutil import relativedelta from odoo import api, fields, models, _ from odoo.addons import decimal_precision as dp from odoo.exceptions import UserError, ValidationError -from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, pycompat +from odoo.tools import DEFAULT_SERVER_DATE_FORMAT import logging @@ -99,7 +99,7 @@ class Warehouse(models.Model): 'wh_output_stock_loc_id': {'name': _('Output'), 'active': delivery_steps != 'ship_only', 'usage': 'internal'}, 'wh_pack_stock_loc_id': {'name': _('Packing Zone'), 'active': delivery_steps == 'pick_pack_ship', 'usage': 'internal'}, } - for field_name, values in pycompat.items(sub_locations): + for field_name, values in sub_locations.items(): values['location_id'] = vals['view_location_id'] if vals.get('company_id'): values['company_id'] = vals.get('company_id') @@ -240,10 +240,10 @@ class Warehouse(models.Model): }, } data = self._get_picking_type_values(self.reception_steps, self.delivery_steps, self.wh_pack_stock_loc_id) - for field_name, values in pycompat.items(data): + for field_name in data: data[field_name].update(create_data[field_name]) - for picking_type, values in pycompat.items(data): + for picking_type, values in data.items(): sequence = IrSequenceSudo.create(sequence_data[picking_type]) values.update(warehouse_id=self.id, color=color, sequence_id=sequence.id) warehouse_data[picking_type] = PickingType.create(values).id @@ -598,8 +598,8 @@ class Warehouse(models.Model): @api.one def _update_picking_type(self): picking_type_values = self._get_picking_type_values(self.reception_steps, self.delivery_steps, self.wh_pack_stock_loc_id) - for field_name, values in pycompat.items(picking_type_values): - getattr(self, field_name).write(values) + for field_name, values in picking_type_values.items(): + self[field_name].write(values) @api.multi def _update_name_and_code(self, new_name=False, new_code=False): diff --git a/addons/stock/wizard/make_procurement.py b/addons/stock/wizard/make_procurement.py index 369995e7a15..2fa3db75b5d 100644 --- a/addons/stock/wizard/make_procurement.py +++ b/addons/stock/wizard/make_procurement.py @@ -2,7 +2,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import api, fields, models -from odoo.tools import pycompat class MakeProcurement(models.TransientModel): @@ -51,8 +50,8 @@ class MakeProcurement(models.TransientModel): @api.onchange('product_id') def onchange_product_id(self): if self.product_id: - for key, value in pycompat.items(self.onchange_product_id_dict(self.product_id.id)): - setattr(self, key, value) + for key, value in self.onchange_product_id_dict(self.product_id.id).items(): + self[key] = value @api.model def create(self, values): diff --git a/addons/stock_landed_costs/models/stock_landed_cost.py b/addons/stock_landed_costs/models/stock_landed_cost.py index aeb6e42366f..5fd5ce8f63b 100644 --- a/addons/stock_landed_costs/models/stock_landed_cost.py +++ b/addons/stock_landed_costs/models/stock_landed_cost.py @@ -7,7 +7,6 @@ from odoo import api, fields, models, tools, _ from odoo.addons import decimal_precision as dp from odoo.addons.stock_landed_costs.models import product from odoo.exceptions import UserError -from odoo.tools import pycompat class StockMove(models.Model): @@ -123,7 +122,7 @@ class LandedCost(models.Model): for val_line in landed_cost.valuation_adjustment_lines: val_to_cost_lines[val_line.cost_line_id] += val_line.additional_landed_cost if any(tools.float_compare(cost_line.price_unit, val_amount, precision_digits=prec_digits) != 0 - for cost_line, val_amount in pycompat.items(val_to_cost_lines)): + for cost_line, val_amount in val_to_cost_lines.items()): return False return True @@ -204,9 +203,8 @@ class LandedCost(models.Model): towrite_dict[valuation.id] = value else: towrite_dict[valuation.id] += value - if towrite_dict: - for key, value in pycompat.items(towrite_dict): - AdjustementLines.browse(key).write({'additional_landed_cost': value}) + for key, value in towrite_dict.items(): + AdjustementLines.browse(key).write({'additional_landed_cost': value}) return True diff --git a/addons/survey/models/survey.py b/addons/survey/models/survey.py index 84692c63f9d..7bcf53f67ab 100644 --- a/addons/survey/models/survey.py +++ b/addons/survey/models/survey.py @@ -15,8 +15,6 @@ from odoo.exceptions import UserError, ValidationError from odoo.addons.website.models.website import slug -from odoo.tools import pycompat - email_validator = re.compile(r"[^@]+@[^@]+\.[^@]+") _logger = logging.getLogger(__name__) @@ -26,7 +24,7 @@ def dict_keys_startswith(dictionary, string): .. note:: This function uses dictionary comprehensions (Python >= 2.7) """ - return {k: v for k, v in pycompat.items(dictionary) if k.startswith(string)} + return {k: v for k, v in dictionary.items() if k.startswith(string)} class SurveyStage(models.Model): @@ -240,7 +238,7 @@ class Survey(models.Model): answers[input_line.value_suggested.id]['count'] += 1 if input_line.answer_type == 'text' and (not(current_filters) or input_line.user_input_id.id in current_filters): comments.append(input_line) - result_summary = {'answers': list(pycompat.values(answers)), 'comments': comments} + result_summary = {'answers': list(answers.values()), 'comments': comments} # Calculate and return statistics for matrix if question.type == 'matrix': @@ -640,7 +638,7 @@ class SurveyQuestion(models.Model): if self.comments_allowed: comment_answer = answer_candidates.pop(("%s_%s" % (answer_tag, 'comment')), '').strip() # Preventing answers with blank value - if all(not answer.strip() for answer in pycompat.values(answer_candidates)) and answer_candidates: + if all(not answer.strip() for answer in answer_candidates.values()) and answer_candidates: errors.update({answer_tag: self.constr_error_msg}) # There is no answer neither comments (if comments count as answer) if not answer_candidates and self.comment_count_as_answer and (not comment_flag or not comment_answer): diff --git a/addons/survey/tests/test_survey.py b/addons/survey/tests/test_survey.py index 04a65a02562..b5f9897438b 100644 --- a/addons/survey/tests/test_survey.py +++ b/addons/survey/tests/test_survey.py @@ -13,8 +13,6 @@ from odoo.exceptions import UserError from odoo.tests.common import TransactionCase from odoo.addons.website.models.website import slug -from odoo.tools import pycompat - class TestSurvey(TransactionCase): @@ -179,7 +177,7 @@ class TestSurvey(TransactionCase): base_url = self.env['ir.config_parameter'].get_param('web.base.url') urltypes = {'public': 'start', 'print': 'print', 'result': 'results'} - for urltype, urltxt in pycompat.items(urltypes): + for urltype, urltxt in urltypes.items(): survey_url = getattr(self.survey1, urltype + '_url') survey_url_relative = getattr(self.survey1.with_context({'relative_url': True}), urltype + '_url') self.assertTrue(validate_url(survey_url)) @@ -211,8 +209,8 @@ class TestSurvey(TransactionCase): answers = [input_portal.user_input_line_ids[0], input_public.user_input_line_ids[0]] expected_values = {'answer_type': 'free_text', 'value_free_text': "Test Answer"} for answer in answers: - for field, value in pycompat.items(expected_values): - self.assertEqual(getattr(answer, field), value, msg="Unable to answer the survey. Expected behaviour of %s is not proper." % (field)) + for field, value in expected_values.items(): + self.assertEqual(answer[field], value, msg="Unable to answer the survey. Expected behaviour of %s is not proper." % (field)) def test_10_survey_result_simple_multiple_choice(self): question = self.env['survey.question'].sudo(self.survey_manager).create({ @@ -265,7 +263,7 @@ class TestSurvey(TransactionCase): 'print': {'method': 'print', 'token': '/test', 'text': 'Print'}, 'result': {'method': 'result', 'token': '', 'text': 'Results of the'}, 'test': {'method': 'public', 'token': '/phantom', 'text': 'Results of the'}} - for action, val in pycompat.items(actions): + for action, val in actions.items(): result = getattr(self.survey1.with_context({'survey_token': val['token'][1:]}), 'action_' + action + '_survey')() url = getattr(self.survey1.with_context({'relative_url': True}), val['method'] + '_url') + val['token'] self.assertEqual(result['url'], url) diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 114d7ba2e4e..abf019371dc 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -963,7 +963,7 @@ class Binary(http.Controller): def force_contenttype(self, headers, contenttype='image/png'): dictheaders = dict(headers) dictheaders['Content-Type'] = contenttype - return list(pycompat.items(dictheaders)) + return list(dictheaders.items()) @http.route(['/web/content', '/web/content/<string:xmlid>', @@ -1216,7 +1216,7 @@ class Export(http.Controller): else: fields['.id'] = fields.pop('id', {'string': 'ID'}) - fields_sequence = sorted(pycompat.items(fields), + fields_sequence = sorted(fields.items(), key=lambda field: odoo.tools.ustr(field[1].get('string', ''))) records = [] @@ -1227,7 +1227,7 @@ class Export(http.Controller): if field.get('readonly'): # If none of the field's states unsets readonly, skip the field if all(dict(attrs).get('readonly', True) - for attrs in pycompat.values(field.get('states', {}))): + for attrs in field.get('states', {}).values()): continue if not field.get('exportable', True): continue @@ -1319,7 +1319,7 @@ class Export(http.Controller): export_fields = [field.split('/', 1)[1] for field in fields] return ( (prefix + '/' + k, prefix_string + '/' + v) - for k, v in pycompat.items(self.fields_info(model, export_fields))) + for k, v in self.fields_info(model, export_fields).items()) class ExportFormat(object): raw_data = False diff --git a/addons/web_diagram/controllers/main.py b/addons/web_diagram/controllers/main.py index 56b6c76eefe..d29b60df40e 100644 --- a/addons/web_diagram/controllers/main.py +++ b/addons/web_diagram/controllers/main.py @@ -2,7 +2,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. import odoo.http as http -from odoo.tools import pycompat from odoo.tools.safe_eval import safe_eval @@ -46,7 +45,7 @@ class DiagramView(http.Controller): isolate_nodes[blnk_node['id']] = blnk_node y = [ t['y'] - for t in pycompat.values(nodes) + for t in nodes.values() if t['x'] == 20 if t['y'] ] @@ -99,11 +98,11 @@ class DiagramView(http.Controller): color='white', options={} ) - for color, expr in pycompat.items(bgcolors): + for color, expr in bgcolors.items(): if safe_eval(expr, act): n['color'] = color - for shape, expr in pycompat.items(shapes): + for shape, expr in shapes.items(): if safe_eval(expr, act): n['shape'] = shape diff --git a/addons/web_editor/models/ir_ui_view.py b/addons/web_editor/models/ir_ui_view.py index 96c27bc923d..977f02f4b44 100644 --- a/addons/web_editor/models/ir_ui_view.py +++ b/addons/web_editor/models/ir_ui_view.py @@ -91,7 +91,7 @@ class IrUiView(models.Model): @api.model def to_field_ref(self, el): # filter out meta-information inserted in the document - attributes = {k: v for k, v in pycompat.items(el.attrib) + attributes = {k: v for k, v in el.attrib.items() if not k.startswith('data-oe-')} attributes['t-field'] = el.get('data-oe-expression') diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py index 20e2320b68a..ef8245598a1 100644 --- a/addons/website/controllers/main.py +++ b/addons/website/controllers/main.py @@ -38,11 +38,11 @@ class QueryURL(object): def __call__(self, path=None, path_args=None, **kw): path = path or self.path - for key, value in pycompat.items(self.args): + for key, value in self.args.items(): kw.setdefault(key, value) path_args = OrderedSet(path_args or []) | self.path_args paths, fragments = {}, [] - for key, value in pycompat.items(kw): + for key, value in kw.items(): if value and key in path_args: if isinstance(value, models.BaseModel): paths[key] = slug(value) diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index c06ff77de90..133d0928caa 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -14,7 +14,7 @@ import odoo from odoo import api, models from odoo import SUPERUSER_ID from odoo.http import request -from odoo.tools import config, pycompat +from odoo.tools import config from odoo.exceptions import QWebException from odoo.tools.safe_eval import safe_eval @@ -244,7 +244,7 @@ class Http(models.AbstractModel): def _postprocess_args(cls, arguments, rule): super(Http, cls)._postprocess_args(arguments, rule) - for key, val in pycompat.items(arguments): + for key, val in arguments.items(): # Replace uid placeholder by the current request.uid if isinstance(val, models.BaseModel) and isinstance(val._uid, RequestUID): arguments[key] = val.sudo(request.uid) diff --git a/addons/website/models/ir_qweb.py b/addons/website/models/ir_qweb.py index e6cedfe07d2..a20db972c0b 100644 --- a/addons/website/models/ir_qweb.py +++ b/addons/website/models/ir_qweb.py @@ -5,7 +5,6 @@ import ast from odoo import models from odoo.http import request -from odoo.tools import pycompat class QWeb(models.AbstractModel): @@ -82,7 +81,7 @@ class QWeb(models.AbstractModel): atts = super(QWeb, self)._get_dynamic_att(tagName, atts, options, values) if options.get('rendering_bundle'): return atts - for name, value in pycompat.items(atts): + for name, value in atts.items(): atts[name] = self._website_build_attribute(tagName, name, value, options, values) return atts diff --git a/addons/website/models/website.py b/addons/website/models/website.py index 77be240cfbe..55f44887f03 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -363,7 +363,7 @@ class Website(models.Model): def get_url_localized(router, lang): arguments = dict(request.endpoint_arguments) - for key, val in list(pycompat.items(arguments)): + for key, val in list(arguments.items()): if isinstance(val, models.BaseModel): arguments[key] = val.with_context(lang=lang) return router.build(request.endpoint, arguments) @@ -496,7 +496,7 @@ class Website(models.Model): endpoint = rule.endpoint methods = endpoint.routing.get('methods') or ['GET'] - converters = list(pycompat.values(rule._converters)) + converters = list(rule._converters.values()) if not ('GET' in methods and endpoint.routing['type'] == 'http' and endpoint.routing['auth'] in ('none', 'public') @@ -541,7 +541,7 @@ class Website(models.Model): values = [{}] # converters with a domain are processed after the other ones convitems = sorted( - pycompat.items(converters), + converters.items(), key=lambda x: hasattr(x[1], 'domain') and (x[1].domain != '[]')) for (i, (name, converter)) in enumerate(convitems): newval = [] @@ -557,7 +557,7 @@ class Website(models.Model): for value in values: domain_part, url = rule.build(value, append_unknown=False) page = {'loc': url} - for key, val in pycompat.items(value): + for key, val in value.items(): if key.startswith('__'): page[key[2:]] = val if url in ('/sitemap.xml',): diff --git a/addons/website/tests/test_converter.py b/addons/website/tests/test_converter.py index 9267826c689..311c035bbac 100644 --- a/addons/website/tests/test_converter.py +++ b/addons/website/tests/test_converter.py @@ -4,8 +4,6 @@ import unittest from odoo.addons.website.models.website import slugify, unslug -from odoo.tools import pycompat - class TestUnslug(unittest.TestCase): @@ -25,7 +23,7 @@ class TestUnslug(unittest.TestCase): 'foo1': (None, None), } - for slug, expected in pycompat.items(tests): + for slug, expected in tests.items(): self.assertEqual(unslug(slug), expected) diff --git a/addons/website/tests/test_views.py b/addons/website/tests/test_views.py index af9d362cfb9..7293eae4c56 100644 --- a/addons/website/tests/test_views.py +++ b/addons/website/tests/test_views.py @@ -11,11 +11,10 @@ from lxml import etree as ET, html from lxml.html import builder as h from odoo.tests import common -from odoo.tools import pycompat def attrs(**kwargs): - return {'data-oe-%s' % key: str(value) for key, value in pycompat.items(kwargs)} + return {'data-oe-%s' % key: str(value) for key, value in kwargs.items()} class TestViewSaving(common.TransactionCase): diff --git a/addons/website_crm_partner_assign/controllers/main.py b/addons/website_crm_partner_assign/controllers/main.py index 3c18c7cf470..6e300e66cd0 100644 --- a/addons/website_crm_partner_assign/controllers/main.py +++ b/addons/website_crm_partner_assign/controllers/main.py @@ -13,7 +13,6 @@ from odoo.http import request from odoo.addons.website.models.website import slug, unslug from odoo.addons.website_partner.controllers.main import WebsitePartnerPage -from odoo.tools import pycompat from odoo.tools.translate import _ from odoo.addons.website_portal.controllers.main import website_account @@ -151,7 +150,7 @@ class WebsiteAccount(website_account): 'pager': pager, 'searchbar_sortings': searchbar_sortings, 'sortby': sortby, - 'searchbar_filters': OrderedDict(sorted(pycompat.items(searchbar_filters))), + 'searchbar_filters': OrderedDict(sorted(searchbar_filters.items())), 'filterby': filterby, }) return request.render("website_crm_partner_assign.portal_my_opportunities", values) diff --git a/addons/website_crm_partner_assign/models/crm_lead.py b/addons/website_crm_partner_assign/models/crm_lead.py index f1f002d5dd0..b73be955c42 100644 --- a/addons/website_crm_partner_assign/models/crm_lead.py +++ b/addons/website_crm_partner_assign/models/crm_lead.py @@ -5,7 +5,6 @@ import random from odoo.addons.base_geolocalize.models.res_partner import geo_find, geo_query_address from odoo import api, fields, models, _ -from odoo.tools import pycompat class CrmLead(models.Model): @@ -45,7 +44,7 @@ class CrmLead(models.Model): if lead.partner_assigned_id and lead.partner_assigned_id.user_id != lead.user_id: salesmans_leads.setdefault(lead.partner_assigned_id.user_id.id, []).append(lead.id) - for salesman_id, leads_ids in pycompat.items(salesmans_leads): + for salesman_id, leads_ids in salesmans_leads.items(): leads = self.browse(leads_ids) leads.write({'user_id': salesman_id}) diff --git a/addons/website_crm_partner_assign/wizard/crm_forward_to_partner.py b/addons/website_crm_partner_assign/wizard/crm_forward_to_partner.py index cb2fbf3ba03..5aa8073192f 100644 --- a/addons/website_crm_partner_assign/wizard/crm_forward_to_partner.py +++ b/addons/website_crm_partner_assign/wizard/crm_forward_to_partner.py @@ -3,7 +3,6 @@ from odoo import api, fields, models, _ from odoo.exceptions import UserError -from odoo.tools import pycompat class CrmLeadForwardToPartner(models.TransientModel): @@ -86,7 +85,7 @@ class CrmLeadForwardToPartner(models.TransientModel): else: partners_leads[partner.id] = {'partner': partner, 'leads': [lead_details]} - for partner_id, partner_leads in pycompat.items(partners_leads): + for partner_id, partner_leads in partners_leads.items(): in_portal = False if portal_group: for contact in (partner.child_ids or partner).filtered(lambda contact: contact.user_ids): diff --git a/addons/website_event/controllers/main.py b/addons/website_event/controllers/main.py index cd020a74372..5aed9a25ffa 100644 --- a/addons/website_event/controllers/main.py +++ b/addons/website_event/controllers/main.py @@ -9,7 +9,6 @@ from dateutil.relativedelta import relativedelta from odoo import fields, http, _ from odoo.addons.website.models.website import slug from odoo.http import request -from odoo.tools import pycompat class WebsiteEventController(http.Controller): @@ -80,7 +79,7 @@ class WebsiteEventController(http.Controller): def dom_without(without): domain = [('state', "in", ['draft', 'confirm', 'done'])] - for key, search in pycompat.items(domain_search): + for key, search in domain_search.items(): if key != without: domain += search return domain @@ -234,16 +233,16 @@ class WebsiteEventController(http.Controller): ''' Process data posted from the attendee details form. ''' registrations = {} global_values = {} - for key, value in pycompat.items(details): + for key, value in details.items(): counter, field_name = key.split('-', 1) if counter == '0': global_values[field_name] = value else: registrations.setdefault(counter, dict())[field_name] = value - for key, value in pycompat.items(global_values): - for registration in pycompat.values(registrations): + for key, value in global_values.items(): + for registration in registrations.values(): registration[key] = value - return list(pycompat.values(registrations)) + return list(registrations.values()) @http.route(['/event/<model("event.event"):event>/registration/confirm'], type='http', auth="public", methods=['POST'], website=True) def registration_confirm(self, event, **post): diff --git a/addons/website_event_questions/controllers/main.py b/addons/website_event_questions/controllers/main.py index e709e0b3d06..684999a26ff 100644 --- a/addons/website_event_questions/controllers/main.py +++ b/addons/website_event_questions/controllers/main.py @@ -3,8 +3,6 @@ from odoo.addons.website_event.controllers.main import WebsiteEventController -from odoo.tools import pycompat - class WebsiteEvent(WebsiteEventController): @@ -13,7 +11,7 @@ class WebsiteEvent(WebsiteEventController): registrations = super(WebsiteEvent, self)._process_registration_details(details) for registration in registrations: answer_ids = [] - for key, value in pycompat.items(registration): + for key, value in registration.items(): if key.startswith('answer_ids-'): answer_ids.append([4, int(value)]) registration['answer_ids'] = answer_ids diff --git a/addons/website_event_sale/controllers/main.py b/addons/website_event_sale/controllers/main.py index 324fa1026ed..7ccb7f9e4b5 100644 --- a/addons/website_event_sale/controllers/main.py +++ b/addons/website_event_sale/controllers/main.py @@ -4,7 +4,6 @@ from odoo import http, _ from odoo.addons.website_event.controllers.main import WebsiteEventController from odoo.http import request -from odoo.tools import pycompat class WebsiteEventSaleController(WebsiteEventController): @@ -16,7 +15,7 @@ class WebsiteEventSaleController(WebsiteEventController): def _process_tickets_details(self, data): ticket_post = {} - for key, value in pycompat.items(data): + for key, value in data.items(): if not key.startswith('nb_register') or '-' not in key: continue items = key.split('-') diff --git a/addons/website_event_track/controllers/main.py b/addons/website_event_track/controllers/main.py index 1864b28379c..f11aa0bea13 100644 --- a/addons/website_event_track/controllers/main.py +++ b/addons/website_event_track/controllers/main.py @@ -8,7 +8,7 @@ import pytz from odoo import fields, http from odoo.http import request -from odoo.tools import html_escape as escape, html2plaintext, pycompat +from odoo.tools import html_escape as escape, html2plaintext class WebsiteEventTrackController(http.Controller): @@ -75,7 +75,7 @@ class WebsiteEventTrackController(http.Controller): days = {} tracks_by_days = {} - for day, tracks in pycompat.items(days_tracks): + for day, tracks in days_tracks.items(): tracks_by_days[day] = tracks days[day] = self._prepare_calendar(event, tracks) diff --git a/addons/website_form/controllers/main.py b/addons/website_form/controllers/main.py index cdf1034c7a9..978692e894a 100644 --- a/addons/website_form/controllers/main.py +++ b/addons/website_form/controllers/main.py @@ -10,7 +10,7 @@ from psycopg2 import IntegrityError from odoo import http from odoo.http import request -from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, pycompat +from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT from odoo.tools.translate import _ from odoo.exceptions import ValidationError from odoo.addons.base.ir.ir_qweb.fields import nl2br @@ -118,7 +118,7 @@ class WebsiteForm(http.Controller): error_fields = [] - for field_name, field_value in pycompat.items(values): + for field_name, field_value in values.items(): # If the value of the field if a file if hasattr(field_value, 'filename'): # Undo file upload field name indexing @@ -164,7 +164,7 @@ class WebsiteForm(http.Controller): if hasattr(dest_model, "website_form_input_filter"): data['record'] = dest_model.website_form_input_filter(request, data['record']) - missing_required_fields = [label for label, field in pycompat.items(authorized_fields) if field['required'] and not label in data['record']] + missing_required_fields = [label for label, field in authorized_fields.items() if field['required'] and not label in data['record']] if any(error_fields): raise ValidationError(error_fields + missing_required_fields) diff --git a/addons/website_form/models/models.py b/addons/website_form/models/models.py index 654fbfa9ee4..67364d59dc2 100644 --- a/addons/website_form/models/models.py +++ b/addons/website_form/models/models.py @@ -5,7 +5,6 @@ import itertools from odoo import models, fields, api from odoo.http import request -from odoo.tools import pycompat class website_form_config(models.Model): @@ -42,7 +41,7 @@ class website_form_model(models.Model): ]) } return { - k: v for k, v in pycompat.items(self.get_authorized_fields(self.model)) + k: v for k, v in self.get_authorized_fields(self.model).items() if k in included } @@ -52,7 +51,7 @@ class website_form_model(models.Model): model = self.env[model_name] fields_get = model.fields_get() - for key, val in pycompat.items(model._inherits): + for key, val in model._inherits.items(): fields_get.pop(val, None) # Unrequire fields with default values diff --git a/addons/website_livechat/controllers/main.py b/addons/website_livechat/controllers/main.py index 675b56e561f..753e4eef1ae 100644 --- a/addons/website_livechat/controllers/main.py +++ b/addons/website_livechat/controllers/main.py @@ -3,7 +3,6 @@ from odoo import http from odoo.http import request -from odoo.tools import pycompat class WebsiteLivechat(http.Controller): @@ -27,7 +26,7 @@ class WebsiteLivechat(http.Controller): # compute percentage percentage = dict.fromkeys(['great', 'okay', 'bad'], 0) for grade in repartition: - percentage[grade] = repartition[grade] * 100 / sum(pycompat.values(repartition)) if sum(pycompat.values(repartition)) else 0 + percentage[grade] = repartition[grade] * 100 / sum(repartition.values()) if sum(repartition.values()) else 0 # the value dict to render the template values = { diff --git a/addons/website_portal/controllers/main.py b/addons/website_portal/controllers/main.py index 3b2fbfc2a2d..865312cc7c6 100644 --- a/addons/website_portal/controllers/main.py +++ b/addons/website_portal/controllers/main.py @@ -4,7 +4,6 @@ from odoo import http from odoo.http import request from odoo import tools -from odoo.tools import pycompat from odoo.tools.translate import _ from odoo.exceptions import ValidationError @@ -134,7 +133,7 @@ class website_account(http.Controller): error["vat"] = 'error' # error message for empty required fields - if [err for err in pycompat.values(error) if err == 'missing']: + if [err for err in error.values() if err == 'missing']: error_message.append(_('Some required fields are empty.')) unknown = [k for k in data if k not in self.MANDATORY_BILLING_FIELDS + self.OPTIONAL_BILLING_FIELDS] diff --git a/addons/website_portal_purchase/controllers/website_portal.py b/addons/website_portal_purchase/controllers/website_portal.py index 874c311f92a..4d8762e4346 100644 --- a/addons/website_portal_purchase/controllers/website_portal.py +++ b/addons/website_portal_purchase/controllers/website_portal.py @@ -6,7 +6,6 @@ from collections import OrderedDict from odoo import http from odoo.exceptions import AccessError from odoo.http import request -from odoo.tools import pycompat from odoo.tools.translate import _ from odoo.addons.website_portal.controllers.main import website_account, get_records_pager @@ -89,7 +88,7 @@ class WebsitePortal(website_account): 'archive_groups': archive_groups, 'searchbar_sortings': searchbar_sortings, 'sortby': sortby, - 'searchbar_filters': OrderedDict(sorted(pycompat.items(searchbar_filters))), + 'searchbar_filters': OrderedDict(sorted(searchbar_filters.items())), 'filterby': filterby, 'default_url': '/my/purchase', }) diff --git a/addons/website_project/controllers/main.py b/addons/website_project/controllers/main.py index d8716efd9ac..720c4f65700 100644 --- a/addons/website_project/controllers/main.py +++ b/addons/website_project/controllers/main.py @@ -8,7 +8,6 @@ from odoo.http import request from odoo.addons.website_portal.controllers.main import website_account, get_records_pager from odoo.osv.expression import OR -from odoo.tools import pycompat class WebsiteAccount(website_account): @@ -156,7 +155,7 @@ class WebsiteAccount(website_account): 'searchbar_inputs': searchbar_inputs, 'search_in': search_in, 'sortby': sortby, - 'searchbar_filters': OrderedDict(sorted(pycompat.items(searchbar_filters))), + 'searchbar_filters': OrderedDict(sorted(searchbar_filters.items())), 'filterby': filterby, }) return request.render("website_project.my_tasks", values) diff --git a/addons/website_project_issue/controllers/main.py b/addons/website_project_issue/controllers/main.py index 1ce21cff8e8..940544a2188 100644 --- a/addons/website_project_issue/controllers/main.py +++ b/addons/website_project_issue/controllers/main.py @@ -105,7 +105,7 @@ class WebsiteAccount(website_account): 'searchbar_sortings': searchbar_sortings, 'searchbar_inputs': searchbar_inputs, 'sortby': sortby, - 'searchbar_filters': OrderedDict(sorted(pycompat.items(searchbar_filters))), + 'searchbar_filters': OrderedDict(sorted(searchbar_filters.items())), 'filterby': filterby, 'search_in': search_in, 'search': search, diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index 51462df1de7..40057484efe 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -12,8 +12,6 @@ from odoo.addons.website.controllers.main import QueryURL from odoo.exceptions import ValidationError from odoo.addons.website_form.controllers.main import WebsiteForm -from odoo.tools import pycompat - _logger = logging.getLogger(__name__) PPG = 20 # Products Per Page @@ -78,10 +76,10 @@ class TableCompute(object): index += 1 # Format table according to HTML needs - rows = sorted(pycompat.items(self.table)) + rows = sorted(self.table.items()) rows = [r[1] for r in rows] for col in range(len(rows)): - cols = sorted(pycompat.items(rows[col])) + cols = sorted(rows[col].items()) x += len(cols) rows[col] = [r[1] for r in cols if r[1]] @@ -373,7 +371,7 @@ class WebsiteSale(http.Controller): return request.redirect("/shop/cart") def _filter_attributes(self, **kw): - return {k: v for k, v in pycompat.items(kw) if "attribute" in k} + return {k: v for k, v in kw.items() if "attribute" in k} @http.route(['/shop/cart/update_json'], type='json', auth="public", methods=['POST'], website=True, csrf=False) def cart_update_json(self, product_id, line_id=None, add_qty=None, set_qty=None, display=True): @@ -491,7 +489,7 @@ class WebsiteSale(http.Controller): except ValidationError: error["vat"] = 'error' - if [err for err in pycompat.items(error) if err == 'missing']: + if [err for err in error.items() if err == 'missing']: error_message.append(_('Some required fields are empty.')) return error, error_message @@ -517,7 +515,7 @@ class WebsiteSale(http.Controller): def values_postprocess(self, order, mode, values, errors, error_msg): new_values = {} authorized_fields = request.env['ir.model']._get('res.partner')._get_form_writable_fields() - for k, v in pycompat.items(values): + for k, v in values.items(): # don't drop empty value, it could be a field to reset if k in authorized_fields and v is not None: new_values[k] = v @@ -680,7 +678,7 @@ class WebsiteSale(http.Controller): # if form posted if 'post_values' in post: values = {} - for field_name, field_value in pycompat.items(post): + for field_name, field_value in post.items(): if field_name in request.env['sale.order']._fields and field_name.startswith('x_'): values[field_name] = field_value if values: diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py index cffff7f2f3d..724d24b5c03 100644 --- a/addons/website_sale/models/sale_order.py +++ b/addons/website_sale/models/sale_order.py @@ -6,7 +6,6 @@ import random from odoo import api, models, fields, _ from odoo.http import request from odoo.exceptions import UserError, ValidationError -from odoo.tools import pycompat _logger = logging.getLogger(__name__) @@ -93,7 +92,7 @@ class SaleOrder(models.Model): # add untracked attributes in the name untracked_attributes = [] - for k, v in pycompat.items(attributes): + for k, v in attributes.items(): # attribute should be like 'attribute-48-1' where 48 is the product_id, 1 is the attribute_id and v is the attribute value attribute_value = self.env['product.attribute.value'].sudo().browse(int(v)) if attribute_value and not attribute_value.attribute_id.create_variant: diff --git a/addons/website_sale/tests/test_website_sale_pricelist.py b/addons/website_sale/tests/test_website_sale_pricelist.py index cf97fd815cc..21accb52814 100644 --- a/addons/website_sale/tests/test_website_sale_pricelist.py +++ b/addons/website_sale/tests/test_website_sale_pricelist.py @@ -2,7 +2,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from mock import patch from odoo.tests.common import TransactionCase -from odoo.tools import pycompat class TestWebsitePriceList(TransactionCase): @@ -61,7 +60,7 @@ class TestWebsitePriceList(TransactionCase): 'CA': ['Canada'], 'US': ['USD', 'EUR', 'Benelux', 'Canada'] } - for country, result in pycompat.items(country_list): + for country, result in country_list.items(): pls = self.get_pl(show, current_pl, country) self.assertEquals(len(set(pls.mapped('name')) & set(result)), len(pls), 'Test failed for %s (%s %s vs %s %s)' % (country, len(pls), pls.mapped('name'), len(result), result)) @@ -78,7 +77,7 @@ class TestWebsitePriceList(TransactionCase): 'CA': ['Canada'] } - for country, result in pycompat.items(country_list): + for country, result in country_list.items(): pls = self.get_pl(show, current_pl, country) self.assertEquals(len(set(pls.mapped('name')) & set(result)), len(pls), 'Test failed for %s (%s %s vs %s %s)' % (country, len(pls), pls.mapped('name'), len(result), result)) @@ -99,7 +98,7 @@ class TestWebsitePriceList(TransactionCase): 'CA': False } - for country, result in pycompat.items(country_list): + for country, result in country_list.items(): self.args['country'] = country # mock patch method could not pass env context available = self.website.is_pricelist_available(christmas_pl) @@ -120,7 +119,7 @@ class TestWebsitePriceList(TransactionCase): 'CA': ['EUR', 'Canada'], 'US': ['USD', 'EUR', 'Benelux', 'Canada'] } - for country, result in pycompat.items(country_list): + for country, result in country_list.items(): pls = self.get_pl(show, current_pl, country) self.assertEquals(len(set(pls.mapped('name')) & set(result)), len(pls), 'Test failed for %s (%s %s vs %s %s)' % (country, len(pls), pls.mapped('name'), len(result), result)) diff --git a/addons/website_sale_options/controllers/main.py b/addons/website_sale_options/controllers/main.py index 8349f0e08bc..af48c17f2e1 100644 --- a/addons/website_sale_options/controllers/main.py +++ b/addons/website_sale_options/controllers/main.py @@ -5,8 +5,6 @@ from odoo import http from odoo.http import request from odoo.addons.website_sale.controllers.main import WebsiteSale -from odoo.tools import pycompat - class WebsiteSaleOptions(WebsiteSale): @@ -26,7 +24,7 @@ class WebsiteSaleOptions(WebsiteSale): option_ids = product.optional_product_ids.mapped('product_variant_ids').ids optional_product_ids = [] - for k, v in pycompat.items(kw): + for k, v in kw.items(): if "optional-product-" in k and int(kw.get(k.replace("product", "add"))) and int(v) in option_ids: optional_product_ids.append(int(v)) diff --git a/addons/website_slides/models/slides.py b/addons/website_slides/models/slides.py index a4de9105a1c..ad5df26cadd 100644 --- a/addons/website_slides/models/slides.py +++ b/addons/website_slides/models/slides.py @@ -12,7 +12,7 @@ import re from werkzeug import urls from odoo import api, fields, models, SUPERUSER_ID, _ -from odoo.tools import image, pycompat +from odoo.tools import image from odoo.tools.translate import html_translate from odoo.exceptions import Warning from odoo.addons.website.models.website import slug @@ -323,8 +323,8 @@ class Slide(models.Model): values = res['values'] if not values.get('document_id'): raise Warning(_('Please enter valid Youtube or Google Doc URL')) - for key, value in pycompat.items(values): - setattr(self, key, value) + for key, value in values.items(): + self[key] = value # website date_published = fields.Datetime('Publish Date') @@ -385,7 +385,7 @@ class Slide(models.Model): values['date_published'] = datetime.datetime.now() if values.get('url') and not values.get('document_id'): doc_data = self._parse_document_url(values['url']).get('values', dict()) - for key, value in pycompat.items(doc_data): + for key, value in doc_data.items(): values.setdefault(key, value) # Do not publish slide if user has not publisher rights if not self.user_has_groups('website.group_website_publisher'): @@ -399,7 +399,7 @@ class Slide(models.Model): def write(self, values): if values.get('url') and values['url'] != self.url: doc_data = self._parse_document_url(values['url']).get('values', dict()) - for key, value in pycompat.items(doc_data): + for key, value in doc_data.items(): values.setdefault(key, value) if values.get('channel_id'): custom_channels = self.env['slide.channel'].search([('custom_slide_id', '=', self.id), ('id', '!=', values.get('channel_id'))]) |
