diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py index 46db7c5c8e7..4a2b0824d24 100644 --- a/addons/account/models/account_bank_statement.py +++ b/addons/account/models/account_bank_statement.py @@ -2,7 +2,7 @@ from odoo import api, fields, models, _ from odoo.osv import expression -from odoo.tools import float_is_zero, pycompat +from odoo.tools import float_is_zero from odoo.tools import float_compare, float_round, float_repr from odoo.tools.misc import formatLang, format_date from odoo.exceptions import UserError, ValidationError @@ -528,10 +528,10 @@ class AccountBankStatementLine(models.Model): for aml_dict in counterpart_aml_dicts: if aml_dict['move_line'].reconciled: raise UserError(_('A selected move line was already reconciled.')) - if isinstance(aml_dict['move_line'], pycompat.integer_types): + if isinstance(aml_dict['move_line'], int): aml_dict['move_line'] = aml_obj.browse(aml_dict['move_line']) for aml_dict in (counterpart_aml_dicts + new_aml_dicts): - if aml_dict.get('tax_ids') and isinstance(aml_dict['tax_ids'][0], pycompat.integer_types): + if aml_dict.get('tax_ids') and isinstance(aml_dict['tax_ids'][0], int): # Transform the value in the format required for One2many and Many2many fields aml_dict['tax_ids'] = [(4, id, None) for id in aml_dict['tax_ids']] if any(line.journal_entry_ids for line in self): diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index c0eb0808dc4..391a151e2c7 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -1486,7 +1486,7 @@ class AccountInvoice(models.Model): :param date: payment date, defaults to fields.Date.context_today(self) :param writeoff_acc: account in which to create a writeoff if pay_amount < self.residual, so that the invoice is fully paid """ - if isinstance(pay_journal, pycompat.integer_types): + if isinstance(pay_journal, int): pay_journal = self.env['account.journal'].browse([pay_journal]) assert len(self) == 1, "Can only pay one invoice at a time." diff --git a/addons/account/models/chart_template.py b/addons/account/models/chart_template.py index 4c5c9645fef..1bed913ba37 100644 --- a/addons/account/models/chart_template.py +++ b/addons/account/models/chart_template.py @@ -4,7 +4,6 @@ from odoo.exceptions import AccessError from odoo import api, fields, models, _ from odoo import SUPERUSER_ID from odoo.exceptions import UserError -from odoo.tools import pycompat import logging @@ -592,7 +591,7 @@ class AccountChartTemplate(models.Model): # regular accounts created and that liquidity transfer account records = super(AccountChartTemplate, self)._load_records(data_list, update) account_data_list = [] - for data, record in pycompat.izip(data_list, records): + for data, record in zip(data_list, records): # Create the transfer account only for leaf chart template in the hierarchy. if record.parent_id: continue @@ -652,7 +651,7 @@ class AccountChartTemplate(models.Model): vals = self._get_account_vals(company, account_template, code_acc, tax_template_ref) template_vals.append((account_template, vals)) accounts = self._create_records_with_xmlid('account.account', template_vals, company) - for template, account in pycompat.izip(acc_template, accounts): + for template, account in zip(acc_template, accounts): acc_template_ref[template.id] = account.id return acc_template_ref @@ -752,7 +751,7 @@ class AccountChartTemplate(models.Model): # then create fiscal position taxes and accounts tax_template_vals = [] account_template_vals = [] - for position, fp in pycompat.izip(positions, fps): + for position, fp in zip(positions, fps): for tax in position.tax_ids: tax_template_vals.append((tax, { 'tax_src_id': tax_template_ref[tax.tax_src_id.id], @@ -893,7 +892,7 @@ class AccountTaxTemplate(models.Model): taxes = ChartTemplate._create_records_with_xmlid('account.tax', template_vals, company) # fill in tax_template_to_tax and todo_dict - for tax, (template, vals) in pycompat.izip(taxes, template_vals): + for tax, (template, vals) in zip(taxes, template_vals): tax_template_to_tax[template.id] = tax.id # Since the accounts have not been created yet, we have to wait before filling these fields todo_dict[tax.id] = { diff --git a/addons/account/models/reconciliation_widget.py b/addons/account/models/reconciliation_widget.py index 934272c1c81..65f3992c3ba 100644 --- a/addons/account/models/reconciliation_widget.py +++ b/addons/account/models/reconciliation_widget.py @@ -3,7 +3,6 @@ from odoo import api, fields, models, _ from odoo.exceptions import UserError from odoo.osv import expression -from odoo.tools import pycompat from odoo.tools.misc import formatLang @@ -30,7 +29,7 @@ class AccountReconciliation(models.AbstractModel): AccountMoveLine = self.env['account.move.line'] ctx = dict(self._context, force_price_include=False) - for st_line, datum in pycompat.izip(st_lines, data): + for st_line, datum in zip(st_lines, data): payment_aml_rec = AccountMoveLine.browse(datum.get('payment_aml_ids', [])) for aml_dict in datum.get('counterpart_aml_dicts', []): diff --git a/addons/account_facturx/models/account_invoice.py b/addons/account_facturx/models/account_invoice.py index b6a649542c5..619bd64d354 100644 --- a/addons/account_facturx/models/account_invoice.py +++ b/addons/account_facturx/models/account_invoice.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from odoo import api, models, fields, tools, _ -from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, pycompat, float_repr +from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, float_repr from odoo.tests.common import Form from datetime import datetime @@ -249,7 +249,7 @@ class AccountInvoice(models.Model): # ['file.xml', {'/Type': '/Filespec', '/F': 'file.xml', '/EF': {'/F': IndirectObject(22, 0)}}] embedded_files = reader.trailer['/Root']['/Names']['/EmbeddedFiles']['/Names'] # '[::2]' because it's a list [fn_1, content_1, fn_2, content_2, ..., fn_n, content_2] - for filename_obj, content_obj in list(pycompat.izip(embedded_files, embedded_files[1:]))[::2]: + for filename_obj, content_obj in list(zip(embedded_files, embedded_files[1:]))[::2]: content = content_obj.getObject()['/EF']['/F'].getData() if filename_obj == 'factur-x.xml': diff --git a/addons/auth_ldap/models/res_company_ldap.py b/addons/auth_ldap/models/res_company_ldap.py index 54f5dda89e6..7f36b1ba2dc 100644 --- a/addons/auth_ldap/models/res_company_ldap.py +++ b/addons/auth_ldap/models/res_company_ldap.py @@ -7,7 +7,7 @@ from ldap.filter import filter_format from odoo import _, api, fields, models, tools from odoo.exceptions import AccessDenied -from odoo.tools.pycompat import to_native +from odoo.tools.pycompat import to_text _logger = logging.getLogger(__name__) @@ -109,7 +109,7 @@ class CompanyLDAP(models.Model): if len(results) == 1: dn = results[0][0] conn = self._connect(conf) - conn.simple_bind_s(dn, to_native(password)) + conn.simple_bind_s(dn, to_text(password)) conn.unbind() entry = results[0] except ldap.INVALID_CREDENTIALS: @@ -146,8 +146,8 @@ class CompanyLDAP(models.Model): conn = self._connect(conf) ldap_password = conf['ldap_password'] or '' ldap_binddn = conf['ldap_binddn'] or '' - conn.simple_bind_s(to_native(ldap_binddn), to_native(ldap_password)) - results = conn.search_st(to_native(conf['ldap_base']), ldap.SCOPE_SUBTREE, filter, retrieve_attributes, timeout=60) + conn.simple_bind_s(to_text(ldap_binddn), to_text(ldap_password)) + results = conn.search_st(to_text(conf['ldap_base']), ldap.SCOPE_SUBTREE, filter, retrieve_attributes, timeout=60) conn.unbind() except ldap.INVALID_CREDENTIALS: _logger.error('LDAP bind failed.') diff --git a/addons/base_import/models/base_import.py b/addons/base_import/models/base_import.py index 35d5692e95b..d6c05217bc9 100644 --- a/addons/base_import/models/base_import.py +++ b/addons/base_import/models/base_import.py @@ -263,15 +263,15 @@ class Import(models.TransientModel): def _read_xls_book(self, book): sheet = book.sheet_by_index(0) # emulate Sheet.get_rows for pre-0.9.4 - for row in pycompat.imap(sheet.row, range(sheet.nrows)): + for row in map(sheet.row, range(sheet.nrows)): values = [] for cell in row: if cell.ctype is xlrd.XL_CELL_NUMBER: is_float = cell.value % 1 != 0.0 values.append( - pycompat.text_type(cell.value) + str(cell.value) if is_float - else pycompat.text_type(int(cell.value)) + else str(int(cell.value)) ) elif cell.ctype is xlrd.XL_CELL_DATE: is_datetime = cell.value % 1 != 0.0 @@ -642,7 +642,7 @@ class Import(models.TransientModel): if options.get('headers'): rows_to_import = itertools.islice(rows_to_import, 1, None) data = [ - list(row) for row in pycompat.imap(mapper, rows_to_import) + list(row) for row in map(mapper, rows_to_import) # don't try inserting completely empty rows (e.g. from # filtering out o2m fields) if any(row) @@ -863,7 +863,7 @@ class Import(models.TransientModel): return { 'messages': [{ 'type': 'error', - 'message': pycompat.text_type(error), + 'message': str(error), 'record': False, }] } diff --git a/addons/base_import_module/models/ir_module.py b/addons/base_import_module/models/ir_module.py index 425ad1a01f4..128594cc824 100644 --- a/addons/base_import_module/models/ir_module.py +++ b/addons/base_import_module/models/ir_module.py @@ -11,7 +11,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__) @@ -88,7 +88,7 @@ class IrModule(models.Model): with open(full_path, 'rb') as fp: data = base64.b64encode(fp.read()) url_path = '/{}{}'.format(module, full_path.split(path)[1].replace(os.path.sep, '/')) - if not isinstance(url_path, pycompat.text_type): + if not isinstance(url_path, str): url_path = url_path.decode(sys.getfilesystemencoding()) filename = os.path.split(url_path)[1] values = dict( diff --git a/addons/board/models/board.py b/addons/board/models/board.py index cb876d61330..a3355755b2f 100644 --- a/addons/board/models/board.py +++ b/addons/board/models/board.py @@ -2,7 +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 Board(models.AbstractModel): diff --git a/addons/bus/controllers/main.py b/addons/bus/controllers/main.py index bdbdd47096b..a5a0e3e189b 100644 --- a/addons/bus/controllers/main.py +++ b/addons/bus/controllers/main.py @@ -4,8 +4,6 @@ from odoo import exceptions, _ from odoo.http import Controller, request, route from odoo.addons.bus.models.bus import dispatch -from odoo.tools import pycompat - class BusController(Controller): """ Examples: @@ -16,7 +14,7 @@ class BusController(Controller): @route('/longpolling/send', type="json", auth="public") def send(self, channel, message): - if not isinstance(channel, pycompat.string_types): + if not isinstance(channel, str): raise Exception("bus.Bus only string channels are allowed.") return request.env['bus.bus'].sendone(channel, message) @@ -35,7 +33,7 @@ class BusController(Controller): options = {} if not dispatch: raise Exception("bus.Bus unavailable") - if [c for c in channels if not isinstance(c, pycompat.string_types)]: + if [c for c in channels if not isinstance(c, str)]: raise Exception("bus.Bus only string channels are allowed.") if request.registry.in_test_mode(): raise exceptions.UserError(_("bus.Bus not available in test mode")) diff --git a/addons/bus/models/bus.py b/addons/bus/models/bus.py index d5d84fa77d2..7a7f8b497db 100644 --- a/addons/bus/models/bus.py +++ b/addons/bus/models/bus.py @@ -117,8 +117,7 @@ class ImDispatch(object): # it will handle a longpolling request if not odoo.evented: current = threading.current_thread() - current._Thread__daemonic = True # PY2 - current._daemonic = True # PY3 + current._daemonic = True # rename the thread to avoid tests waiting for a longpolling current.setName("openerp.longpolling.request.%s" % current.ident) diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index f0986c096e0..bb6c41ab8ac 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -35,7 +35,7 @@ def calendar_id2real_id(calendar_id=None, with_date=False): :param with_date: if a value is passed to this param it will return dates based on value of withdate + calendar_id :return: real event id """ - if calendar_id and isinstance(calendar_id, pycompat.string_types): + if calendar_id and isinstance(calendar_id, str): res = [bit for bit in calendar_id.split('-') if bit] if len(res) == 2: real_id = res[0] @@ -49,7 +49,7 @@ def calendar_id2real_id(calendar_id=None, with_date=False): def get_real_ids(ids): - if isinstance(ids, (pycompat.string_types, pycompat.integer_types)): + if isinstance(ids, (str, int)): return calendar_id2real_id(ids) if isinstance(ids, (list, tuple)): @@ -71,7 +71,7 @@ def any_id2key(record_id): :type record_id: int | str :rtype: (int, str) """ - if isinstance(record_id, pycompat.integer_types): + if isinstance(record_id, int): return record_id, u'' (real_id, virtual_id) = record_id.split('-') @@ -587,7 +587,7 @@ class Meeting(models.Model): """ Get recurrent start and stop dates based on Rule string""" start_dates = self._get_recurrent_date_by_event(date_field='start') stop_dates = self._get_recurrent_date_by_event(date_field='stop') - return list(pycompat.izip(start_dates, stop_dates)) + return list(zip(start_dates, stop_dates)) @api.multi def _get_recurrent_date_by_event(self, date_field='start'): @@ -697,9 +697,8 @@ class Meeting(models.Model): 'time_format': record_lang.time_format } - # formats will be used for str{f,p}time() which do not support unicode in Python 2, coerce to str - format_date = pycompat.to_native(lang_params.get("date_format", '%B-%d-%Y')) - format_time = pycompat.to_native(lang_params.get("time_format", '%I-%M %p')) + format_date = lang_params.get("date_format", '%B-%d-%Y') + format_time = lang_params.get("time_format", '%I-%M %p') return (format_date, format_time) @api.model @@ -715,7 +714,6 @@ class Meeting(models.Model): 2) if event all day ,return : AllDay, July-31-2013 """ timezone = self._context.get('tz') or self.env.user.partner_id.tz or 'UTC' - timezone = pycompat.to_native(timezone) # make safe for str{p,f}time() # get date/time format according to context format_date, format_time = self._get_date_formats() @@ -1188,7 +1186,7 @@ class Meeting(models.Model): pile.reverse() new_pile = [] for item in pile: - if not isinstance(item, pycompat.string_types): + if not isinstance(item, str): res = item elif str(item) == str('&'): first = new_pile.pop() @@ -1355,7 +1353,7 @@ class Meeting(models.Model): if interval == 'day': # Day number (1-31) - result = pycompat.text_type(date.day) + result = str(date.day) elif interval == 'month': # Localized month name and year @@ -1468,7 +1466,7 @@ class Meeting(models.Model): @api.returns('mail.message', lambda value: value.id) def message_post(self, **kwargs): thread_id = self.id - if isinstance(self.id, pycompat.string_types): + if isinstance(self.id, str): thread_id = get_real_ids(self.id) if self.env.context.get('default_date'): context = dict(self.env.context) @@ -1505,7 +1503,7 @@ class Meeting(models.Model): for arg in args: if arg[0] == 'id': for n, calendar_id in enumerate(arg[2]): - if isinstance(calendar_id, pycompat.string_types): + if isinstance(calendar_id, str): arg[2][n] = calendar_id.split('-')[0] return super(Meeting, self)._name_search(name=name, args=args, operator=operator, limit=limit, name_get_uid=name_get_uid) @@ -1661,7 +1659,7 @@ class Meeting(models.Model): continue res = real_data[real_id].copy() ls = calendar_id2real_id(calendar_id, with_date=res and res.get('duration', 0) > 0 and res.get('duration') or 1) - if not isinstance(ls, (pycompat.string_types, pycompat.integer_types)) and len(ls) >= 2: + if not isinstance(ls, (str, int)) and len(ls) >= 2: res['start'] = ls[1] res['stop'] = ls[2] diff --git a/addons/calendar/models/ir_attachment.py b/addons/calendar/models/ir_attachment.py index b19f752a507..ae1fe6aafb9 100644 --- a/addons/calendar/models/ir_attachment.py +++ b/addons/calendar/models/ir_attachment.py @@ -5,8 +5,6 @@ from odoo import api, models from odoo.addons.calendar.models.calendar import get_real_ids -from odoo.tools import pycompat - class Attachment(models.Model): @@ -18,13 +16,13 @@ class Attachment(models.Model): args = list(args) if any([leaf for leaf in args if leaf[0] == "res_model" and leaf[2] == 'calendar.event']): for index in range(len(args)): - if args[index][0] == "res_id" and isinstance(args[index][2], pycompat.string_types): + if args[index][0] == "res_id" and isinstance(args[index][2], str): args[index] = (args[index][0], args[index][1], get_real_ids(args[index][2])) return super(Attachment, self)._search(args, offset=offset, limit=limit, order=order, count=count, access_rights_uid=access_rights_uid) @api.multi def write(self, vals): """ When posting an attachment (new or not), convert the virtual ids in real ids. """ - if isinstance(vals.get('res_id'), pycompat.string_types): + if isinstance(vals.get('res_id'), str): vals['res_id'] = get_real_ids(vals.get('res_id')) return super(Attachment, self).write(vals) diff --git a/addons/calendar/models/mail_message.py b/addons/calendar/models/mail_message.py index 426c7a78d52..cd8ed5d89ae 100644 --- a/addons/calendar/models/mail_message.py +++ b/addons/calendar/models/mail_message.py @@ -5,8 +5,6 @@ from odoo import api, models from odoo.addons.calendar.models.calendar import get_real_ids -from odoo.tools import pycompat - class Message(models.Model): @@ -18,7 +16,7 @@ class Message(models.Model): args = list(args) for index in range(len(args)): if args[index][0] == "res_id": - if isinstance(args[index][2], pycompat.string_types): + if isinstance(args[index][2], str): args[index] = (args[index][0], args[index][1], get_real_ids(args[index][2])) elif isinstance(args[index][2], list): args[index] = (args[index][0], args[index][1], [get_real_ids(x) for x in args[index][2]]) diff --git a/addons/gamification/models/goal.py b/addons/gamification/models/goal.py index a44d562500b..dba9d63a329 100644 --- a/addons/gamification/models/goal.py +++ b/addons/gamification/models/goal.py @@ -7,7 +7,6 @@ from datetime import date, datetime, timedelta from odoo import api, fields, models, _, exceptions from odoo.osv import expression -from odoo.tools import pycompat from odoo.tools.safe_eval import safe_eval _logger = logging.getLogger(__name__) @@ -285,7 +284,7 @@ class Goal(models.Model): safe_eval(code, cxt, mode="exec", nocopy=True) # the result of the evaluated codeis put in the 'result' local variable, propagated to the context result = cxt.get('result') - if result is not None and isinstance(result, (float, pycompat.integer_types)): + if isinstance(result, (float, int)): goals_to_write.update(goal._get_write_values(result)) else: _logger.error( @@ -326,7 +325,7 @@ class Goal(models.Model): for goal in [g for g in goals if g.id in query_goals]: for user_value in user_values: queried_value = field_name in user_value and user_value[field_name] or False - if isinstance(queried_value, tuple) and len(queried_value) == 2 and isinstance(queried_value[0], pycompat.integer_types): + if isinstance(queried_value, tuple) and len(queried_value) == 2 and isinstance(queried_value[0], int): queried_value = queried_value[0] if queried_value == query_goals[goal.id]: new_value = user_value.get(field_name+'_count', goal.current) diff --git a/addons/google_drive/models/google_drive.py b/addons/google_drive/models/google_drive.py index f65616c31d4..58191842aaa 100644 --- a/addons/google_drive/models/google_drive.py +++ b/addons/google_drive/models/google_drive.py @@ -9,7 +9,6 @@ import werkzeug.urls from odoo import api, fields, models from odoo.exceptions import RedirectWarning, UserError -from odoo.tools import pycompat from odoo.tools.safe_eval import safe_eval from odoo.tools.translate import _ @@ -155,7 +154,7 @@ class GoogleDrive(models.Model): :return: the config id and config name ''' # TO DO in master: fix my signature and my model - if isinstance(res_model, pycompat.string_types): + if isinstance(res_model, str): res_model = self.env['ir.model'].search([('model', '=', res_model)]).id if not res_id: raise UserError(_("Creating google drive may only be done by one at a time.")) diff --git a/addons/hw_escpos/escpos/escpos.py b/addons/hw_escpos/escpos/escpos.py index 0369aa2a0a4..a92b0d44eb1 100644 --- a/addons/hw_escpos/escpos/escpos.py +++ b/addons/hw_escpos/escpos/escpos.py @@ -13,7 +13,6 @@ from hashlib import md5 from PIL import Image from xml.etree import ElementTree as ET -from odoo.tools import pycompat try: import jcconv @@ -30,7 +29,7 @@ from .exceptions import * def utfstr(stuff): """ converts stuff to string and does without failing if stuff is a utf8 string """ - if isinstance(stuff,pycompat.string_types): + if isinstance(stuff, str): return stuff else: return str(stuff) diff --git a/addons/l10n_ch/models/mail_template.py b/addons/l10n_ch/models/mail_template.py index b089d0b5f86..e3a1deca1dd 100644 --- a/addons/l10n_ch/models/mail_template.py +++ b/addons/l10n_ch/models/mail_template.py @@ -4,7 +4,6 @@ import base64 from odoo import api, models -from odoo.tools import pycompat class MailTemplate(models.Model): @@ -21,7 +20,7 @@ class MailTemplate(models.Model): rslt = super(MailTemplate, self).generate_email(res_ids, fields) multi_mode = True - if isinstance(res_ids, pycompat.integer_types): + if isinstance(res_ids, int): res_ids = [res_ids] multi_mode = False diff --git a/addons/l10n_lu/scripts/tax2csv.py b/addons/l10n_lu/scripts/tax2csv.py index 23fec3c734c..2a2da358b4b 100644 --- a/addons/l10n_lu/scripts/tax2csv.py +++ b/addons/l10n_lu/scripts/tax2csv.py @@ -26,7 +26,7 @@ class LuxTaxGenerator: yield keys for i in range(1, self.sheet_tax_codes.nrows): row = (c.value for c in self.sheet_tax_codes.row(i)) - d = OrderedDict(pycompat.izip(keys, row)) + d = OrderedDict(zip(keys, row)) d['sign'] = int(d['sign']) d['sequence'] = int(d['sequence']) yield d @@ -36,14 +36,14 @@ class LuxTaxGenerator: yield keys for i in range(1, self.sheet_taxes.nrows): row = (c.value for c in self.sheet_taxes.row(i)) - yield OrderedDict(pycompat.izip(keys, row)) + yield OrderedDict(zip(keys, row)) def iter_fiscal_pos_map(self): keys = [c.value for c in self.sheet_fiscal_pos_map.row(0)] yield keys for i in range(1, self.sheet_fiscal_pos_map.nrows): row = (c.value for c in self.sheet_fiscal_pos_map.row(i)) - yield OrderedDict(pycompat.izip(keys, row)) + yield OrderedDict(zip(keys, row)) def tax_codes_to_csv(self): writer = pycompat.csv_writer(open('account.tax.code.template-%s.csv' % diff --git a/addons/mail/controllers/main.py b/addons/mail/controllers/main.py index 7a9d6b82838..6694fbf72b1 100644 --- a/addons/mail/controllers/main.py +++ b/addons/mail/controllers/main.py @@ -12,7 +12,7 @@ from odoo import api, http, registry, SUPERUSER_ID, _ from odoo.addons.web.controllers.main import binary_content from odoo.exceptions import AccessError from odoo.http import request -from odoo.tools import consteq, pycompat +from odoo.tools import consteq _logger = logging.getLogger(__name__) @@ -192,7 +192,7 @@ class MailController(http.Controller): model, res_id = message.model, message.res_id # ============================================================================================== - if res_id and isinstance(res_id, pycompat.string_types): + if res_id and isinstance(res_id, str): res_id = int(res_id) return self._redirect_to_record(model, res_id, access_token, **kwargs) diff --git a/addons/mail/models/ir_model.py b/addons/mail/models/ir_model.py index 0b029f3e1a1..b85a6adae3e 100644 --- a/addons/mail/models/ir_model.py +++ b/addons/mail/models/ir_model.py @@ -3,7 +3,6 @@ from odoo import _, api, fields, models from odoo.exceptions import UserError -from odoo.tools import pycompat class IrModel(models.Model): @@ -48,7 +47,7 @@ class IrModel(models.Model): model_class = super(IrModel, self)._instanciate(model_data) if model_data.get('is_mail_thread') and model_class._name != 'mail.thread': parents = model_class._inherit or [] - parents = [parents] if isinstance(parents, pycompat.string_types) else parents + parents = [parents] if isinstance(parents, str) else parents model_class._inherit = parents + ['mail.thread'] return model_class diff --git a/addons/mail/models/mail_activity.py b/addons/mail/models/mail_activity.py index d7829ae0a1a..b925f59b1be 100644 --- a/addons/mail/models/mail_activity.py +++ b/addons/mail/models/mail_activity.py @@ -9,7 +9,6 @@ import pytz from odoo import api, exceptions, fields, models, _ -from odoo.tools import pycompat from odoo.tools.misc import clean_context _logger = logging.getLogger(__name__) @@ -657,7 +656,7 @@ class MailActivityMixin(models.AbstractModel): return False render_context = render_context or dict() - if isinstance(views_or_xmlid, pycompat.string_types): + if isinstance(views_or_xmlid, str): views = self.env.ref(views_or_xmlid, raise_if_not_found=False) else: views = views_or_xmlid diff --git a/addons/mail/models/mail_blacklist.py b/addons/mail/models/mail_blacklist.py index 919d3c20823..0329bea96d6 100644 --- a/addons/mail/models/mail_blacklist.py +++ b/addons/mail/models/mail_blacklist.py @@ -62,7 +62,7 @@ class MailBlackList(models.Model): if args: new_args = [] for arg in args: - if isinstance(arg, (list, tuple)) and arg[0] == 'email' and isinstance(arg[2], tools.pycompat.text_type): + if isinstance(arg, (list, tuple)) and arg[0] == 'email' and isinstance(arg[2], str): normalized = tools.email_normalize(arg[2]) if normalized: new_args.append([arg[0], arg[1], normalized]) diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py index b9cb878d393..cd0e9778e45 100644 --- a/addons/mail/models/mail_channel.py +++ b/addons/mail/models/mail_channel.py @@ -11,7 +11,7 @@ from uuid import uuid4 from odoo import _, api, fields, models, modules, tools from odoo.exceptions import UserError, ValidationError from odoo.osv import expression -from odoo.tools import ormcache, pycompat +from odoo.tools import ormcache from odoo.tools.safe_eval import safe_eval MODERATION_FIELDS = ['moderation', 'moderator_ids', 'moderation_ids', 'moderation_notify', 'moderation_notify_msg', 'moderation_guidelines', 'moderation_guidelines_msg'] @@ -357,7 +357,7 @@ class Channel(models.Model): email = '' if self.moderation and message_type in ['email', 'comment']: author_id = kwargs.get('author_id') - if author_id and isinstance(author_id, pycompat.integer_types): + if author_id and isinstance(author_id, int): email = self.env['res.partner'].browse([author_id]).email elif author_id: email = author_id.email diff --git a/addons/mail/models/mail_template.py b/addons/mail/models/mail_template.py index 4f3689ba99b..80cc1507357 100644 --- a/addons/mail/models/mail_template.py +++ b/addons/mail/models/mail_template.py @@ -14,7 +14,6 @@ from werkzeug import urls from odoo import _, api, fields, models, tools from odoo.exceptions import UserError -from odoo.tools import pycompat _logger = logging.getLogger(__name__) @@ -45,7 +44,7 @@ def format_tz(env, dt, tz=False, format=False): return format_datetime(ts, format or 'medium', locale=env.context.get("lang") or 'en_US') if format: - return pycompat.text_type(ts.strftime(format)) + return str(ts.strftime(format)) else: lang = env.context.get("lang") langs = env['res.lang'] @@ -54,9 +53,9 @@ def format_tz(env, dt, tz=False, format=False): format_date = langs.date_format or '%B-%d-%Y' format_time = langs.time_format or '%I-%M %p' - fdate = pycompat.text_type(ts.strftime(format_date)) - ftime = pycompat.text_type(ts.strftime(format_time)) - return u"%s %s%s" % (fdate, ftime, (u' (%s)' % tz) if tz else u'') + fdate = ts.strftime(format_date) + ftime = ts.strftime(format_time) + return "%s %s%s" % (fdate, ftime, (' (%s)' % tz) if tz else '') def format_amount(env, amount, currency): fmt = "%.{0}f".format(currency.decimal_places) @@ -303,7 +302,7 @@ class MailTemplate(models.Model): :param int res_ids: list of ids of document records those mails are related to. """ multi_mode = True - if isinstance(res_ids, pycompat.integer_types): + if isinstance(res_ids, int): multi_mode = False res_ids = [res_ids] @@ -349,7 +348,7 @@ class MailTemplate(models.Model): @api.multi def get_email_template(self, res_ids): multi_mode = True - if isinstance(res_ids, pycompat.integer_types): + if isinstance(res_ids, int): res_ids = [res_ids] multi_mode = False @@ -413,7 +412,7 @@ class MailTemplate(models.Model): """ self.ensure_one() multi_mode = True - if isinstance(res_ids, pycompat.integer_types): + if isinstance(res_ids, int): res_ids = [res_ids] multi_mode = False if fields is None: diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 3149780e926..b950cf756e3 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -277,7 +277,7 @@ class MailThread(models.AbstractModel): thread._message_log(body=_('%s created') % doc_name) # auto_subscribe: take values and defaults into account - for thread, values in pycompat.izip(threads, vals_list): + for thread, values in zip(threads, vals_list): create_values = dict(values) for key, val in self._context.items(): if key.startswith('default_') and key[8:] not in create_values: @@ -290,7 +290,7 @@ class MailThread(models.AbstractModel): track_threads = threads.with_context(lang=self.env.user.lang) else: track_threads = threads - for thread, values in pycompat.izip(track_threads, vals_list): + for thread, values in zip(track_threads, vals_list): tracked_fields = thread._get_tracked_fields(list(values)) if tracked_fields: initial_values = {thread.id: dict.fromkeys(tracked_fields, False)} @@ -578,7 +578,7 @@ class MailThread(models.AbstractModel): for field_name, (template, post_kwargs) in templates.items(): if not template: continue - if isinstance(template, pycompat.string_types): + if isinstance(template, str): self.message_post_with_view(template, **post_kwargs) else: self.message_post_with_template(template.id, **post_kwargs) @@ -1388,15 +1388,9 @@ class MailThread(models.AbstractModel): # convert it to utf-8 for transport between the mailgate script and here. if isinstance(message, xmlrpclib.Binary): message = bytes(message.data) - # message_from_string parses from a *native string*, except apparently - # sometimes message is ISO-8859-1 binary data or some shit and the - # straightforward version (pycompat.to_native) won't work right -> - # always encode message to bytes then use the relevant method - # depending on ~python version - if isinstance(message, pycompat.text_type): + if isinstance(message, str): message = message.encode('utf-8') - extract = getattr(email, 'message_from_bytes', email.message_from_string) - msg_txt = extract(message) + msg_txt = email.message_from_bytes(message) # parse the message, verify we are not in a loop by checking message_id is not duplicated msg = self.message_parse(msg_txt, save_original=save_original) @@ -1510,8 +1504,7 @@ class MailThread(models.AbstractModel): for node in to_remove: node.getparent().remove(node) if postprocessed: - body = etree.tostring(root, pretty_print=False, encoding='UTF-8') - body = pycompat.to_native(body) + body = etree.tostring(root, pretty_print=False, encoding='unicode') return body, attachments def _message_extract_payload(self, message, save_original=False): @@ -1623,7 +1616,7 @@ class MailThread(models.AbstractModel): } if not isinstance(message, Message): # message_from_string works on a native str - message = pycompat.to_native(message) + message = pycompat.to_text(message) message = email.message_from_string(message) message_id = message['message-id'] @@ -1883,7 +1876,7 @@ class MailThread(models.AbstractModel): cid = info and info.get('cid') else: continue - if isinstance(content, pycompat.text_type): + if isinstance(content, str): content = content.encode('utf-8') elif content is None: continue @@ -1977,7 +1970,7 @@ class MailThread(models.AbstractModel): partner_ids.add(partner_id[1]) if isinstance(partner_id, (list, tuple)) and partner_id[0] == 6 and len(partner_id) == 3: partner_ids |= set(partner_id[2]) - elif isinstance(partner_id, pycompat.integer_types): + elif isinstance(partner_id, int): partner_ids.add(partner_id) else: pass # we do not manage anything else @@ -2097,7 +2090,7 @@ class MailThread(models.AbstractModel): values['slug'] = slug except ImportError: values['slug'] = lambda self: self.id - if isinstance(views_or_xmlid, pycompat.string_types): + if isinstance(views_or_xmlid, str): views = self.env.ref(views_or_xmlid, raise_if_not_found=False) else: views = views_or_xmlid diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index b9a5845896c..c2ef637d299 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -5,7 +5,6 @@ import base64 import re from odoo import _, api, fields, models, SUPERUSER_ID, tools -from odoo.tools import pycompat from odoo.tools.safe_eval import safe_eval @@ -453,7 +452,7 @@ class MailComposer(models.TransientModel): """ self.ensure_one() multi_mode = True - if isinstance(res_ids, pycompat.integer_types): + if isinstance(res_ids, int): multi_mode = False res_ids = [res_ids] @@ -503,7 +502,7 @@ class MailComposer(models.TransientModel): """ Call email_template.generate_email(), get fields relevant for mail.compose.message, transform email_cc and email_to into partner_ids """ multi_mode = True - if isinstance(res_ids, pycompat.integer_types): + if isinstance(res_ids, int): multi_mode = False res_ids = [res_ids] diff --git a/addons/payment_adyen/models/payment.py b/addons/payment_adyen/models/payment.py index 6ed0c938e08..a18bd385f50 100644 --- a/addons/payment_adyen/models/payment.py +++ b/addons/payment_adyen/models/payment.py @@ -14,7 +14,7 @@ from werkzeug import urls 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.pycompat import to_native +from odoo.tools.pycompat import to_text _logger = logging.getLogger(__name__) @@ -193,7 +193,7 @@ class TxAdyen(models.Model): shasign_check = tx.acquirer_id._adyen_generate_merchant_sig_sha256('out', data) else: shasign_check = tx.acquirer_id._adyen_generate_merchant_sig('out', data) - if to_native(shasign_check) != to_native(data.get('merchantSig')): + if to_text(shasign_check) != to_text(data.get('merchantSig')): error_msg = _('Adyen: invalid merchantSig, received %s, computed %s') % (data.get('merchantSig'), shasign_check) _logger.warning(error_msg) raise ValidationError(error_msg) diff --git a/addons/point_of_sale/tests/test_point_of_sale_flow.py b/addons/point_of_sale/tests/test_point_of_sale_flow.py index 9b77988337c..d76c660d0fc 100644 --- a/addons/point_of_sale/tests/test_point_of_sale_flow.py +++ b/addons/point_of_sale/tests/test_point_of_sale_flow.py @@ -3,7 +3,7 @@ import time import odoo from odoo import fields -from odoo.tools import float_compare, mute_logger, test_reports, pycompat +from odoo.tools import float_compare, mute_logger, test_reports from odoo.addons.point_of_sale.tests.common import TestPointOfSaleCommon @@ -665,9 +665,9 @@ class TestPointOfSaleFlow(TestPointOfSaleCommon): debit_lines = self.pos_order_pos0.account_move.mapped('line_ids.debit') credit_lines = self.pos_order_pos0.account_move.mapped('line_ids.credit') amount_currency_lines = self.pos_order_pos0.account_move.mapped('line_ids.amount_currency') - for a, b in pycompat.izip(sorted(debit_lines), [0.0, 0.0, 0.0, 0.0, 879.55]): + for a, b in zip(sorted(debit_lines), [0.0, 0.0, 0.0, 0.0, 879.55]): self.assertAlmostEqual(a, b) - for a, b in pycompat.izip(sorted(credit_lines), [0.0, 22.5, 40.91, 388.64, 427.5]): + for a, b in zip(sorted(credit_lines), [0.0, 22.5, 40.91, 388.64, 427.5]): self.assertAlmostEqual(a, b) - for a, b in pycompat.izip(sorted(amount_currency_lines), [-855.0, -777.27, -81.82, -45.0, 1752.75]): + for a, b in zip(sorted(amount_currency_lines), [-855.0, -777.27, -81.82, -45.0, 1752.75]): self.assertAlmostEqual(a, b) diff --git a/addons/product/models/product.py b/addons/product/models/product.py index 990090b4218..a564a79dda4 100644 --- a/addons/product/models/product.py +++ b/addons/product/models/product.py @@ -9,7 +9,7 @@ from odoo.osv import expression from odoo.addons import decimal_precision as dp -from odoo.tools import float_compare, pycompat +from odoo.tools import float_compare class ProductCategory(models.Model): @@ -165,11 +165,11 @@ class ProductProduct(models.Model): quantity = self._context.get('quantity', 1.0) # Support context pricelists specified as display_name or ID for compatibility - if isinstance(pricelist_id_or_name, pycompat.string_types): + if isinstance(pricelist_id_or_name, str): pricelist_name_search = self.env['product.pricelist'].name_search(pricelist_id_or_name, operator='=', limit=1) if pricelist_name_search: pricelist = self.env['product.pricelist'].browse([pricelist_name_search[0][0]]) - elif isinstance(pricelist_id_or_name, pycompat.integer_types): + elif isinstance(pricelist_id_or_name, int): pricelist = self.env['product.pricelist'].browse(pricelist_id_or_name) if pricelist: @@ -268,7 +268,7 @@ class ProductProduct(models.Model): @api.one def _set_image_value(self, value): - if isinstance(value, pycompat.text_type): + if isinstance(value, str): value = value.encode('ascii') image = tools.image_resize_image_big(value) if self.product_tmpl_id.image: @@ -308,7 +308,7 @@ class ProductProduct(models.Model): @api.model_create_multi def create(self, vals_list): products = super(ProductProduct, self.with_context(create_product_product=True)).create(vals_list) - for product, vals in pycompat.izip(products, vals_list): + for product, vals in zip(products, vals_list): # When a unique variant is created from tmpl then the standard price is set by _set_standard_price if not (self.env.context.get('create_from_tmpl') and len(product.product_tmpl_id.product_variant_ids) == 1): product._set_standard_price(vals.get('standard_price') or 0.0) diff --git a/addons/product/models/product_pricelist.py b/addons/product/models/product_pricelist.py index bec6eb8fdcf..4cae61d9a0b 100644 --- a/addons/product/models/product_pricelist.py +++ b/addons/product/models/product_pricelist.py @@ -8,8 +8,6 @@ from odoo.exceptions import UserError, ValidationError from odoo.addons import decimal_precision as dp -from odoo.tools import pycompat - class Pricelist(models.Model): _name = "product.pricelist" @@ -262,7 +260,7 @@ class Pricelist(models.Model): return { product_id: res_tuple[0] for product_id, res_tuple in self._compute_price_rule( - list(pycompat.izip(products, quantities, partners)), + list(zip(products, quantities, partners)), date=date, uom_id=uom_id ).items() @@ -304,7 +302,7 @@ class Pricelist(models.Model): def _price_get_multi(self, pricelist, products_by_qty_by_partner): """ Mono pricelist, multi product - return price per product """ return pricelist.get_products_price( - list(pycompat.izip(**products_by_qty_by_partner))) + list(zip(**products_by_qty_by_partner))) def _get_partner_pricelist(self, partner_id, company_id=None): """ Retrieve the applicable pricelist for a given partner in a given company. diff --git a/addons/product/models/product_template.py b/addons/product/models/product_template.py index c9b6a753a68..866bc898286 100644 --- a/addons/product/models/product_template.py +++ b/addons/product/models/product_template.py @@ -9,7 +9,6 @@ from odoo.addons import decimal_precision as dp from odoo import api, fields, models, tools, _ from odoo.exceptions import ValidationError, RedirectWarning, except_orm -from odoo.tools import pycompat from odoo.exceptions import UserError @@ -182,11 +181,11 @@ class ProductTemplate(models.Model): quantity = self._context.get('quantity', 1.0) # Support context pricelists specified as display_name or ID for compatibility - if isinstance(pricelist_id_or_name, pycompat.string_types): + if isinstance(pricelist_id_or_name, str): pricelist_data = self.env['product.pricelist'].name_search(pricelist_id_or_name, operator='=', limit=1) if pricelist_data: pricelist = self.env['product.pricelist'].browse(pricelist_data[0][0]) - elif isinstance(pricelist_id_or_name, pycompat.integer_types): + elif isinstance(pricelist_id_or_name, int): pricelist = self.env['product.pricelist'].browse(pricelist_id_or_name) if pricelist: @@ -340,7 +339,7 @@ class ProductTemplate(models.Model): templates.with_context(create_from_tmpl=True).create_variant_ids() # This is needed to set given values to first variant after creation - for template, vals in pycompat.izip(templates, vals_list): + for template, vals in zip(templates, vals_list): related_vals = {} if vals.get('barcode'): related_vals['barcode'] = vals['barcode'] diff --git a/addons/sale/tests/test_sale_to_invoice.py b/addons/sale/tests/test_sale_to_invoice.py index 5a66e4c6359..2d6de021ea5 100644 --- a/addons/sale/tests/test_sale_to_invoice.py +++ b/addons/sale/tests/test_sale_to_invoice.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo.tools import pycompat, float_is_zero +from odoo.tools import float_is_zero from .test_sale_common import TestCommonSaleNoChart @@ -138,7 +138,7 @@ class TestSaleToInvoice(TestCommonSaleNoChart): invoice.action_invoice_open() # Check discount appeared on both SO lines and invoice lines - for line, inv_line in pycompat.izip(self.sale_order.order_line, invoice.invoice_line_ids): + for line, inv_line in zip(self.sale_order.order_line, invoice.invoice_line_ids): self.assertEquals(line.discount, inv_line.discount, 'Discount on lines of order and invoice should be same') def test_invoice_refund(self): diff --git a/addons/stock/models/product.py b/addons/stock/models/product.py index ed3f845883b..1065250df49 100644 --- a/addons/stock/models/product.py +++ b/addons/stock/models/product.py @@ -4,7 +4,6 @@ from odoo import api, fields, models, _ from odoo.addons import decimal_precision as dp from odoo.exceptions import UserError -from odoo.tools import pycompat from odoo.tools.float_utils import float_round from datetime import datetime import operator as py_operator @@ -167,9 +166,9 @@ class Product(models.Model): ]) location_ids = [] if self.env.context.get('location', False): - if isinstance(self.env.context['location'], pycompat.integer_types): + if isinstance(self.env.context['location'], int): location_ids = [self.env.context['location']] - elif isinstance(self.env.context['location'], pycompat.string_types): + elif isinstance(self.env.context['location'], str): domain = [('complete_name', 'ilike', self.env.context['location'])] if self.env.context.get('force_company', False): domain += [('company_id', '=', self.env.context['force_company'])] @@ -178,9 +177,9 @@ class Product(models.Model): location_ids = self.env.context['location'] else: if self.env.context.get('warehouse', False): - if isinstance(self.env.context['warehouse'], pycompat.integer_types): + if isinstance(self.env.context['warehouse'], int): wids = [self.env.context['warehouse']] - elif isinstance(self.env.context['warehouse'], pycompat.string_types): + elif isinstance(self.env.context['warehouse'], str): domain = [('name', 'ilike', self.env.context['warehouse'])] if self.env.context.get('force_company', False): domain += [('company_id', '=', self.env.context['force_company'])] @@ -316,7 +315,7 @@ class Product(models.Model): @api.model def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False): res = super(Product, self).fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu) - if self._context.get('location') and isinstance(self._context['location'], pycompat.integer_types): + if self._context.get('location') and isinstance(self._context['location'], int): location = self.env['stock.location'].browse(self._context['location']) fields = res.get('fields') if fields: diff --git a/addons/stock/models/stock_move_line.py b/addons/stock/models/stock_move_line.py index 5d3c03ed833..b92954e3199 100644 --- a/addons/stock/models/stock_move_line.py +++ b/addons/stock/models/stock_move_line.py @@ -6,7 +6,6 @@ from collections import Counter from odoo import api, fields, models, _ from odoo.addons import decimal_precision as dp from odoo.exceptions import UserError, ValidationError -from odoo.tools.pycompat import izip from odoo.tools.float_utils import float_round, float_compare, float_is_zero diff --git a/addons/stock_account/models/product.py b/addons/stock_account/models/product.py index 81fa093ccd5..c95a3b3cd1f 100644 --- a/addons/stock_account/models/product.py +++ b/addons/stock_account/models/product.py @@ -3,7 +3,7 @@ from odoo import api, fields, models, tools, _ from odoo.exceptions import UserError -from odoo.tools import float_is_zero, pycompat +from odoo.tools import float_is_zero from odoo.addons import decimal_precision as dp from odoo.exceptions import ValidationError diff --git a/addons/stock_account/models/stock.py b/addons/stock_account/models/stock.py index 5a7920108c6..37c69251c19 100644 --- a/addons/stock_account/models/stock.py +++ b/addons/stock_account/models/stock.py @@ -5,7 +5,7 @@ from collections import defaultdict from odoo import api, fields, models, _ from odoo.exceptions import UserError -from odoo.tools import float_compare, float_round, float_is_zero, pycompat +from odoo.tools import float_compare, float_round, float_is_zero import logging _logger = logging.getLogger(__name__) diff --git a/addons/survey/wizard/survey_invite.py b/addons/survey/wizard/survey_invite.py index 4f8f57276cb..7aa47259262 100644 --- a/addons/survey/wizard/survey_invite.py +++ b/addons/survey/wizard/survey_invite.py @@ -10,7 +10,6 @@ from werkzeug import urls from odoo import api, fields, models, _ from odoo.exceptions import UserError -from odoo.tools import pycompat _logger = logging.getLogger(__name__) @@ -215,7 +214,7 @@ class SurveyInvite(models.TransientModel): if wizard.public != 'email_private': return None else: - token = pycompat.text_type(uuid.uuid4()) + token = str(uuid.uuid4()) # create response with token survey_user_input = SurveyUserInput.create({ 'survey_id': wizard.survey_id.id, diff --git a/addons/utm/models/utm_mixin.py b/addons/utm/models/utm_mixin.py index c239501c972..6d9413c51d9 100644 --- a/addons/utm/models/utm_mixin.py +++ b/addons/utm/models/utm_mixin.py @@ -3,7 +3,6 @@ from odoo import api, fields, models, SUPERUSER_ID from odoo.http import request -from odoo.tools import pycompat class UtmMixin(models.AbstractModel): @@ -34,7 +33,7 @@ class UtmMixin(models.AbstractModel): # ir_http dispatch saves the url params in a cookie value = request.httprequest.cookies.get(cookie_name) # if we receive a string for a many2one, we search/create the id - if field.type == 'many2one' and isinstance(value, pycompat.string_types) and value: + if field.type == 'many2one' and isinstance(value, str) and value: Model = self.env[field.comodel_name] records = Model.search([('name', '=', value)], limit=1) if not records: diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 619db9e1403..d0059a25a95 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -1490,7 +1490,7 @@ class CSVExport(ExportFormat, http.Controller): row = [] for d in data: # Spreadsheet apps tend to detect formulas on leading =, + and - - if isinstance(d, pycompat.string_types) and d.startswith(('=', '-', '+')): + if isinstance(d, str) and d.startswith(('=', '-', '+')): d = "'" + d row.append(pycompat.to_text(d)) @@ -1533,7 +1533,7 @@ class ExcelExport(ExportFormat, http.Controller): for cell_index, cell_value in enumerate(row): cell_style = base_style - if isinstance(cell_value, bytes) and not isinstance(cell_value, pycompat.string_types): + if isinstance(cell_value, bytes) and not isinstance(cell_value, str): # because xls uses raw export, we can get a bytes object # here. xlwt does not support bytes values in Python 3 -> # assume this is base64 and decode to a string, if this @@ -1543,7 +1543,7 @@ class ExcelExport(ExportFormat, http.Controller): except UnicodeDecodeError: raise UserError(_("Binary fields can not be exported to Excel unless their content is base64-encoded. That does not seem to be the case for %s.") % fields[cell_index]) - if isinstance(cell_value, pycompat.string_types): + if isinstance(cell_value, str): cell_value = re.sub("\r", " ", pycompat.to_text(cell_value)) # Excel supports a maximum of 32767 characters in each cell: cell_value = cell_value[:32767] diff --git a/addons/web/models/ir_qweb.py b/addons/web/models/ir_qweb.py index 058ceb5d87b..ed5441e37ff 100644 --- a/addons/web/models/ir_qweb.py +++ b/addons/web/models/ir_qweb.py @@ -32,7 +32,7 @@ class Image(models.AbstractModel): aclasses = ['img', 'img-fluid'] if options.get('qweb_img_responsive', True) else ['img'] aclasses += options.get('class', '').split() - classes = ' '.join(pycompat.imap(escape, aclasses)) + classes = ' '.join(map(escape, aclasses)) max_size = None if options.get('resize'): diff --git a/addons/web/models/models.py b/addons/web/models/models.py index 2e3bd54788d..fe01ffe6938 100644 --- a/addons/web/models/models.py +++ b/addons/web/models/models.py @@ -3,7 +3,6 @@ from datetime import datetime import babel.dates import pytz -from odoo.tools import pycompat from odoo.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT from odoo import _, api, fields, models diff --git a/addons/web_editor/controllers/main.py b/addons/web_editor/controllers/main.py index 3b1f3cc8ac1..3a2e0d1d7aa 100644 --- a/addons/web_editor/controllers/main.py +++ b/addons/web_editor/controllers/main.py @@ -14,7 +14,6 @@ from lxml import etree, html from odoo.http import request from odoo import http, tools -from odoo.tools import pycompat from odoo.modules.module import get_resource_path, get_module_path logger = logging.getLogger(__name__) @@ -40,7 +39,7 @@ class Web_Editor(http.Controller): debug=request.debug) for k in kwargs: - if isinstance(kwargs[k], pycompat.string_types) and kwargs[k].isdigit(): + if isinstance(kwargs[k], str) and kwargs[k].isdigit(): kwargs[k] = int(kwargs[k]) trans = dict( @@ -205,7 +204,7 @@ class Web_Editor(http.Controller): uploads += attachments.read(['name', 'mimetype', 'checksum', 'url', 'res_id', 'res_model', 'access_token']) except Exception as e: logger.exception("Failed to upload image to attachment") - message = pycompat.text_type(e) + message = str(e) return """ in test_mail) cleaner = _Cleaner(**kwargs) cleaned = cleaner.clean_html(src) - assert isinstance(cleaned, pycompat.text_type) + assert isinstance(cleaned, str) # MAKO compatibility: $, { and } inside quotes are escaped, preventing correct mako execution cleaned = cleaned.replace(u'%24', u'$') cleaned = cleaned.replace(u'%7B', u'{') @@ -238,7 +238,7 @@ def html_sanitize(src, silent=True, sanitize_tags=True, sanitize_attributes=Fals # html considerations so real html content match database value cleaned.replace(u'\xa0', u' ') except etree.ParserError as e: - if u'empty' in pycompat.text_type(e): + if 'empty' in str(e): return u"" if not silent: raise diff --git a/odoo/tools/misc.py b/odoo/tools/misc.py index 762c07e535c..b165eb3a130 100644 --- a/odoo/tools/misc.py +++ b/odoo/tools/misc.py @@ -281,7 +281,7 @@ def flatten(list): """ r = [] for e in list: - if isinstance(e, (bytes, pycompat.text_type)) or not isinstance(e, collections.Iterable): + if isinstance(e, (bytes, str)) or not isinstance(e, collections.Iterable): r.append(e) else: r.extend(flatten(e)) @@ -304,7 +304,7 @@ def reverse_enumerate(l): File "", line 1, in StopIteration """ - return pycompat.izip(range(len(l)-1, -1, -1), reversed(l)) + return zip(range(len(l)-1, -1, -1), reversed(l)) def partition(pred, elems): """ Return a pair equivalent to: @@ -468,7 +468,7 @@ def human_size(sz): if not sz: return False units = ('bytes', 'Kb', 'Mb', 'Gb') - if isinstance(sz,pycompat.string_types): + if isinstance(sz, str): sz=len(sz) s, i = float(sz), 0 while s >= 1024 and i < len(units)-1: @@ -814,7 +814,7 @@ class mute_logger(object): def __enter__(self): for logger in self.loggers: - assert isinstance(logger, pycompat.string_types),\ + assert isinstance(logger, str),\ "A logger name must be a string, got %s" % type(logger) logging.getLogger(logger).addFilter(self) @@ -1148,7 +1148,7 @@ def formatLang(env, value, digits=None, grouping=True, monetary=False, dp=False, if not digits and digits is not 0: digits = DEFAULT_DIGITS - if isinstance(value, pycompat.string_types) and not value: + if isinstance(value, str) and not value: return '' lang = env.context.get('lang') or env.user.company_id.partner_id.lang or 'en_US' @@ -1178,7 +1178,7 @@ def format_date(env, value, lang_code=False, date_format=False): ''' if not value: return '' - if isinstance(value, pycompat.string_types): + if isinstance(value, str): if len(value) < DATE_LENGTH: return '' if len(value) > DATE_LENGTH: @@ -1198,7 +1198,7 @@ def format_date(env, value, lang_code=False, date_format=False): def _consteq(str1, str2): """ Constant-time string comparison. Suitable to compare bytestrings of fixed, known length only, because length difference is optimized. """ - return len(str1) == len(str2) and sum(ord(x)^ord(y) for x, y in pycompat.izip(str1, str2)) == 0 + return len(str1) == len(str2) and sum(ord(x)^ord(y) for x, y in zip(str1, str2)) == 0 consteq = getattr(passlib.utils, 'consteq', _consteq) diff --git a/odoo/tools/parse_version.py b/odoo/tools/parse_version.py index be509a1504f..f897c024505 100644 --- a/odoo/tools/parse_version.py +++ b/odoo/tools/parse_version.py @@ -7,8 +7,6 @@ from __future__ import print_function import re -from odoo.tools import pycompat - component_re = re.compile(r'(\d+ | [a-z]+ | \.| -)', re.VERBOSE) replace = {'pre':'c', 'preview':'c','-':'final-','_':'final-','rc':'c','dev':'@','saas':'','~':''}.get @@ -74,7 +72,7 @@ if __name__ == '__main__': if verbose: print(v, pv) - for a, b in pycompat.izip(pvs, pvs[1:]): + for a, b in zip(pvs, pvs[1:]): assert a < b, '%s < %s == %s' % (a, b, a < b) chk(('0', '4.2', '4.2.3.4', '5.0.0-alpha', '5.0.0-rc1', '5.0.0-rc1.1', '5.0.0_rc2', '5.0.0_rc3', '5.0.0'), False) diff --git a/odoo/tools/safe_eval.py b/odoo/tools/safe_eval.py index ccb2e3e25b4..813fd822e39 100644 --- a/odoo/tools/safe_eval.py +++ b/odoo/tools/safe_eval.py @@ -24,7 +24,6 @@ import logging import sys import werkzeug -from . import pycompat from .misc import ustr from . import pycompat @@ -273,7 +272,7 @@ _BUILTINS = { 'None': None, 'bytes': bytes, 'str': str, - 'unicode': pycompat.text_type, + 'unicode': str, 'bool': bool, 'int': int, 'float': float, diff --git a/odoo/tools/test_reports.py b/odoo/tools/test_reports.py index 803d9fc18c5..ef3e61ecb42 100644 --- a/odoo/tools/test_reports.py +++ b/odoo/tools/test_reports.py @@ -13,7 +13,7 @@ import tempfile from subprocess import Popen, PIPE from .. import api -from . import pycompat, ustr, config +from . import ustr, config from .safe_eval import safe_eval _logger = logging.getLogger(__name__) @@ -88,7 +88,7 @@ def try_report_action(cr, uid, action_id, active_model=None, active_ids=None, Eg. 'OK' or 'fa-print' :param our_module: the name of the calling module (string), like 'account' """ - if not our_module and isinstance(action_id, pycompat.string_types): + if not our_module and isinstance(action_id, str): if '.' in action_id: our_module = action_id.split('.', 1)[0] @@ -109,7 +109,7 @@ def try_report_action(cr, uid, action_id, active_model=None, active_ids=None, if not wiz_buttons: wiz_buttons = [] - if isinstance(action_id, pycompat.string_types): + if isinstance(action_id, str): if '.' in action_id: _, act_xmlid = action_id.split('.', 1) else: @@ -120,7 +120,7 @@ def try_report_action(cr, uid, action_id, active_model=None, active_ids=None, action = env.ref(action_id) act_model, act_id = action._name, action.id else: - assert isinstance(action_id, pycompat.integer_types) + assert isinstance(action_id, int) act_model = 'ir.action.act_window' # assume that act_id = action_id act_xmlid = '<%s>' % act_id @@ -134,7 +134,7 @@ def try_report_action(cr, uid, action_id, active_model=None, active_ids=None, if datas.get('id',False): context.update( {'active_id': datas.get('id',False), 'active_ids': datas.get('ids',[]), 'active_model': datas.get('model',False)}) context1 = action.get('context', {}) - if isinstance(context1, pycompat.string_types): + if isinstance(context1, str): context1 = safe_eval(context1, dict(context)) context.update(context1) env = env(context=context) diff --git a/odoo/tools/translate.py b/odoo/tools/translate.py index 3854e9436d4..40188738816 100644 --- a/odoo/tools/translate.py +++ b/odoo/tools/translate.py @@ -130,7 +130,7 @@ csv.register_dialect("UNIX", UNIX_LINE_TERMINATOR) # FIXME: holy shit this whole thing needs to be cleaned up hard it's a mess def encode(s): - assert isinstance(s, pycompat.text_type) + assert isinstance(s, str) return s # which elements are translated inline @@ -651,8 +651,8 @@ class PoFile(object): u"msgid %s\n" u"msgstr %s\n\n" ) % ( - quote(pycompat.text_type(source)), - quote(pycompat.text_type(trad)) + quote(str(source)), + quote(str(trad)) ) self.buffer.write(msg) @@ -1100,7 +1100,7 @@ def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, dic = dict.fromkeys(('type', 'name', 'res_id', 'src', 'value', 'comments', 'imd_model', 'imd_name', 'module')) dic['lang'] = lang - dic.update(pycompat.izip(fields, row)) + dic.update(zip(fields, row)) # ignore empty value that may be set from base language if not dic['value']: @@ -1124,8 +1124,8 @@ def trans_load_data(cr, fileobj, fileformat, lang, lang_name=None, verbose=True, if not res_id and dic['type'] != 'code': return - if isinstance(res_id, pycompat.integer_types) or \ - (isinstance(res_id, pycompat.string_types) and res_id.isdigit()): + if isinstance(res_id, int) or \ + (isinstance(res_id, str) and res_id.isdigit()): dic['res_id'] = int(res_id) if module_name: dic['module'] = module_name