diff options
| author | Xavier Morel <xmo@odoo.com> | 2017-04-11 12:44:29 +0200 |
|---|---|---|
| committer | Xavier Morel <xmo@odoo.com> | 2017-04-11 14:53:29 +0200 |
| commit | 3979f6802eeea275f949d28ddf4c18f84fc0f5aa (patch) | |
| tree | 0c67d60c80b2ece2e452837c187a79e9444334d8 | |
| parent | ca74b5e1c8a48bcdeb396625ec0d8028a5a9d5f1 (diff) | |
[#8530] convert exception handlers to except..as syntax
Futurize fixers:
* lib2to3.fixes.fix_except
53 files changed, 209 insertions, 121 deletions
diff --git a/addons/auth_ldap/models/res_company_ldap.py b/addons/auth_ldap/models/res_company_ldap.py index 05dcb275afa..4f280530bbe 100644 --- a/addons/auth_ldap/models/res_company_ldap.py +++ b/addons/auth_ldap/models/res_company_ldap.py @@ -112,7 +112,7 @@ class CompanyLDAP(models.Model): entry = results[0] except ldap.INVALID_CREDENTIALS: return False - except ldap.LDAPError, e: + except ldap.LDAPError as e: _logger.error('An LDAP exception occurred: %s', e) return entry @@ -149,7 +149,7 @@ class CompanyLDAP(models.Model): conn.unbind() except ldap.INVALID_CREDENTIALS: _logger.error('LDAP bind failed.') - except ldap.LDAPError, e: + except ldap.LDAPError as e: _logger.error('An LDAP exception occurred: %s', e) return results diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py index aa3f4e69b5c..0d09f1e68aa 100644 --- a/addons/auth_oauth/controllers/main.py +++ b/addons/auth_oauth/controllers/main.py @@ -160,7 +160,7 @@ class OAuthController(http.Controller): redirect = werkzeug.utils.redirect(url, 303) redirect.autocorrect_location_header = False return redirect - except Exception, e: + except Exception as e: # signup error _logger.exception("OAuth2: %s" % str(e)) url = "/web/login?oauth_error=2" diff --git a/addons/auth_oauth/models/res_users.py b/addons/auth_oauth/models/res_users.py index f48802c2310..fc7aaca4f56 100644 --- a/addons/auth_oauth/models/res_users.py +++ b/addons/auth_oauth/models/res_users.py @@ -79,7 +79,7 @@ class ResUsers(models.Model): assert len(oauth_user) == 1 oauth_user.write({'oauth_access_token': params['access_token']}) return oauth_user.login - except AccessDenied, access_denied_exception: + except AccessDenied as access_denied_exception: if self.env.context.get('no_user_creation'): return None state = json.loads(params['state']) diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py index 0ddca4cc626..6c1b0facad3 100644 --- a/addons/auth_signup/controllers/main.py +++ b/addons/auth_signup/controllers/main.py @@ -33,7 +33,7 @@ class AuthSignupHome(Home): try: self.do_signup(qcontext) return super(AuthSignupHome, self).web_login(*args, **kw) - except (SignupError, AssertionError), e: + except (SignupError, AssertionError) as e: if request.env["res.users"].sudo().search([("login", "=", qcontext.get("login"))]): qcontext["error"] = _("Another user is already registered using this email address.") else: @@ -62,7 +62,7 @@ class AuthSignupHome(Home): except SignupError: qcontext['error'] = _("Could not reset your password") _logger.exception('error when resetting password') - except Exception, e: + except Exception as e: qcontext['error'] = e.message or e.name response = request.render('auth_signup.reset_password', qcontext) diff --git a/addons/auth_signup/models/res_users.py b/addons/auth_signup/models/res_users.py index a0871c35fa8..d99961076be 100644 --- a/addons/auth_signup/models/res_users.py +++ b/addons/auth_signup/models/res_users.py @@ -93,7 +93,7 @@ class ResUsers(models.Model): try: with self.env.cr.savepoint(): return template_user.with_context(no_reset_password=True).copy(values) - except Exception, e: + except Exception as e: # copy may failed if asked login is not available. raise SignupError(ustr(e)) diff --git a/addons/base_gengo/wizard/base_gengo_translations.py b/addons/base_gengo/wizard/base_gengo_translations.py index e75f88eace5..d6e5ce9176a 100644 --- a/addons/base_gengo/wizard/base_gengo_translations.py +++ b/addons/base_gengo/wizard/base_gengo_translations.py @@ -90,7 +90,7 @@ class BaseGengoTranslations(models.TransientModel): ) gengo.getAccountStats() return (True, gengo) - except Exception, e: + except Exception as e: _logger.exception('Gengo connection failed') return (False, _("Gengo connection failed with this message:\n``%s``") % e) @@ -277,5 +277,5 @@ class BaseGengoTranslations(models.TransientModel): _logger.info("%s Translation terms have been posted to Gengo successfully", len(term_ids)) if not len(term_ids) == limit: break - except Exception, e: + except Exception as e: _logger.error("%s", e) diff --git a/addons/base_import/models/base_import.py b/addons/base_import/models/base_import.py index ad69cb01402..334b09846eb 100644 --- a/addons/base_import/models/base_import.py +++ b/addons/base_import/models/base_import.py @@ -503,7 +503,7 @@ class Import(models.TransientModel): 'advanced_mode': any([len(models.fix_import_export_id_paths(col)) > 1 for col in headers]), 'debug': self.user_has_groups('base.group_no_one'), } - except Exception, error: + except Exception as error: # Due to lazy generators, UnicodeDecodeError (for # instance) may only be raised when serializing the # preview to a list in the return. @@ -616,9 +616,9 @@ class Import(models.TransientModel): if line[index]: try: line[index] = dt.strftime(dt.strptime(ustr(line[index]).encode('utf-8'), user_format), server_format) - except ValueError, e: + except ValueError as e: raise ValueError(_("Column %s contains incorrect values. Error in line %d: %s") % (name, num + 1, ustr(e.message))) - except Exception, e: + except Exception as e: raise ValueError(_("Error Parsing Date [%s:L%d]: %s") % (name, num + 1, ustr(e.message))) elif field['type'] in ('float', 'monetary') and name in import_fields: @@ -656,7 +656,7 @@ class Import(models.TransientModel): data, import_fields = self._convert_import_data(fields, options) # Parse date and float field data = self._parse_import_data(data, import_fields, options) - except ValueError, error: + except ValueError as error: return [{ 'type': 'error', 'message': unicode(error), diff --git a/addons/base_import_module/controllers/main.py b/addons/base_import_module/controllers/main.py index 1bc7ab0a15f..ca76cd53b8e 100644 --- a/addons/base_import_module/controllers/main.py +++ b/addons/base_import_module/controllers/main.py @@ -10,7 +10,7 @@ def webservice(f): def wrap(*args, **kw): try: return f(*args, **kw) - except Exception, e: + except Exception as e: return Response(response=str(e), status=500) return wrap diff --git a/addons/base_import_module/models/ir_module.py b/addons/base_import_module/models/ir_module.py index 6e7c404df39..9a703b40978 100644 --- a/addons/base_import_module/models/ir_module.py +++ b/addons/base_import_module/models/ir_module.py @@ -109,7 +109,7 @@ class IrModule(models.Model): path = opj(module_dir, mod_name) self.import_module(mod_name, path, force=force) success.append(mod_name) - except Exception, e: + except Exception as e: _logger.exception('Error while importing module') errors[mod_name] = exception_to_unicode(e) r = ["Successfully imported module '%s'" % mod for mod in success] diff --git a/addons/bus/models/bus.py b/addons/bus/models/bus.py index 466592505a9..8795a6047c8 100644 --- a/addons/bus/models/bus.py +++ b/addons/bus/models/bus.py @@ -168,7 +168,7 @@ class ImDispatch(object): while True: try: self.loop() - except Exception, e: + except Exception as e: _logger.exception("Bus.loop error, sleep and retry") time.sleep(TIMEOUT) diff --git a/addons/fetchmail/models/fetchmail.py b/addons/fetchmail/models/fetchmail.py index 45f7e81a240..d12b9ec72a0 100644 --- a/addons/fetchmail/models/fetchmail.py +++ b/addons/fetchmail/models/fetchmail.py @@ -132,7 +132,7 @@ class FetchmailServer(models.Model): try: connection = server.connect() server.write({'state': 'done'}) - except Exception, err: + except Exception as err: _logger.info("Failed to connect to %s server %s.", server.type, server.name, exc_info=True) raise UserError(_("Connection test failed: %s") % tools.ustr(err)) finally: diff --git a/addons/gamification/models/goal.py b/addons/gamification/models/goal.py index d9ebb699cd0..1e9975ea97f 100644 --- a/addons/gamification/models/goal.py +++ b/addons/gamification/models/goal.py @@ -85,7 +85,7 @@ class GoalDefinition(models.Model): }) # dummy search to make sure the domain is valid Obj.search_count(domain) - except (ValueError, SyntaxError), e: + except (ValueError, SyntaxError) as e: msg = e.message or (e.msg + '\n' + e.text) raise exceptions.UserError(_("The domain for the definition %s seems incorrect, please check it.\n\n%s") % (definition.name, msg)) return True @@ -102,7 +102,7 @@ class GoalDefinition(models.Model): if not (field and field.store): raise exceptions.UserError( _("The model configuration for the definition %s seems incorrect, please check it.\n\n%s not stored") % (definition.name, definition.field_id.name)) - except KeyError, e: + except KeyError as e: raise exceptions.UserError( _("The model configuration for the definition %s seems incorrect, please check it.\n\n%s not found") % (definition.name, e.message)) diff --git a/addons/google_account/models/google_service.py b/addons/google_account/models/google_service.py index 07fa2d12cf5..9cd47c39179 100644 --- a/addons/google_account/models/google_service.py +++ b/addons/google_account/models/google_service.py @@ -135,7 +135,7 @@ class GoogleService(models.TransientModel): try: dummy, response, dummy = self._do_request(GOOGLE_TOKEN_ENDPOINT, params=data, headers=headers, type='POST', preuri='') return response - except urllib2.HTTPError, error: + except urllib2.HTTPError as error: if error.code == 400: # invalid grant with registry(request.session.db).cursor() as cur: self.env(cur)['res.users'].browse(self.env.uid).write({'google_%s_rtoken' % service: False}) @@ -182,7 +182,7 @@ class GoogleService(models.TransientModel): ask_time = datetime.strptime(resp.headers.get('date'), "%a, %d %b %Y %H:%M:%S %Z") except: pass - except urllib2.HTTPError, error: + except urllib2.HTTPError as error: if error.code in (204, 404): status = error.code response = "" diff --git a/addons/google_calendar/models/google_calendar.py b/addons/google_calendar/models/google_calendar.py index fb2e2e4f611..169368b9bd5 100644 --- a/addons/google_calendar/models/google_calendar.py +++ b/addons/google_calendar/models/google_calendar.py @@ -291,7 +291,7 @@ class GoogleCalendar(models.AbstractModel): try: status, content, ask_time = self.env['google.service']._do_request(url, params, headers, type='GET') - except urllib2.HTTPError, e: + except urllib2.HTTPError as e: if e.code == 401: # Token invalid / Acces unauthorized error_msg = _("Your token is invalid or has been revoked !") @@ -356,7 +356,7 @@ class GoogleCalendar(models.AbstractModel): url = "/calendar/v3/calendars/%s/events/%s" % ('primary', google_id) try: status, content, ask_time = self.env['google.service']._do_request(url, params, headers, type='GET') - except Exception, e: + except Exception as e: _logger.info("Calendar Synchro - In except of get_one_event_synchro") _logger.info(exception_to_unicode(e)) return False @@ -550,7 +550,7 @@ class GoogleCalendar(models.AbstractModel): _logger.info("[%s] Calendar Synchro - Failed - NEED RESET !", user_to_sync) else: _logger.info("[%s] Calendar Synchro - Done with status : %s !", user_to_sync, resp.get("status")) - except Exception, e: + except Exception as e: _logger.info("[%s] Calendar Synchro - Exception : %s !", user_to_sync, exception_to_unicode(e)) _logger.info("Calendar Synchro - Ended by cron") @@ -676,7 +676,7 @@ class GoogleCalendar(models.AbstractModel): if lastSync: try: all_event_from_google = self.get_event_synchro_dict(lastSync=lastSync) - except urllib2.HTTPError, e: + except urllib2.HTTPError as e: if e.code == 410: # GONE, Google is lost. # we need to force the rollback from this cursor, because it locks my res_users but I need to write in this tuple before to raise. self.env.cr.rollback() @@ -842,7 +842,7 @@ class GoogleCalendar(models.AbstractModel): try: # if already deleted from gmail or never created recs.delete_an_event(current_event[0]) - except Exception, e: + except Exception as e: if e.code in (401, 410,): pass else: diff --git a/addons/mrp/tests/test_multicompany.py b/addons/mrp/tests/test_multicompany.py index 8a1d1fc3716..f7d34516340 100644 --- a/addons/mrp/tests/test_multicompany.py +++ b/addons/mrp/tests/test_multicompany.py @@ -29,5 +29,5 @@ class TestMrpMulticompany(common.TransactionCase): if defaults.get(field): try: StockLocation.check_access_rule([defaults[field]], 'read') - except Exception, exc: + except Exception as exc: assert False, "unreadable location %s: %s" % (field, exc) diff --git a/addons/payment_ogone/controllers/main.py b/addons/payment_ogone/controllers/main.py index af2e9e05732..2dfa2747ab8 100644 --- a/addons/payment_ogone/controllers/main.py +++ b/addons/payment_ogone/controllers/main.py @@ -39,7 +39,7 @@ class OgoneController(http.Controller): acq = request.env['payment.acquirer'].browse(int(post.get('acquirer_id'))) try: acq.s2s_process(post) - except Exception, e: + except Exception as e: # synthax error: 'CHECK ERROR: |Not a valid date\n\n50001111: None' error = e.message.splitlines()[0].split('|')[-1] or '' return werkzeug.utils.redirect(post.get('return_url', '/') + (error and '#error=%s' % werkzeug.url_quote(error) or '')) diff --git a/addons/report/controllers/main.py b/addons/report/controllers/main.py index 265e48bea35..7e0fd9f8123 100644 --- a/addons/report/controllers/main.py +++ b/addons/report/controllers/main.py @@ -117,7 +117,7 @@ class ReportController(Controller): return response else: return - except Exception, e: + except Exception as e: se = _serialize_exception(e) error = { 'code': 200, diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 771735c752d..621fea372f9 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -67,7 +67,7 @@ def serialize_exception(f): def wrap(*args, **kwargs): try: return f(*args, **kwargs) - except Exception, e: + except Exception as e: _logger.exception("An exception occured during an http request") se = _serialize_exception(e) error = { @@ -670,7 +670,7 @@ class Database(http.Controller): dispatch_rpc('db', 'create_database', [master_pwd, name, bool(post.get('demo')), lang, password, post['login'], country_code]) request.session.authenticate(name, post['login'], password) return http.local_redirect('/web/') - except Exception, e: + except Exception as e: error = "Database creation error: %s" % e return self._render_template(error=error) @@ -679,7 +679,7 @@ class Database(http.Controller): try: dispatch_rpc('db', 'duplicate_database', [master_pwd, name, new_name]) return http.local_redirect('/web/database/manager') - except Exception, e: + except Exception as e: error = "Database duplication error: %s" % e return self._render_template(error=error) @@ -689,7 +689,7 @@ class Database(http.Controller): dispatch_rpc('db','drop', [master_pwd, name]) request._cr = None # dropping a database leads to an unusable cursor return http.local_redirect('/web/database/manager') - except Exception, e: + except Exception as e: error = "Database deletion error: %s" % e return self._render_template(error=error) @@ -706,7 +706,7 @@ class Database(http.Controller): dump_stream = odoo.service.db.dump_db(name, None, backup_format) response = werkzeug.wrappers.Response(dump_stream, headers=headers, direct_passthrough=True) return response - except Exception, e: + except Exception as e: _logger.exception('Database.backup') error = "Database backup error: %s" % e return self._render_template(error=error) @@ -717,7 +717,7 @@ class Database(http.Controller): data = base64.b64encode(backup_file.read()) dispatch_rpc('db', 'restore', [master_pwd, name, data, str2bool(copy)]) return http.local_redirect('/web/database/manager') - except Exception, e: + except Exception as e: error = "Database restore error: %s" % e return self._render_template(error=error) @@ -726,7 +726,7 @@ class Database(http.Controller): try: dispatch_rpc('db', 'change_admin_password', [master_pwd, master_pwd_new]) return http.local_redirect('/web/database/manager') - except Exception, e: + except Exception as e: error = "Master password update error: %s" % e return self._render_template(error=error) @@ -772,7 +772,7 @@ class Session(http.Controller): def get_lang_list(self): try: return dispatch_rpc('db', 'list_lang', []) or [] - except Exception, e: + except Exception as e: return {"error": e, "title": _("Languages")} @http.route('/web/session/modules', type='json', auth="user") @@ -1050,7 +1050,7 @@ class Binary(http.Controller): data = ufile.read() args = [len(data), ufile.filename, ufile.content_type, base64.b64encode(data)] - except Exception, e: + except Exception as e: args = [False, e.message] return out % (json.dumps(callback), json.dumps(args)) diff --git a/addons/web_editor/controllers/main.py b/addons/web_editor/controllers/main.py index 054850b0926..5a3eca776ef 100644 --- a/addons/web_editor/controllers/main.py +++ b/addons/web_editor/controllers/main.py @@ -173,7 +173,7 @@ class Web_Editor(http.Controller): u"than 42 million pixel") if not disable_optimization and image.format in ('PNG', 'JPEG'): data = tools.image_save_for_web(image) - except IOError, e: + except IOError as e: pass attachment = Attachments.create({ @@ -185,7 +185,7 @@ class Web_Editor(http.Controller): }) attachments += attachment uploads += attachments.read(['name', 'mimetype', 'checksum', 'url']) - except Exception, e: + except Exception as e: logger.exception("Failed to upload image to attachment") message = unicode(e) diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py index 82ef021bc81..ccdd44e1c4d 100644 --- a/addons/website/controllers/main.py +++ b/addons/website/controllers/main.py @@ -117,7 +117,7 @@ class Website(Home): try: request.website.get_template(page) - except ValueError, e: + except ValueError as e: # page not found if request.website.is_publisher(): values.pop('deletable') @@ -208,7 +208,7 @@ class Website(Home): def website_info(self): try: request.website.get_template('website.website_info').name - except Exception, e: + except Exception as e: return request.env['ir.http']._handle_exception(e, 404) Module = request.env['ir.module.module'].sudo() apps = Module.search([('state', '=', 'installed'), ('application', '=', True)]) diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index c62486d34a0..b6902b17c41 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -249,7 +249,7 @@ class Http(models.AbstractModel): try: _, path = rule.build(arguments) assert path is not None - except Exception, e: + except Exception as e: return cls._handle_exception(e, code=404) if getattr(request, 'website_multilang', False) and request.httprequest.method in ('GET', 'HEAD'): @@ -276,7 +276,7 @@ class Http(models.AbstractModel): else: # if parent excplicitely returns a plain response, then we don't touch it return response - except Exception, e: + except Exception as e: if 'werkzeug' in config['dev_mode'] and (not isinstance(exception, QWebException) or not exception.qweb.get('cause')): raise exception = e diff --git a/addons/website_form/controllers/main.py b/addons/website_form/controllers/main.py index df7aa42810d..6a93f387ec1 100644 --- a/addons/website_form/controllers/main.py +++ b/addons/website_form/controllers/main.py @@ -28,7 +28,7 @@ class WebsiteForm(http.Controller): try: data = self.extract_data(model_record, request.params) # If we encounter an issue while extracting data - except ValidationError, e: + except ValidationError as e: # I couldn't find a cleaner way to pass data to an exception return json.dumps({'error_fields' : e.args[0]}) diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index 407a2e7cd11..8b4a1d34d0d 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -96,7 +96,7 @@ class WebsiteSaleForm(WebsiteForm): model_record = request.env.ref('sale.model_sale_order') try: data = self.extract_data(model_record, kwargs) - except ValidationError, e: + except ValidationError as e: return json.dumps({'error_fields': e.args[0]}) order = request.website.sale_get_order() @@ -762,7 +762,7 @@ class WebsiteSale(http.Controller): # Auto-confirm SO if necessary tx._confirm_so() return dict(success=True, url='/shop/payment/validate') - except Exception, e: + except Exception as e: _logger.warning(_("Payment transaction (%s) failed : <%s>") % (tx.id, str(e))) return dict(success=False, error=_("Payment transaction failed (Contact Administrator)")) return dict(success=False, error='Tx missmatch') diff --git a/addons/website_twitter/models/website_twitter.py b/addons/website_twitter/models/website_twitter.py index cf0fe5d4d07..2b17411b72c 100644 --- a/addons/website_twitter/models/website_twitter.py +++ b/addons/website_twitter/models/website_twitter.py @@ -35,7 +35,7 @@ class WebsiteTwitter(models.Model): request = Request(url) request.add_header('Authorization', 'Bearer %s' % access_token) return json.load(urlopen(request, timeout=URLOPEN_TIMEOUT)) - except HTTPError, e: + except HTTPError as e: _logger.debug("Twitter API request failed with code: %r, msg: %r, content: %r", e.code, e.msg, e.fp.read()) raise diff --git a/addons/website_twitter/models/website_twitter_config.py b/addons/website_twitter/models/website_twitter_config.py index d92c376a0d1..49542e39606 100644 --- a/addons/website_twitter/models/website_twitter_config.py +++ b/addons/website_twitter/models/website_twitter_config.py @@ -49,13 +49,13 @@ class WebsiteTwitterConfig(models.TransientModel): try: self.website_id.fetch_favorite_tweets() - except HTTPError, e: + except HTTPError as e: _logger.info("%s - %s" % (e.code, e.reason), exc_info=True) raise UserError("%s - %s" % (e.code, e.reason) + ':' + self._get_twitter_exception_message(e.code)) - except URLError, e: + except URLError as e: _logger.info(_('We failed to reach a twitter server.'), exc_info=True) raise UserError(_('Internet connection refused') + ' ' + _('We failed to reach a twitter server.')) - except Exception, e: + except Exception as e: _logger.info(_('Please double-check your Twitter API Key and Secret!'), exc_info=True) raise UserError(_('Twitter authorization error!') + ' ' + _('Please double-check your Twitter API Key and Secret!')) diff --git a/doc/python3.rst b/doc/python3.rst new file mode 100644 index 00000000000..a0db3381a57 --- /dev/null +++ b/doc/python3.rst @@ -0,0 +1,88 @@ +:orphan: + +================================== +Python 3 compatibility/conversions +================================== + +Goal (notsure?): for v11 to provide an alpha/beta Python 3 compatibility, for +v12 to provide official Python 3 support and drop Python 2 in either v12 or +v13. + +Python 2 and Python 3 are somewhat different language, but following +backports, forward ports and cross-compatibility library it is possible to +use a subset of Python 2 and Python 3 in order to have a system compatible +with both. + +Here are a few useful steps or reminders to make Python 2 code compatible +with Python 3. + +References/useful documents: + +* `How do I port to Python 3? <https://eev.ee/blog/2016/07/31/python-faq-how-do-i-port-to-python-3/>`_ +* `Python-Future <http://python-future.org/index.html>`_ +* `Porting Python 2 code to Python 3 <https://docs.python.org/3/howto/pyporting.html>`_ +* `Porting to Python 3: A Guide <http://lucumr.pocoo.org/2010/2/11/porting-to-python-3-a-guide/>`_ (a bit outdated but useful for the extensive comments on strings and IO) + +Versions Support +================ + +A cross compatible Odoo would only support Python 2.7 and Python 3.5 and +above: Python 2.7 backported some Python 3 features, and Python 2 features +were reintroduced in various Python 3 in order to make conversion easier. +Python 3.6 adds great features (f-strings, ...) and performance improvements +(ordered compact dicts) but does not seem to reintroduce compatibility +features whereas: + +* Python 3.5 reintroduced ``%`` for bytes/bytestrings (:pep:`461`) +* Python 3.4 has no specific compatibility improvement but is the lowest P3 + version for PyLint +* Python 3.3 reintroduced the "u" prefix for proper (unicode) strings +* Python 3.2 made ``range`` views more list-like and reintroduced ``callable`` + +.. warning:: + + Python 3 adds plenty of great features (keyword-only parameters, + generator delegation, pathlib, ...), do not use them until Python 2 + support is dropped + +Fixes +===== + +Exception Handlers +------------------ + +.. important:: + + All exception handlers must be converted to ``except ... as ..``. Valid + forms are:: + + except Exception: + except (Exception1, ...): + except Exception as name: + except (Exception1, ...) as name: + +In Python 2, ``except`` statements are of the form:: + + except Exception[, name]: + +or:: + + except (Exception1, Exception2)[, name]: + +But because the name is optional, this gets confusing and people can stumble +into the first form when trying for the second and write:: + + except Exception1, Exception: + +which will *not* yield the expected result. + +Python 3 changes this syntax to:: + + except Exception[ as name]: + +or:: + + except (Exception1, Exception2)[ as name]: + +This form was implemented in Python 2.5 and is thus compatible across the +board. diff --git a/odoo/addons/base/ir/ir_cron.py b/odoo/addons/base/ir/ir_cron.py index a6f29ee0d95..3edf3fab094 100644 --- a/odoo/addons/base/ir/ir_cron.py +++ b/odoo/addons/base/ir/ir_cron.py @@ -95,7 +95,7 @@ class ir_cron(models.Model): end_time = time.time() _logger.debug('%.3fs (cron %s, server action %d with uid %d)', end_time - start_time, cron_name, server_action_id, self.env.uid) self.pool.signal_caches_change() - except Exception, e: + except Exception as e: self._handle_callback_exception(cron_name, server_action_id, job_id, e) @classmethod @@ -166,7 +166,7 @@ class ir_cron(models.Model): jobs = cr.dictfetchall() else: _logger.warning('Skipping database %s as its base version is not %s.', db_name, BASE_VERSION) - except psycopg2.ProgrammingError, e: + except psycopg2.ProgrammingError as e: if e.pgcode == '42P01': # Class 42 — Syntax Error or Access Rule Violation; 42P01: undefined_table # The table ir_cron does not exist; this is probably not an OpenERP database. @@ -206,7 +206,7 @@ class ir_cron(models.Model): finally: job_cr.close() - except psycopg2.OperationalError, e: + except psycopg2.OperationalError as e: if e.pgcode == '55P03': # Class 55: Object not in prerequisite state; 55P03: lock_not_available _logger.debug('Another process/thread is already busy executing job `%s`, skipping it.', job['cron_name']) diff --git a/odoo/addons/base/ir/ir_fields.py b/odoo/addons/base/ir/ir_fields.py index 0d880687cfb..26c351d6fa8 100644 --- a/odoo/addons/base/ir/ir_fields.py +++ b/odoo/addons/base/ir/ir_fields.py @@ -83,7 +83,7 @@ class IrFieldsConverter(models.AbstractModel): # uniform handling w = ImportWarning(w) log(field, w) - except ValueError, e: + except ValueError as e: log(field, e) return converted diff --git a/odoo/addons/base/ir/ir_http.py b/odoo/addons/base/ir/ir_http.py index 1d942e75a86..75676910461 100644 --- a/odoo/addons/base/ir/ir_http.py +++ b/odoo/addons/base/ir/ir_http.py @@ -176,7 +176,7 @@ class IrHttp(models.AbstractModel): try: rule, arguments = cls._find_handler(return_rule=True) func = rule.endpoint - except werkzeug.exceptions.NotFound, e: + except werkzeug.exceptions.NotFound as e: return cls._handle_exception(e) # check authentication level @@ -195,7 +195,7 @@ class IrHttp(models.AbstractModel): result = request.dispatch() if isinstance(result, Exception): raise result - except Exception, e: + except Exception as e: return cls._handle_exception(e) return result diff --git a/odoo/addons/base/ir/ir_qweb/assetsbundle.py b/odoo/addons/base/ir/ir_qweb/assetsbundle.py index 47a7cd1b8b8..5bc2dec8a9b 100644 --- a/odoo/addons/base/ir/ir_qweb/assetsbundle.py +++ b/odoo/addons/base/ir/ir_qweb/assetsbundle.py @@ -523,7 +523,7 @@ class JavascriptAsset(WebAsset): def _fetch_content(self): try: return super(JavascriptAsset, self)._fetch_content() - except AssetError, e: + except AssetError as e: return "console.error(%s);" % json.dumps(e.message) def to_html(self): @@ -572,7 +572,7 @@ class StylesheetAsset(WebAsset): content = self.rx_charset.sub('', content) return content - except AssetError, e: + except AssetError as e: self.bundle.css_errors.append(e.message) return '' diff --git a/odoo/addons/base/ir/ir_qweb/qweb.py b/odoo/addons/base/ir/ir_qweb/qweb.py index 89281963de7..e4b618a47e4 100644 --- a/odoo/addons/base/ir/ir_qweb/qweb.py +++ b/odoo/addons/base/ir/ir_qweb/qweb.py @@ -281,9 +281,9 @@ class QWeb(object): _options['ast_calls'] = [] def_name = self._create_def(_options, body, prefix='template_%s' % name.replace('.', '_')) _options['ast_calls'] += ast_calls - except QWebException, e: + except QWebException as e: raise e - except Exception, e: + except Exception as e: path = _options['last_path_node'] node = element.getroottree().xpath(path) raise QWebException("Error when compiling AST", e, path, etree.tostring(node[0]), name) @@ -301,9 +301,9 @@ class QWeb(object): ns = {} unsafe_eval(compile(astmod, '<template>', 'exec'), ns) compiled = ns[def_name] - except QWebException, e: + except QWebException as e: raise e - except Exception, e: + except Exception as e: path = _options['last_path_node'] node = element.getroottree().xpath(path) raise QWebException("Error when compiling AST", e, path, node and etree.tostring(node[0]), name) @@ -315,9 +315,9 @@ class QWeb(object): values = dict(self.default_values(), **values) try: return compiled(self, append, values, options, log) - except QWebException, e: + except QWebException as e: raise e - except Exception, e: + except Exception as e: path = log['last_path_node'] element, document = self.get_template(template, options) node = element.getroottree().xpath(path) @@ -341,9 +341,9 @@ class QWeb(object): else: try: document = options.get('load', self.load)(template, options) - except QWebException, e: + except QWebException as e: raise e - except Exception, e: + except Exception as e: raise QWebException("load could not load template", name=template) if document is not None: diff --git a/odoo/addons/base/module/module.py b/odoo/addons/base/module/module.py index 04cb68f61c2..1178fcca49f 100644 --- a/odoo/addons/base/module/module.py +++ b/odoo/addons/base/module/module.py @@ -310,7 +310,7 @@ class Module(models.Model): terp = cls.get_module_info(module_name) try: cls._check_external_dependencies(terp) - except Exception, e: + except Exception as e: if newstate == 'to install': msg = _('Unable to install module "%s" because an external dependency is not met: %s') elif newstate == 'to upgrade': diff --git a/odoo/addons/base/res/res_font.py b/odoo/addons/base/res/res_font.py index 9107455f728..873bea5aa03 100644 --- a/odoo/addons/base/res/res_font.py +++ b/odoo/addons/base/res/res_font.py @@ -79,7 +79,7 @@ class ResFont(models.Model): font = ttfonts.TTFontFile(font_path) _logger.debug("Found font %s at %s", font.name, font_path) found_fonts.append((font.familyName, font.name, font_path, font.styleName)) - except Exception, ex: + except Exception as ex: _logger.warning("Could not register Font %s: %s", font_path, ex) for family, name, path, mode in found_fonts: diff --git a/odoo/cli/deploy.py b/odoo/cli/deploy.py index 2e97d838ec2..2547ebdcd78 100644 --- a/odoo/cli/deploy.py +++ b/odoo/cli/deploy.py @@ -95,5 +95,5 @@ class Deploy(Command): args.url = 'https://%s' % args.url result = self.deploy_module(args.path, args.url, args.login, args.password, args.db, force=args.force) print(result) - except Exception, e: + except Exception as e: sys.exit("ERROR: %s" % e) diff --git a/odoo/cli/start.py b/odoo/cli/start.py index 043c411ad8d..306722b23da 100644 --- a/odoo/cli/start.py +++ b/odoo/cli/start.py @@ -56,9 +56,9 @@ class Start(Command): # TODO: forbid some database names ? eg template1, ... try: _create_empty_database(args.db_name) - except DatabaseExists, e: + except DatabaseExists as e: pass - except Exception, e: + except Exception as e: die("Could not create database `%s`. (%s)" % (args.db_name, e)) if '--db-filter' not in cmdargs: diff --git a/odoo/http.py b/odoo/http.py index cef63e8f639..015c00342b4 100644 --- a/odoo/http.py +++ b/odoo/http.py @@ -131,11 +131,11 @@ def dispatch_rpc(service_name, method, params): return result except NO_POSTMORTEM: raise - except odoo.exceptions.DeferredException, e: + except odoo.exceptions.DeferredException as e: _logger.exception(odoo.tools.exception_to_unicode(e)) odoo.tools.debugger.post_mortem(odoo.tools.config, e.traceback) raise - except Exception, e: + except Exception as e: _logger.exception(odoo.tools.exception_to_unicode(e)) odoo.tools.debugger.post_mortem(odoo.tools.config, sys.exc_info()) raise @@ -687,7 +687,7 @@ class JsonRequest(WebRequest): rpc_request.debug(logline) return self._json_response(result) - except Exception, e: + except Exception as e: return self._handle_exception(e) def serialize_exception(e): @@ -777,7 +777,7 @@ class HttpRequest(WebRequest): 'redirect': redirect, }) return werkzeug.utils.redirect('/web/login?%s' % query) - except werkzeug.exceptions.HTTPException, e: + except werkzeug.exceptions.HTTPException as e: return e def dispatch(self): @@ -1391,7 +1391,7 @@ class Root(object): if isinstance(result, Response) and result.is_qweb: try: result.flatten() - except(Exception), e: + except(Exception) as e: if request.db: result = request.registry['ir.http']._handle_exception(e) else: @@ -1448,7 +1448,7 @@ class Root(object): def _dispatch_nodb(): try: func, arguments = self.nodb_routing_map.bind_to_environ(request.httprequest.environ).match() - except werkzeug.exceptions.HTTPException, e: + except werkzeug.exceptions.HTTPException as e: return request._handle_exception(e) request.set_handler(func, arguments, "none") result = request.dispatch() @@ -1483,7 +1483,7 @@ class Root(object): response = self.get_response(httprequest, result, explicit_session) return response(environ, start_response) - except werkzeug.exceptions.HTTPException, e: + except werkzeug.exceptions.HTTPException as e: return e(environ, start_response) def get_db_router(self, db): diff --git a/odoo/models.py b/odoo/models.py index 8e88b82c788..e5805e74bba 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -941,7 +941,7 @@ class BaseModel(object): valid = names and not (set(names) & field_names) valid = valid or func(self) extra_error = None - except Exception, e: + except Exception as e: _logger.debug('Exception while validating constraint', exc_info=True) valid = False extra_error = tools.ustr(e) @@ -964,9 +964,9 @@ class BaseModel(object): if set(check._constrains) & field_names: try: check(self) - except ValidationError, e: + except ValidationError as e: raise - except Exception, e: + except Exception as e: raise ValidationError("%s\n\n%s" % (_("Error while validating constraint"), tools.ustr(e))) @api.model diff --git a/odoo/modules/module.py b/odoo/modules/module.py index ecf95be088b..be2977c131e 100644 --- a/odoo/modules/module.py +++ b/odoo/modules/module.py @@ -373,7 +373,7 @@ def load_openerp_module(module_name): if info['post_load']: getattr(sys.modules['odoo.addons.' + module_name], info['post_load'])() - except Exception, e: + except Exception as e: msg = "Couldn't load module %s" % (module_name) _logger.critical(msg) _logger.critical(e) @@ -427,7 +427,7 @@ def get_test_modules(module): modpath = 'odoo.addons.' + module try: mod = importlib.import_module('.tests', modpath) - except Exception, e: + except Exception as e: # If module has no `tests` sub-module, no problem. if str(e) != 'No module named tests': _logger.exception('Can not `import %s`.', module) diff --git a/odoo/report/render/rml2pdf/trml2pdf.py b/odoo/report/render/rml2pdf/trml2pdf.py index 22eac51cfab..47ab8d313a5 100644 --- a/odoo/report/render/rml2pdf/trml2pdf.py +++ b/odoo/report/render/rml2pdf/trml2pdf.py @@ -1015,7 +1015,7 @@ class _rml_template(object): self.doc_tmpl.build(fis,canvasmaker=NumberedCanvas) else: self.doc_tmpl.build(fis) - except platypus.doctemplate.LayoutError, e: + except platypus.doctemplate.LayoutError as e: e.name = 'Print Error' e.value = 'The document you are trying to print contains a table row that does not fit on one page. Please try to split it in smaller rows or contact your administrator.' raise @@ -1026,7 +1026,7 @@ def parseNode(rml, localcontext=None, fout=None, images=None, path='.', title=No #try to override some font mappings try: SetCustomFonts(r) - except Exception, exc: + except Exception as exc: _logger.info('Cannot set font mapping: %s', "".join(traceback.format_exception_only(type(exc),exc))) fp = StringIO() r.render(fp) diff --git a/odoo/report/render/rml2pdf/utils.py b/odoo/report/render/rml2pdf/utils.py index 0a9a6bd44bf..785e12fdc41 100644 --- a/odoo/report/render/rml2pdf/utils.py +++ b/odoo/report/render/rml2pdf/utils.py @@ -34,7 +34,7 @@ def _child_get(node, self=None, tagname=None): safe_eval(n.get('rml_except'), {}, self.localcontext) except GeneratorExit: continue - except Exception, e: + except Exception as e: _logger.info('rml_except: "%s"', n.get('rml_except',''), exc_info=True) continue if n.get('rml_tag'): @@ -46,7 +46,7 @@ def _child_get(node, self=None, tagname=None): yield n2 except GeneratorExit: yield n - except Exception, e: + except Exception as e: _logger.info('rml_tag: "%s"', n.get('rml_tag',''), exc_info=True) yield n else: @@ -57,7 +57,7 @@ def _child_get(node, self=None, tagname=None): safe_eval(n.get('rml_except'), {}, self.localcontext) except GeneratorExit: continue - except Exception, e: + except Exception as e: _logger.info('rml_except: "%s"', n.get('rml_except',''), exc_info=True) continue if self and self.localcontext and n.get('rml_tag'): @@ -70,7 +70,7 @@ def _child_get(node, self=None, tagname=None): tagname = '' except GeneratorExit: pass - except Exception, e: + except Exception as e: _logger.info('rml_tag: "%s"', n.get('rml_tag',''), exc_info=True) pass if (tagname is None) or (n.tag==tagname): diff --git a/odoo/service/db.py b/odoo/service/db.py index a9968963fb8..e20dcb7442a 100644 --- a/odoo/service/db.py +++ b/odoo/service/db.py @@ -73,7 +73,7 @@ def _initialize_db(id, db_name, demo, lang, user_password, login='admin', countr cr.execute('SELECT login, password FROM res_users ORDER BY login') cr.commit() - except Exception, e: + except Exception as e: _logger.exception('CREATE DATABASE failed:') def _create_empty_database(name): @@ -145,7 +145,7 @@ def exp_drop(db_name): try: cr.execute('DROP DATABASE "%s"' % db_name) - except Exception, e: + except Exception as e: _logger.info('DROP DB: %s failed:\n%s', db_name, e) raise Exception("Couldn't drop database %s: %s" % (db_name, e)) else: @@ -287,7 +287,7 @@ def exp_rename(old_name, new_name): try: cr.execute('ALTER DATABASE "%s" RENAME TO "%s"' % (old_name, new_name)) _logger.info('RENAME DB: %s -> %s', old_name, new_name) - except Exception, e: + except Exception as e: _logger.info('RENAME DB: %s -> %s failed:\n%s', old_name, new_name, e) raise Exception("Couldn't rename database %s to %s: %s" % (old_name, new_name, e)) diff --git a/odoo/service/model.py b/odoo/service/model.py index 8ad94fd4f56..6502f74d2bb 100644 --- a/odoo/service/model.py +++ b/odoo/service/model.py @@ -134,7 +134,7 @@ def check(f): tries += 1 _logger.info("%s, retry %d/%d in %.04f sec..." % (errorcodes.lookup(e.pgcode), tries, MAX_TRIES_ON_CONCURRENCY_FAILURE, wait_time)) time.sleep(wait_time) - except IntegrityError, inst: + except IntegrityError as inst: registry = odoo.registry(dbname) for key in registry._sql_error.keys(): if key in inst[0]: diff --git a/odoo/service/report.py b/odoo/service/report.py index 011fb19ca63..efeef65f656 100644 --- a/odoo/service/report.py +++ b/odoo/service/report.py @@ -59,7 +59,7 @@ def exp_render_report(db, uid, object, ids, datas=None, context=None): self_reports[id]['result'] = result self_reports[id]['format'] = format self_reports[id]['state'] = True - except Exception, exception: + except Exception as exception: _logger.exception('Exception: %s\n', exception) if hasattr(exception, 'name') and hasattr(exception, 'value'): @@ -98,7 +98,7 @@ def exp_report(db, uid, object, ids, datas=None, context=None): self_reports[id]['result'] = result self_reports[id]['format'] = format self_reports[id]['state'] = True - except Exception, exception: + except Exception as exception: _logger.exception('Exception: %s\n', exception) if hasattr(exception, 'name') and hasattr(exception, 'value'): self_reports[id]['exception'] = odoo.exceptions.DeferredException(tools.ustr(exception.name), tools.ustr(exception.value)) diff --git a/odoo/service/server.py b/odoo/service/server.py index 85bdfc12e0c..97d99983597 100644 --- a/odoo/service/server.py +++ b/odoo/service/server.py @@ -173,7 +173,7 @@ class CommonServer(object): """ try: sock.shutdown(socket.SHUT_RDWR) - except socket.error, e: + except socket.error as e: if e.errno == errno.EBADF: # Werkzeug > 0.9.6 closes the socket itself (see commit # https://github.com/mitsuhiko/werkzeug/commit/4d8ca089) @@ -422,7 +422,7 @@ class PreforkServer(CommonServer): def pipe_ping(self, pipe): try: os.write(pipe[1], '.') - except IOError, e: + except IOError as e: if e.errno not in [errno.EAGAIN, errno.EINTR]: raise @@ -468,7 +468,7 @@ class PreforkServer(CommonServer): def worker_kill(self, pid, sig): try: os.kill(pid, sig) - except OSError, e: + except OSError as e: if e.errno == errno.ESRCH: self.worker_pop(pid) @@ -506,7 +506,7 @@ class PreforkServer(CommonServer): _logger.critical(msg, wpid) raise Exception(msg % wpid) self.worker_pop(wpid) - except OSError, e: + except OSError as e: if e.errno == errno.ECHILD: break raise @@ -546,10 +546,10 @@ class PreforkServer(CommonServer): # empty pipe while os.read(fd, 1): pass - except OSError, e: + except OSError as e: if e.errno not in [errno.EAGAIN]: raise - except select.error, e: + except select.error as e: if e[0] not in [errno.EINTR]: raise @@ -626,7 +626,7 @@ class PreforkServer(CommonServer): _logger.debug("Multiprocess clean stop") self.stop() break - except Exception, e: + except Exception as e: _logger.exception(e) self.stop(False) return -1 @@ -659,7 +659,7 @@ class Worker(object): def sleep(self): try: select.select([self.multi.socket], [], [], self.multi.beat) - except select.error, e: + except select.error as e: if e[0] not in [errno.EINTR]: raise @@ -748,7 +748,7 @@ class WorkerHTTP(Worker): # receiving the full reply try: self.server.process_request(client, addr) - except IOError, e: + except IOError as e: if e.errno != errno.EPIPE: raise self.request_count += 1 @@ -757,7 +757,7 @@ class WorkerHTTP(Worker): try: client, addr = self.multi.socket.accept() self.process_request(client, addr) - except socket.error, e: + except socket.error as e: if e[0] not in (errno.EAGAIN, errno.ECONNABORTED): raise diff --git a/odoo/service/wsgi_server.py b/odoo/service/wsgi_server.py index 9669fabf5d3..3f4dc4b46ad 100644 --- a/odoo/service/wsgi_server.py +++ b/odoo/service/wsgi_server.py @@ -55,7 +55,7 @@ def xmlrpc_return(start_response, service, method, params, string_faultcode=Fals try: result = odoo.http.dispatch_rpc(service, method, params) response = xmlrpclib.dumps((result,), methodresponse=1, allow_none=False, encoding=None) - except Exception, e: + except Exception as e: if string_faultcode: response = xmlrpc_handle_exception_string(e) else: diff --git a/odoo/tests/common.py b/odoo/tests/common.py index c2464864972..c16ce8b0425 100644 --- a/odoo/tests/common.py +++ b/odoo/tests/common.py @@ -312,7 +312,7 @@ class HttpCase(TransactionCase): # read a byte try: ready, _, _ = select.select([phantom.stdout], [], [], 0.5) - except select.error, e: + except select.error as e: # In Python 2, select.error has no relation to IOError or # OSError, and no errno/strerror/filename, only a pair of # unnamed arguments (matching errno and strerror) diff --git a/odoo/tools/convert.py b/odoo/tools/convert.py index 1301e035241..c7faab244d3 100644 --- a/odoo/tools/convert.py +++ b/odoo/tools/convert.py @@ -781,7 +781,7 @@ form: module.record_id""" % (xml_id,) elif rec.tag in self._tags: try: self._tags[rec.tag](rec, de, mode=mode) - except Exception, e: + except Exception as e: self.cr.rollback() exc_info = sys.exc_info() raise ParseError, (ustr(e), etree.tostring(rec).rstrip(), rec.getroottree().docinfo.URL, rec.sourceline), exc_info[2] diff --git a/odoo/tools/mail.py b/odoo/tools/mail.py index e1a4eeb9c54..490006082d5 100644 --- a/odoo/tools/mail.py +++ b/odoo/tools/mail.py @@ -233,7 +233,7 @@ def html_sanitize(src, silent=True, sanitize_tags=True, sanitize_attributes=Fals cleaned = cleaned.replace('%>', '%>') # html considerations so real html content match database value cleaned.replace(u'\xa0', ' ') - except etree.ParserError, e: + except etree.ParserError as e: if 'empty' in str(e): return "" if not silent: diff --git a/odoo/tools/safe_eval.py b/odoo/tools/safe_eval.py index 4d8e5b63d9f..14020378c21 100644 --- a/odoo/tools/safe_eval.py +++ b/odoo/tools/safe_eval.py @@ -156,7 +156,7 @@ def test_expr(expr, allowed_codes, mode="eval"): code_obj = compile(expr, "", mode) except (SyntaxError, TypeError, ValueError): raise - except Exception, e: + except Exception as e: import sys exc_info = sys.exc_info() raise ValueError, '"%s" while compiling\n%r' % (ustr(e), expr), exc_info[2] @@ -319,7 +319,7 @@ def safe_eval(expr, globals_dict=None, locals_dict=None, mode="eval", nocopy=Fal raise except odoo.exceptions.MissingError: raise - except Exception, e: + except Exception as e: import sys exc_info = sys.exc_info() raise ValueError, '%s: "%s" while evaluating\n%r' % (ustr(type(e)), ustr(e), expr), exc_info[2] diff --git a/odoo/tools/test_reports.py b/odoo/tools/test_reports.py index 962f84b2ed7..ef09862bc01 100644 --- a/odoo/tools/test_reports.py +++ b/odoo/tools/test_reports.py @@ -218,7 +218,7 @@ def try_report_action(cr, uid, action_id, active_model=None, active_ids=None, 'type': button.getAttribute('type'), 'weight': button_weight, }) - except Exception, e: + except Exception as e: _logger.warning("Cannot resolve the view arch and locate the buttons!", exc_info=True) raise AssertionError(e.args[0]) diff --git a/odoo/tools/translate.py b/odoo/tools/translate.py index c947ae5e75d..b33b356a2f9 100644 --- a/odoo/tools/translate.py +++ b/odoo/tools/translate.py @@ -846,7 +846,7 @@ def trans_generate(lang, modules, cr): if model=='ir.model.fields': try: field_name = encode(record.name) - except AttributeError, exc: + except AttributeError as exc: _logger.error("name error in %s: %s", xml_name, str(exc)) continue field_model = env.get(record.model) diff --git a/odoo/tools/xml_utils.py b/odoo/tools/xml_utils.py index d179559db75..df4c5669644 100644 --- a/odoo/tools/xml_utils.py +++ b/odoo/tools/xml_utils.py @@ -10,7 +10,7 @@ def check_with_xsd(tree_or_str, xsd_path): xsd_schema = etree.XMLSchema(xml_schema_doc) try: xsd_schema.assertValid(tree_or_str) - except etree.DocumentInvalid, xml_errors: + except etree.DocumentInvalid as xml_errors: #import UserError only here to avoid circular import statements with tools.func being imported in exceptions.py from odoo.exceptions import UserError raise UserError('\n'.join([e.message for e in xml_errors.error_log])) diff --git a/odoo/tools/yaml_import.py b/odoo/tools/yaml_import.py index 8e9e1342a70..cefc3667a9e 100644 --- a/odoo/tools/yaml_import.py +++ b/odoo/tools/yaml_import.py @@ -227,7 +227,7 @@ class YamlInterpreter(object): for test in expressions: try: success = unsafe_eval(test, self.eval_context, RecordDictWrapper(record)) - except Exception, e: + except Exception as e: _logger.debug('Exception during evaluation of !assert block in yaml_file %s.', self.filename, exc_info=True) raise YamlImportAbortion(e) if not success: @@ -240,12 +240,12 @@ class YamlInterpreter(object): rmsg = '' try: lmsg = unsafe_eval(left, self.eval_context, RecordDictWrapper(record)) - except Exception, e: + except Exception as e: lmsg = '<exc>' try: rmsg = unsafe_eval(right, self.eval_context, RecordDictWrapper(record)) - except Exception, e: + except Exception as e: rmsg = '<exc>' msg += 'values: ! %s %s %s' @@ -605,11 +605,11 @@ class YamlInterpreter(object): try: code_obj = compile(statements, self.filename, 'exec') unsafe_eval(code_obj, {'ref': self.get_id}, code_context) - except AssertionError, e: + except AssertionError as e: self._log_assert_failure('AssertionError in Python code %s (line %d): %s', python.name, python.first_line, e) return - except Exception, e: + except Exception as e: _logger.debug('Exception during evaluation of !python block in yaml_file %s.', self.filename, exc_info=True) raise else: @@ -847,7 +847,7 @@ class YamlInterpreter(object): is_preceded_by_comment = self._log_node(node, is_preceded_by_comment) try: self._process_node(node) - except Exception, e: + except Exception as e: _logger.exception(e) raise |
