From fab11839074bb326419e4c873f6237e2f7ad8f9a Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 29 Jan 2020 07:28:01 +0000 Subject: [PATCH 1/7] [IMP] enable deprecation warnings --- odoo/netsvc.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/odoo/netsvc.py b/odoo/netsvc.py index ee4c60348b4..a9c1a365986 100644 --- a/odoo/netsvc.py +++ b/odoo/netsvc.py @@ -6,14 +6,12 @@ import logging.handlers import os import platform import pprint -from . import release import sys import threading import time +import warnings -import psycopg2 - -import odoo +from . import release from . import sql_db from . import tools @@ -130,6 +128,16 @@ def init_logger(): logging.addLevelName(25, "INFO") logging.captureWarnings(True) + # enable deprecation warnings (disabled by default) + warnings.filterwarnings('once', category=DeprecationWarning) + # ignore deprecation warnings from invalid escape (there's a ton and it's + # pretty likely a super low-value signal) + warnings.filterwarnings('ignore', r'^invalid escape sequence \\.', category=DeprecationWarning) + # ignore warning from older setuptools version using imp + warnings.filterwarnings('ignore', category=DeprecationWarning, module='setuptools.depends') + # ignore warning from zeep using defusedxml.lxml + warnings.filterwarnings('ignore', category=DeprecationWarning, module='zeep.loader') + from .tools.translate import resetlocale resetlocale() From 3bdf9307436f17d34dce64fa9ec3a08be4518975 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 29 Jan 2020 07:52:45 +0000 Subject: [PATCH 2/7] [FIX] core: remove import of deprecated `imp` module Was already not used, it's just that the import was not removed. Remove a bunch of other unused imports while at it. --- odoo/modules/module.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/odoo/modules/module.py b/odoo/modules/module.py index 154a4df1093..508d138ee7a 100644 --- a/odoo/modules/module.py +++ b/odoo/modules/module.py @@ -3,26 +3,20 @@ import ast import collections -import imp import importlib import inspect import itertools import logging import os -import pkg_resources -import re import sys import time -import types import unittest import threading -from operator import itemgetter from os.path import join as opj import odoo import odoo.tools as tools import odoo.release as release -from odoo import SUPERUSER_ID, api from odoo.tools import pycompat MANIFEST_NAMES = ('__manifest__.py', '__openerp__.py') From 7ad955d5b1c7885affeb35a1b1420a035d227798 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 29 Jan 2020 08:42:46 +0000 Subject: [PATCH 3/7] [FIX] test_documentation_examples: deprecation warning assertDictContainsSubset has been deprecated since 3.2 and is not documented anymore, apparently because the order of its parameters is less than obvious. Consequently, remove the call to said dict & replace it with assertions on item sets. Note: the odd formatting is because these bits are literal-include-ed in the documentation as sub-slices (just the relevant code lines), so ideally they shouldn't be moved around and no additional content should be added to those specific lines. --- .../test_documentation_examples/tests/test_extension.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/odoo/addons/test_documentation_examples/tests/test_extension.py b/odoo/addons/test_documentation_examples/tests/test_extension.py index e005f835586..957a81b5820 100644 --- a/odoo/addons/test_documentation_examples/tests/test_extension.py +++ b/odoo/addons/test_documentation_examples/tests/test_extension.py @@ -9,8 +9,9 @@ class TestBasicInheritance(common.TransactionCase): record = env['extension.0'].create({}) - self.assertDictContainsSubset( + reference =\ {'name': "A", 'description': "Extended"} - , + values =\ record.read()[0] - ) + + self.assertLess(reference.items(), values.items()) From eae19fc2cd3496d4b59e4d8029fcceb5eaa3a561 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 29 Jan 2020 08:44:47 +0000 Subject: [PATCH 4/7] [FIX] core: int() deprecation warning __int__ should always return an integer, not a bool and not a completely unrelated type either. --- odoo/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/odoo/models.py b/odoo/models.py index 4b04263bba0..77ba7c8eaa3 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -5625,7 +5625,7 @@ Record ids: %(records)s return set(self._ids) >= set(other._ids) def __int__(self): - return self.id + return self.id or 0 def __str__(self): return "%s%s" % (self._name, getattr(self, '_ids', "")) From de590816d8d06730d99499db9a068f8d0e2cd3f9 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 29 Jan 2020 09:12:11 +0000 Subject: [PATCH 5/7] [FIX] *: deprecated access to url_ utilities through werkzeug root In 0.15 accessing werkzeug.urls functions directly through werkzeug is deprecated, the shortcut will be removed in the eventual werkzeug 1.0. Fix existing uses of these shortcuts. Also cleanup some imports when they're not far from a werkzeug* import being altered. --- addons/auth_oauth/controllers/main.py | 6 +++--- addons/google_spreadsheet/models/google_drive.py | 2 +- addons/hr/models/hr_employee.py | 5 +---- .../wizard/hr_expense_sheet_register_payment.py | 2 +- addons/http_routing/models/ir_http.py | 8 +++++--- addons/l10n_ch/models/res_bank.py | 2 +- addons/mail/controllers/main.py | 5 +++-- addons/mail/models/mail_thread.py | 3 +-- addons/payment_ingenico/models/payment.py | 6 +++--- addons/transifex/models/ir_translation.py | 10 +++------- addons/web/controllers/main.py | 4 ++-- addons/web_editor/models/ir_attachment.py | 2 +- addons/website/controllers/main.py | 5 +++-- addons/website/models/res_partner.py | 11 +++-------- addons/website_crm_partner_assign/controllers/main.py | 4 ++-- addons/website_customer/controllers/main.py | 2 +- addons/website_event/models/event_event.py | 4 ++-- addons/website_membership/controllers/main.py | 2 +- odoo/addons/base/models/ir_ui_view.py | 4 ++-- odoo/addons/base/models/res_bank.py | 2 +- odoo/http.py | 2 +- 21 files changed, 41 insertions(+), 50 deletions(-) diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py index 00eea3268b6..3d1a6b53af3 100644 --- a/addons/auth_oauth/controllers/main.py +++ b/addons/auth_oauth/controllers/main.py @@ -66,7 +66,7 @@ class OAuthLogin(Home): scope=provider['scope'], state=json.dumps(state), ) - provider['auth_link'] = "%s?%s" % (provider['auth_endpoint'], werkzeug.url_encode(params)) + provider['auth_link'] = "%s?%s" % (provider['auth_endpoint'], werkzeug.urls.url_encode(params)) return providers def get_state(self, provider): @@ -76,7 +76,7 @@ class OAuthLogin(Home): state = dict( d=request.session.db, p=provider['id'], - r=werkzeug.url_quote_plus(redirect), + r=werkzeug.urls.url_quote_plus(redirect), ) token = request.params.get('token') if token: @@ -134,7 +134,7 @@ class OAuthController(http.Controller): cr.commit() action = state.get('a') menu = state.get('m') - redirect = werkzeug.url_unquote_plus(state['r']) if state.get('r') else False + redirect = werkzeug.urls.url_unquote_plus(state['r']) if state.get('r') else False url = '/web' if redirect: url = redirect diff --git a/addons/google_spreadsheet/models/google_drive.py b/addons/google_spreadsheet/models/google_drive.py index f3c04608e72..0f4f830b673 100644 --- a/addons/google_spreadsheet/models/google_drive.py +++ b/addons/google_spreadsheet/models/google_drive.py @@ -74,7 +74,7 @@ class GoogleDrive(models.Model): try: req = requests.post( - 'https://spreadsheets.google.com/feeds/cells/%s/od6/private/full/batch?%s' % (spreadsheet_key, werkzeug.url_encode({'v': 3, 'access_token': access_token})), + 'https://spreadsheets.google.com/feeds/cells/%s/od6/private/full/batch?%s' % (spreadsheet_key, werkzeug.urls.url_encode({'v': 3, 'access_token': access_token})), data=request, headers={'content-type': 'application/atom+xml', 'If-Match': '*'}, timeout=TIMEOUT, diff --git a/addons/hr/models/hr_employee.py b/addons/hr/models/hr_employee.py index 0324babaf23..1fcdf4584ae 100644 --- a/addons/hr/models/hr_employee.py +++ b/addons/hr/models/hr_employee.py @@ -4,14 +4,11 @@ import base64 from random import choice from string import digits -import itertools -from werkzeug import url_encode -import pytz +from werkzeug.urls import url_encode from odoo import api, fields, models, _ from odoo.exceptions import ValidationError, AccessError from odoo.modules.module import get_module_resource -from odoo.addons.resource.models.resource_mixin import timezone_datetime class HrEmployeePrivate(models.Model): diff --git a/addons/hr_expense/wizard/hr_expense_sheet_register_payment.py b/addons/hr_expense/wizard/hr_expense_sheet_register_payment.py index c13fec1939f..0c7050b1d7a 100644 --- a/addons/hr_expense/wizard/hr_expense_sheet_register_payment.py +++ b/addons/hr_expense/wizard/hr_expense_sheet_register_payment.py @@ -3,7 +3,7 @@ from odoo import api, fields, models, _ from odoo.exceptions import UserError, ValidationError -from werkzeug import url_encode +from werkzeug.urls import url_encode class HrExpenseSheetRegisterPaymentWizard(models.TransientModel): diff --git a/addons/http_routing/models/ir_http.py b/addons/http_routing/models/ir_http.py index de512bdcdd8..d4755f0b2b7 100644 --- a/addons/http_routing/models/ir_http.py +++ b/addons/http_routing/models/ir_http.py @@ -7,7 +7,9 @@ import os import re import traceback import unicodedata -import werkzeug +import werkzeug.exceptions +import werkzeug.routing +import werkzeug.urls # optional python-slugify import (https://github.com/un33k/python-slugify) try: @@ -550,8 +552,8 @@ class IrHttp(models.AbstractModel): return cls._handle_exception(e) if getattr(request, 'is_frontend_multilang', False) and request.httprequest.method in ('GET', 'HEAD'): - generated_path = werkzeug.url_unquote_plus(path) - current_path = werkzeug.url_unquote_plus(request.httprequest.path) + generated_path = werkzeug.urls.url_unquote_plus(path) + current_path = werkzeug.urls.url_unquote_plus(request.httprequest.path) if generated_path != current_path: if request.lang != cls._get_default_lang(): path = '/' + request.lang.url_code + path diff --git a/addons/l10n_ch/models/res_bank.py b/addons/l10n_ch/models/res_bank.py index 90dedc00b8f..5feb7dd6676 100644 --- a/addons/l10n_ch/models/res_bank.py +++ b/addons/l10n_ch/models/res_bank.py @@ -148,7 +148,7 @@ class ResPartnerBank(models.Model): ref_type, reference, communication) - qr_code_url = '/report/barcode/?type=%s&value=%s&width=%s&height=%s&humanreadable=1' % ('QR', werkzeug.url_quote_plus(qr_code_string), 256, 256) + qr_code_url = '/report/barcode/?type=%s&value=%s&width=%s&height=%s&humanreadable=1' % ('QR', werkzeug.urls.url_quote_plus(qr_code_string), 256, 256) return qr_code_url def validate_swiss_code_arguments(self, currency, debitor): diff --git a/addons/mail/controllers/main.py b/addons/mail/controllers/main.py index 243c16c9abd..4f99295b937 100644 --- a/addons/mail/controllers/main.py +++ b/addons/mail/controllers/main.py @@ -4,9 +4,10 @@ import base64 import logging import psycopg2 -import werkzeug +import werkzeug.utils +import werkzeug.wrappers -from werkzeug import url_encode +from werkzeug.urls import url_encode from odoo import api, http, registry, SUPERUSER_ID, _ from odoo.exceptions import AccessError diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 2e94ea0cf44..e033cab3b63 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -24,7 +24,6 @@ except ImportError: from collections import namedtuple from email.message import EmailMessage from lxml import etree -from werkzeug import url_encode from werkzeug import urls from odoo import _, api, exceptions, fields, models, tools, registry, SUPERUSER_ID @@ -2482,7 +2481,7 @@ class MailThread(models.AbstractModel): token = self._notify_encode_link(base_link, params) params['token'] = token - link = '%s?%s' % (base_link, url_encode(params)) + link = '%s?%s' % (base_link, urls.url_encode(params)) if self: link = self[0].get_base_url() + link diff --git a/addons/payment_ingenico/models/payment.py b/addons/payment_ingenico/models/payment.py index 0399ec68c46..2e719ce033c 100644 --- a/addons/payment_ingenico/models/payment.py +++ b/addons/payment_ingenico/models/payment.py @@ -9,7 +9,7 @@ from unicodedata import normalize import requests from lxml import etree, objectify -from werkzeug import urls, url_encode +from werkzeug import urls from odoo import api, fields, models, _ from odoo.addons.payment.models.payment_acquirer import ValidationError @@ -177,7 +177,7 @@ class PaymentAcquirerOgone(models.Model): 'DECLINEURL': urls.url_join(base_url, OgoneController._decline_url), 'EXCEPTIONURL': urls.url_join(base_url, OgoneController._exception_url), 'CANCELURL': urls.url_join(base_url, OgoneController._cancel_url), - 'PARAMPLUS': url_encode(param_plus), + 'PARAMPLUS': urls.url_encode(param_plus), } if self.save_token in ['ask', 'always']: temp_ogone_tx_values.update({ @@ -365,7 +365,7 @@ class PaymentTxOgone(models.Model): 'ECI': 9, # Recurring (from eCommerce) 'ALIAS': self.payment_token_id.acquirer_ref, 'RTIMEOUT': 30, - 'PARAMPLUS': url_encode(param_plus), + 'PARAMPLUS': urls.url_encode(param_plus), 'EMAIL': self.partner_id.email or '', 'CN': self.partner_id.name or '', } diff --git a/addons/transifex/models/ir_translation.py b/addons/transifex/models/ir_translation.py index ed1150f8d14..1f17fc47d3a 100644 --- a/addons/transifex/models/ir_translation.py +++ b/addons/transifex/models/ir_translation.py @@ -1,14 +1,10 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -try: - from configparser import ConfigParser -except ImportError: - # python2 import - from ConfigParser import ConfigParser +from configparser import ConfigParser from os.path import join as opj import os -import werkzeug +import werkzeug.urls import odoo from odoo import models, fields @@ -84,7 +80,7 @@ class IrTranslation(models.Model): 'project': project, 'lang': lang_code, 'module': translation.module, - 'src': "text:'" + werkzeug.url_quote_plus( + 'src': "text:'" + werkzeug.urls.url_quote_plus( translation.src[:50].replace("\n", "").replace("'", "") ) + "'", } diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 798077daf40..cdc43a07c6e 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -26,7 +26,7 @@ import werkzeug.utils import werkzeug.wrappers import werkzeug.wsgi from collections import OrderedDict, defaultdict, Counter -from werkzeug.urls import url_decode, iri_to_uri +from werkzeug.urls import url_encode, url_decode, iri_to_uri from lxml import etree import unicodedata @@ -1257,7 +1257,7 @@ class Session(http.Controller): 'state': json.dumps({'d': request.db, 'u': ICP.get_param('web.base.url')}), 'scope': 'userinfo', } - return 'https://accounts.odoo.com/oauth2/auth?' + werkzeug.url_encode(params) + return 'https://accounts.odoo.com/oauth2/auth?' + url_encode(params) @http.route('/web/session/destroy', type='json', auth="user") def destroy(self): diff --git a/addons/web_editor/models/ir_attachment.py b/addons/web_editor/models/ir_attachment.py index bd8c27165d2..7c8ff486ea6 100644 --- a/addons/web_editor/models/ir_attachment.py +++ b/addons/web_editor/models/ir_attachment.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from werkzeug import url_quote +from werkzeug.urls import url_quote from odoo import api, models, fields, tools diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py index 687f49e919b..83c0df51ff8 100644 --- a/addons/website/controllers/main.py +++ b/addons/website/controllers/main.py @@ -7,6 +7,7 @@ import os import logging import pytz import requests +import werkzeug.urls import werkzeug.utils import werkzeug.wrappers @@ -51,9 +52,9 @@ class QueryURL(object): paths[key] = u"%s" % value elif value: if isinstance(value, list) or isinstance(value, set): - fragments.append(werkzeug.url_encode([(key, item) for item in value])) + fragments.append(werkzeug.urls.url_encode([(key, item) for item in value])) else: - fragments.append(werkzeug.url_encode([(key, value)])) + fragments.append(werkzeug.urls.url_encode([(key, value)])) for key in path_args: value = paths.get(key) if value is not None: diff --git a/addons/website/models/res_partner.py b/addons/website/models/res_partner.py index cc832f3d3f9..c75d7ea8c75 100644 --- a/addons/website/models/res_partner.py +++ b/addons/website/models/res_partner.py @@ -1,15 +1,10 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -import werkzeug +import werkzeug.urls from odoo import models, fields - -def urlplus(url, params): - return werkzeug.Href(url)(params or None) - - class Partner(models.Model): _name = 'res.partner' _inherit = ['res.partner', 'website.published.multi.mixin'] @@ -27,14 +22,14 @@ class Partner(models.Model): 'sensor': 'false', 'key': google_maps_api_key, } - return urlplus('//maps.googleapis.com/maps/api/staticmap', params) + return '//maps.googleapis.com/maps/api/staticmap?'+werkzeug.urls.url_encode(params) def google_map_link(self, zoom=10): params = { 'q': '%s, %s %s, %s' % (self.street or '', self.city or '', self.zip or '', self.country_id and self.country_id.display_name or ''), 'z': zoom, } - return urlplus('https://maps.google.com/maps', params) + return 'https://maps.google.com/maps' + werkzeug.urls.url_encode(params) def _get_name(self): name = super(Partner, self)._get_name() diff --git a/addons/website_crm_partner_assign/controllers/main.py b/addons/website_crm_partner_assign/controllers/main.py index 99422b03160..4be4cf83057 100644 --- a/addons/website_crm_partner_assign/controllers/main.py +++ b/addons/website_crm_partner_assign/controllers/main.py @@ -2,7 +2,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. import datetime -import werkzeug +import werkzeug.urls from collections import OrderedDict from werkzeug.exceptions import NotFound @@ -308,7 +308,7 @@ class WebsiteCrmPartnerAssign(WebsitePartnerPage): 'google_map_partner_ids': google_map_partner_ids, 'pager': pager, 'searches': post, - 'search_path': "%s" % werkzeug.url_encode(post), + 'search_path': "%s" % werkzeug.urls.url_encode(post), 'google_maps_api_key': google_maps_api_key, } return request.render("website_crm_partner_assign.index", values, status=partners and 200 or 404) diff --git a/addons/website_customer/controllers/main.py b/addons/website_customer/controllers/main.py index 4a7a931297d..7ef94366be8 100644 --- a/addons/website_customer/controllers/main.py +++ b/addons/website_customer/controllers/main.py @@ -132,7 +132,7 @@ class WebsiteCustomer(http.Controller): 'google_map_partner_ids': google_map_partner_ids, 'pager': pager, 'post': post, - 'search_path': "?%s" % werkzeug.url_encode(post), + 'search_path': "?%s" % werkzeug.urls.url_encode(post), 'tag': tag, 'tags': tags, 'google_maps_api_key': google_maps_api_key, diff --git a/addons/website_event/models/event_event.py b/addons/website_event/models/event_event.py index 6a8f1fd8eeb..491b8b60b17 100644 --- a/addons/website_event/models/event_event.py +++ b/addons/website_event/models/event_event.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -import werkzeug +import werkzeug.urls import json from odoo import api, fields, models, _ @@ -147,7 +147,7 @@ class Event(models.Model): } if self.address_id: params.update(location=self.sudo().address_id.contact_address.replace('\n', ' ')) - encoded_params = werkzeug.url_encode(params) + encoded_params = werkzeug.urls.url_encode(params) google_url = GOOGLE_CALENDAR_URL + encoded_params iCal_url = '/event/%d/ics?%s' % (self.id, encoded_params) return {'google_url': google_url, 'iCal_url': iCal_url} diff --git a/addons/website_membership/controllers/main.py b/addons/website_membership/controllers/main.py index d9e8cbdd757..ac5c6a8e47b 100644 --- a/addons/website_membership/controllers/main.py +++ b/addons/website_membership/controllers/main.py @@ -155,7 +155,7 @@ class WebsiteMembership(http.Controller): 'google_map_partner_ids': google_map_partner_ids, 'pager': pager, 'post': post, - 'search': "?%s" % werkzeug.url_encode(post), + 'search': "?%s" % werkzeug.urls.url_encode(post), 'search_count': count_members, 'google_maps_api_key': google_maps_api_key, } diff --git a/odoo/addons/base/models/ir_ui_view.py b/odoo/addons/base/models/ir_ui_view.py index f2662bc040c..73a4ea9cae1 100644 --- a/odoo/addons/base/models/ir_ui_view.py +++ b/odoo/addons/base/models/ir_ui_view.py @@ -16,7 +16,7 @@ import uuid from dateutil.relativedelta import relativedelta from difflib import HtmlDiff -import werkzeug +import werkzeug, werkzeug.urls from lxml import etree from lxml.etree import LxmlError from lxml.builder import E @@ -1595,7 +1595,7 @@ actual arch. debug=request.session.debug if request else '', test_mode_enabled=bool(config['test_enable'] or config['test_file']), json=json_scriptsafe, - quote_plus=werkzeug.url_quote_plus, + quote_plus=werkzeug.urls.url_quote_plus, time=time, datetime=datetime, relativedelta=relativedelta, diff --git a/odoo/addons/base/models/res_bank.py b/odoo/addons/base/models/res_bank.py index 4b212f5bb08..be7b8245ca8 100644 --- a/odoo/addons/base/models/res_bank.py +++ b/odoo/addons/base/models/res_bank.py @@ -132,7 +132,7 @@ class ResPartnerBank(models.Model): if comment: communication = (comment[:137] + '...') if len(comment) > 140 else comment qr_code_string = 'BCD\n001\n1\nSCT\n%s\n%s\n%s\nEUR%s\n\n\n%s' % (self.bank_bic or "", self.company_id.name, self.acc_number, amount, communication) - qr_code_url = '/report/barcode/?type=%s&value=%s&width=%s&height=%s&humanreadable=1' % ('QR', werkzeug.url_quote_plus(qr_code_string), 128, 128) + qr_code_url = '/report/barcode/?' + werkzeug.urls.url_encode({'type': 'QR', 'value': qr_code_string, 'width': 128, 'height': 128, 'humanreadable': 1}) return qr_code_url def _validate_qr_code_arguments(self): diff --git a/odoo/http.py b/odoo/http.py index 5164f29a042..4c0cf76005c 100644 --- a/odoo/http.py +++ b/odoo/http.py @@ -167,7 +167,7 @@ def local_redirect(path, query=None, keep_hash=False, code=303): if not query: query = {} if query: - url += '?' + werkzeug.url_encode(query) + url += '?' + urls.url_encode(query) return werkzeug.utils.redirect(url, code) def redirect_with_hash(url, code=303): From 672709c125dae6dfb1e8931b656c04993315cf4e Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 29 Jan 2020 12:08:31 +0000 Subject: [PATCH 6/7] [FIX] core, base: CryptContext.encrypt is deprecated However encrypt was marked as deprecated in the same version hash was added, so we need a conditional check to support <= 1.6. --- odoo/addons/base/models/res_users.py | 3 ++- odoo/tools/config.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/odoo/addons/base/models/res_users.py b/odoo/addons/base/models/res_users.py index 22e73042883..45b5c96ed52 100644 --- a/odoo/addons/base/models/res_users.py +++ b/odoo/addons/base/models/res_users.py @@ -296,8 +296,9 @@ class Users(models.Model): def _set_password(self): ctx = self._crypt_context() + hash_password = ctx.hash if hasattr(ctx, 'hash') else ctx.encrypt for user in self: - self._set_encrypted_password(user.id, ctx.encrypt(user.password)) + self._set_encrypted_password(user.id, hash_password(user.password)) def _set_encrypted_password(self, uid, pw): assert self._crypt_context().identify(pw) != 'plaintext' diff --git a/odoo/tools/config.py b/odoo/tools/config.py index 9401d94ecda..79978fd1d0c 100644 --- a/odoo/tools/config.py +++ b/odoo/tools/config.py @@ -694,7 +694,8 @@ class configmanager(object): return os.path.join(self['data_dir'], 'filestore', dbname) def set_admin_password(self, new_password): - self.options['admin_passwd'] = crypt_context.encrypt(new_password) + hash_password = crypt_context.hash if hasattr(crypt_context, 'hash') else crypt_context.encrypt + self.options['admin_passwd'] = hash_password(new_password) def verify_admin_password(self, password): """Verifies the super-admin password, possibly updating the stored hash if needed""" From b1e58ab6c621a4df4b9413eaf4dcb58e9e8d46ed Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 29 Jan 2020 12:11:24 +0000 Subject: [PATCH 7/7] [FIX] product: deprecation warning triggered by assertion Replace an assertRaises(StopIteration) by a next() with a default value. Following PEP 479, *any* StopIteration reaching the toplevel of a generator triggers a DeprecationWarning. And while the assertRaises looks innocuous, both _assertRaises and the underlying clear_upon_failure are implemented with functools.contextmanager, which wraps a generator. As a result, exceptions raised in the assertRaises "body" get reinjected inside the wrapped context manager[0] and if the exception is a StopIteration it triggers the warning. By not using assertRaises we side-step the issue. [0] https://github.com/python/cpython/blob/b6999e5690c7006b0ba4049cfd638513c982a90c/Lib/contextlib.py#L131 --- .../product/tests/test_product_attribute_value_config.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/addons/product/tests/test_product_attribute_value_config.py b/addons/product/tests/test_product_attribute_value_config.py index 12d27b59c6f..3c672523e6e 100644 --- a/addons/product/tests/test_product_attribute_value_config.py +++ b/addons/product/tests/test_product_attribute_value_config.py @@ -352,8 +352,7 @@ class TestProductAttributeValueConfig(TestProductAttributeValueCommon): self.assertEqual(next(gen), computer_ssd_512 + computer_ram_32 + computer_hdd_1) self.assertEqual(next(gen), computer_ssd_512 + computer_ram_32 + computer_hdd_2) self.assertEqual(next(gen), computer_ssd_512 + computer_ram_32 + computer_hdd_4) - with self.assertRaises(StopIteration): - next(gen) + self.assertIsNone(next(gen, None)) # Give priority to ram_16 but it is not allowed by hdd_1 so it should return hhd_2 instead # Test invalidate_cache on product.attribute.value write @@ -392,8 +391,7 @@ class TestProductAttributeValueConfig(TestProductAttributeValueCommon): self._add_exclude(computer_ram_32, computer_hdd_4) self.assertEqual(self.computer._get_first_possible_combination(), self.env['product.template.attribute.value']) gen = self.computer._get_possible_combinations() - with self.assertRaises(StopIteration): - next(gen) + self.assertIsNone(next(gen, None)) def test_get_closest_possible_combinations(self): computer_ssd_256 = self._get_product_template_attribute_value(self.ssd_256) @@ -417,8 +415,7 @@ class TestProductAttributeValueConfig(TestProductAttributeValueCommon): self.assertEqual(next(gen), computer_ssd_256 + computer_ram_32 + computer_hdd_1) self.assertEqual(next(gen), computer_ssd_512 + computer_ram_8 + computer_hdd_1) self.assertEqual(next(gen), computer_ssd_512 + computer_ram_32 + computer_hdd_1) - with self.assertRaises(StopIteration): - next(gen) + self.assertIsNone(next(gen, None)) # CASE contains computer_hdd_2 self.assertEqual(self.computer._get_closest_possible_combination(computer_hdd_2),