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