summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Torres <adt@odoo.com>2018-11-08 15:27:30 +0000
committerAdrian Torres <adt@odoo.com>2018-11-29 09:28:17 +0000
commit52f5528cfb6d1152ee226e268247dc685a8ba329 (patch)
treeb44ecfa477b50dd3e488f09f623eecc8bc8e9d7d
parente5c864a596b72515837f0ed1e07550398ecc1ab0 (diff)
[REF] *: replace deprecated pycompat helpers for builtins
This commit replaces calls to pycompat helpers that were intended for python 2 <-> python 3 interoperability for python 3 builtins, as python 2 is no longer officially supported by Odoo. This includes: * calls to imap/izip/ifilter replaced by map/zip/filter * uses of text_type replaced by str * uses of unichr replaced by chr * calls to implements_to_string, implements_iterator removed * string_types and integer_types replaced by str, int respectively * calls to to_native replaced by calls to to_text This is done in preparation to the removal of these deprecated helpers in the following commit.
-rw-r--r--addons/account/models/account_bank_statement.py6
-rw-r--r--addons/account/models/account_invoice.py2
-rw-r--r--addons/account/models/chart_template.py9
-rw-r--r--addons/account/models/reconciliation_widget.py3
-rw-r--r--addons/account_facturx/models/account_invoice.py4
-rw-r--r--addons/auth_ldap/models/res_company_ldap.py8
-rw-r--r--addons/base_import/models/base_import.py10
-rw-r--r--addons/base_import_module/models/ir_module.py4
-rw-r--r--addons/board/models/board.py1
-rw-r--r--addons/bus/controllers/main.py6
-rw-r--r--addons/bus/models/bus.py3
-rw-r--r--addons/calendar/models/calendar.py24
-rw-r--r--addons/calendar/models/ir_attachment.py6
-rw-r--r--addons/calendar/models/mail_message.py4
-rw-r--r--addons/gamification/models/goal.py5
-rw-r--r--addons/google_drive/models/google_drive.py3
-rw-r--r--addons/hw_escpos/escpos/escpos.py3
-rw-r--r--addons/l10n_ch/models/mail_template.py3
-rw-r--r--addons/l10n_lu/scripts/tax2csv.py6
-rw-r--r--addons/mail/controllers/main.py4
-rw-r--r--addons/mail/models/ir_model.py3
-rw-r--r--addons/mail/models/mail_activity.py3
-rw-r--r--addons/mail/models/mail_blacklist.py2
-rw-r--r--addons/mail/models/mail_channel.py4
-rw-r--r--addons/mail/models/mail_template.py15
-rw-r--r--addons/mail/models/mail_thread.py27
-rw-r--r--addons/mail/wizard/mail_compose_message.py5
-rw-r--r--addons/payment_adyen/models/payment.py4
-rw-r--r--addons/point_of_sale/tests/test_point_of_sale_flow.py8
-rw-r--r--addons/product/models/product.py10
-rw-r--r--addons/product/models/product_pricelist.py6
-rw-r--r--addons/product/models/product_template.py7
-rw-r--r--addons/sale/tests/test_sale_to_invoice.py4
-rw-r--r--addons/stock/models/product.py11
-rw-r--r--addons/stock/models/stock_move_line.py1
-rw-r--r--addons/stock_account/models/product.py2
-rw-r--r--addons/stock_account/models/stock.py2
-rw-r--r--addons/survey/wizard/survey_invite.py3
-rw-r--r--addons/utm/models/utm_mixin.py3
-rw-r--r--addons/web/controllers/main.py6
-rw-r--r--addons/web/models/ir_qweb.py2
-rw-r--r--addons/web/models/models.py1
-rw-r--r--addons/web_editor/controllers/main.py5
-rw-r--r--addons/web_editor/models/ir_qweb.py2
-rw-r--r--addons/web_editor/models/ir_ui_view.py7
-rw-r--r--addons/website/controllers/main.py4
-rw-r--r--addons/website/models/ir_ui_view.py7
-rw-r--r--addons/website/models/res_partner.py3
-rw-r--r--addons/website/models/website.py5
-rw-r--r--addons/website/tests/test_crawl.py1
-rw-r--r--addons/website_forum/models/forum.py4
-rw-r--r--addons/website_sale/models/product.py5
-rw-r--r--doc/_extensions/github_link.py4
-rw-r--r--doc/_extensions/odoo_ext/translator.py8
-rw-r--r--doc/python3.rst26
-rw-r--r--odoo/addons/base/models/assetsbundle.py6
-rw-r--r--odoo/addons/base/models/ir_actions.py4
-rw-r--r--odoo/addons/base/models/ir_config_parameter.py6
-rw-r--r--odoo/addons/base/models/ir_fields.py12
-rw-r--r--odoo/addons/base/models/ir_http.py2
-rw-r--r--odoo/addons/base/models/ir_mail_server.py12
-rw-r--r--odoo/addons/base/models/ir_model.py6
-rw-r--r--odoo/addons/base/models/ir_module.py4
-rw-r--r--odoo/addons/base/models/ir_property.py4
-rw-r--r--odoo/addons/base/models/ir_qweb.py4
-rw-r--r--odoo/addons/base/models/ir_qweb_fields.py4
-rw-r--r--odoo/addons/base/models/ir_translation.py5
-rw-r--r--odoo/addons/base/models/ir_ui_view.py12
-rw-r--r--odoo/addons/base/models/qweb.py39
-rw-r--r--odoo/addons/base/models/res_bank.py3
-rw-r--r--odoo/addons/base/models/res_partner.py3
-rw-r--r--odoo/addons/base/models/res_users.py16
-rw-r--r--odoo/addons/base/tests/test_api.py6
-rw-r--r--odoo/addons/base/tests/test_float.py4
-rw-r--r--odoo/addons/base/tests/test_func.py4
-rw-r--r--odoo/addons/base/tests/test_orm.py6
-rw-r--r--odoo/addons/base/tests/test_res_config.py7
-rw-r--r--odoo/addons/base/tests/test_translate.py3
-rw-r--r--odoo/addons/test_impex/models.py7
-rw-r--r--odoo/addons/test_impex/tests/test_export.py9
-rw-r--r--odoo/addons/test_new_api/models.py3
-rw-r--r--odoo/addons/test_new_api/tests/test_attributes.py3
-rw-r--r--odoo/addons/test_new_api/tests/test_new_fields.py6
-rw-r--r--odoo/addons/test_performance/tests/test_performance.py4
-rw-r--r--odoo/fields.py30
-rw-r--r--odoo/http.py10
-rw-r--r--odoo/models.py50
-rw-r--r--odoo/modules/migration.py1
-rw-r--r--odoo/modules/module.py4
-rw-r--r--odoo/osv/expression.py22
-rw-r--r--odoo/osv/orm.py3
-rw-r--r--odoo/service/db.py3
-rw-r--r--odoo/sql_db.py4
-rw-r--r--odoo/tests/common.py3
-rw-r--r--odoo/tools/appdirs.py3
-rw-r--r--odoo/tools/cache.py4
-rw-r--r--odoo/tools/config.py12
-rw-r--r--odoo/tools/convert.py6
-rw-r--r--odoo/tools/float_utils.py3
-rw-r--r--odoo/tools/image.py4
-rw-r--r--odoo/tools/mail.py6
-rw-r--r--odoo/tools/misc.py14
-rw-r--r--odoo/tools/parse_version.py4
-rw-r--r--odoo/tools/safe_eval.py3
-rw-r--r--odoo/tools/test_reports.py10
-rw-r--r--odoo/tools/translate.py12
106 files changed, 313 insertions, 426 deletions
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 """<script type='text/javascript'>
window.attachments = %s;
diff --git a/addons/web_editor/models/ir_qweb.py b/addons/web_editor/models/ir_qweb.py
index 22a923e1854..5d006ea1ca9 100644
--- a/addons/web_editor/models/ir_qweb.py
+++ b/addons/web_editor/models/ir_qweb.py
@@ -223,7 +223,7 @@ class DateTime(models.AbstractModel):
attrs = super(DateTime, self).attributes(record, field_name, options, values)
if options.get('inherit_branding'):
value = record[field_name]
- if isinstance(value, pycompat.string_types):
+ if isinstance(value, str):
value = fields.Datetime.from_string(value)
if value:
# convert from UTC (server timezone) to user timezone
diff --git a/addons/web_editor/models/ir_ui_view.py b/addons/web_editor/models/ir_ui_view.py
index 532e3de70d9..23bf488ed47 100644
--- a/addons/web_editor/models/ir_ui_view.py
+++ b/addons/web_editor/models/ir_ui_view.py
@@ -7,7 +7,6 @@ from lxml import etree, html
from odoo.exceptions import AccessError
from odoo import api, fields, models
-from odoo.tools import pycompat
_logger = logging.getLogger(__name__)
@@ -117,7 +116,7 @@ class IrUiView(models.Model):
return False
if len(arch1) != len(arch2):
return False
- return all(self._are_archs_equal(arch1, arch2) for arch1, arch2 in pycompat.izip(arch1, arch2))
+ return all(self._are_archs_equal(arch1, arch2) for arch1, arch2 in zip(arch1, arch2))
@api.multi
def replace_arch_section(self, section_xpath, replacement, replace_tail=False):
@@ -201,9 +200,9 @@ class IrUiView(models.Model):
@api.model
def _view_obj(self, view_id):
- if isinstance(view_id, pycompat.string_types):
+ if isinstance(view_id, str):
return self.search([('key', '=', view_id)]) or self.env.ref(view_id)
- elif isinstance(view_id, pycompat.integer_types):
+ elif isinstance(view_id, int):
return self.browse(view_id)
# assume it's already a view object (WTF?)
return view_id
diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py
index e68d208fb52..50f1373665a 100644
--- a/addons/website/controllers/main.py
+++ b/addons/website/controllers/main.py
@@ -16,7 +16,7 @@ import odoo
from odoo import http, models, fields, _
from odoo.http import request
-from odoo.tools import pycompat, OrderedSet
+from odoo.tools import OrderedSet
from odoo.addons.http_routing.models.ir_http import slug, _guess_mimetype
from odoo.addons.web.controllers.main import Binary
from odoo.addons.portal.controllers.portal import pager as portal_pager
@@ -410,7 +410,7 @@ class Website(Home):
action = action_id = None
# find the action_id: either an xml_id, the path, or an ID
- if isinstance(path_or_xml_id_or_id, pycompat.string_types) and '.' in path_or_xml_id_or_id:
+ if isinstance(path_or_xml_id_or_id, str) and '.' in path_or_xml_id_or_id:
action = request.env.ref(path_or_xml_id_or_id, raise_if_not_found=False)
if not action:
action = ServerActions.search([('website_path', '=', path_or_xml_id_or_id), ('website_published', '=', True)], limit=1)
diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py
index b739c32c934..f45f602fa8b 100644
--- a/addons/website/models/ir_ui_view.py
+++ b/addons/website/models/ir_ui_view.py
@@ -10,7 +10,6 @@ from odoo import tools
from odoo.addons.http_routing.models.ir_http import url_for
from odoo.osv import expression
from odoo.http import request
-from odoo.tools import pycompat
_logger = logging.getLogger(__name__)
@@ -167,7 +166,7 @@ class View(models.Model):
@api.model
def _view_obj(self, view_id):
- if isinstance(view_id, pycompat.string_types):
+ if isinstance(view_id, str):
if 'website_id' in self._context:
domain = [('key', '=', view_id)] + self.env['website'].website_domain(self._context.get('website_id'))
order = 'website_id'
@@ -179,7 +178,7 @@ class View(models.Model):
return views.filter_duplicate()
else:
return self.env.ref(view_id)
- elif isinstance(view_id, pycompat.integer_types):
+ elif isinstance(view_id, int):
return self.browse(view_id)
# assume it's already a view object (WTF?)
@@ -216,7 +215,7 @@ class View(models.Model):
@api.model
@tools.ormcache_context('self._uid', 'xml_id', keys=('website_id',))
def get_view_id(self, xml_id):
- if 'website_id' in self._context and not isinstance(xml_id, pycompat.integer_types):
+ if 'website_id' in self._context and not isinstance(xml_id, int):
current_website = self.env['website'].browse(self._context.get('website_id'))
domain = ['&', ('key', '=', xml_id)] + current_website.website_domain()
diff --git a/addons/website/models/res_partner.py b/addons/website/models/res_partner.py
index 81ae2e73b92..45d65919cd9 100644
--- a/addons/website/models/res_partner.py
+++ b/addons/website/models/res_partner.py
@@ -4,7 +4,6 @@
import werkzeug
from odoo import api, fields, models
-from odoo.tools.pycompat import izip
def urlplus(url, params):
@@ -51,5 +50,5 @@ class Partner(models.Model):
super(Partner, self2)._compute_display_name()
# onchange uses the cache to retrieve value, we need to copy computed_value into the initial env
- for record, record2 in izip(self, self2):
+ for record, record2 in zip(self, self2):
record.display_name = record2.display_name
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index 66b73c95b37..593c1b721d7 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -13,7 +13,6 @@ from odoo import api, fields, models, tools
from odoo.addons.http_routing.models.ir_http import slugify, _guess_mimetype
from odoo.addons.website.models.ir_http import sitemap_qs2dom
from odoo.addons.portal.controllers.portal import pager
-from odoo.tools import pycompat
from odoo.http import request
from odoo.osv import expression
from odoo.osv.expression import FALSE_DOMAIN
@@ -509,7 +508,7 @@ class Website(models.Model):
@api.model
def get_template(self, template):
View = self.env['ir.ui.view']
- if isinstance(template, pycompat.integer_types):
+ if isinstance(template, int):
view_id = template
else:
if '.' not in template:
@@ -1187,7 +1186,7 @@ class Menu(models.Model):
for menu in data['data']:
mid = menu['id']
# new menu are prefixed by new-
- if isinstance(mid, pycompat.string_types):
+ if isinstance(mid, str):
new_menu = self.create({'name': menu['name'], 'website_id': website_id})
replace_id(mid, new_menu.id)
for menu in data['data']:
diff --git a/addons/website/tests/test_crawl.py b/addons/website/tests/test_crawl.py
index 2c138658740..81907aa3a16 100644
--- a/addons/website/tests/test_crawl.py
+++ b/addons/website/tests/test_crawl.py
@@ -10,7 +10,6 @@ from werkzeug import urls
import odoo
import re
-from odoo.tools import pycompat
_logger = logging.getLogger(__name__)
diff --git a/addons/website_forum/models/forum.py b/addons/website_forum/models/forum.py
index 960a241d948..ab1c3d97288 100644
--- a/addons/website_forum/models/forum.py
+++ b/addons/website_forum/models/forum.py
@@ -12,7 +12,7 @@ from werkzeug.exceptions import Forbidden
from odoo import api, fields, models, modules, tools, SUPERUSER_ID, _
from odoo.exceptions import UserError, ValidationError
-from odoo.tools import pycompat, misc
+from odoo.tools import misc
_logger = logging.getLogger(__name__)
@@ -376,7 +376,7 @@ class Post(models.Model):
is_admin = user.id == SUPERUSER_ID
# sudoed recordset instead of individual posts so values can be
# prefetched in bulk
- for post, post_sudo in pycompat.izip(self, self.sudo()):
+ for post, post_sudo in zip(self, self.sudo()):
is_creator = post.create_uid == user
post.karma_accept = post.forum_id.karma_answer_accept_own if post.parent_id.create_uid == user else post.forum_id.karma_answer_accept_all
diff --git a/addons/website_sale/models/product.py b/addons/website_sale/models/product.py
index d1ddf51c581..d8921442080 100644
--- a/addons/website_sale/models/product.py
+++ b/addons/website_sale/models/product.py
@@ -3,7 +3,6 @@
from odoo import api, fields, models, tools, _
from odoo.addons import decimal_precision as dp
-from odoo.tools import pycompat
from odoo.tools.translate import html_translate
from odoo.tools import float_is_zero
@@ -137,7 +136,7 @@ class ProductTemplate(models.Model):
# This makes sure that every template below has a corresponding product in the zipped result.
self = self.filtered('product_variant_id')
# use mapped who returns a recordset with only itself to prefetch (and don't prefetch every product_variant_ids)
- for template, product in pycompat.izip(self, self.mapped('product_variant_id')):
+ for template, product in zip(self, self.mapped('product_variant_id')):
template.website_price = product.website_price
template.website_public_price = product.website_public_price
template.website_price_difference = product.website_price_difference
@@ -204,7 +203,7 @@ class Product(models.Model):
ret = self.env.user.has_group('account.group_show_line_subtotals_tax_excluded') and 'total_excluded' or 'total_included'
- for p, p2 in pycompat.izip(self, self2):
+ for p, p2 in zip(self, self2):
taxes = partner.property_account_position_id.map_tax(p.sudo().taxes_id.filtered(lambda x: x.company_id == company_id), p, partner)
p.website_price = taxes.compute_all(p2.price, pricelist.currency_id, quantity=qty, product=p2, partner=partner)[ret]
price_without_pricelist = taxes.compute_all(p.list_price, pricelist.currency_id)[ret]
diff --git a/doc/_extensions/github_link.py b/doc/_extensions/github_link.py
index 72d51bfeb60..8f7a0084039 100644
--- a/doc/_extensions/github_link.py
+++ b/doc/_extensions/github_link.py
@@ -4,8 +4,6 @@ import os.path
from werkzeug import urls
-from odoo.tools import pycompat
-
"""
* adds github_link(mode) context variable: provides URL (in relevant mode) of
current document on github
@@ -100,7 +98,7 @@ def add_doc_link(app, pagename, templatename, context, doctree):
# in 1.3 source_suffix can be a list
# in 1.8 source_suffix can be a mapping
# FIXME: will break if we ever add support for !rst markdown documents maybe
- if not isinstance(source_suffix, pycompat.string_types):
+ if not isinstance(source_suffix, str):
source_suffix = next(iter(source_suffix))
# can't use functools.partial because 3rd positional is line not mode
context['github_link'] = lambda mode='edit': make_github_link(
diff --git a/doc/_extensions/odoo_ext/translator.py b/doc/_extensions/odoo_ext/translator.py
index 491f02a2ad3..211159e219c 100644
--- a/doc/_extensions/odoo_ext/translator.py
+++ b/doc/_extensions/odoo_ext/translator.py
@@ -13,8 +13,6 @@ from docutils import nodes
from sphinx import addnodes, util
from sphinx.locale import admonitionlabels
-from odoo.tools import pycompat
-
def _parents(node):
while node.parent:
@@ -66,7 +64,7 @@ class BootstrapTranslator(nodes.NodeVisitor, object):
self.param_separator = ','
def encode(self, text):
- return pycompat.text_type(text).translate({
+ return str(text).translate({
ord('&'): u'&amp;',
ord('<'): u'&lt;',
ord('"'): u'&quot;',
@@ -75,7 +73,7 @@ class BootstrapTranslator(nodes.NodeVisitor, object):
})
def starttag(self, node, tagname, **attributes):
- tagname = pycompat.text_type(tagname).lower()
+ tagname = str(tagname).lower()
# extract generic attributes
attrs = {name.lower(): value for name, value in attributes.items()}
@@ -110,7 +108,7 @@ class BootstrapTranslator(nodes.NodeVisitor, object):
# only "space characters" SPACE, CHARACTER TABULATION, LINE FEED,
# FORM FEED and CARRIAGE RETURN should be collapsed, not al White_Space
def attval(self, value, whitespace=re.compile(u'[ \t\n\f\r]+')):
- return self.encode(whitespace.sub(u' ', pycompat.text_type(value)))
+ return self.encode(whitespace.sub(' ', str(value)))
def astext(self):
return u''.join(self.body)
diff --git a/doc/python3.rst b/doc/python3.rst
index 88475d7dc4a..ac24983ceb7 100644
--- a/doc/python3.rst
+++ b/doc/python3.rst
@@ -299,8 +299,6 @@ under the single ``int`` type.
* the ``L`` suffix for integer literals must be removed
* calls to ``long`` must be replaced by calls to ``int``
- * ``(int, long)`` for type-checking purposes must be replaced by
- :py:data:`odoo.tools.pycompat.integer_types`
* the ``L`` suffix on numbers is unsupported in Python 3, and unnecessary in
@@ -311,18 +309,6 @@ under the single ``int`` type.
subtype of ``int`` (nor the reverse), and ``isinstance(value, (int, long))``
is thus generally necessary to catch all integrals.
- For that case, Odoo 11 now provides a compatibility module with an
- :py:data:`~odoo.tools.pycompat.integer_types` definition which can be used
- for type-testing.
-
- It is a tuple of types so when used with ``isinstance`` it can be provided
- directly or inside an other tuple alongside other types e.g.
- ``isinstance(value, (BaseModel, integer_types))``.
-
- However when used with ``type`` directly (which should be avoided) you
- should use the ``in`` operator, and if you need other types you need to
- concatenate ``integer_types`` to an other tuple.
-
``reduce``
##########
@@ -411,18 +397,6 @@ Both versions have the following prefixes for string literals:
For best cross-version compatibility you should avoid unprefixed string
literals unless you *specifically* need a "native string" [#native-string]_.
-For easier type-testing, :mod:`odoo.tools.pycompat` provides the following
-constants:
-
-* :data:`~odoo.tools.pycompat.string_types` is an alias/type tuple for testing
- string types, essentially a replacement of testing for ``basestring`` or
- ``(str, unicode)``.
-* :data:`~odoo.tools.pycompat.text_type` is the proper *text* type for the
- current version, it should mostly be used for converting non-bytes objects
- to text.
-* ``bytes`` should be avoided for type conversions, though it can be used to
- check if an object is a bytestring.
-
``open``
--------
diff --git a/odoo/addons/base/models/assetsbundle.py b/odoo/addons/base/models/assetsbundle.py
index f3754859b4b..73a569b5bd8 100644
--- a/odoo/addons/base/models/assetsbundle.py
+++ b/odoo/addons/base/models/assetsbundle.py
@@ -17,7 +17,7 @@ from datetime import datetime
from subprocess import Popen, PIPE
from collections import OrderedDict
from odoo import fields, tools, SUPERUSER_ID
-from odoo.tools.pycompat import string_types, to_text
+from odoo.tools.pycompat import to_text
from odoo.http import request
from odoo.modules.module import get_resource_path
from .qweb import escape
@@ -120,7 +120,7 @@ class AssetsBundle(object):
for tagName, attributes, content in nodes:
html = u"<%s " % tagName
for name, value in attributes.items():
- if value or isinstance(value, string_types):
+ if value or isinstance(value, str):
html += u' %s="%s"' % (name, escape(to_text(value)))
if content is None:
html += u'/>'
@@ -602,7 +602,7 @@ class WebAsset(object):
tagName, attributes, content = self.to_node()
html = u"<%s " % tagName
for name, value in attributes.items():
- if value or isinstance(value, string_types):
+ if value or isinstance(value, str):
html += u' %s="%s"' % (name, escape(to_text(value)))
if content is None:
html += u'/>'
diff --git a/odoo/addons/base/models/ir_actions.py b/odoo/addons/base/models/ir_actions.py
index 634e5f60ca8..bb45ea1a75f 100644
--- a/odoo/addons/base/models/ir_actions.py
+++ b/odoo/addons/base/models/ir_actions.py
@@ -5,7 +5,7 @@ import odoo
from odoo import api, fields, models, tools, SUPERUSER_ID, _
from odoo.exceptions import MissingError, UserError, ValidationError, AccessError
from odoo.tools.safe_eval import safe_eval, test_python_expr
-from odoo.tools import pycompat, wrap_module
+from odoo.tools import wrap_module
from odoo.http import request
import base64
@@ -774,7 +774,7 @@ class IrActionsActClient(models.Model):
@api.depends('params_store')
def _compute_params(self):
self_bin = self.with_context(bin_size=False, bin_size_params_store=False)
- for record, record_bin in pycompat.izip(self, self_bin):
+ for record, record_bin in zip(self, self_bin):
record.params = record_bin.params_store and safe_eval(record_bin.params_store, {'uid': self._uid})
def _inverse_params(self):
diff --git a/odoo/addons/base/models/ir_config_parameter.py b/odoo/addons/base/models/ir_config_parameter.py
index eed10daadd8..04f8062d1f1 100644
--- a/odoo/addons/base/models/ir_config_parameter.py
+++ b/odoo/addons/base/models/ir_config_parameter.py
@@ -8,7 +8,7 @@ import uuid
import logging
from odoo import api, fields, models
-from odoo.tools import config, ormcache, mute_logger, pycompat
+from odoo.tools import config, ormcache, mute_logger
_logger = logging.getLogger(__name__)
@@ -16,8 +16,8 @@ _logger = logging.getLogger(__name__)
A dictionary holding some configuration parameters to be initialized when the database is created.
"""
_default_parameters = {
- "database.secret": lambda: pycompat.text_type(uuid.uuid4()),
- "database.uuid": lambda: pycompat.text_type(uuid.uuid1()),
+ "database.secret": lambda: str(uuid.uuid4()),
+ "database.uuid": lambda: str(uuid.uuid1()),
"database.create_date": fields.Datetime.now,
"web.base.url": lambda: "http://localhost:%s" % config.get('http_port'),
"base.login_cooldown_after": lambda: 10,
diff --git a/odoo/addons/base/models/ir_fields.py b/odoo/addons/base/models/ir_fields.py
index 90208e7a86a..e6392441f74 100644
--- a/odoo/addons/base/models/ir_fields.py
+++ b/odoo/addons/base/models/ir_fields.py
@@ -8,7 +8,7 @@ import psycopg2
import pytz
from odoo import api, fields, models, _
-from odoo.tools import ustr, pycompat
+from odoo.tools import ustr
REFERENCING_FIELDS = {None, 'id', '.id'}
def only_ref_fields(record):
@@ -39,9 +39,9 @@ class IrFieldsConverter(models.AbstractModel):
@api.model
def _format_import_error(self, error_type, error_msg, error_params=(), error_args=None):
# sanitize error params for later formatting by the import system
- sanitize = lambda p: p.replace('%', '%%') if isinstance(p, pycompat.string_types) else p
+ sanitize = lambda p: p.replace('%', '%%') if isinstance(p, str) else p
if error_params:
- if isinstance(error_params, pycompat.string_types):
+ if isinstance(error_params, str):
error_params = sanitize(error_params)
elif isinstance(error_params, dict):
error_params = {k: sanitize(v) for k, v in error_params.items()}
@@ -79,7 +79,7 @@ class IrFieldsConverter(models.AbstractModel):
try:
converted[field], ws = converters[field](value)
for w in ws:
- if isinstance(w, pycompat.string_types):
+ if isinstance(w, str):
# wrap warning string in an ImportWarning for
# uniform handling
w = ImportWarning(w)
@@ -270,14 +270,14 @@ class IrFieldsConverter(models.AbstractModel):
for item, label in selection:
label = ustr(label)
labels = [label] + self._get_translations(('selection', 'model', 'code'), label)
- if value == pycompat.text_type(item) or value in labels:
+ if value == str(item) or value in labels:
return item, []
raise self._format_import_error(
ValueError,
_(u"Value '%s' not found in selection field '%%(field)s'"),
value,
- {'moreinfo': [_label or pycompat.text_type(item) for item, _label in selection if _label or item]}
+ {'moreinfo': [_label or str(item) for item, _label in selection if _label or item]}
)
@api.model
diff --git a/odoo/addons/base/models/ir_http.py b/odoo/addons/base/models/ir_http.py
index 205be37929e..63d12137d7a 100644
--- a/odoo/addons/base/models/ir_http.py
+++ b/odoo/addons/base/models/ir_http.py
@@ -332,7 +332,7 @@ class IrHttp(models.AbstractModel):
if module_resource_path.startswith(module_path):
with open(module_resource_path, 'rb') as f:
content = base64.b64encode(f.read())
- last_update = pycompat.text_type(os.path.getmtime(module_resource_path))
+ last_update = str(os.path.getmtime(module_resource_path))
if not module_resource_path:
module_resource_path = obj.url
diff --git a/odoo/addons/base/models/ir_mail_server.py b/odoo/addons/base/models/ir_mail_server.py
index 3bc39f4cb54..b7597ebaa77 100644
--- a/odoo/addons/base/models/ir_mail_server.py
+++ b/odoo/addons/base/models/ir_mail_server.py
@@ -62,7 +62,7 @@ def encode_header(header_text):
return ""
header_text = ustr(header_text) # FIXME: require unicode higher up?
if is_ascii(header_text):
- return pycompat.to_native(header_text)
+ return pycompat.to_text(header_text)
return Header(header_text, 'utf-8')
def encode_header_param(param_text):
@@ -83,7 +83,7 @@ def encode_header_param(param_text):
return ""
param_text = ustr(param_text) # FIXME: require unicode higher up?
if is_ascii(param_text):
- return pycompat.to_native(param_text) # TODO: is that actually necessary?
+ return pycompat.to_text(param_text) # TODO: is that actually necessary?
return Charset("utf-8").header_encode(param_text)
address_pattern = re.compile(r'([^ ,<@]+@[^> ,]+)')
@@ -121,7 +121,7 @@ def encode_rfc2822_address_header(header_text):
name = Header(pycompat.to_text(name)).encode()
return formataddr((name, email))
- addresses = getaddresses([pycompat.to_native(ustr(header_text))])
+ addresses = getaddresses([pycompat.to_text(ustr(header_text))])
return COMMASPACE.join(encode_addr(a) for a in addresses)
@@ -268,8 +268,8 @@ class IrMailServer(models.Model):
# The user/password must be converted to bytestrings in order to be usable for
# certain hashing schemes, like HMAC.
# See also bug #597143 and python issue #5285
- smtp_user = pycompat.to_native(ustr(smtp_user))
- smtp_password = pycompat.to_native(ustr(smtp_password))
+ smtp_user = pycompat.to_text(ustr(smtp_user))
+ smtp_password = pycompat.to_text(ustr(smtp_password))
connection.login(smtp_user, smtp_password)
return connection
@@ -344,7 +344,7 @@ class IrMailServer(models.Model):
msg['Date'] = formatdate()
# Custom headers may override normal headers or provide additional ones
for key, value in headers.items():
- msg[pycompat.to_native(ustr(key))] = encode_header(value)
+ msg[pycompat.to_text(ustr(key))] = encode_header(value)
if subtype == 'html' and not body_alternative:
# Always provide alternative text body ourselves if possible.
diff --git a/odoo/addons/base/models/ir_model.py b/odoo/addons/base/models/ir_model.py
index c9b45104c65..089689a35a2 100644
--- a/odoo/addons/base/models/ir_model.py
+++ b/odoo/addons/base/models/ir_model.py
@@ -282,7 +282,7 @@ class IrModel(models.Model):
def _instanciate(self, model_data):
""" Return a class for the custom model given by parameters ``model_data``. """
class CustomModel(models.Model):
- _name = pycompat.to_native(model_data['model'])
+ _name = pycompat.to_text(model_data['model'])
_description = model_data['name']
_module = False
_custom = True
@@ -1152,7 +1152,7 @@ class IrModelAccess(models.Model):
else:
model_name = model
- if isinstance(group_ids, pycompat.integer_types):
+ if isinstance(group_ids, int):
group_ids = [group_ids]
query = """ SELECT 1 FROM ir_model_access a
@@ -1190,7 +1190,7 @@ class IrModelAccess(models.Model):
# User root have all accesses
return True
- assert isinstance(model, pycompat.string_types), 'Not a model name: %s' % (model,)
+ assert isinstance(model, str), 'Not a model name: %s' % (model,)
assert mode in ('read', 'write', 'create', 'unlink'), 'Invalid access mode'
# TransientModel records have no access rights, only an implicit access rule
diff --git a/odoo/addons/base/models/ir_module.py b/odoo/addons/base/models/ir_module.py
index 350b4d7a489..824365424cc 100644
--- a/odoo/addons/base/models/ir_module.py
+++ b/odoo/addons/base/models/ir_module.py
@@ -14,8 +14,6 @@ import zipfile
import requests
-from odoo.tools import pycompat
-
from docutils import nodes
from docutils.core import publish_string
from docutils.transforms import Transform, writer_aux
@@ -684,7 +682,7 @@ class Module(models.Model):
updated_values = {}
for key in values:
old = getattr(mod, key)
- updated = tools.ustr(values[key]) if isinstance(values[key], pycompat.string_types) else values[key]
+ updated = tools.ustr(values[key]) if isinstance(values[key], str) else values[key]
if (old or updated) and updated != old:
updated_values[key] = values[key]
if terp.get('installable', True) and mod.state == 'uninstallable':
diff --git a/odoo/addons/base/models/ir_property.py b/odoo/addons/base/models/ir_property.py
index cfe3cd968d7..2d5c1742cfa 100644
--- a/odoo/addons/base/models/ir_property.py
+++ b/odoo/addons/base/models/ir_property.py
@@ -3,7 +3,7 @@
from odoo import api, fields, models, _
from odoo.exceptions import UserError
-from odoo.tools import pycompat, ormcache
+from odoo.tools import ormcache
TYPE2FIELD = {
'char': 'value_text',
@@ -82,7 +82,7 @@ class Property(models.Model):
if field == 'value_reference':
if isinstance(value, models.BaseModel):
value = '%s,%d' % (value._name, value.id)
- elif isinstance(value, pycompat.integer_types):
+ elif isinstance(value, int):
field_id = values.get('fields_id')
if not field_id:
if not prop:
diff --git a/odoo/addons/base/models/ir_qweb.py b/odoo/addons/base/models/ir_qweb.py
index 18717316f57..2e4070d2665 100644
--- a/odoo/addons/base/models/ir_qweb.py
+++ b/odoo/addons/base/models/ir_qweb.py
@@ -11,8 +11,6 @@ from lxml import html
from lxml import etree
from werkzeug import urls
-from odoo.tools import pycompat
-
from odoo import api, models, tools
from odoo.tools.safe_eval import assert_valid_codeobj, _BUILTINS, _SAFE_OPCODES
from odoo.http import request
@@ -130,7 +128,7 @@ class IrQWeb(models.AbstractModel, QWeb):
view = self.env['ir.ui.view'].browse(view_id)
return view.inherit_id is not None
- if isinstance(name, pycompat.integer_types) or is_child_view(name):
+ if isinstance(name, int) or is_child_view(name):
for node in etree.fromstring(template):
if node.get('t-name'):
node.set('t-name', str(name))
diff --git a/odoo/addons/base/models/ir_qweb_fields.py b/odoo/addons/base/models/ir_qweb_fields.py
index 023a9b6ef07..81e4c700d1a 100644
--- a/odoo/addons/base/models/ir_qweb_fields.py
+++ b/odoo/addons/base/models/ir_qweb_fields.py
@@ -234,7 +234,7 @@ class DateTimeConverter(models.AbstractModel):
lang = self.user_lang()
locale = babel.Locale.parse(lang.code)
- if isinstance(value, pycompat.string_types):
+ if isinstance(value, str):
value = fields.Datetime.from_string(value)
value = fields.Datetime.context_timestamp(self, value)
@@ -572,7 +572,7 @@ class RelativeDatetimeConverter(models.AbstractModel):
def value_to_html(self, value, options):
locale = babel.Locale.parse(self.user_lang().code)
- if isinstance(value, pycompat.string_types):
+ if isinstance(value, str):
value = fields.Datetime.from_string(value)
# value should be a naive datetime in UTC. So is fields.Datetime.now()
diff --git a/odoo/addons/base/models/ir_translation.py b/odoo/addons/base/models/ir_translation.py
index 103f5a64675..4aeae7c2cd6 100644
--- a/odoo/addons/base/models/ir_translation.py
+++ b/odoo/addons/base/models/ir_translation.py
@@ -8,7 +8,6 @@ from difflib import get_close_matches
from odoo import api, fields, models, tools, SUPERUSER_ID, _
from odoo.exceptions import AccessError, UserError, ValidationError
from odoo.modules import get_module_path, get_module_resource
-from odoo.tools import pycompat
_logger = logging.getLogger(__name__)
@@ -406,10 +405,10 @@ class IrTranslation(models.Model):
# always pass unicode so we can remove the string encoding/decoding.
if not lang:
return tools.ustr(source or '')
- if isinstance(types, pycompat.string_types):
+ if isinstance(types, str):
types = (types,)
if res_id:
- if isinstance(res_id, pycompat.integer_types):
+ if isinstance(res_id, int):
res_id = (res_id,)
else:
res_id = tuple(res_id)
diff --git a/odoo/addons/base/models/ir_ui_view.py b/odoo/addons/base/models/ir_ui_view.py
index 2c49ee065b8..b1c2a02505e 100644
--- a/odoo/addons/base/models/ir_ui_view.py
+++ b/odoo/addons/base/models/ir_ui_view.py
@@ -277,11 +277,11 @@ actual arch.
@api.depends('arch')
def _compute_arch_base(self):
# 'arch_base' is the same as 'arch' without translation
- for view, view_wo_lang in pycompat.izip(self, self.with_context(lang=None)):
+ for view, view_wo_lang in zip(self, self.with_context(lang=None)):
view.arch_base = view_wo_lang.arch
def _inverse_arch_base(self):
- for view, view_wo_lang in pycompat.izip(self, self.with_context(lang=None)):
+ for view, view_wo_lang in zip(self, self.with_context(lang=None)):
view_wo_lang.arch = view.arch_base
@api.depends('write_date')
@@ -293,7 +293,7 @@ actual arch.
view.model_data_id = data['id']
def _search_model_data_id(self, operator, value):
- name = 'name' if isinstance(value, pycompat.string_types) else 'id'
+ name = 'name' if isinstance(value, str) else 'id'
domain = [('model', '=', 'ir.ui.view'), (name, operator, value)]
data = self.env['ir.model.data'].sudo().search(domain)
return [('id', 'in', data.mapped('res_id'))]
@@ -1030,7 +1030,7 @@ actual arch.
if editable and not node.get('domain'):
domain = field._description_domain(self.env)
# process the field's domain as if it was in the view
- if isinstance(domain, pycompat.string_types):
+ if isinstance(domain, str):
process_expr(domain, get, 'domain', domain)
# retrieve subfields of 'parent'
model = self.env[field.comodel_name]
@@ -1175,7 +1175,7 @@ actual arch.
view ID or an XML ID. Note that this method may be overridden for other
kinds of template values.
"""
- if isinstance(template, pycompat.integer_types):
+ if isinstance(template, int):
return template
if '.' not in template:
raise ValueError('Invalid template id: %r' % template)
@@ -1277,7 +1277,7 @@ actual arch.
@api.multi
def render(self, values=None, engine='ir.qweb', minimal_qcontext=False):
- assert isinstance(self.id, pycompat.integer_types)
+ assert isinstance(self.id, int)
qcontext = dict() if minimal_qcontext else self._prepare_qcontext()
qcontext.update(values or {})
diff --git a/odoo/addons/base/models/qweb.py b/odoo/addons/base/models/qweb.py
index 51693c55cb1..071967093d4 100644
--- a/odoo/addons/base/models/qweb.py
+++ b/odoo/addons/base/models/qweb.py
@@ -35,18 +35,6 @@ unsafe_eval = eval
_logger = logging.getLogger(__name__)
-# in Python 2, arguments (within the ast.arguments structure) are expressions
-# (since they can be tuples), generally
-# ast.Name(id: identifyer, ctx=ast.Param()), whereas in Python 3 they are
-# ast.arg(arg: identifier, annotation: expr?) provide a toplevel arg()
-# function which matches ast.arg producing the relevant ast.Name in Python 2.
-arg = getattr(ast, 'arg', lambda arg, annotation: ast.Name(id=arg, ctx=ast.Param()))
-# also Python 3's arguments has grown *2* new mandatory arguments, kwonlyargs
-# and kw_defaults for keyword-only arguments and their default values (if any)
-# so add a shim for *that* based on the signature of Python 3 I guess?
-arguments = ast.arguments
-if pycompat.PY2:
- arguments = lambda args, vararg, kwonlyargs, kw_defaults, kwarg, defaults: ast.arguments(args=args, vararg=vararg, kwarg=kwarg, defaults=defaults)
####################################
### qweb tools ###
####################################
@@ -98,7 +86,7 @@ class Contextifier(ast.NodeTransformer):
if args.kwarg: names.append(args.kwarg)
# remap defaults in case there's any
return ast.copy_location(ast.Lambda(
- args=arguments(
+ args=ast.arguments(
args=args.args,
defaults=[self.visit(default) for default in args.defaults],
vararg=args.vararg,
@@ -190,7 +178,7 @@ def foreach_iterator(base_ctx, enum, name):
if isinstance(enum, Mapping):
enum = enum.items()
else:
- enum = pycompat.izip(*tee(enum))
+ enum = zip(*tee(enum))
value_key = '%s_value' % name
index_key = '%s_index' % name
first_key = '%s_first' % name
@@ -526,11 +514,10 @@ class QWeb(object):
Define:
* escape
* to_text (empty string for a None or False, otherwise unicode string)
- * string_types (replacement for basestring)
"""
return ast.parse(dedent("""
from collections import OrderedDict
- from odoo.tools.pycompat import to_text, string_types
+ from odoo.tools.pycompat import to_text
from odoo.addons.base.models.qweb import escape, foreach_iterator
"""))
@@ -547,12 +534,12 @@ class QWeb(object):
# def $name(self, append, values, options, log)
fn = ast.FunctionDef(
name=name,
- args=arguments(args=[
- arg(arg='self', annotation=None),
- arg(arg='append', annotation=None),
- arg(arg='values', annotation=None),
- arg(arg='options', annotation=None),
- arg(arg='log', annotation=None),
+ args=ast.arguments(args=[
+ ast.arg(arg='self', annotation=None),
+ ast.arg(arg='append', annotation=None),
+ ast.arg(arg='values', annotation=None),
+ ast.arg(arg='options', annotation=None),
+ ast.arg(arg='log', annotation=None),
], defaults=[], vararg=None, kwarg=None, kwonlyargs=[], kw_defaults=[]),
body=body or [ast.Return()],
decorator_list=[])
@@ -743,7 +730,7 @@ class QWeb(object):
func=ast.Name(id='isinstance', ctx=ast.Load()),
args=[
ast.Name(id='value', ctx=ast.Load()),
- ast.Name(id='string_types', ctx=ast.Load())
+ ast.Name(id='str', ctx=ast.Load())
],
keywords=[],
starargs=None, kwargs=None
@@ -1508,7 +1495,7 @@ class QWeb(object):
keys = []
values = []
for key, value in options['nsmap'].items():
- if isinstance(key, pycompat.string_types):
+ if isinstance(key, str):
keys.append(ast.Str(s=key))
elif key is None:
keys.append(ast.Name(id='None', ctx=ast.Load()))
@@ -1646,7 +1633,7 @@ class QWeb(object):
for m in _FORMAT_REGEX.finditer(f):
literal = f[base_idx:m.start()]
if literal:
- elts.append(ast.Str(literal if isinstance(literal, pycompat.text_type) else literal.decode('utf-8')))
+ elts.append(ast.Str(literal if isinstance(literal, str) else literal.decode('utf-8')))
expr = m.group(1) or m.group(2)
elts.append(self._compile_strexpr(expr))
@@ -1654,7 +1641,7 @@ class QWeb(object):
# string past last regex match
literal = f[base_idx:]
if literal:
- elts.append(ast.Str(literal if isinstance(literal, pycompat.text_type) else literal.decode('utf-8')))
+ elts.append(ast.Str(literal if isinstance(literal, str) else literal.decode('utf-8')))
return reduce(lambda acc, it: ast.BinOp(
left=acc,
diff --git a/odoo/addons/base/models/res_bank.py b/odoo/addons/base/models/res_bank.py
index 88ff7b7984c..0a2392f38e0 100644
--- a/odoo/addons/base/models/res_bank.py
+++ b/odoo/addons/base/models/res_bank.py
@@ -6,7 +6,6 @@ import collections
from odoo import api, fields, models, _
from odoo.osv import expression
-from odoo.tools import pycompat
import werkzeug.urls
@@ -108,7 +107,7 @@ class ResPartnerBank(models.Model):
if args[pos][0] == 'acc_number':
op = args[pos][1]
value = args[pos][2]
- if not isinstance(value, pycompat.string_types) and isinstance(value, collections.Iterable):
+ if not isinstance(value, str) and isinstance(value, collections.Iterable):
value = [sanitize_account_number(i) for i in value]
else:
value = sanitize_account_number(value)
diff --git a/odoo/addons/base/models/res_partner.py b/odoo/addons/base/models/res_partner.py
index 6792f44b772..522387d2fbb 100644
--- a/odoo/addons/base/models/res_partner.py
+++ b/odoo/addons/base/models/res_partner.py
@@ -18,7 +18,6 @@ from odoo import api, fields, models, tools, SUPERUSER_ID, _
from odoo.modules import get_module_resource
from odoo.osv.expression import get_unaccent_wrapper
from odoo.exceptions import UserError, ValidationError
-from odoo.tools import pycompat
# Global variables used for the warning fields declared on the res.partner
# in the following modules : sale, purchase, account, stock
@@ -551,7 +550,7 @@ class Partner(models.Model):
vals['image'] = self._get_default_image(vals.get('type'), vals.get('is_company'), vals.get('parent_id'))
tools.image_resize_images(vals, sizes={'image': (1024, None)})
partners = super(Partner, self).create(vals_list)
- for partner, vals in pycompat.izip(partners, vals_list):
+ for partner, vals in zip(partners, vals_list):
partner._fields_sync(vals)
partner._handle_first_contact_creation()
return partners
diff --git a/odoo/addons/base/models/res_users.py b/odoo/addons/base/models/res_users.py
index 5b4202da7c2..dfa5f61e25b 100644
--- a/odoo/addons/base/models/res_users.py
+++ b/odoo/addons/base/models/res_users.py
@@ -21,7 +21,7 @@ from odoo.exceptions import AccessDenied, AccessError, UserError, ValidationErro
from odoo.http import request
from odoo.osv import expression
from odoo.service.db import check_super
-from odoo.tools import partition, pycompat, collections
+from odoo.tools import partition, collections
_logger = logging.getLogger(__name__)
@@ -110,7 +110,7 @@ class Groups(models.Model):
@api.depends('category_id.name', 'name')
def _compute_full_name(self):
# Important: value must be stored in environment of group, not group1!
- for group, group1 in pycompat.izip(self, self.sudo()):
+ for group, group1 in zip(self, self.sudo()):
if group1.category_id:
group.full_name = '%s / %s' % (group1.category_id.name, group1.name)
else:
@@ -124,7 +124,7 @@ class Groups(models.Model):
return expression.AND(domains)
else:
return expression.OR(domains)
- if isinstance(operand, pycompat.string_types):
+ if isinstance(operand, str):
lst = False
operand = [operand]
where = []
@@ -421,7 +421,7 @@ class Users(models.Model):
@api.model
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
- groupby_fields = set([groupby] if isinstance(groupby, pycompat.string_types) else groupby)
+ groupby_fields = set([groupby] if isinstance(groupby, str) else groupby)
if groupby_fields.intersection(USER_PRIVATE_FIELDS):
raise AccessError(_("Invalid 'group by' parameter"))
return super(Users, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy)
@@ -910,7 +910,7 @@ class GroupsImplied(models.Model):
def create(self, vals_list):
user_ids_list = [vals.pop('users', None) for vals in vals_list]
groups = super(GroupsImplied, self).create(vals_list)
- for group, user_ids in pycompat.izip(groups, user_ids_list):
+ for group, user_ids in zip(groups, user_ids_list):
if user_ids:
# delegate addition of users to add implied groups
group.write({'users': user_ids})
@@ -922,7 +922,7 @@ class GroupsImplied(models.Model):
if values.get('users') or values.get('implied_ids'):
# add all implied groups (to all users of each group)
for group in self:
- vals = {'users': list(pycompat.izip(repeat(4), group.with_context(active_test=False).users.ids))}
+ vals = {'users': list(zip(repeat(4), group.with_context(active_test=False).users.ids))}
super(GroupsImplied, group.trans_implied_ids).write(vals)
return res
@@ -1164,8 +1164,8 @@ class UsersView(models.Model):
if 'groups_id' not in values and (add or rem):
# remove group ids in `rem` and add group ids in `add`
values1['groups_id'] = list(itertools.chain(
- pycompat.izip(repeat(3), rem),
- pycompat.izip(repeat(4), add)
+ zip(repeat(3), rem),
+ zip(repeat(4), add)
))
return values1
diff --git a/odoo/addons/base/tests/test_api.py b/odoo/addons/base/tests/test_api.py
index 270a8d75df4..5c7c2ef64d3 100644
--- a/odoo/addons/base/tests/test_api.py
+++ b/odoo/addons/base/tests/test_api.py
@@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models
-from odoo.tools import mute_logger, pycompat
+from odoo.tools import mute_logger
from odoo.tests import common
from odoo.exceptions import AccessError
@@ -69,8 +69,8 @@ class TestAPI(common.TransactionCase):
self.cr.execute("SELECT COUNT(*) FROM res_partner WHERE active")
count1 = self.cr.fetchone()[0]
count2 = self.env['res.partner'].search([], count=True)
- self.assertIsInstance(count1, pycompat.integer_types)
- self.assertIsInstance(count2, pycompat.integer_types)
+ self.assertIsInstance(count1, int)
+ self.assertIsInstance(count2, int)
self.assertEqual(count1, count2)
@mute_logger('odoo.models')
diff --git a/odoo/addons/base/tests/test_float.py b/odoo/addons/base/tests/test_float.py
index a5f91982303..4447b9de1c0 100644
--- a/odoo/addons/base/tests/test_float.py
+++ b/odoo/addons/base/tests/test_float.py
@@ -4,7 +4,7 @@
from math import log10
from odoo.tests.common import TransactionCase
-from odoo.tools import float_compare, float_is_zero, float_repr, float_round, float_split_str, pycompat
+from odoo.tools import float_compare, float_is_zero, float_repr, float_round, float_split_str
class TestFloatPrecision(TransactionCase):
@@ -111,7 +111,7 @@ class TestFloatPrecision(TransactionCase):
# Note: max precision for double floats is 53 bits of precision or
# 17 significant decimal digits
for magnitude in range(7):
- for frac, exp, prec in pycompat.izip(fractions, expecteds, precisions):
+ for frac, exp, prec in zip(fractions, expecteds, precisions):
for sign in [-1,1]:
for x in range(0, 10000, 97):
n = x * 10 ** magnitude
diff --git a/odoo/addons/base/tests/test_func.py b/odoo/addons/base/tests/test_func.py
index 1b630060d7f..b0b540acb5d 100644
--- a/odoo/addons/base/tests/test_func.py
+++ b/odoo/addons/base/tests/test_func.py
@@ -5,7 +5,7 @@ import functools
import unittest
from odoo.tests.common import tagged
-from odoo.tools import frozendict, pycompat
+from odoo.tools import frozendict
from odoo.tools.func import compose
@@ -18,7 +18,7 @@ class TestCompose(unittest.TestCase):
def test_decorator(self):
""" ensure compose() can be partially applied as a decorator
"""
- @functools.partial(compose, pycompat.text_type)
+ @functools.partial(compose, str)
def mul(a, b):
return a * b
diff --git a/odoo/addons/base/tests/test_orm.py b/odoo/addons/base/tests/test_orm.py
index af515299d21..f51f928ab16 100644
--- a/odoo/addons/base/tests/test_orm.py
+++ b/odoo/addons/base/tests/test_orm.py
@@ -5,7 +5,7 @@ from collections import defaultdict
from odoo.exceptions import AccessError, MissingError
from odoo.tests.common import TransactionCase
-from odoo.tools import mute_logger, pycompat
+from odoo.tools import mute_logger
class TestORM(TransactionCase):
@@ -243,7 +243,7 @@ class TestORM(TransactionCase):
records = self.env['res.bank'].create(vals_list)
self.assertEqual(len(records), len(vals_list))
- for record, vals in pycompat.izip(records, vals_list):
+ for record, vals in zip(records, vals_list):
self.assertEqual(record.name, vals['name'])
self.assertEqual(record.email, vals.get('email', False))
@@ -279,7 +279,7 @@ class TestInherits(TransactionCase):
""" `default_get` cannot return a dictionary or a new id """
defaults = self.env['res.users'].default_get(['partner_id'])
if 'partner_id' in defaults:
- self.assertIsInstance(defaults['partner_id'], (bool, pycompat.integer_types))
+ self.assertIsInstance(defaults['partner_id'], (bool, int))
def test_create(self):
""" creating a user should automatically create a new partner """
diff --git a/odoo/addons/base/tests/test_res_config.py b/odoo/addons/base/tests/test_res_config.py
index 0f634b36cb3..70d1aed99b8 100644
--- a/odoo/addons/base/tests/test_res_config.py
+++ b/odoo/addons/base/tests/test_res_config.py
@@ -5,7 +5,6 @@ import logging
from odoo import exceptions
from odoo.tests.common import TransactionCase, tagged
-from odoo.tools import pycompat
_logger = logging.getLogger(__name__)
@@ -46,8 +45,8 @@ class TestResConfig(TransactionCase):
# Check types
self.assertIsInstance(res, tuple)
self.assertEqual(len(res), 2, "The result should contain 2 elements")
- self.assertIsInstance(res[0], pycompat.string_types)
- self.assertIsInstance(res[1], pycompat.integer_types)
+ self.assertIsInstance(res[0], str)
+ self.assertIsInstance(res[1], int)
# Check returned values
self.assertEqual(res[0], self.expected_path)
@@ -58,7 +57,7 @@ class TestResConfig(TransactionCase):
res = self.ResConfig.get_option_name(self.full_field_name)
# Check type
- self.assertIsInstance(res, pycompat.string_types)
+ self.assertIsInstance(res, str)
# Check returned value
self.assertEqual(res, self.expected_name)
diff --git a/odoo/addons/base/tests/test_translate.py b/odoo/addons/base/tests/test_translate.py
index c9d7f35ec4c..11bdf3d1cc8 100644
--- a/odoo/addons/base/tests/test_translate.py
+++ b/odoo/addons/base/tests/test_translate.py
@@ -3,7 +3,6 @@
import unittest
-from odoo.tools import pycompat
from odoo.tools import mute_logger
from odoo.tools.translate import quote, unquote, xml_translate, html_translate
from odoo.tests.common import TransactionCase, tagged
@@ -319,7 +318,7 @@ class TestXMLTranslation(TransactionCase):
'arch': archf % terms,
})
for lang, trans_terms in kwargs.items():
- for src, val in pycompat.izip(terms, trans_terms):
+ for src, val in zip(terms, trans_terms):
self.env['ir.translation'].create({
'type': 'model_terms',
'name': 'ir.ui.view,arch_db',
diff --git a/odoo/addons/test_impex/models.py b/odoo/addons/test_impex/models.py
index 410b1df7bbf..45cf4af4402 100644
--- a/odoo/addons/test_impex/models.py
+++ b/odoo/addons/test_impex/models.py
@@ -2,7 +2,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
-from odoo.tools import pycompat
def selection_fn(model):
@@ -51,7 +50,7 @@ for name, field in MODELS:
@api.model
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
- if isinstance(name, pycompat.string_types) and name.split(':')[0] == self._name:
+ if isinstance(name, str) and name.split(':')[0] == self._name:
record_ids = self._search([('value', operator, int(name.split(':')[1]))], access_rights_uid=name_get_uid)
return self.browse(record_ids).name_get()
else:
@@ -73,7 +72,7 @@ class One2ManyChild(models.Model):
@api.model
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
- if isinstance(name, pycompat.string_types) and name.split(':')[0] == self._name:
+ if isinstance(name, str) and name.split(':')[0] == self._name:
record_ids = self._search([('value', operator, int(name.split(':')[1]))], access_rights_uid=name_get_uid)
return self.browse(record_ids).name_get()
else:
@@ -132,7 +131,7 @@ class Many2ManyChild(models.Model):
@api.model
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
- if isinstance(name, pycompat.string_types) and name.split(':')[0] == self._name:
+ if isinstance(name, str) and name.split(':')[0] == self._name:
record_ids = self._search([('value', operator, int(name.split(':')[1]))], access_rights_uid=name_get_uid)
return self.browse(record_ids).name_get()
else:
diff --git a/odoo/addons/test_impex/tests/test_export.py b/odoo/addons/test_impex/tests/test_export.py
index f44da3ef838..058d7581bf2 100644
--- a/odoo/addons/test_impex/tests/test_export.py
+++ b/odoo/addons/test_impex/tests/test_export.py
@@ -6,7 +6,6 @@ import pstats
from cProfile import Profile
from odoo.tests import common
-from odoo.tools import pycompat
class CreatorCase(common.TransactionCase):
@@ -88,7 +87,7 @@ class test_integer_field(CreatorCase):
def test_huge(self):
self.assertEqual(
self.export(2**31-1),
- [[pycompat.text_type(2**31-1)]])
+ [[str(2**31-1)]])
class test_float_field(CreatorCase):
@@ -338,7 +337,7 @@ class test_m2o(CreatorCase):
record = self.env['export.integer'].create({'value': 42})
self.assertEqual(
self.export(record.id, fields=['value/.id', 'value/value']),
- [[pycompat.text_type(record.id), u'42']])
+ [[str(record.id), '42']])
def test_external_id(self):
record = self.env['export.integer'].create({'value': 42})
@@ -537,9 +536,9 @@ class test_o2m_multiple(CreatorCase):
"""
fields = ['const', 'child1/value', 'child2/value']
child1 = [(0, False, {'value': v, 'str': 'record%.02d' % index})
- for index, v in pycompat.izip(itertools.count(), [4, 42, 36, 4, 13])]
+ for index, v in zip(itertools.count(), [4, 42, 36, 4, 13])]
child2 = [(0, False, {'value': v, 'str': 'record%.02d' % index})
- for index, v in pycompat.izip(itertools.count(10), [8, 12, 8, 55, 33, 13])]
+ for index, v in zip(itertools.count(10), [8, 12, 8, 55, 33, 13])]
self.assertEqual(
self.export(child1=child1, child2=False, fields=fields),
diff --git a/odoo/addons/test_new_api/models.py b/odoo/addons/test_new_api/models.py
index a35c886b905..90edf910944 100644
--- a/odoo/addons/test_new_api/models.py
+++ b/odoo/addons/test_new_api/models.py
@@ -5,7 +5,6 @@ import datetime
from odoo import models, fields, api, _
from odoo.exceptions import AccessError, ValidationError
-from odoo.tools import pycompat
class Category(models.Model):
@@ -51,7 +50,7 @@ class Category(models.Model):
categories.append(category[0])
categories.append(self)
# assign parents following sequence
- for parent, child in pycompat.izip(categories, categories[1:]):
+ for parent, child in zip(categories, categories[1:]):
if parent and child:
child.parent = parent
# assign name of last category, and reassign display_name (to normalize it)
diff --git a/odoo/addons/test_new_api/tests/test_attributes.py b/odoo/addons/test_new_api/tests/test_attributes.py
index b37afe7e30d..94a048f2554 100644
--- a/odoo/addons/test_new_api/tests/test_attributes.py
+++ b/odoo/addons/test_new_api/tests/test_attributes.py
@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
from odoo.tests import common
-from odoo.tools import pycompat
ANSWER_TO_ULTIMATE_QUESTION = 42
@@ -17,7 +16,7 @@ class TestAttributes(common.TransactionCase):
self.assertTrue(hasattr(instance, 'unknown'))
# Is it the right type ?
- self.assertIsInstance(instance.unknown, pycompat.integer_types)
+ self.assertIsInstance(instance.unknown, int)
# Is it the right value, in case of, we don't know ;-)
self.assertEqual(instance.unknown, ANSWER_TO_ULTIMATE_QUESTION)
diff --git a/odoo/addons/test_new_api/tests/test_new_fields.py b/odoo/addons/test_new_api/tests/test_new_fields.py
index 021fad63e39..358efcb575f 100644
--- a/odoo/addons/test_new_api/tests/test_new_fields.py
+++ b/odoo/addons/test_new_api/tests/test_new_fields.py
@@ -6,7 +6,7 @@ from datetime import date, datetime, time
from odoo import fields
from odoo.exceptions import AccessError, UserError
from odoo.tests import common
-from odoo.tools import mute_logger, float_repr, pycompat
+from odoo.tools import mute_logger, float_repr
from odoo.tools.date_utils import add, subtract, start_of, end_of
@@ -18,8 +18,8 @@ class TestFields(common.TransactionCase):
discussion = self.env.ref('test_new_api.discussion_0')
# read field as a record attribute or as a record item
- self.assertIsInstance(discussion.name, pycompat.string_types)
- self.assertIsInstance(discussion['name'], pycompat.string_types)
+ self.assertIsInstance(discussion.name, str)
+ self.assertIsInstance(discussion['name'], str)
self.assertEqual(discussion['name'], discussion.name)
# read it with method read()
diff --git a/odoo/addons/test_performance/tests/test_performance.py b/odoo/addons/test_performance/tests/test_performance.py
index e81c1175265..7ea5fbcdadc 100644
--- a/odoo/addons/test_performance/tests/test_performance.py
+++ b/odoo/addons/test_performance/tests/test_performance.py
@@ -5,7 +5,7 @@ from collections import defaultdict
import json
from odoo.tests.common import TransactionCase, users, warmup
-from odoo.tools import pycompat, mute_logger
+from odoo.tools import mute_logger
class TestPerformance(TransactionCase):
@@ -399,7 +399,7 @@ class TestPerformance(TransactionCase):
model.invalidate_cache()
result = model.read_group([], ['partner_id', 'value'], ['partner_id'])
self.assertEqual(len(result), len(expected))
- for res, exp in pycompat.izip(result, expected):
+ for res, exp in zip(result, expected):
self.assertEqual(res['__domain'], exp['__domain'])
self.assertEqual(res['partner_id'][0], exp['partner_id'][0])
self.assertEqual(res['partner_id_count'], exp['partner_id_count'])
diff --git a/odoo/fields.py b/odoo/fields.py
index d877cd71f87..5a523f28fb9 100644
--- a/odoo/fields.py
+++ b/odoo/fields.py
@@ -496,7 +496,7 @@ class Field(MetaField('DummyField', (object,), {})):
deps = getattr(func, '_depends', ())
return deps(model) if callable(deps) else deps
- if isinstance(self.compute, pycompat.string_types):
+ if isinstance(self.compute, str):
# if the compute method has been overridden, concatenate all their _depends
self.depends = tuple(
dep
@@ -517,7 +517,7 @@ class Field(MetaField('DummyField', (object,), {})):
def _setup_related_full(self, model):
""" Setup the attributes of a related field. """
# fix the type of self.related if necessary
- if isinstance(self.related, pycompat.string_types):
+ if isinstance(self.related, str):
self.related = tuple(self.related.split('.'))
# determine the chain of fields, and make sure they are all set up
@@ -604,7 +604,7 @@ class Field(MetaField('DummyField', (object,), {})):
for name in self.related[:-1]:
values = [first(value[name]) for value in values]
# assign final values to records
- for record, value in pycompat.izip(records, values):
+ for record, value in zip(records, values):
record[self.name] = value[self.related_field.name]
def _inverse_related(self, records):
@@ -791,7 +791,7 @@ class Field(MetaField('DummyField', (object,), {})):
""" Convert ``value`` from the ``write`` format to the SQL format. """
if value is None or value is False:
return None
- return pycompat.to_native(value)
+ return pycompat.to_text(value)
def convert_to_cache(self, value, record, validate=True):
""" Convert ``value`` to the cache format; ``value`` may come from an
@@ -1028,7 +1028,7 @@ class Field(MetaField('DummyField', (object,), {})):
for field in fields:
for record in records:
cache.set(record, field, field.convert_to_cache(False, record, validate=False))
- if isinstance(self.compute, pycompat.string_types):
+ if isinstance(self.compute, str):
getattr(records, self.compute)()
else:
self.compute(records)
@@ -1062,7 +1062,7 @@ class Field(MetaField('DummyField', (object,), {})):
# HACK: if result is in the wrong cache, copy values
if recs.env != env:
computed = record._field_computed[self]
- for source, target in pycompat.izip(recs, recs.with_env(env)):
+ for source, target in zip(recs, recs.with_env(env)):
try:
values = {f.name: source[f.name] for f in computed}
target._cache.update(target._convert_to_cache(values, validate=False))
@@ -1100,14 +1100,14 @@ class Field(MetaField('DummyField', (object,), {})):
def determine_inverse(self, records):
""" Given the value of ``self`` on ``records``, inverse the computation. """
- if isinstance(self.inverse, pycompat.string_types):
+ if isinstance(self.inverse, str):
getattr(records, self.inverse)()
else:
self.inverse(records)
def determine_domain(self, records, operator, value):
""" Return a domain representing a condition on ``self``. """
- if isinstance(self.search, pycompat.string_types):
+ if isinstance(self.search, str):
return getattr(records, self.search)(operator, value)
else:
return self.search(records, operator, value)
@@ -1773,14 +1773,14 @@ class Binary(Field):
if isinstance(value, bytes):
return psycopg2.Binary(value)
try:
- return psycopg2.Binary(pycompat.text_type(value).encode('ascii'))
+ return psycopg2.Binary(str(value).encode('ascii'))
except UnicodeEncodeError:
raise UserError(_("ASCII characters are required for %s in %s") % (value, self.name))
def convert_to_cache(self, value, record, validate=True):
if isinstance(value, _BINARY):
return bytes(value)
- if isinstance(value, pycompat.integer_types) and \
+ if isinstance(value, int) and \
(record._context.get('bin_size') or
record._context.get('bin_size_' + self.name)):
# If the client requests only the size of the field, we return that
@@ -1912,7 +1912,7 @@ class Selection(Field):
translated according to context language
"""
selection = self.selection
- if isinstance(selection, pycompat.string_types):
+ if isinstance(selection, str):
return getattr(env[self.model_name], selection)()
if callable(selection):
return selection(env[self.model_name])
@@ -1929,7 +1929,7 @@ class Selection(Field):
def get_values(self, env):
""" return a list of the possible values """
selection = self.selection
- if isinstance(selection, pycompat.string_types):
+ if isinstance(selection, str):
selection = getattr(env[self.model_name], selection)()
elif callable(selection):
selection = selection(env[self.model_name])
@@ -1980,7 +1980,7 @@ class Reference(Selection):
if isinstance(value, BaseModel):
if not validate or (value._name in self.get_values(record.env) and len(value) <= 1):
return process(value._name, value.id) if value else False
- elif isinstance(value, pycompat.string_types):
+ elif isinstance(value, str):
res_model, res_id = value.split(',')
if record.env[res_model].browse(int(res_id)).exists():
return process(res_model, int(res_id))
@@ -2309,7 +2309,7 @@ class _RelationalMulti(_Relational):
self.depends += tuple(
self.name + '.' + arg[0]
for arg in self.domain
- if isinstance(arg, (tuple, list)) and isinstance(arg[0], pycompat.string_types)
+ if isinstance(arg, (tuple, list)) and isinstance(arg[0], str)
)
@@ -2708,7 +2708,7 @@ class Many2many(_RelationalMulti):
if to_create:
# create lines in batch, and link them
lines = comodel.create([vals for ids, vals in to_create])
- for line, (ids, vals) in pycompat.izip(lines, to_create):
+ for line, (ids, vals) in zip(lines, to_create):
relation_add(ids, line.id)
if to_delete:
diff --git a/odoo/http.py b/odoo/http.py
index d5650e4ef9b..3b44a7d2054 100644
--- a/odoo/http.py
+++ b/odoo/http.py
@@ -518,7 +518,7 @@ def route(route=None, **kw):
if isinstance(response, Response) or f.routing_type == 'json':
return response
- if isinstance(response, (bytes, pycompat.text_type)):
+ if isinstance(response, (bytes, str)):
return Response(response)
if isinstance(response, werkzeug.exceptions.HTTPException):
@@ -1330,7 +1330,7 @@ class Root(object):
path_static = opj(addons_path, module, 'static')
if manifest_path and os.path.isdir(path_static):
manifest_data = open(manifest_path, 'rb').read()
- manifest = ast.literal_eval(pycompat.to_native(manifest_data))
+ manifest = ast.literal_eval(pycompat.to_text(manifest_data))
if not manifest.get('installable', True):
continue
manifest['addons_path'] = addons_path
@@ -1405,7 +1405,7 @@ class Root(object):
else:
raise
- if isinstance(result, (bytes, pycompat.text_type)):
+ if isinstance(result, (bytes, str)):
response = Response(result, mimetype='text/html')
else:
response = result
@@ -1579,7 +1579,7 @@ def send_file(filepath_or_fp, mimetype=None, as_attachment=False, filename=None,
:param cache_timeout: the timeout in seconds for the headers.
"""
- if isinstance(filepath_or_fp, pycompat.string_types):
+ if isinstance(filepath_or_fp, str):
if not filename:
filename = os.path.basename(filepath_or_fp)
file = open(filepath_or_fp, 'rb')
@@ -1629,7 +1629,7 @@ def send_file(filepath_or_fp, mimetype=None, as_attachment=False, filename=None,
mtime,
size,
adler32(
- filename.encode('utf-8') if isinstance(filename, pycompat.text_type)
+ filename.encode('utf-8') if isinstance(filename, str)
else filename
) & 0xffffffff
))
diff --git a/odoo/models.py b/odoo/models.py
index 1af6cd9c173..bbd4a67d1e1 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -52,7 +52,7 @@ from . import tools
from .exceptions import AccessError, MissingError, ValidationError, UserError
from .osv.query import Query
from .tools import frozendict, lazy_classproperty, lazy_property, ormcache, \
- Collector, LastOrderedSet, OrderedSet, pycompat, groupby
+ Collector, LastOrderedSet, OrderedSet, groupby
from .tools.config import config
from .tools.func import frame_codeinfo
from .tools.misc import CountingStream, clean_context, DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT
@@ -182,7 +182,7 @@ class NewId(object):
return False
__nonzero__ = __bool__
-IdType = pycompat.integer_types + pycompat.string_types + (NewId,)
+IdType = (int, str, NewId)
# maximum number of prefetched records
@@ -418,7 +418,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
# determine inherited models
parents = cls._inherit
- parents = [parents] if isinstance(parents, pycompat.string_types) else (parents or [])
+ parents = [parents] if isinstance(parents, str) else (parents or [])
# determine the model's name
name = cls._name or (len(parents) == 1 and parents[0]) or cls.__name__
@@ -980,7 +980,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
# copy non-relational fields to record dict
record = {fnames[0]: value
- for fnames, value in pycompat.izip(fields_, row)
+ for fnames, value in zip(fields_, row)
if not is_relational(fnames[0])}
# Get all following rows which have relational values attached to
@@ -994,13 +994,13 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
# get only cells for this sub-field, should be strictly
# non-empty, field path [None] is for name_get field
- indices, subfields = pycompat.izip(*((index, fnames[1:] or [None])
+ indices, subfields = zip(*((index, fnames[1:] or [None])
for index, fnames in enumerate(fields_)
if fnames[0] == relfield))
# return all rows which have at least one value for the
# subfields of relfield
- relfield_data = [it for it in pycompat.imap(itemgetter_tuple(indices), record_span) if any(it)]
+ relfield_data = [it for it in map(itemgetter_tuple(indices), record_span) if any(it)]
record[relfield] = [
subrecord
for subrecord, _subinfo in comodel._extract_records(subfields, relfield_data, log=log)
@@ -1033,7 +1033,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
# processing of response, but injects human readable in message
exc_vals = dict(base, record=record, field=field_names[field])
record = dict(base, type=type, record=record, field=field,
- message=pycompat.text_type(exception.args[0]) % exc_vals)
+ message=str(exception.args[0]) % exc_vals)
if len(exception.args) > 1 and exception.args[1]:
record.update(exception.args[1])
log(record)
@@ -1528,7 +1528,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
provided domain <reference/orm/domains>`.
"""
res = self.search(args, count=True)
- return res if isinstance(res, pycompat.integer_types) else len(res)
+ return res if isinstance(res, int) else len(res)
@api.model
@api.returns('self',
@@ -1673,7 +1673,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
# override defaults with the provided values, never allow the other way around
defaults = self.default_get(list(missing_defaults))
for name, value in defaults.items():
- if self._fields[name].type == 'many2many' and value and isinstance(value[0], pycompat.integer_types):
+ if self._fields[name].type == 'many2many' and value and isinstance(value[0], int):
# convert a list of ids into a list of commands
defaults[name] = [(6, 0, value)]
elif self._fields[name].type == 'one2many' and value and isinstance(value[0], dict):
@@ -1948,7 +1948,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
value = False if value is None else value
gb = groupby_dict.get(key)
if gb and gb['type'] in ('date', 'datetime') and value:
- if isinstance(value, pycompat.string_types):
+ if isinstance(value, str):
dt_format = DEFAULT_SERVER_DATETIME_FORMAT if gb['type'] == 'datetime' else DEFAULT_SERVER_DATE_FORMAT
value = datetime.datetime.strptime(value, dt_format)
if gb['tz_convert']:
@@ -2061,7 +2061,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
"""
result = self._read_group_raw(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy)
- groupby = [groupby] if isinstance(groupby, pycompat.string_types) else list(OrderedSet(groupby))
+ groupby = [groupby] if isinstance(groupby, str) else list(OrderedSet(groupby))
dt = [
f for f in groupby
if self._fields[f.split(':')[0]].type in ('date', 'datetime') # e.g. 'date:month'
@@ -2085,7 +2085,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
query = self._where_calc(domain)
fields = fields or [f.name for f in self._fields.values() if f.store]
- groupby = [groupby] if isinstance(groupby, pycompat.string_types) else list(OrderedSet(groupby))
+ groupby = [groupby] if isinstance(groupby, str) else list(OrderedSet(groupby))
groupby_list = groupby[:1] if lazy else groupby
annotated_groupbys = [self._read_group_process_groupby(gb, query) for gb in groupby_list]
groupby_fields = [g['field'] for g in annotated_groupbys]
@@ -3276,7 +3276,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
# groups by dependence (in case they depend on each other)
field_groups = sorted(
(fields for _inv, fields in groupby(inverse_fields, attrgetter('inverse'))),
- key=lambda fields: min(pycompat.imap(self.pool.field_sequence, fields)),
+ key=lambda fields: min(map(self.pool.field_sequence, fields)),
)
for fields in field_groups:
# If a field is not stored, its inverse method will probably
@@ -3497,7 +3497,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
data['inherited'][model_name]
for data in parent_data_list
])
- for parent, data in pycompat.izip(parents, parent_data_list):
+ for parent, data in zip(parents, parent_data_list):
data['stored'][parent_name] = parent.id
# create records with stored fields
@@ -3510,7 +3510,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
# by dependence (in case they depend on each other)
field_groups = sorted(
(fields for _inv, fields in groupby(inversed_fields, attrgetter('inverse'))),
- key=lambda fields: min(pycompat.imap(self.pool.field_sequence, fields)),
+ key=lambda fields: min(map(self.pool.field_sequence, fields)),
)
for fields in field_groups:
# determine which records to inverse for those fields
@@ -3606,7 +3606,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
# the new records
records = self.browse(ids)
- for data, record in pycompat.izip(data_list, records):
+ for data, record in zip(data_list, records):
data['record'] = record
# update parent_path
@@ -3625,7 +3625,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
for field in sorted(other_fields, key=attrgetter('_sequence')):
field.create([
(other, data['stored'][field.name])
- for other, data in pycompat.izip(others, data_list)
+ for other, data in zip(others, data_list)
if field.name in data['stored']
])
@@ -3801,7 +3801,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
# create records
records = self.create([data['values'] for data in to_create])
- for data, record in pycompat.izip(to_create, records):
+ for data, record in zip(to_create, records):
data['record'] = record
# create or update XMLIDs
@@ -4186,7 +4186,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
# foreseen in copy_data()
old_lines = old[name].sorted(key='id')
new_lines = new[name].sorted(key='id')
- for (old_line, new_line) in pycompat.izip(old_lines, new_lines):
+ for (old_line, new_line) in zip(old_lines, new_lines):
# don't pass excluded as it is not about those lines
old_line.copy_translations(new_line)
@@ -4247,7 +4247,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
"""
ids, new_ids = [], []
for i in self._ids:
- (ids if isinstance(i, pycompat.integer_types) else new_ids).append(i)
+ (ids if isinstance(i, int) else new_ids).append(i)
if not ids:
return self
query = """SELECT id FROM "%s" WHERE id IN %%s""" % self._table
@@ -4791,7 +4791,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
"""
if not func:
return self # support for an empty path of fields
- if isinstance(func, pycompat.string_types):
+ if isinstance(func, str):
recs = self
for name in func.split('.'):
recs = recs._mapped_func(operator.itemgetter(name))
@@ -4819,7 +4819,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
:param func: a function or a dot-separated sequence of field names
"""
- if isinstance(func, pycompat.string_types):
+ if isinstance(func, str):
name = func
func = lambda rec: any(rec.mapped(name))
return self.browse([rec.id for rec in self if func(rec)])
@@ -4836,7 +4836,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
if key is None:
recs = self.search([('id', 'in', self.ids)])
return self.browse(reversed(recs._ids)) if reverse else recs
- if isinstance(key, pycompat.string_types):
+ if isinstance(key, str):
key = itemgetter(key)
return self.browse(item.id for item in sorted(self, key=key, reverse=reverse))
@@ -4924,7 +4924,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
"""
if isinstance(item, BaseModel) and self._name == item._name:
return len(item) == 1 and item.id in self._ids
- elif isinstance(item, pycompat.string_types):
+ elif isinstance(item, str):
return item in self._fields
else:
raise TypeError("Mixing apples and oranges: %s in %s" % (item, self))
@@ -5042,7 +5042,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
rs = inst[10:20] # subset of inst
nm = rs['name'] # name of first record in inst
"""
- if isinstance(key, pycompat.string_types):
+ if isinstance(key, str):
# important: one must call the field's getter
return self._fields[key].__get__(self, type(self))
elif isinstance(key, slice):
diff --git a/odoo/modules/migration.py b/odoo/modules/migration.py
index 57d217e770d..4081232b5ff 100644
--- a/odoo/modules/migration.py
+++ b/odoo/modules/migration.py
@@ -13,7 +13,6 @@ from odoo.modules.module import get_resource_path
import odoo.release as release
import odoo.tools as tools
from odoo.tools.parse_version import parse_version
-from odoo.tools import pycompat
if pycompat.PY2:
import imp
diff --git a/odoo/modules/module.py b/odoo/modules/module.py
index 93be467b0f3..4f7f80ca396 100644
--- a/odoo/modules/module.py
+++ b/odoo/modules/module.py
@@ -324,13 +324,13 @@ def load_information_from_description_file(module, mod_path=None):
'summary': '',
'website': '',
}
- info.update(pycompat.izip(
+ info.update(zip(
'depends data demo test init_xml update_xml demo_xml'.split(),
iter(list, None)))
f = tools.file_open(manifest_file, mode='rb')
try:
- info.update(ast.literal_eval(pycompat.to_native(f.read())))
+ info.update(ast.literal_eval(pycompat.to_text(f.read())))
finally:
f.close()
diff --git a/odoo/osv/expression.py b/odoo/osv/expression.py
index 483f325322c..1eecceeca6c 100644
--- a/odoo/osv/expression.py
+++ b/odoo/osv/expression.py
@@ -403,7 +403,7 @@ def normalize_leaf(element):
def is_operator(element):
""" Test whether an object is a valid domain operator. """
- return isinstance(element, pycompat.string_types) and element in DOMAIN_OPERATORS
+ return isinstance(element, str) and element in DOMAIN_OPERATORS
def is_leaf(element, internal=False):
@@ -424,7 +424,7 @@ def is_leaf(element, internal=False):
return (isinstance(element, tuple) or isinstance(element, list)) \
and len(element) == 3 \
and element[1] in INTERNAL_OPS \
- and ((isinstance(element[0], pycompat.string_types) and element[0])
+ and ((isinstance(element[0], str) and element[0])
or tuple(element) in (TRUE_LEAF, FALSE_LEAF))
@@ -723,11 +723,11 @@ class expression(object):
return the list of related ids
"""
names = []
- if isinstance(value, pycompat.string_types):
+ if isinstance(value, str):
names = [value]
- elif value and isinstance(value, (tuple, list)) and all(isinstance(item, pycompat.string_types) for item in value):
+ elif value and isinstance(value, (tuple, list)) and all(isinstance(item, str) for item in value):
names = value
- elif isinstance(value, pycompat.integer_types):
+ elif isinstance(value, int):
if not value:
# given this nonsensical domain, it is generally cheaper to
# interpret False as [], so that "X child_of False" will
@@ -955,7 +955,7 @@ class expression(object):
if right is not False:
# determine ids2 in comodel
- if isinstance(right, pycompat.string_types):
+ if isinstance(right, str):
op2 = (TERM_OPERATORS_NEGATION[operator]
if operator in NEGATIVE_TERM_OPERATORS else operator)
ids2 = [x[0] for x in comodel.name_search(right, domain or [], op2, limit=None)]
@@ -1012,7 +1012,7 @@ class expression(object):
elif right is not False:
# determine ids2 in comodel
- if isinstance(right, pycompat.string_types):
+ if isinstance(right, str):
domain = field.domain
if callable(domain):
domain = domain(model)
@@ -1064,8 +1064,8 @@ class expression(object):
res_ids.append(False) # TODO this should not be appended if False was in 'right'
return left, 'in', res_ids
# resolve string-based m2o criterion into IDs
- if isinstance(right, pycompat.string_types) or \
- right and isinstance(right, (tuple, list)) and all(isinstance(item, pycompat.string_types) for item in right):
+ if isinstance(right, str) or \
+ right and isinstance(right, (tuple, list)) and all(isinstance(item, str) for item in right):
push(create_substitution_leaf(leaf, _get_expression(comodel, left, right, operator), model))
else:
# right == [] or right == False and all other cases are handled by __leaf_to_sql()
@@ -1097,7 +1097,7 @@ class expression(object):
else:
if field.type == 'datetime' and right:
- if isinstance(right, pycompat.string_types) and len(right) == 10:
+ if isinstance(right, str) and len(right) == 10:
if operator in ('>', '<='):
right += ' 23:59:59'
else:
@@ -1267,7 +1267,7 @@ class expression(object):
query = '(%s %s %s)' % (unaccent(column + cast), sql_operator, unaccent(format))
if need_wildcard:
- native_str = pycompat.to_native(right)
+ native_str = pycompat.to_text(right)
if not native_str:
query = '(%s OR %s."%s" IS NULL)' % (query, table_alias, left)
params = ['%%%s%%' % native_str]
diff --git a/odoo/osv/orm.py b/odoo/osv/orm.py
index 0d5c7e66fb1..e316949dae1 100644
--- a/odoo/osv/orm.py
+++ b/odoo/osv/orm.py
@@ -3,7 +3,6 @@ import warnings
from lxml import etree
-from odoo.tools import pycompat
from ..exceptions import except_orm
from ..models import (
MetaModel,
@@ -125,7 +124,7 @@ def setup_modifiers(node, field=None, context=None, in_tree_view=False):
def test_modifiers(what, expected):
modifiers = {}
- if isinstance(what, pycompat.string_types):
+ if isinstance(what, str):
node = etree.fromstring(what)
transfer_node_to_modifiers(node, modifiers)
simplify_modifiers(modifiers)
diff --git a/odoo/service/db.py b/odoo/service/db.py
index df641cb2c50..0cc86e4ee66 100644
--- a/odoo/service/db.py
+++ b/odoo/service/db.py
@@ -25,7 +25,6 @@ import odoo.sql_db
import odoo.tools
from odoo.sql_db import db_connect
from odoo.release import version_info
-from odoo.tools import pycompat
_logger = logging.getLogger(__name__)
@@ -259,7 +258,7 @@ def exp_restore(db_name, data, copy=False):
@check_db_management_enabled
def restore_db(db, dump_file, copy=False):
- assert isinstance(db, pycompat.string_types)
+ assert isinstance(db, str)
if exp_db_exist(db):
_logger.info('RESTORE DB: %s already exists', db)
raise Exception("Database already exists")
diff --git a/odoo/sql_db.py b/odoo/sql_db.py
index afa396148f0..a21890f69f5 100644
--- a/odoo/sql_db.py
+++ b/odoo/sql_db.py
@@ -41,7 +41,6 @@ psycopg2.extensions.register_type(psycopg2.extensions.new_type((700, 701, 1700,)
from . import tools
from .tools.func import frame_codeinfo
-from .tools import pycompat
from .tools import parse_version as pv
if pv(psycopg2.__version__) < pv('2.7'):
@@ -52,8 +51,7 @@ if pv(psycopg2.__version__) < pv('2.7'):
raise ValueError("A string literal cannot contain NUL (0x00) characters.")
return QuotedString(adapted)
- for type_ in pycompat.string_types:
- psycopg2.extensions.register_adapter(type_, adapt_string)
+ psycopg2.extensions.register_adapter(str, adapt_string)
from datetime import timedelta
import threading
diff --git a/odoo/tests/common.py b/odoo/tests/common.py
index 0bcd4d4c967..89a9473e432 100644
--- a/odoo/tests/common.py
+++ b/odoo/tests/common.py
@@ -33,7 +33,6 @@ from lxml import etree, html
from odoo.models import BaseModel
from odoo.osv.expression import normalize_domain
-from odoo.tools import pycompat
from odoo.tools import single_email_re
from odoo.tools.misc import find_in_path
from odoo.tools.safe_eval import safe_eval
@@ -1091,7 +1090,7 @@ class Form(object):
if isinstance(view, BaseModel):
assert view._name == 'ir.ui.view', "the view parameter must be a view id, xid or record, got %s" % view
view_id = view.id
- elif isinstance(view, pycompat.string_types):
+ elif isinstance(view, str):
view_id = env.ref(view).id
else:
view_id = view or False
diff --git a/odoo/tools/appdirs.py b/odoo/tools/appdirs.py
index 5bd5afb11cb..67ba75625c1 100644
--- a/odoo/tools/appdirs.py
+++ b/odoo/tools/appdirs.py
@@ -13,7 +13,6 @@ from __future__ import print_function
# http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120
# - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html
# - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
-from . import pycompat
__version_info__ = (1, 3, 0)
__version__ = '.'.join(str(v) for v in __version_info__)
@@ -392,7 +391,7 @@ def _get_win_folder_with_pywin32(csidl_name):
# not return unicode strings when there is unicode data in the
# path.
try:
- dir = pycompat.text_type(dir)
+ dir = str(dir)
# Downgrade to short path name if have highbit chars. See
# <http://bugs.activestate.com/show_bug.cgi?id=85099>.
diff --git a/odoo/tools/cache.py b/odoo/tools/cache.py
index 052f89545a2..8481df0d33d 100644
--- a/odoo/tools/cache.py
+++ b/odoo/tools/cache.py
@@ -8,8 +8,6 @@ from decorator import decorator
from inspect import formatargspec, getargspec
import logging
-from . import pycompat
-
unsafe_eval = eval
_logger = logging.getLogger(__name__)
@@ -139,7 +137,7 @@ class ormcache_multi(ormcache):
def determine_key(self):
""" Determine the function that computes a cache key from arguments. """
assert self.skiparg is None, "ormcache_multi() no longer supports skiparg"
- assert isinstance(self.multi, pycompat.string_types), "ormcache_multi() parameter multi must be an argument name"
+ assert isinstance(self.multi, str), "ormcache_multi() parameter multi must be an argument name"
super(ormcache_multi, self).determine_key()
diff --git a/odoo/tools/config.py b/odoo/tools/config.py
index 47c5b633cff..812e4e2adc6 100644
--- a/odoo/tools/config.py
+++ b/odoo/tools/config.py
@@ -13,7 +13,7 @@ import os
import sys
import odoo
from .. import release, conf, loglevels
-from . import appdirs, pycompat
+from . import appdirs
from passlib.context import CryptContext
crypt_context = CryptContext(schemes=['pbkdf2_sha512', 'plaintext'],
@@ -418,10 +418,10 @@ class configmanager(object):
if getattr(opt, arg):
self.options[arg] = getattr(opt, arg)
# ... or keep, but cast, the config file value.
- elif isinstance(self.options[arg], pycompat.string_types) and self.casts[arg].type in optparse.Option.TYPE_CHECKER:
+ elif isinstance(self.options[arg], str) and self.casts[arg].type in optparse.Option.TYPE_CHECKER:
self.options[arg] = optparse.Option.TYPE_CHECKER[self.casts[arg].type](self.casts[arg], arg, self.options[arg])
- if isinstance(self.options['log_handler'], pycompat.string_types):
+ if isinstance(self.options['log_handler'], str):
self.options['log_handler'] = self.options['log_handler'].split(',')
self.options['log_handler'].extend(opt.log_handler)
@@ -453,7 +453,7 @@ class configmanager(object):
if getattr(opt, arg) is not None:
self.options[arg] = getattr(opt, arg)
# ... or keep, but cast, the config file value.
- elif isinstance(self.options[arg], pycompat.string_types) and self.casts[arg].type in optparse.Option.TYPE_CHECKER:
+ elif isinstance(self.options[arg], str) and self.casts[arg].type in optparse.Option.TYPE_CHECKER:
self.options[arg] = optparse.Option.TYPE_CHECKER[self.casts[arg].type](self.casts[arg], arg, self.options[arg])
self.options['root_path'] = os.path.abspath(os.path.expanduser(os.path.expandvars(os.path.join(os.path.dirname(__file__), '..'))))
@@ -563,7 +563,7 @@ class configmanager(object):
def save(self):
p = ConfigParser.RawConfigParser()
- loglevelnames = dict(pycompat.izip(self._LOGLEVELS.values(), self._LOGLEVELS))
+ loglevelnames = dict(zip(self._LOGLEVELS.values(), self._LOGLEVELS))
p.add_section('options')
for opt in sorted(self.options):
if opt in ('version', 'language', 'translate_out', 'translate_in', 'overwrite_existing_translations', 'init', 'update'):
@@ -609,7 +609,7 @@ class configmanager(object):
def __setitem__(self, key, value):
self.options[key] = value
- if key in self.options and isinstance(self.options[key], pycompat.string_types) and \
+ if key in self.options and isinstance(self.options[key], str) and \
key in self.casts and self.casts[key].type in optparse.Option.TYPE_CHECKER:
self.options[key] = optparse.Option.TYPE_CHECKER[self.casts[key].type](self.casts[key], key, self.options[key])
diff --git a/odoo/tools/convert.py b/odoo/tools/convert.py
index 2e984a39618..36e1bdcd4b5 100644
--- a/odoo/tools/convert.py
+++ b/odoo/tools/convert.py
@@ -128,7 +128,7 @@ def _eval_xml(self, node, env):
# So funny story: in Python 3, bytes(n: int) returns a
# bytestring of n nuls. In Python 2 it obviously returns the
# stringified number, which is what we're expecting here
- s = s.replace(found, pycompat.text_type(self.idref[id]))
+ s = s.replace(found, str(self.idref[id]))
s = s.replace('%%', '%') # Quite weird but it's for (somewhat) backward compatibility sake
return s
@@ -575,7 +575,7 @@ form: module.record_id""" % (xml_id,)
f_val = int(f_val)
elif model._fields[f_name].type in ['float', 'monetary']:
f_val = float(f_val)
- elif model._fields[f_name].type == 'boolean' and isinstance(f_val, pycompat.string_types):
+ elif model._fields[f_name].type == 'boolean' and isinstance(f_val, str):
f_val = str2bool(f_val)
res[f_name] = f_val
@@ -793,7 +793,7 @@ def convert_xml_import(cr, module, xmlfile, idref=None, mode='init', noupdate=Fa
_logger.info(ustr(relaxng.error_log.last_error))
raise
- if isinstance(xmlfile, pycompat.string_types):
+ if isinstance(xmlfile, str):
xml_filename = xmlfile
else:
xml_filename = xmlfile.name
diff --git a/odoo/tools/float_utils.py b/odoo/tools/float_utils.py
index 041a87cabbe..c5c2946a5ce 100644
--- a/odoo/tools/float_utils.py
+++ b/odoo/tools/float_utils.py
@@ -4,7 +4,6 @@
from __future__ import print_function
import math
-from odoo.tools import pycompat
if not pycompat.PY2:
import builtins
@@ -224,7 +223,7 @@ if __name__ == "__main__":
expecteds = ['.00', '.02', '.01', '.68', '.67', '.46', '.456', '.4556']
precisions = [2, 2, 2, 2, 2, 2, 3, 4]
for magnitude in range(7):
- for frac, exp, prec in pycompat.izip(fractions, expecteds, precisions):
+ for frac, exp, prec in zip(fractions, expecteds, precisions):
for sign in [-1,1]:
for x in range(0, 10000, 97):
n = x * 10**magnitude
diff --git a/odoo/tools/image.py b/odoo/tools/image.py
index 2814aaaaa3f..0cf79978193 100644
--- a/odoo/tools/image.py
+++ b/odoo/tools/image.py
@@ -9,8 +9,6 @@ from PIL import ImageEnhance
from random import randrange
# Preload PIL with the minimal subset of image formats we need
-from odoo.tools import pycompat
-
Image.preinit()
Image._initialized = 2
@@ -291,7 +289,7 @@ def image_get_resized_images(base64_source, return_big=False, return_medium=True
size_big = sizes.get(big_name, (1024, 1024))
size_medium = sizes.get(medium_name, (128, 128))
size_small = sizes.get(small_name, (64, 64))
- if isinstance(base64_source, pycompat.text_type):
+ if isinstance(base64_source, str):
base64_source = base64_source.encode('ascii')
if return_big:
return_dict[big_name] = image_resize_image_big(base64_source, avoid_if_small=avoid_resize_big, size=size_big)
diff --git a/odoo/tools/mail.py b/odoo/tools/mail.py
index 3bb080094ab..847fcfcf2f3 100644
--- a/odoo/tools/mail.py
+++ b/odoo/tools/mail.py
@@ -16,7 +16,7 @@ from lxml import etree
import odoo
from odoo.loglevels import ustr
-from odoo.tools import pycompat, misc
+from odoo.tools import misc
_logger = logging.getLogger(__name__)
@@ -224,7 +224,7 @@ def html_sanitize(src, silent=True, sanitize_tags=True, sanitize_attributes=Fals
# some corner cases make the parser crash (such as <SCRIPT/XSS SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT> 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'&nbsp;')
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 "<stdin>", line 1, in <module>
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